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
}