using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Syntriax.Engine.Core; using Syntriax.Engine.Core.Abstract; namespace Pong.Behaviours; public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : BehaviourOverride, ICamera2D { public event OnMatrixTransformChangedDelegate? OnMatrixTransformChanged = null; public event OnViewportChangedDelegate? OnViewportChanged = null; public event OnZoomChangedDelegate? OnZoomChanged = null; private Matrix _matrixTransform = Matrix.Identity; private Viewport _viewport = default; private float _zoom = 1f; public GraphicsDeviceManager Graphics { get; } = Graphics; 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 = Math.Max(0.1f, value); if (_zoom == newValue) return; _zoom = newValue; OnZoomChanged?.Invoke(this); } } public float Rotation { get => Transform.Rotation; set => Transform.Rotation = value; } public event IAssignableTransform.OnTransformAssignedDelegate? OnTransformAssigned { add => GameObject.OnTransformAssigned += value; remove => GameObject.OnTransformAssigned -= value; } ITransform IAssignableTransform.Transform => GameObject.Transform; bool IAssignableTransform.Assign(ITransform transform) => GameObject.Assign(transform); // 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(EngineConverter.screenScale); } public Vector2D WorldToScreenPosition(Vector2D worldPosition) { Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), MatrixTransform).ToVector2D(); return screenPosition.Scale(EngineConverter.screenScale); } protected override void OnFirstActiveFrame() => Viewport = Graphics.GraphicsDevice.Viewport; protected override void OnPreDraw() { MatrixTransform = Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 0f)) * Matrix.CreateRotationZ(Rotation * Math.DegreeToRadian) * Matrix.CreateScale(Zoom) * Matrix.CreateTranslation(new Vector3(_viewport.Width * .5f, _viewport.Height * .5f, 0f)); } public delegate void OnMatrixTransformChangedDelegate(MonoGameCamera2DBehaviour sender); public delegate void OnViewportChangedDelegate(MonoGameCamera2DBehaviour sender); public delegate void OnZoomChangedDelegate(MonoGameCamera2DBehaviour sender); }