gum-variable-deep-dive
Deep dive into the full variable lifecycle — from VariableSave on ElementSave through runtime application on GraphicalUiElement and Forms controls. Load this when working on styling, theming, RefreshStyles, or when you need to understand how variable values flow from save data to live visuals.
Best use case
gum-variable-deep-dive is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Deep dive into the full variable lifecycle — from VariableSave on ElementSave through runtime application on GraphicalUiElement and Forms controls. Load this when working on styling, theming, RefreshStyles, or when you need to understand how variable values flow from save data to live visuals.
Teams using gum-variable-deep-dive should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/gum-variable-deep-dive/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How gum-variable-deep-dive Compares
| Feature / Agent | gum-variable-deep-dive | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Deep dive into the full variable lifecycle — from VariableSave on ElementSave through runtime application on GraphicalUiElement and Forms controls. Load this when working on styling, theming, RefreshStyles, or when you need to understand how variable values flow from save data to live visuals.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Variable Lifecycle Deep Dive
For individual subsystem references, see: **gum-tool-save-classes** (save model),
**gum-property-assignment** (instantiation + SetProperty), **gum-forms-controls** (Forms
state machine), **gum-runtime-variable-references** (ApplyAllVariableReferences).
This skill connects them into one end-to-end picture.
## The Three Layers
| Layer | Classes | Role |
|-------|---------|------|
| Save data | `ElementSave`, `StateSave`, `VariableSave`, `StateSaveCategory` | Serialized project data (XML). Edited by the Gum tool. |
| Visual runtime | `GraphicalUiElement` / `InteractiveGue` | Live layout + rendering. Holds references to StateSave objects. |
| Forms behavioral | `FrameworkElement` subclasses (Button, CheckBox, etc.) | Logical controls. Drive categorical state changes (Highlighted, Disabled, etc.) on the Visual. |
## Key Insight: Shared References, Not Copies
During `ToGraphicalUiElement` → `SetGraphicalUiElement`, the method
`AddStatesAndCategoriesRecursivelyToGue` stores the **same `StateSave` and
`StateSaveCategory` instances** from the `ElementSave` into the GUE's `mStates` and
`mCategories` dictionaries. No cloning occurs.
This means: when `ApplyAllVariableReferences()` modifies `VariableSave.Value` entries on an
`ElementSave`'s states, those changes are **immediately visible** through the GUE's state
dictionaries. The data is already updated — but the live visuals haven't re-read it yet.
## Instantiation Flow (One-Time)
`ElementSave.ToGraphicalUiElement()` → `SetGraphicalUiElement()`:
1. **AddStatesAndCategoriesRecursivelyToGue** — walks inheritance chain, stores state/category
references on the GUE
2. **CreateGraphicalComponent** — creates the underlying `IRenderable`
3. **AddExposedVariablesRecursively** — registers exposed variable bindings
4. **CreateChildrenRecursively** — for each `InstanceSave`, calls
`instance.ToGraphicalUiElement()` recursively (each child gets its own full instantiation)
5. **SetInitialState** → `SetVariablesRecursively` — applies default state values including
instance-qualified variables (e.g., `"MyButton.Width"`) that set properties on children
6. **AfterFullCreation** — triggers Forms wrapping (e.g., `DefaultFromFileButtonRuntime`
sets `FormsControlAsObject = new Button(this)`)
After this, save data changes do NOT automatically propagate. The GUE must be told to re-read.
## Runtime Usage: With vs Without a Gum Project
- **With a loaded project:** `ElementSave`/`ScreenSave`/`ComponentSave` are present.
`ToGraphicalUiElement` creates the full tree. States on the GUE reference the ElementSave's
states (shared instances).
- **Without a project:** `ElementSave` classes are not used. But `StateSave`,
`StateSaveCategory`, and `VariableSave` are still used directly — code can create states
in code and call `ApplyState()` on any GUE.
## Applying States at Runtime
### Default (uncategorized) state
`SetInitialState()` calls `SetVariablesRecursively(elementSave, elementSave.DefaultState)`,
which walks the inheritance chain (base type defaults first), then applies the element's own
default state via `ApplyState`. This includes instance-qualified variables that set properties
on children.
### Categorical states (Forms)
Forms controls call `UpdateState()` in response to interactions (hover, click, disable).
`UpdateState()` determines the current state name (e.g., "Highlighted") and calls
`Visual.SetProperty("ButtonCategoryState", stateName)`, which triggers `ApplyState` on the
matching `StateSave` within the category. This applies on top of the default state.
### The ordering matters
During creation, the order is: children get their own defaults first, then the parent's
default state applies instance-qualified overrides on top. Categorical states (Forms) are
applied last.
## Refreshing After Style Changes
After calling `ApplyAllVariableReferences()` to propagate variable reference changes into
`VariableSave` values, call `RefreshStyles()` to push those values to live visuals:
- `GraphicalUiElement.RefreshStyles()` — recursively re-applies default states, current
Forms categorical states, and runtime properties on a subtree
- `GumService.Default.RefreshStyles()` — convenience that calls `RefreshStyles()` on all
three roots (Root, PopupRoot, ModalRoot)
### Three-pass architecture
`RefreshStyles` uses a three-pass approach to preserve runtime state:
1. **Save** — walks the tree calling `FrameworkElement.SaveRuntimeProperties()` on each
Forms control. Controls save values that are stored on the visual layer and would be
lost during state re-application.
2. **Refresh** — walks the tree calling `SetVariablesRecursively` (children first, then
parent instance-qualified variables on top).
3. **Restore** — walks the tree calling `UpdateState()` + `ApplyRuntimeProperties()` on
each Forms control. This re-applies the current categorical state and restores any
saved runtime values.
The save must happen before ANY state re-application, and the restore must happen AFTER ALL
state re-application. This prevents parent instance-qualified variables (e.g.,
`"TextBoxInstance.Text" = ""`) from overwriting restored values.
### Controls with runtime state preservation
| Control | SaveRuntimeProperties | ApplyRuntimeProperties |
|---------|----------------------|----------------------|
| **Slider** | — | `UpdateThumbPositionAccordingToValue()` |
| **ScrollBar** | — | `UpdateThumbPositionAccordingToValue()` |
| **ScrollViewer** | — | Re-syncs `innerPanel.Y/X` from ScrollBar values |
| **TextBoxBase** | Saves text, caret index, selection length | Restores text, caret, selection; calls `UpdatePlaceholderVisibility`, `UpdateToSelection`, `UpdateToIsFocused` |
| **ComboBox** | Saves displayed text | Restores displayed text |
| **CheckBox/RadioButton** | — | No override needed; `UpdateState()` factors in `IsChecked` |
| **Expander** | — | No override needed; `UpdateState()` sets `contentContainer.Visible` |
The delegates `SaveFormsRuntimePropertiesAction` and `UpdateFormsStateAction` on
`GraphicalUiElement` bridge the GumRuntime → MonoGameGum boundary (GumRuntime cannot
reference FrameworkElement directly).
Typical workflow:
```csharp
// 1. Change a style variable
var colorState = ObjectFinder.Self.GetElementSave("Standards/ColoredRectangle")
.DefaultState;
colorState.GetVariableSave("Red").Value = 255;
// 2. Propagate variable references across the project
ObjectFinder.Self.GumProjectSave.ApplyAllVariableReferences();
// 3. Push to all live visuals
GumService.Default.RefreshStyles();
```Related Skills
gum-tool-variable-references
Reference guide for Gum's variable reference system — Excel-like cross-instance/cross-element variable binding using Roslyn-parsed assignment syntax. Load this when working on VariableReferenceLogic, EvaluatedSyntax, ApplyVariableReferences, VariableChangedThroughReference, or the VariableReferences VariableListSave.
gum-tool-variable-grid
Reference guide for Gum's Variables tab and DataUiGrid system. Load this when working on the Variables tab, DataUiGrid control, MemberCategory, InstanceMember, category population, property grid refresh, or category expansion state persistence.
gum-runtime-variable-references
Reference guide for runtime variable reference propagation and the optional Gum.Expressions NuGet. Load this when working on ApplyAllVariableReferences, GumExpressionService, runtime styling/theming, or the GumExpressions project.
validate-code-changes
Validate all code changes on the current branch. Spawns QA and refactoring agents in parallel to review for correctness, edge cases, code quality, and pattern adherence. Use when ready to review branch changes before merging.
skills-writer
Creates and updates skill files (.claude/skills/*/SKILL.md) by reading source code and condensing knowledge into concise reference guides. Use when asked to create a new skill, update an existing skill, or document a subsystem for Claude Code agent context.
gum-unit-tests
Reference guide for writing unit tests in the Gum repository. Load this when writing or modifying tests in Gum.ProjectServices.Tests, Gum.Cli.Tests, or any other Gum test project.
gum-tool-viewmodels
Reference guide for Gum tool ViewModel conventions. Load this when working on ViewModels, XAML views, data binding, DependsOn, or visibility properties in the Gum tool.
gum-tool-undo
Reference guide for Gum's undo/redo system. Load this when working on undo/redo behavior, the History tab, UndoManager, UndoPlugin, UndoSnapshot, or stale reference issues after undo.
gum-tool-selection
Reference guide for Gum's editor selection system. Load this when working on click/drag selection, the rectangle/marquee selector, input handlers (move, resize, rotate, polygon points), the IsActive flag, locked instance behavior, SelectionManager coordination, or the selection event cascade (plugin events, forced default state, tree view sync).
gum-tool-save-classes
Reference guide for Gum's save/load data model. Load this when working with GumProjectSave, ScreenSave, ComponentSave, StandardElementSave, ElementSave, StateSave, VariableSave, InstanceSave, BehaviorSave, or any serialization/deserialization of Gum project files.
gum-tool-plugins
Reference guide for the Gum tool's plugin system, including visualization plugins (EditorTabPlugin_XNA, TextureCoordinateSelectionPlugin). Load this when working on plugin registration, PluginBase, InternalPlugin, PluginManager, plugin events, visualization/rendering concerns, or finding which internal plugin owns a feature.
gum-tool-output
Reference guide for Gum's Output tab system. Load this when working on the Output tab, IOutputManager, MainOutputViewModel, GuiCommands.PrintOutput, or adding output/error messages to the tool.