Original Behaviour was using old methods for detecting entering/exiting universe, they are now all under the same hood and the original is kept for UniverseEntranceManager because it needs to enter the universe without itself. The internal behaviour kept under a subnamespace of "Core.Internal" for the purpose that it might come in handy for other use cases.
106 lines
3.2 KiB
C#
106 lines
3.2 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
using Engine.Core;
|
|
|
|
namespace Engine.Integration.MonoGame;
|
|
|
|
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, IPreDraw
|
|
{
|
|
public Event<MonoGameCamera2D> OnMatrixTransformChanged { get; } = new();
|
|
public Event<MonoGameCamera2D> OnViewportChanged { get; } = new();
|
|
public Event<MonoGameCamera2D> OnZoomChanged { get; } = new();
|
|
|
|
private Matrix _matrixTransform = Matrix.Identity;
|
|
|
|
private Viewport _viewport = default;
|
|
private float _zoom = 1f;
|
|
|
|
public GraphicsDeviceManager Graphics { get; private set; } = null!;
|
|
public ITransform2D Transform { get; private set; } = null!;
|
|
|
|
public Matrix MatrixTransform
|
|
{
|
|
get => _matrixTransform;
|
|
set
|
|
{
|
|
if (_matrixTransform == value)
|
|
return;
|
|
|
|
_matrixTransform = value;
|
|
OnMatrixTransformChanged.Invoke(this);
|
|
}
|
|
}
|
|
|
|
public Vector2D Position
|
|
{
|
|
get => Transform.Position;
|
|
set => Transform.Position = value;
|
|
}
|
|
|
|
public Viewport Viewport
|
|
{
|
|
get => _viewport;
|
|
set
|
|
{
|
|
if (_viewport.Equals(value))
|
|
return;
|
|
|
|
_viewport = value;
|
|
OnViewportChanged.Invoke(this);
|
|
}
|
|
}
|
|
|
|
public float Zoom
|
|
{
|
|
get => _zoom;
|
|
set
|
|
{
|
|
float newValue = Engine.Core.Math.Max(0.1f, value);
|
|
|
|
if (_zoom == newValue)
|
|
return;
|
|
|
|
_zoom = newValue;
|
|
OnZoomChanged.Invoke(this);
|
|
}
|
|
}
|
|
|
|
public float Rotation
|
|
{
|
|
get => Transform.Rotation;
|
|
set => Transform.Rotation = value;
|
|
}
|
|
|
|
// TODO This causes delay since OnPreDraw calls assuming this is called in in Update
|
|
public Vector2D ScreenToWorldPosition(Vector2D screenPosition)
|
|
{
|
|
Vector2D worldPosition = Vector2.Transform(screenPosition.ToVector2(), Matrix.Invert(MatrixTransform)).ToVector2D();
|
|
return worldPosition.Scale(EngineConverterExtensions.screenScale);
|
|
}
|
|
public Vector2D WorldToScreenPosition(Vector2D worldPosition)
|
|
{
|
|
Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), MatrixTransform).ToVector2D();
|
|
return screenPosition.Scale(EngineConverterExtensions.screenScale);
|
|
}
|
|
|
|
public void FirstActiveFrame()
|
|
{
|
|
Graphics = BehaviourController.UniverseObject.Universe.FindRequiredBehaviour<MonoGameWindowContainer>().Window.Graphics;
|
|
Viewport = Graphics.GraphicsDevice.Viewport;
|
|
}
|
|
|
|
public void PreDraw()
|
|
{
|
|
MatrixTransform =
|
|
Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 0f)) *
|
|
Matrix.CreateRotationZ(Rotation * Engine.Core.Math.DegreeToRadian) *
|
|
Matrix.CreateScale(Transform.Scale.X.Max(Transform.Scale.Y)) *
|
|
Matrix.CreateScale(Zoom) *
|
|
Matrix.CreateTranslation(new Vector3(_viewport.Width * .5f, _viewport.Height * .5f, 0f));
|
|
}
|
|
|
|
protected sealed override void InitializeInternal() => Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
|
|
protected sealed override void FinalizeInternal() => Transform = null!;
|
|
}
|