1using System.Collections.ObjectModel;
13public sealed class ViewManager
16 private readonly List<View> _views =
new();
28 private ViewManager() { }
32 _renderSurfaceHost = renderSurfaceHost;
42 public ReadOnlyCollection<View>
Views => _views.AsReadOnly();
70 public void AddView(Rectangle targetRectPx,
float zoom = 1f,
int zOrder = 0, RectangleF? worldBoundsPx =
null)
72 if (worldBoundsPx is
null)
73 worldBoundsPx = RectangleF.Empty;
75 var cam =
new Camera(_renderSurfaceHost.Scene)
78 WorldBoundsPx = worldBoundsPx.Value,
79 FollowLerpPerSecond = 0f
82 cam.
SnapTo(
new PointF(0, 0));
86 TargetRectPx = targetRectPx,
90 var view =
new View(cam, vp) { ZOrder = zOrder };
91 view.Viewport.TargetRectChanged += OnViewportTargetRectChanged;
92 view.Viewport.ZoomChanged += OnViewportZoomChanged;
95 _renderSurfaceHost.Scene.FullRefreshNeeded =
true;
110 if (_renderSurfaceHost.RenderSurfaceAdapter is
null)
111 throw new InvalidOperationException(
"RenderSurfaceAdapter is not available.");
115 var backbuffer = _renderSurfaceHost.Backbuffer;
116 var bounds =
new Rectangle(0, 0, backbuffer.Width, backbuffer.Height);
118 RectangleF worldBoundsPx = RectangleF.Empty;
119 if (_renderSurfaceHost.Scene is not
null)
120 worldBoundsPx = _renderSurfaceHost.Scene.GetWorldBoundsPx();
122 AddView(bounds, zoom, zOrder, worldBoundsPx);
133 if (_renderSurfaceHost.RenderSurfaceAdapter is
null)
134 throw new InvalidOperationException(
"RenderSurfaceAdapter is not available.");
138 var backbuffer = _renderSurfaceHost.Backbuffer;
139 int width = backbuffer.Width;
140 int height = backbuffer.Height;
142 int halfWidth = width / 2;
144 RectangleF worldBoundsPx = RectangleF.Empty;
145 if (_renderSurfaceHost.Scene is not
null)
146 worldBoundsPx = _renderSurfaceHost.Scene.GetWorldBoundsPx();
150 new Rectangle(0, 0, halfWidth, height),
153 worldBoundsPx: worldBoundsPx);
157 new Rectangle(halfWidth, 0, width - halfWidth, height),
160 worldBoundsPx: worldBoundsPx);
171 if (_renderSurfaceHost.RenderSurfaceAdapter is
null)
172 throw new InvalidOperationException(
"RenderSurfaceAdapter is not available.");
176 var backbuffer = _renderSurfaceHost.Backbuffer;
177 int width = backbuffer.Width;
178 int height = backbuffer.Height;
180 int halfHeight = height / 2;
182 RectangleF worldBoundsPx = RectangleF.Empty;
183 if (_renderSurfaceHost.Scene is not
null)
184 worldBoundsPx = _renderSurfaceHost.Scene.GetWorldBoundsPx();
188 new Rectangle(0, 0, width, halfHeight),
191 worldBoundsPx: worldBoundsPx);
195 new Rectangle(0, halfHeight, width, height - halfHeight),
198 worldBoundsPx: worldBoundsPx);
212 foreach (var view
in _views!)
214 view.Viewport.TargetRectChanged -= OnViewportTargetRectChanged;
215 view.Viewport.ZoomChanged -= OnViewportZoomChanged;
221 if (_renderSurfaceHost.Scene is not
null)
222 _renderSurfaceHost.Scene.FullRefreshNeeded =
true;
239 int idx = _views.IndexOf(view);
241 return Array.Empty<
View>();
244 return _views.GetRange(0, idx);
261 int idx = _views.IndexOf(view);
262 if (idx < 0 || idx >= _views.Count - 1)
263 return Array.Empty<
View>();
266 return _views.GetRange(idx + 1, _views.Count - (idx + 1));
269 #region internal methods
271 internal void UpdateCameras(
float dtSeconds)
273 foreach (var view
in _views)
274 view.Update(dtSeconds);
277 internal void BindToScene(
Scene scene,
bool limitCameraToWorldBoundPx)
279 RectangleF worldBoundsPx = limitCameraToWorldBoundPx ? scene.
GetWorldBoundsPx() : RectangleF.Empty;
284 AddView(
new Rectangle(0, 0, _renderSurfaceHost.Backbuffer.Width, _renderSurfaceHost.Backbuffer.Height), 1, 0, worldBoundsPx);
288 foreach (var view
in _views)
290 view.Camera.WorldBoundsPx = worldBoundsPx;
295 #endregion internal methods
297 #region private methods
299 private void OnViewportZoomChanged(ViewportZoomChangedEventArgs args)
301 if (_renderSurfaceHost.Scene is not
null)
302 _renderSurfaceHost.Scene.FullRefreshNeeded =
true;
305 private void OnViewportTargetRectChanged(ViewportResizedEventArgs args)
307 if (_renderSurfaceHost.Scene is not
null)
308 _renderSurfaceHost.Scene.FullRefreshNeeded =
true;
311 private void SortViews()
313 _views.Sort(
static (a, b) =>
315 int cmp = a.ZOrder.CompareTo(b.ZOrder);
321 return a.Id.CompareTo(b.Id);
325 #endregion private methods
Represents a base class for hosting a render surface, providing functionality for managing rendering ...
Represents a world-space camera for a Scene. The camera tracks a world-space upper-left position in p...
void SnapTo(PointF worldUpperLeftPx)
Instantly moves the camera to the specified world-space position, interpreted as the upper-left corne...
Manages a collection of views for a render surface, handling view creation, removal,...
void ConfigureVerticalSplit(float leftZoom=1f, float rightZoom=1f)
Removes all existing views and creates a vertical split-screen layout: left and right views sharing t...
void ClearViews()
Removes all views from the manager, unsubscribing from their events and marking the scene as needing ...
IReadOnlyList< View > GetViewsAbove(View view)
Returns all views that are rendered in front of (above) the specified view, based on Z-order....
Action< View >? ViewRemoved
Occurs after a View is removed.
ReadOnlyCollection< View > Views
Gets a read-only collection of all views currently managed by this view manager. Views are sorted by ...
void ConfigureHorizontalSplit(float topZoom=1f, float bottomZoom=1f)
Removes all existing views and creates a horizontal split-screen layout: top and bottom views sharing...
void ConfigureSingleFullView(float zoom=1f, int zOrder=0)
Removes all existing views and creates a single full-screen view that occupies the entire logical Bac...
IReadOnlyList< View > GetViewsBelow(View view)
Returns all views that are rendered behind (below) the specified view, based on Z-order....
void AddView(Rectangle targetRectPx, float zoom=1f, int zOrder=0, RectangleF? worldBoundsPx=null)
Creates and adds a new view with the specified screen rectangle, zoom level, and Z-order....
Action< View >? ViewAdded
Occurs after a new View is added.
Represents a rendered view of a scene, combining a camera position with a viewport configuration to c...
A rectangular window on the render target with its own zoom and placement. Viewport never moves the w...
Represents a game scene containing multiple layers of tiles, sprites, and game objects....
RectangleF GetWorldBoundsPx()
Computes a world-space pixel bounding rectangle that encloses all layers in the scene.