using System; using Godot; public partial class CameraController : Camera2D { [Export] public float ZoomStep = 0.1f; [Export] public float MinZoom = 0.5f; [Export] public float MaxZoom = 3.0f; [Export] private float minX = 0f; [Export] private float maxX = 0f; [Export] private float minY = 0f; [Export] private float maxY = 0f; private bool _dragging; private Vector2 _grabWorldPos; public override void _Input(InputEvent @event) { // Middle mouse drag if (@event is InputEventMouseButton mb) { if (mb.ButtonIndex == MouseButton.Middle) { _dragging = mb.Pressed; if (_dragging) _grabWorldPos = GetGlobalMousePosition(); } // Scroll zoom if (mb.Pressed && (mb.ButtonIndex == MouseButton.WheelUp || mb.ButtonIndex == MouseButton.WheelDown)) { Vector2 mouseBeforeZoom = GetGlobalMousePosition(); float zoomFactor = mb.ButtonIndex == MouseButton.WheelUp ? -ZoomStep : ZoomStep; float newZoom = Mathf.Clamp(Zoom.X + zoomFactor, MinZoom, MaxZoom); Zoom = new Vector2(newZoom, newZoom); // keep cursor locked to same world point Vector2 mouseAfterZoom = GetGlobalMousePosition(); GlobalPosition += mouseBeforeZoom - mouseAfterZoom; ClampPos(); } } if (_dragging && @event is InputEventMouseMotion) { Vector2 currentWorld = GetGlobalMousePosition(); GlobalPosition += _grabWorldPos - currentWorld; ClampPos(); } } private void ClampPos() { var t = GetCanvasTransform(); var camrect = t.AffineInverse().BasisXform(GetViewportRect().Size); GlobalPosition = new Vector2( Mathf.Clamp(GlobalPosition.X, LimitLeft + camrect.X / 2, LimitRight - camrect.X / 2), Mathf.Clamp(GlobalPosition.Y, LimitTop + camrect.Y / 2, LimitBottom - camrect.Y / 2) ); } }