namespace Mibo.Adaptive open Microsoft.Xna.Framework open Microsoft.Xna.Framework.Graphics open Mibo.Elmish // ───────────────────────────────────────────────────────────────────────────── // MonoGame-specific AdaptiveProgram wrapper. // // Mirrors MonoGameProgram (the MVU wrapper): wraps an AdaptiveProgram and adds // a slot for device-level configuration callbacks (Game * GraphicsDeviceManager // -> unit) that the backend-neutral Core type cannot hold. The host // (AdaptiveMonoGameGame) runs these callbacks in its constructor, after the Core // GameConfig but before Initialize, so settings like GraphicsProfile, vsync, and // fullscreen take effect at device-creation time. // ───────────────────────────────────────────────────────────────────────────── /// /// MonoGame-specific wrapper around an /// , carrying device-level /// configuration that the backend-neutral type cannot hold. /// /// /// Build one with , /// add MonoGame-specific configuration with /// , then pass /// the result to . /// /// /// /// let program = /// AdaptiveProgram.mkProgram init update /// |> AdaptiveProgram.withConfig(fun cfg -> /// { cfg with Width = 1280; Height = 720; Title = "My Game" }) /// /// let mgProgram = /// program /// |> AdaptiveMonoGameProgram.ofProgram /// |> AdaptiveMonoGameProgram.withConfig(fun (game, graphics) -> /// graphics.SynchronizeWithVerticalRetrace <- false) /// /// use game = new AdaptiveMonoGameGame<_>(mgProgram) /// game.Run() /// /// type AdaptiveMonoGameProgram<'Frame> = { /// The backend-neutral adaptive program. Program: AdaptiveProgram<'Frame> /// /// Device-level configuration callbacks invoked in the /// constructor, after the /// Core callbacks and /// before Initialize/GraphicsDevice creation. /// DeviceConfig: (Game * GraphicsDeviceManager -> unit) list } /// MonoGame-specific adaptive program builder extensions. module AdaptiveMonoGameProgram = /// /// Wraps an into an /// with no device-level /// configuration. /// let ofProgram (program: AdaptiveProgram<'Frame>) : AdaptiveMonoGameProgram<'Frame> = { Program = program; DeviceConfig = [] } /// /// Adds a device-level configuration callback that receives the Game /// instance and GraphicsDeviceManager for low-level setup. /// /// /// Invoked in the /// constructor, after the /// Core callbacks and /// before Initialize / GraphicsDevice creation — so settings /// like GraphicsProfile and PreferredBackBufferWidth/Height /// take effect. /// Use this for properties that require direct /// GraphicsDeviceManager/Game access: /// GraphicsProfile, SynchronizeWithVerticalRetrace (vsync), /// IsFullScreen, HardwareModeSwitch, /// Window.AllowUserResizing, Content.RootDirectory, etc. /// let withConfig (configure: Game * GraphicsDeviceManager -> unit) (program: AdaptiveMonoGameProgram<'Frame>) : AdaptiveMonoGameProgram<'Frame> = { program with DeviceConfig = configure :: program.DeviceConfig }