11 private Rectangle _targetRectPx =
new Rectangle(0, 0, 1280, 720);
12 private float _zoom = 1f;
13 private float? _zoomTarget;
14 private float _zoomLerpPerSecond;
15 private float? _zoomDurationSeconds;
16 private float _zoomElapsedSeconds;
17 private float _zoomStart;
28 public event Action<ViewportZoomChangedEventArgs>?
ZoomChanged;
39 if (value == _targetRectPx)
42 var oldRect = _targetRectPx;
43 _targetRectPx = value;
55 public void Resize(
int width,
int height)
58 TargetRectPx =
new Rectangle(rect.Left, rect.Top, width, height);
71 if (Math.Abs(value - _zoom) < 1e-6f)
87 internal bool IsZoomAnimating => _zoomTarget is not
null;
98 _zoomLerpPerSecond = 0f;
99 _zoomDurationSeconds =
null;
100 _zoomElapsedSeconds = 0f;
112 public void ZoomTo(
float targetZoom,
float lerpPerSecond)
114 if (lerpPerSecond <= 0f)
121 _zoomTarget = targetZoom;
122 _zoomLerpPerSecond = lerpPerSecond;
123 _zoomDurationSeconds =
null;
124 _zoomElapsedSeconds = 0f;
135 if (durationSeconds <= 0f)
142 _zoomTarget = targetZoom;
144 _zoomDurationSeconds = durationSeconds;
145 _zoomElapsedSeconds = 0f;
148 _zoomLerpPerSecond = 0f;
156 internal void UpdateZoom(
float dtSeconds)
158 if (_zoomTarget is
null)
161 float target = _zoomTarget.Value;
162 float dt = Math.Max(0f, dtSeconds);
164 if (_zoomDurationSeconds is { } durationSeconds)
166 _zoomElapsedSeconds = Math.Min(_zoomElapsedSeconds + dt, durationSeconds);
168 float progress = durationSeconds > 0f ? _zoomElapsedSeconds / durationSeconds : 1f;
172 const float decay = 4.605170186f;
174 float normalization = 1f - MathF.Exp(-decay);
175 float easedProgress = (1f - MathF.Exp(-decay * progress)) / normalization;
177 Zoom = _zoomStart + (target - _zoomStart) * easedProgress;
179 if (_zoomElapsedSeconds >= durationSeconds)
188 if (_zoomLerpPerSecond <= 0f)
191 float t = 1f - MathF.Exp(-_zoomLerpPerSecond * dt);
193 float newZoom = _zoom + (target - _zoom) * t;
197 if (Math.Abs(newZoom - target) < 1e-4f)
Provides data for the Viewport.TargetRectChanged event, which is raised when a viewport's target rect...
Provides data for the Viewport.ZoomChanged event, which is raised when a viewport's zoom level change...
A rectangular window on the render target with its own zoom and placement. Viewport never moves the w...
Rectangle TargetRectPx
Screen-space rectangle (in SCREEN / RenderSurface pixels) where this view is drawn....
PointF ScreenOffsetPx
Optional per-view HUD/safe-area offset in screen pixels.
void ZoomToOverDuration(float targetZoom, float durationSeconds)
Smoothly animates the zoom using exponential easing and snaps exactly to the target when the requeste...
Action< ViewportResizedEventArgs >? TargetRectChanged
Fired whenever TargetRectPx changes (viewport resized or moved). Provides the Viewport instance and t...
Action< ViewportZoomChangedEventArgs >? ZoomChanged
Occurs when the zoom level of the viewport changes.
void SnapZoom(float zoom)
Instantly sets the zoom level, raising the ZoomChanged event.
void ZoomTo(float targetZoom, float lerpPerSecond)
Smoothly animates the zoom toward a target level using an exponential lerp rate in "per second" units...
void Resize(int width, int height)
Updates the viewport size while preserving its current on-screen origin. This is a convenience around...
SizeF VisibleWorldSizePx
World size visible through this viewport (used for Camera clamping).
float Zoom
Zoom factor applied to the world when rendering this view. Values greater than 1 zoom in,...