using Engine.Core; namespace Engine.Integration.SDL3; public class Sdl3Camera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw { public Event OnViewMatrixChanged { get; } = new(); public Event OnProjectionMatrixChanged { get; } = new(); public Event OnViewportChanged { get; } = new(); public Event OnZoomChanged { get; } = new(); private IWindow window = 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 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 = Vector2D.Transform(screenPosition, Transform); return worldPosition; } public Vector2D WorldToScreenPosition(Vector2D worldPosition) { Vector2D screenPosition = Vector2D.Transform(worldPosition, Transform); return screenPosition; } public void LastActiveFrame() => Transform = null!; public void FirstActiveFrame() { window = BehaviourController.UniverseObject.Universe.FindRequiredBehaviour(); Transform = BehaviourController.GetRequiredBehaviour(); } public void PreDraw() { ProjectionMatrix = Matrix4x4.CreateOrthographicViewCentered(window.Size.X, window.Size.Y); ViewMatrix = Matrix4x4.Identity .ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y)) .ApplyScale(Zoom) .ApplyRotationZ(-Transform.Rotation * Math.DegreeToRadian) .ApplyTranslation(new Vector3D(-Transform.Position.X, -Transform.Position.Y, 0f)); } }