diff --git a/.claude/skills/project-export/SKILL.md b/.claude/skills/project-export/SKILL.md index eca743b..24bda05 100644 --- a/.claude/skills/project-export/SKILL.md +++ b/.claude/skills/project-export/SKILL.md @@ -28,17 +28,15 @@ XnaFiddle **always** runs the user's code in the browser via KNI's **BlazorGL** The export dialog has a single **runtime** selector (`_exportRuntime`: KNI / MonoGame / FNA); the platform checkboxes are *within* that family. So a multi-platform export is always one family — **KNI and MonoGame can never be combined**, and FNA is single-target. This is enforced in the UI (`SetExportRuntime`, the runtime radios), so `ExportMultiPlatform`'s shared common project only ever sees one family. The exporter itself hard-blocks only the FNA-mixing case (`Export(targets,…)` throws); the KNI/MonoGame split is a UI guarantee. Design consequence: per-target logic never has to reconcile two framework families in one solution. -## MonoGame 3.8.5 (preview) — policy and the `.Native` convention +## MonoGame — the `.Native` shared-reference convention -**Policy — do not relitigate, do not warn.** MonoGame 3.8.5 is in preview but near shipping. Treat it as a first-class, supported target — NOT risky/experimental to be avoided or hedged. **Never warn the user that 3.8.5 is "preview."** We actively track and support it so we are ready the moment stable drops. When work touches MonoGame, prefer adopting 3.8.5's conventions. +MonoGame (currently 3.8.5, GA) is a first-class export target: `Directory.Build.props` has a single `MonoGameFrameworkVersion`, and `WindowsDX12`/`DesktopVK` (the DX12/Vulkan `MonoGame.Framework.Native` + `MonoGame.Runtime.*` backends) are regular, always-available targets like DesktopGL/WindowsDX/Android — no version gating, no preview/stable split anywhere in the codebase. -**`.Native` is the renderer-agnostic compile reference for shared libraries.** `MonoGame.Framework.Native` is a backend-agnostic *managed* framework assembly — no graphics backend baked in — that functions like a reference assembly / `netstandard` lowest-common-denominator. The 3.8.5 `mg2dstartkit` template references it from the shared `.Core` library with `PrivateAssets=All`; each platform head then supplies the concrete backend (`MonoGame.Framework.DesktopGL` / `WindowsDX` / etc. for classic backends; `MonoGame.Framework.Native` + native `MonoGame.Runtime.*.{DX12,Vulkan}` for the new backends). Compiling the shared lib against `.Native` prevents leaking renderer-specific API. Going forward, exported shared/common projects should follow this convention. +**`.Native` is the renderer-agnostic compile reference for shared libraries.** `MonoGame.Framework.Native` is a backend-agnostic *managed* framework assembly — no graphics backend baked in — that functions like a reference assembly / `netstandard` lowest-common-denominator (the convention MonoGame's own `mg2dstartkit` template uses). `GenerateCommonCsproj` in `ProjectExporter.cs` unconditionally references `MonoGame.Framework.Native` with `PrivateAssets=All` for the shared/common project whenever any MonoGame target is present; each platform head then supplies its concrete backend (`MonoGame.Framework.DesktopGL`/`WindowsDX`/`Android` for classic backends; `MonoGame.Framework.Native` + native `MonoGame.Runtime.*.{DX12,Vulkan}` for the new backends). Compiling the shared lib against `.Native` prevents leaking renderer-specific API. **Two independent layers — do not conflate:** -- *Managed reference* — `.Native` is the agnostic contract; ANY backend's `MonoGame.Framework.dll` satisfies it at runtime. Classic and native backends are interchangeable at this layer (the template compiles `.Core` against `.Native` yet ships all-classic heads). -- *Compiled content* — effects / `.xnb` do NOT cross between the classic MGCB pipeline (GL/DX) and the new native Content Builder (DX12/Vulkan). This is the real incompatibility (e.g. Apos.Shapes / Gum shaders failing on DX12/VK) and it is orthogonal to the reference choice. - -**Exporter note:** `ProjectExporter.cs` currently hardwires `MonoGame.Framework.DesktopGL` as the shared-project compile reference (~line 411, the `isMonoGame` branch). The convention-correct reference is `MonoGame.Framework.Native`. +- *Managed reference* — `.Native` is the agnostic contract; ANY backend's `MonoGame.Framework.dll` satisfies it at runtime. Classic and native backends are interchangeable at this layer. +- *Compiled content* — effects / `.xnb` do NOT cross between the classic MGCB pipeline (GL/DX) and the new native Content Builder (DX12/Vulkan). This is the real incompatibility (e.g. Apos.Shapes / Gum shaders failing on DX12/VK) and it is orthogonal to the reference choice. See `BuildPackageList`'s `MonoGameWindowsDX12`/`MonoGameDesktopVK` branch. ## The core design contract @@ -64,7 +62,7 @@ Verified by inspecting `.nupkg` entries, `Content.mgcb`, and file timestamps. - At the **consuming project's build**, `MonoGame.Content.Builder.Task` runs MGCB and compiles `apos-shapes.fx` → `.xnb` (EffectImporter/EffectProcessor). `Content.mgcb`'s `/outputDir:bin/$(Platform)` + `/intermediateDir:obj/$(Platform)` are relative to the **`.mgcb`'s own location**, so MGCB writes the output AND its incremental cache **inside the package cache**: `~/.nuget/packages///buildTransitive/Content/{bin,obj}//…`. The `.xnb` is then copied into the consuming project's output `Content/`. - So a compiled `.xnb` **does** live in the NuGet cache — as **build output, not shipped content**. To distinguish shipped vs. built: list the immutable `.nupkg` entries (not the extracted folder) and cross-check timestamps (built `.xnb` is newer than the extracted source and differs per platform/build). - **Clean-rebuild gotcha:** deleting the consuming project's `bin`/`obj` does **not** force a content recompile — MGCB's incremental cache lives in the **package folder**, so it reuses the cached `.xnb`. To simulate a fresh user, delete `…/buildTransitive/Content/{bin,obj}` (or the whole `//` package folder, which re-extracts source only). A genuinely fresh user has only the `.fx`, so their first build always compiles it. -- This MGCB path exists only for **classic** targets (DesktopGL/WindowsDX, GL/DX). DX12/Vulkan use the separate native Content Builder — why library effects (Apos.Shapes/Gum) don't build/load there. See the *compiled content* layer in the 3.8.5 section. +- This MGCB path exists only for **classic** targets (DesktopGL/WindowsDX, GL/DX). DX12/Vulkan use the separate native Content Builder — why library effects (Apos.Shapes/Gum) don't build/load there. See the *compiled content* layer in the MonoGame `.Native` section. ## Not yet documented (grow only on confusion) diff --git a/Directory.Build.props b/Directory.Build.props index 4a062a3..9750511 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -38,11 +38,7 @@ 8.0.11 - 3.8.4.1 - - 3.8.5-preview.6 + 3.8.5 diff --git a/README.md b/README.md index d346a5c..fed6221 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ Click the **Export** button in the toolbar to download your fiddle as a complete | Runtime | Platforms | |---|---| | KNI | DesktopGL, WindowsDX, Android, BlazorGL (Browser) | -| MonoGame | DesktopGL, WindowsDX, Android | +| MonoGame | DesktopGL, WindowsDX, Android, WindowsDX12, DesktopVK | The exported project includes the correct NuGet packages, entry point (`Program.cs` / `Activity1.cs` / `Index.razor`), and any assets you've loaded. Third-party libraries (Gum, Apos.Shapes, MonoGame.Extended, FontStashSharp, Aether.Physics2D, KernSmith) are detected automatically from your code and included in the `.csproj`. diff --git a/XnaFiddle.BlazorGL/Pages/Index.razor b/XnaFiddle.BlazorGL/Pages/Index.razor index 225a1a7..d78fd2c 100644 --- a/XnaFiddle.BlazorGL/Pages/Index.razor +++ b/XnaFiddle.BlazorGL/Pages/Index.razor @@ -356,8 +356,8 @@ // FNA is a single desktop target — hide every non-Desktop platform. if (_exportRuntime == ExportRuntime.Fna && p != ExportPlatform.DesktopGL) continue; - // WindowsDX12 and DesktopVK are MonoGame 3.8.5 preview-only backends. - if ((p == ExportPlatform.WindowsDX12 || p == ExportPlatform.DesktopVK) && !IsPreviewBackendAvailable) + // WindowsDX12 and DesktopVK are MonoGame-only backends. + if ((p == ExportPlatform.WindowsDX12 || p == ExportPlatform.DesktopVK) && _exportRuntime != ExportRuntime.MonoGame) continue;