Skip to main content

gum-integration

How FlatRedBall integrates the Gum UI layout/rendering library — plugin structure, .gumx projects, runtime wrapper. Triggers: GumPlugin, GraphicalUiElement, GUE, .gumx, .gusx, Gum.Wireframe, PositionedObjectGueWrapper, RenderingLibrary.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
vchelaru/FlatRedBall
آخر نشاط في المصدر
١٣ سبتمبر ٢٠٢٦ في ١٧:١٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٧٦
التفرعات
٧٣

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
gum-integration
description
How FlatRedBall integrates the Gum UI layout/rendering library — plugin structure, .gumx projects, runtime wrapper. Triggers: GumPlugin, GraphicalUiElement, GUE, .gumx, .gusx, Gum.Wireframe, PositionedObjectGueWrapper, RenderingLibrary.
# Gum Integration Gum is a **separate sibling repo** (`..\Gum` relative to this repo, e.g. `C:\Users\vchel\Documents\GitHub\Gum` in this checkout), not a submodule or NuGet package — FlatRedBall references its projects via relative `<ProjectReference>` paths (e.g. `FRBDK\Glue\GumPlugin\GumPlugin\GumPlugin.csproj` → `..\..\..\..\..\Gum\GumCommon\GumCommon.csproj`). Gum is FRB's UI layout/rendering library (screens, components, states, data binding) — general Gum behavior/API questions belong to that repo, not this skill. ## Where things live | Piece | Location | |---|---| | Gum's core runtime element (`GraphicalUiElement`, `Gum.Wireframe` namespace) | sibling `Gum\GumRuntime` | | Gum's low-level rendering/camera abstractions (`RenderingLibrary` namespace — `Camera`, `SystemManagers`, `LayerCameraSettings`) | sibling `Gum\RenderingLibrary` | | Other Gum sub-libraries (data types, MonoGame/Skia backends) | sibling `Gum\GumCore`, `GumCommon`, `GumDataTypes`, `MonoGameGum`, `SkiaGum*` | | Glue's Gum plugin | `FRBDK\Glue\GumPlugin\GumPlugin\` | | FRB-side integration/test shims (not the real Gum source) | `Engines\SkiaGum`, `Tests\EngineUnitTests\Gum` | Glue's Gum plugin has the same "master template → generated copy" split as the [[glue-live-edit]] skill: `Embedded\*.cs` files (`PositionedObjectGueWrapper.cs`, `GraphicalUiElement.Binding.cs`, `GraphicalUiElement.IWindow.cs`, `SystemManagers.FlatRedBall.cs`, `ContentManagerWrapper.cs`) are hand-edited sources copied verbatim into generated game projects — not generator *output*, actual C# that ships as-is. `CodeGeneration\*` is the real generator side: `GueDerivingClassCodeGenerator.cs` (per-Screen/Component derived class), `GumGame1CodeGenerator.cs` (Game1 wiring), `StandardsCodeGenerator.cs` + per-type generators (`NineSliceCodeGenerator.cs`, `TextCodeGenerator.cs`...) and `StateCodeGenerator*.cs` for the property/state pipelines documented in the [[gum-codegen]] skill, `FormsClassCodeGenerator.cs`/`FormsObjectCodeGenerator.cs` for Gum Forms controls. ## The .gumx project Gum UI data lives in its **own file format alongside** `.glux`/`.gluj`, referenced by relative path from the Glue project (e.g. a `.gluj`'s `"Name": "GumProject/GumProject.gumx"`). One `.gumx` (project index, `GumProjectSave` XML) plus one file per element under `Content\GumProject\`: `.gusx` (Screens/Components), `.behx` (behaviors), `.ganx` (animations). `GumProjectManager.cs`/`FileChangeManager.cs` (`GumPlugin\Managers`) load it and watch for external edits (e.g. from the standalone Gum tool). ## Runtime bridging `PositionedObjectGueWrapper : PositionedObject` (`GumPlugin\Embedded\PositionedObjectGueWrapper.cs`) wraps a `GraphicalUiElement` inside FRB's `PositionedObject` hierarchy, so Gum UI can attach to/move with an FRB entity like any other positioned object. Top-level Screens/Components loaded standalone instead get their own generated derived class from `GueDerivingClassCodeGenerator.cs`, extending `GraphicalUiElement` directly rather than going through the wrapper. ## Per-Screen Gum screen (auto-created) Adding an FRB Screen in Glue auto-creates a paired Gum screen so anything placed on it shows up automatically when the FRB Screen loads — you don't need to know this exists until you go looking for "where did `GameScreenGum` come from." - Hook: FRB-screen-created event → `GumPluginCommands.AddScreenForGlueScreen` (`GumPlugin\Managers\GumPluginCommands.cs:199-226`), also triggerable by hand via right-click (`RightClickManager.cs:92`). - **Naming convention**: strip the FRB screen's `Screens/` prefix and append `Gum` — `Screens/GameScreen` → Gum screen `GameScreenGum` (`GetExpectedGumScreenNameFor`, `GumPluginCommands.cs:187-197`). - It's created only if missing, then linked onto the FRB Screen as a normal `NamedObjectSave`/file reference (`RightClickManager.AddGumScreenScreenByName`) — there's no special runtime loading path. Generated codegen (`GueDerivingClassCodeGenerator.cs:890-926`) emits the same `<name>.AddToManagers(...)` call it would for any other Gum object, so the paired screen is added/removed on FRB Screen load/unload exactly like every other object on that Screen. ## World-space Gum objects (health bars, icons, in-world dialog) Placing a Gum object at fixed screen-space UI coordinates is the default. To have it track an FRB entity's world position instead (health bar over an enemy, lock icon over a door), Glue exposes **`NamedObjectSave.AttachToContainer`** — a bool property under the object's "Creation" category, only shown when the object's container is an `EntitySave` and it isn't a list (`NamedObjectPropertyGridDisplayer.cs:330-338`). A sibling property, **`AttachToCamera`** (shown only for Screen-level objects, not Entity), sticks a Gum object to the camera instead of the world. This is **not** a plain FRB-attach and **not** pure coordinate conversion — it's a hybrid, and the mechanism matters if you're debugging drift: - When `AttachToContainer` is true on an Entity, codegen wraps the GUE in `PositionedObjectGueWrapper(this, gumObject)` (`GueDerivingClassCodeGenerator.cs:900-919`), added via `SpriteManager.AddPositionedObject`. The wrapper itself calls `AttachTo(frbObject)` (`Embedded\PositionedObjectGueWrapper.cs:52`) so it inherits the entity's world position/rotation through FRB's normal attachment tree — **but** the actual `GraphicalUiElement` is reparented under an intermediary invisible `GumParent` GUE (`gumObject.Parent = GumParent`, line 69), not attached directly. - Every frame (`UpdateGumObject`, lines 95-170): compute `worldPosition = FrbObject.Position + RelativePosition`, convert to screen pixels via `MathFunctions.AbsoluteToWindow(...)` using `Camera.Main`, then re-derive Gum canvas coordinates as a *ratio* of that screen position to `camera.DestinationRectangle.Width/Height`, scaled by `GraphicalUiElement.CanvasWidth/CanvasHeight` (lines 108-141) — this is the same ratio-based conversion pattern used for edit-mode zoom in [[glue-live-edit]], not a one-shot pixel offset, so it stays correct as the camera pans/zooms. - `GumParent.Width/Height` mirror the FRB object's `ScaleX/ScaleY * 2` when it implements `IReadOnlyScalable`; `GumParent.Visible` mirrors `AbsoluteVisible` (lines 154-169). **Known landmines (straight from code comments, not inferred):** - **In normal gameplay, position tracks the camera zoom but the Gum object's own visual scale does not** — deliberate, so a health bar doesn't shrink to unreadable size when the player zooms out. In the FRB Editor's live-edit mode only, entity-attached Gum content *does* scale with the editor's zoom control, via a dedicated layer — see [[glue-live-edit]]'s Gum zoom section. - **A layer add/remove operates on the element's contained object, not the `GraphicalUiElement` reference.** `AddToManagers`/`MoveToLayer` register Renderables-list membership against `mContainedObjectAsIpso` (e.g. an `InvisibleRenderable` for anything deriving `ContainerRuntime`, like a typical health-bar Component) — never against the GUE reference itself. A raw `Layer.Remove(gue)`/`Layer.Add(gue)` therefore silently fails to remove the real registration while adding a second, independent entry, so the same content draws twice. Always move a GUE between layers via `gue.MoveToLayer(...)`, never manual `Layer` calls on the GUE reference. - **No multiple-camera/multiple-layer support** — explicitly flagged `// todo - need to support multiple cameras and layers` (line 101). If a project has split-screen or multiple FRB layers with independent cameras, world-space attachment is not guaranteed correct. - **3D/perspective cameras are unimplemented** — stubbed `// todo - need to figure out 3D` (line 144); the position math assumes an orthogonal camera. - **No dedicated "world-space" Gum Layer type.** World-space vs screen-space is purely: which FRB `Layer` the entity/object belongs to, plus whether `AttachToContainer` is set — not a distinct kind of Gum `Layer`. Gum `Layer`s are generated 1:1 per FRB `Layer` (`GumLayerCodeGenerator.cs`/`GumLayerAssociationCodeGenerator.cs`). - **Collision follows the wrapper, not the raw GUE.** With `AttachToContainer` set, collision is wired through `GumCollidableExtensions.AddCollision(this, wrapperForAttachment)` (`GumCollidableCodeGenerator.cs:39`) — custom collision code must go through `PositionedObjectGueWrapper`, not the `GraphicalUiElement` directly, or shapes won't track the attached position. ## Vocabulary - **GraphicalUiElement (GUE)** — Gum's core runtime UI node; owns position/size/children/rendering. - **Screen** (`.gusx`) — top-level Gum layout, analogous to an FRB Screen. - **Component** (`.gusx`) — reusable, instantiable UI element (like a prefab/control). - **Standard element** — Gum's built-in primitive types (Text, Sprite/NineSlice, Container, etc.), generated by `StandardsCodeGenerator.cs`. - **Instance** — a placed occurrence of a Component/Standard element inside a Screen/Component. - **State / Variable** — named property sets swappable at runtime; see [[gum-codegen]] for how Glue generates their skip/gating logic. ## Related skills - [[gum-codegen]] — the version-gating skip-list pipelines for standard-element property/state generation (narrower, Glue-only). - [[glue-live-edit]] — covers Gum's dual-zoom sync (`Camera.Main` vs `Renderer.Camera.Zoom`/`LayerCameraSettings.Zoom`) and other edit-mode-specific Gum behavior. - [[gum-shared-source]] — how FRB's `.csproj`s pull in Gum/MonoGameGum source files individually rather than sharing a project, and where the two diverge (e.g. `Cursor`).
عرض على GitHub