112 lines
3.7 KiB
C#
112 lines
3.7 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Microsoft.Xna.Framework.Input;
|
|
|
|
using Engine.Core;
|
|
|
|
namespace Engine.Integration.MonoGame;
|
|
|
|
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw, IUpdate
|
|
{
|
|
public Event<MonoGameCamera2D> OnViewMatrixChanged { get; } = new();
|
|
public Event<MonoGameCamera2D> OnProjectionMatrixChanged { get; } = new();
|
|
public Event<MonoGameCamera2D> OnViewportChanged { get; } = new();
|
|
public Event<MonoGameCamera2D> OnZoomChanged { get; } = new();
|
|
|
|
public GraphicsDeviceManager Graphics { get; private set; } = null!;
|
|
public ITransform2D Transform { get; private set; } = null!;
|
|
|
|
public Matrix4x4 ProjectionMatrix
|
|
{
|
|
get;
|
|
private set
|
|
{
|
|
if (field == value)
|
|
return;
|
|
|
|
field = value;
|
|
OnProjectionMatrixChanged.Invoke(this);
|
|
}
|
|
} = Matrix4x4.Identity;
|
|
|
|
public Matrix4x4 ViewMatrix
|
|
{
|
|
get;
|
|
private set
|
|
{
|
|
if (field == value)
|
|
return;
|
|
|
|
field = value;
|
|
OnViewMatrixChanged.Invoke(this);
|
|
}
|
|
} = Matrix4x4.Identity;
|
|
|
|
public Viewport Viewport
|
|
{
|
|
get;
|
|
set
|
|
{
|
|
if (field.Equals(value))
|
|
return;
|
|
|
|
field = value;
|
|
OnViewportChanged.Invoke(this);
|
|
}
|
|
} = default;
|
|
|
|
public float Zoom
|
|
{
|
|
get;
|
|
set
|
|
{
|
|
float newValue = Math.Max(0.1f, value);
|
|
|
|
if (field == newValue)
|
|
return;
|
|
|
|
field = newValue;
|
|
OnZoomChanged.Invoke(this);
|
|
}
|
|
} = 1f;
|
|
|
|
// 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(), ViewMatrix.Inverse.ToXnaMatrix()).ToVector2D();
|
|
return worldPosition.Scale(EngineConverterExtensions.screenScale);
|
|
}
|
|
public Vector2D WorldToScreenPosition(Vector2D worldPosition)
|
|
{
|
|
Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), ViewMatrix.ToXnaMatrix()).ToVector2D();
|
|
return screenPosition.Scale(EngineConverterExtensions.screenScale);
|
|
}
|
|
|
|
public void LastActiveFrame() => Transform = null!;
|
|
public void FirstActiveFrame()
|
|
{
|
|
Graphics = BehaviourController.UniverseObject.Universe.FindRequiredBehaviour<MonoGameWindowContainer>().Window.Graphics;
|
|
Viewport = Graphics.GraphicsDevice.Viewport;
|
|
Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
|
|
}
|
|
|
|
public void PreDraw()
|
|
{
|
|
ProjectionMatrix = Matrix4x4.CreateOrthographicViewCentered(Viewport.Width, -Viewport.Height);
|
|
ViewMatrix =
|
|
Matrix4x4.CreateTranslation(new Vector3D(-Transform.Position.X, Transform.Position.Y, 0f))
|
|
.ApplyRotationZ(Transform.Rotation * Math.DegreeToRadian)
|
|
.ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y))
|
|
.ApplyScale(Zoom);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
KeyboardInputs keyboardInputs = Universe.FindRequiredBehaviour<KeyboardInputs>();
|
|
if (keyboardInputs.IsPressed(Keys.Right)) Transform.Position += Transform.Right * Universe.Time.DeltaTime * 100;
|
|
if (keyboardInputs.IsPressed(Keys.Up)) Transform.Position += Transform.Up * Universe.Time.DeltaTime * 100;
|
|
if (keyboardInputs.IsPressed(Keys.Down)) Transform.Position += Transform.Down * Universe.Time.DeltaTime * 100;
|
|
if (keyboardInputs.IsPressed(Keys.Left)) Transform.Position += Transform.Left * Universe.Time.DeltaTime * 100;
|
|
}
|
|
}
|