using Friflo.Engine.ECS.Systems; using Microsoft.Xna.Framework; using MrGameEng.Core; using Myra; using Myra.Graphics2D.UI; namespace MrGameEng.UI; /// /// Draw system rendering the scene's Myra . Must run after the scene's /// world rendering (register UI last in the draw phase) — the UI is drawn on top in window /// pixels and also processes mouse/keyboard interaction during render. While /// is set (developer console open), the desktop is drawn /// without processing input, so overlay clicks and keystrokes do not fall through to it. /// public sealed class UiRenderSystem : BaseSystem { private readonly Desktop _desktop; private readonly InputCapture? _capture; /// Creates the system for . public UiRenderSystem(Desktop desktop, InputCapture? capture = null) { _desktop = desktop; _capture = capture; } /// protected override void OnUpdateGroup() { if (_capture?.Captured == true) { // Render() = UpdateInput + UpdateLayout + RenderVisual; пропускаем только ввод. _desktop.UpdateLayout(); _desktop.RenderVisual(); } else { _desktop.Render(); } } } /// Wires the UI module (Myra) into a . public static class SceneUiExtensions { /// /// Creates a Myra for this scene and registers /// in the draw phase. Call from OnLoad /// after UseRenderer2D() so the UI draws on top of the world. /// Build the UI by assigning . The desktop is disposed /// automatically when the scene unloads. /// public static Desktop UseUI(this Scene scene) { var services = scene.Context.Services; // Присваивание идемпотентно; геттер MyraEnvironment.Game бросает исключение, пока // Game не задан, поэтому проверять текущее значение перед записью нельзя. MyraEnvironment.Game = services.Get(); var capture = services.GetOrDefault(); if (capture is null) { capture = new InputCapture(); services.Add(capture); } var desktop = new Desktop(); scene.RegisterUnload(desktop.Dispose); scene.DrawSystems.Add(new UiRenderSystem(desktop, capture)); return desktop; } }