roblox-opencode 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -122
- package/commands/setup-game.md +108 -108
- package/commands/sync-check.md +53 -53
- package/core/roblox-core.md +93 -93
- package/dist/server.js +189 -167
- package/package.json +35 -35
- package/skills/roblox-analytics/SKILL.md +277 -277
- package/skills/roblox-analytics/references/event-batcher.luau +75 -75
- package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
- package/skills/roblox-architecture/SKILL.md +877 -863
- package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
- package/skills/roblox-code-review/SKILL.md +686 -686
- package/skills/roblox-data/SKILL.md +889 -889
- package/skills/roblox-data/references/inventory-systems.md +1729 -1729
- package/skills/roblox-debug/SKILL.md +98 -98
- package/skills/roblox-gui/SKILL.md +1103 -1103
- package/skills/roblox-gui-fusion/SKILL.md +150 -150
- package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
- package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
- package/skills/roblox-gui-fusion/references/shop.luau +411 -411
- package/skills/roblox-luau-mastery/SKILL.md +1618 -1519
- package/skills/roblox-monetization/SKILL.md +1084 -1084
- package/skills/roblox-monetization/references/process-receipt.luau +131 -131
- package/skills/roblox-networking/SKILL.md +669 -669
- package/skills/roblox-networking/references/remote-validator.luau +193 -193
- package/skills/roblox-publish-checklist/SKILL.md +127 -127
- package/skills/roblox-runtime/SKILL.md +753 -753
- package/skills/roblox-sharp-edges/SKILL.md +294 -294
- package/skills/roblox-sync/SKILL.md +126 -126
- package/skills/roblox-testing/SKILL.md +943 -943
- package/skills/roblox-tooling/SKILL.md +149 -149
- package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
- package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
- package/vendor/LICENSES/promise-LICENSE +20 -20
- package/vendor/LICENSES/t-LICENSE +21 -21
- package/vendor/LICENSES/testez-LICENSE +200 -200
- package/vendor/README.md +83 -83
- package/vendor/fusion/Animation/ExternalTime.luau +83 -83
- package/vendor/fusion/Animation/Spring.luau +321 -321
- package/vendor/fusion/Animation/Stopwatch.luau +127 -127
- package/vendor/fusion/Animation/Tween.luau +187 -187
- package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
- package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
- package/vendor/fusion/Animation/lerpType.luau +163 -163
- package/vendor/fusion/Animation/packType.luau +99 -99
- package/vendor/fusion/Animation/springCoefficients.luau +80 -80
- package/vendor/fusion/Animation/unpackType.luau +102 -102
- package/vendor/fusion/Colour/Oklab.luau +70 -70
- package/vendor/fusion/Colour/sRGB.luau +54 -54
- package/vendor/fusion/External.luau +167 -167
- package/vendor/fusion/ExternalDebug.luau +69 -69
- package/vendor/fusion/Graph/Observer.luau +113 -113
- package/vendor/fusion/Graph/castToGraph.luau +28 -28
- package/vendor/fusion/Graph/change.luau +80 -80
- package/vendor/fusion/Graph/depend.luau +32 -32
- package/vendor/fusion/Graph/evaluate.luau +55 -55
- package/vendor/fusion/Instances/Attribute.luau +57 -57
- package/vendor/fusion/Instances/AttributeChange.luau +46 -46
- package/vendor/fusion/Instances/AttributeOut.luau +63 -63
- package/vendor/fusion/Instances/Child.luau +21 -21
- package/vendor/fusion/Instances/Children.luau +147 -147
- package/vendor/fusion/Instances/Hydrate.luau +32 -32
- package/vendor/fusion/Instances/New.luau +52 -52
- package/vendor/fusion/Instances/OnChange.luau +49 -49
- package/vendor/fusion/Instances/OnEvent.luau +53 -53
- package/vendor/fusion/Instances/Out.luau +69 -69
- package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
- package/vendor/fusion/Instances/defaultProps.luau +194 -194
- package/vendor/fusion/LICENSE +21 -21
- package/vendor/fusion/Logging/formatError.luau +48 -48
- package/vendor/fusion/Logging/messages.luau +51 -51
- package/vendor/fusion/Logging/parseError.luau +24 -24
- package/vendor/fusion/Memory/checkLifetime.luau +133 -133
- package/vendor/fusion/Memory/deriveScope.luau +23 -23
- package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
- package/vendor/fusion/Memory/doCleanup.luau +78 -78
- package/vendor/fusion/Memory/innerScope.luau +33 -33
- package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
- package/vendor/fusion/Memory/needsDestruction.luau +16 -16
- package/vendor/fusion/Memory/poisonScope.luau +33 -33
- package/vendor/fusion/Memory/scopePool.luau +54 -54
- package/vendor/fusion/Memory/scoped.luau +26 -26
- package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
- package/vendor/fusion/RobloxExternal.luau +97 -97
- package/vendor/fusion/State/Computed.luau +138 -138
- package/vendor/fusion/State/For/Disassembly.luau +210 -210
- package/vendor/fusion/State/For/ForTypes.luau +30 -30
- package/vendor/fusion/State/For/init.luau +109 -109
- package/vendor/fusion/State/ForKeys.luau +93 -93
- package/vendor/fusion/State/ForPairs.luau +96 -96
- package/vendor/fusion/State/ForValues.luau +93 -93
- package/vendor/fusion/State/Value.luau +87 -87
- package/vendor/fusion/State/castToState.luau +25 -25
- package/vendor/fusion/State/peek.luau +30 -30
- package/vendor/fusion/Types.luau +314 -314
- package/vendor/fusion/Utility/Contextual.luau +90 -90
- package/vendor/fusion/Utility/Safe.luau +22 -22
- package/vendor/fusion/Utility/isSimilar.luau +29 -29
- package/vendor/fusion/Utility/merge.luau +35 -35
- package/vendor/fusion/Utility/nameOf.luau +34 -34
- package/vendor/fusion/Utility/never.luau +13 -13
- package/vendor/fusion/Utility/nicknames.luau +10 -10
- package/vendor/fusion/Utility/xtypeof.luau +26 -26
- package/vendor/fusion/init.luau +82 -82
- package/vendor/profilestore/init.luau +2242 -2242
- package/vendor/promise/init.luau +1982 -1982
- package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
- package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
- package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
- package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
- package/vendor/rbxutil/buffer-util/Types.luau +60 -60
- package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
- package/vendor/rbxutil/buffer-util/init.luau +41 -41
- package/vendor/rbxutil/buffer-util/package.json +16 -16
- package/vendor/rbxutil/buffer-util/wally.toml +9 -9
- package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
- package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
- package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
- package/vendor/rbxutil/comm/Client/init.luau +135 -135
- package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
- package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
- package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
- package/vendor/rbxutil/comm/Server/init.luau +140 -140
- package/vendor/rbxutil/comm/Types.luau +18 -18
- package/vendor/rbxutil/comm/Util.luau +27 -27
- package/vendor/rbxutil/comm/init.luau +35 -35
- package/vendor/rbxutil/comm/wally.toml +13 -13
- package/vendor/rbxutil/component/init.luau +759 -759
- package/vendor/rbxutil/component/init.test.luau +311 -311
- package/vendor/rbxutil/component/wally.toml +14 -14
- package/vendor/rbxutil/concur/init.luau +542 -542
- package/vendor/rbxutil/concur/init.test.luau +364 -364
- package/vendor/rbxutil/concur/wally.toml +8 -8
- package/vendor/rbxutil/enum-list/init.luau +101 -101
- package/vendor/rbxutil/enum-list/init.test.luau +91 -91
- package/vendor/rbxutil/enum-list/wally.toml +8 -8
- package/vendor/rbxutil/find/index.d.ts +20 -20
- package/vendor/rbxutil/find/init.luau +44 -44
- package/vendor/rbxutil/find/package.json +17 -17
- package/vendor/rbxutil/find/wally.toml +8 -8
- package/vendor/rbxutil/input/Gamepad.luau +559 -559
- package/vendor/rbxutil/input/Keyboard.luau +124 -124
- package/vendor/rbxutil/input/Mouse.luau +278 -278
- package/vendor/rbxutil/input/PreferredInput.luau +91 -91
- package/vendor/rbxutil/input/Touch.luau +120 -120
- package/vendor/rbxutil/input/init.luau +33 -33
- package/vendor/rbxutil/input/wally.toml +12 -12
- package/vendor/rbxutil/loader/index.d.ts +15 -15
- package/vendor/rbxutil/loader/init.luau +137 -137
- package/vendor/rbxutil/loader/wally.toml +8 -8
- package/vendor/rbxutil/log/index.d.ts +38 -38
- package/vendor/rbxutil/log/init.luau +746 -746
- package/vendor/rbxutil/log/wally.toml +8 -8
- package/vendor/rbxutil/net/init.luau +190 -190
- package/vendor/rbxutil/net/wally.toml +8 -8
- package/vendor/rbxutil/option/index.d.ts +44 -44
- package/vendor/rbxutil/option/init.luau +489 -489
- package/vendor/rbxutil/option/init.test.luau +342 -342
- package/vendor/rbxutil/option/wally.toml +8 -8
- package/vendor/rbxutil/pid/index.d.ts +53 -53
- package/vendor/rbxutil/pid/init.luau +195 -195
- package/vendor/rbxutil/pid/package.json +16 -16
- package/vendor/rbxutil/pid/wally.toml +9 -9
- package/vendor/rbxutil/quaternion/index.d.ts +117 -117
- package/vendor/rbxutil/quaternion/init.luau +570 -570
- package/vendor/rbxutil/quaternion/package.json +16 -16
- package/vendor/rbxutil/quaternion/wally.toml +9 -9
- package/vendor/rbxutil/query/index.d.ts +43 -43
- package/vendor/rbxutil/query/init.luau +117 -117
- package/vendor/rbxutil/query/package.json +18 -18
- package/vendor/rbxutil/query/wally.toml +9 -9
- package/vendor/rbxutil/sequent/index.d.ts +28 -28
- package/vendor/rbxutil/sequent/init.luau +340 -340
- package/vendor/rbxutil/sequent/package.json +16 -16
- package/vendor/rbxutil/sequent/wally.toml +9 -9
- package/vendor/rbxutil/ser/init.luau +175 -175
- package/vendor/rbxutil/ser/init.test.luau +50 -50
- package/vendor/rbxutil/ser/wally.toml +11 -11
- package/vendor/rbxutil/shake/index.d.ts +36 -36
- package/vendor/rbxutil/shake/init.luau +532 -532
- package/vendor/rbxutil/shake/init.test.luau +267 -267
- package/vendor/rbxutil/shake/package.json +16 -16
- package/vendor/rbxutil/shake/wally.toml +9 -9
- package/vendor/rbxutil/signal/index.d.ts +100 -100
- package/vendor/rbxutil/signal/init.luau +432 -432
- package/vendor/rbxutil/signal/init.test.luau +190 -190
- package/vendor/rbxutil/signal/package.json +17 -17
- package/vendor/rbxutil/signal/wally.toml +9 -9
- package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
- package/vendor/rbxutil/silo/Util.luau +55 -55
- package/vendor/rbxutil/silo/init.luau +338 -338
- package/vendor/rbxutil/silo/init.test.luau +215 -215
- package/vendor/rbxutil/silo/wally.toml +8 -8
- package/vendor/rbxutil/spring/index.d.ts +40 -40
- package/vendor/rbxutil/spring/init.luau +97 -97
- package/vendor/rbxutil/spring/package.json +17 -17
- package/vendor/rbxutil/spring/wally.toml +8 -8
- package/vendor/rbxutil/stream/index.d.ts +88 -88
- package/vendor/rbxutil/stream/init.luau +597 -597
- package/vendor/rbxutil/stream/package.json +18 -18
- package/vendor/rbxutil/stream/wally.toml +9 -9
- package/vendor/rbxutil/streamable/Streamable.luau +202 -202
- package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
- package/vendor/rbxutil/streamable/init.luau +8 -8
- package/vendor/rbxutil/streamable/wally.toml +12 -12
- package/vendor/rbxutil/symbol/init.luau +56 -56
- package/vendor/rbxutil/symbol/init.test.luau +37 -37
- package/vendor/rbxutil/symbol/wally.toml +8 -8
- package/vendor/rbxutil/table-util/init.luau +938 -938
- package/vendor/rbxutil/table-util/init.test.luau +439 -439
- package/vendor/rbxutil/task-queue/index.d.ts +27 -27
- package/vendor/rbxutil/task-queue/init.luau +97 -97
- package/vendor/rbxutil/task-queue/wally.toml +8 -8
- package/vendor/rbxutil/timer/index.d.ts +81 -81
- package/vendor/rbxutil/timer/init.luau +249 -249
- package/vendor/rbxutil/timer/init.test.luau +73 -73
- package/vendor/rbxutil/timer/wally.toml +11 -11
- package/vendor/rbxutil/tree/index.d.ts +15 -15
- package/vendor/rbxutil/tree/init.luau +137 -137
- package/vendor/rbxutil/tree/wally.toml +8 -8
- package/vendor/rbxutil/trove/index.d.ts +46 -46
- package/vendor/rbxutil/trove/init.luau +787 -787
- package/vendor/rbxutil/trove/init.test.luau +203 -203
- package/vendor/rbxutil/trove/wally.toml +8 -8
- package/vendor/rbxutil/typed-remote/init.luau +196 -196
- package/vendor/rbxutil/typed-remote/wally.toml +8 -8
- package/vendor/rbxutil/wait-for/index.d.ts +17 -17
- package/vendor/rbxutil/wait-for/init.luau +257 -257
- package/vendor/rbxutil/wait-for/init.test.luau +182 -182
- package/vendor/rbxutil/wait-for/wally.toml +11 -11
- package/vendor/t/t.lua +1350 -1350
- package/vendor/testez/Context.lua +26 -26
- package/vendor/testez/Expectation.lua +311 -311
- package/vendor/testez/ExpectationContext.lua +38 -38
- package/vendor/testez/LifecycleHooks.lua +89 -89
- package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
- package/vendor/testez/Reporters/TextReporter.lua +105 -105
- package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
- package/vendor/testez/TestBootstrap.lua +146 -146
- package/vendor/testez/TestEnum.lua +27 -27
- package/vendor/testez/TestPlan.lua +304 -304
- package/vendor/testez/TestPlanner.lua +39 -39
- package/vendor/testez/TestResults.lua +111 -111
- package/vendor/testez/TestRunner.lua +188 -188
- package/vendor/testez/TestSession.lua +243 -243
- package/vendor/testez/init.lua +39 -39
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roblox-gui-fusion
|
|
3
|
-
description: Fusion 0.3 game UI - shop, inventory, settings screens. Reactive declarative patterns for Roblox.
|
|
4
|
-
last_reviewed: 2026-05-24
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
<!-- Source patterns: VirtualButFake/fusion-components (MIT), dphfox/Fusion docs -->
|
|
8
|
-
|
|
9
|
-
# Roblox GUI with Fusion
|
|
10
|
-
|
|
11
|
-
## Quick Reference
|
|
12
|
-
|
|
13
|
-
**Framework:** Fusion 0.3 (dphfox/Fusion, MIT). Vendored at `.opencode/vendor/fusion/`.
|
|
14
|
-
|
|
15
|
-
**Require path:** The AI must resolve the Fusion require path based on the project:
|
|
16
|
-
- If `Packages/Fusion` exists (Wally) → `require(ReplicatedStorage.Packages.Fusion)`
|
|
17
|
-
- If `.opencode/vendor/fusion` exists (this plugin) → `require(ReplicatedStorage[".opencode"].vendor.fusion)` or wherever the project root maps in the DataModel
|
|
18
|
-
- If Fusion is elsewhere → match the existing require pattern in the project
|
|
19
|
-
|
|
20
|
-
**When to use this skill:**
|
|
21
|
-
- Building new game UI screens from scratch (shop, inventory, settings, etc.)
|
|
22
|
-
- Any UI with dynamic state (item lists, toggles, selections, animations)
|
|
23
|
-
|
|
24
|
-
**When NOT to use this skill:**
|
|
25
|
-
- Project already has established UI patterns (raw Instance, Roact, Vide) → follow existing patterns instead
|
|
26
|
-
- Simple static HUD with no state → use raw Instance (see `roblox-gui` skill)
|
|
27
|
-
|
|
28
|
-
**Routing logic for the AI:**
|
|
29
|
-
- If the project has existing Fusion code → match its patterns, use these references for architecture only
|
|
30
|
-
- If the project has existing non-Fusion UI → do NOT introduce Fusion, follow what's there
|
|
31
|
-
- If the project has no UI yet (greenfield) → use these references as starting templates, adapt colors/data
|
|
32
|
-
|
|
33
|
-
**Key design rules (framework-agnostic, always apply):**
|
|
34
|
-
- Mobile-first: design for phone, scale up. Touch targets minimum 48x48px.
|
|
35
|
-
- Scale (0-1 proportional) for position/size. Offset only for fixed padding/icons.
|
|
36
|
-
- Container Frame Rule: every logical group gets a Frame with layout modifier inside.
|
|
37
|
-
- UIListLayout/UIGridLayout for auto-arrangement. AutomaticSize on parent.
|
|
38
|
-
- ScreenGui.ResetOnSpawn = false for persistent UI. IgnoreGuiInset = true for fullscreen.
|
|
39
|
-
- Dark palette: off-white text on dark gray (never pure white on pure black).
|
|
40
|
-
- Never use absolute pixel sizes for main containers. UISizeConstraint for min/max bounds.
|
|
41
|
-
- ScrollingFrame: AutomaticCanvasSize. UIListLayout inside for content.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Fusion 0.3 Patterns
|
|
46
|
-
|
|
47
|
-
### Core idioms
|
|
48
|
-
|
|
49
|
-
```luau
|
|
50
|
-
local Fusion = require(path.to.Fusion)
|
|
51
|
-
local scoped = Fusion.scoped
|
|
52
|
-
local peek = Fusion.peek
|
|
53
|
-
local Children = Fusion.Children
|
|
54
|
-
local OnEvent = Fusion.OnEvent
|
|
55
|
-
|
|
56
|
-
-- Create a scope (manages cleanup of all objects created within it)
|
|
57
|
-
local scope = scoped(Fusion)
|
|
58
|
-
|
|
59
|
-
-- Reactive state
|
|
60
|
-
local count = scope:Value(0)
|
|
61
|
-
|
|
62
|
-
-- Derived state (re-computes when dependencies change)
|
|
63
|
-
local label = scope:Computed(function(use)
|
|
64
|
-
return "Count: " .. use(count)
|
|
65
|
-
end)
|
|
66
|
-
|
|
67
|
-
-- Create instances (reactive properties auto-update)
|
|
68
|
-
local gui = scope:New "ScreenGui" {
|
|
69
|
-
Parent = playerGui,
|
|
70
|
-
[Children] = {
|
|
71
|
-
scope:New "TextLabel" {
|
|
72
|
-
Text = label,
|
|
73
|
-
Size = UDim2.fromOffset(200, 50),
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
-- Animate any value
|
|
79
|
-
local smoothPos = scope:Spring(position, 25) -- speed 25
|
|
80
|
-
|
|
81
|
-
-- Read without subscribing (in callbacks)
|
|
82
|
-
local currentCount = peek(count)
|
|
83
|
-
|
|
84
|
-
-- Cleanup everything in the scope
|
|
85
|
-
scope:doCleanup()
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Component pattern
|
|
89
|
-
|
|
90
|
-
```luau
|
|
91
|
-
local function Button(scope: Fusion.Scope, props: {
|
|
92
|
-
Text: Fusion.UsedAs<string>,
|
|
93
|
-
OnClick: () -> (),
|
|
94
|
-
Color: Fusion.UsedAs<Color3>?,
|
|
95
|
-
})
|
|
96
|
-
local isHovering = scope:Value(false)
|
|
97
|
-
|
|
98
|
-
return scope:New "TextButton" {
|
|
99
|
-
Text = props.Text,
|
|
100
|
-
BackgroundColor3 = scope:Spring(scope:Computed(function(use)
|
|
101
|
-
local base = if props.Color then use(props.Color) else Color3.fromRGB(80, 140, 255)
|
|
102
|
-
return if use(isHovering) then base:Lerp(Color3.new(1,1,1), 0.1) else base
|
|
103
|
-
end), 25),
|
|
104
|
-
[OnEvent "Activated"] = props.OnClick,
|
|
105
|
-
[OnEvent "MouseEnter"] = function() isHovering:set(true) end,
|
|
106
|
-
[OnEvent "MouseLeave"] = function() isHovering:set(false) end,
|
|
107
|
-
[Children] = { scope:New "UICorner" { CornerRadius = UDim.new(0, 6) } },
|
|
108
|
-
}
|
|
109
|
-
end
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### List rendering (ForPairs)
|
|
113
|
-
|
|
114
|
-
```luau
|
|
115
|
-
-- Renders a UI element for each item. Automatically adds/removes as data changes.
|
|
116
|
-
scope:ForPairs(items, function(use, itemScope, index, item)
|
|
117
|
-
return index, itemScope:New "TextLabel" {
|
|
118
|
-
Text = item.Name,
|
|
119
|
-
LayoutOrder = index,
|
|
120
|
-
}
|
|
121
|
-
end)
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## References
|
|
127
|
-
|
|
128
|
-
Full production-quality screen implementations are in `references/`:
|
|
129
|
-
|
|
130
|
-
- **shop.luau** - Item grid, currency header, purchase confirmation modal, server-validated buy flow
|
|
131
|
-
- **inventory.luau** - Owned items grid with rarity borders, equip/unequip, detail panel, empty slots
|
|
132
|
-
- **settings-menu.luau** - Tabbed sections, sliders with drag, toggle switches, dropdown selects
|
|
133
|
-
|
|
134
|
-
Each reference is self-contained and demonstrates:
|
|
135
|
-
- Scope-based memory management
|
|
136
|
-
- Component composition (small functions returning instances)
|
|
137
|
-
- Reactive state driving UI updates
|
|
138
|
-
- Spring animations for smooth transitions
|
|
139
|
-
- ForPairs for dynamic lists
|
|
140
|
-
- Modal/overlay patterns
|
|
141
|
-
- Typed props for clear interfaces
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
## Sources
|
|
146
|
-
|
|
147
|
-
- Fusion: github.com/dphfox/Fusion (MIT, 764★)
|
|
148
|
-
- Fusion docs: elttob.uk/Fusion/latest
|
|
149
|
-
- Component patterns: VirtualButFake/fusion-components (MIT, 31 components)
|
|
150
|
-
- Fusion 0.3 release notes: github.com/dphfox/Fusion/releases/tag/v0.3-beta
|
|
1
|
+
---
|
|
2
|
+
name: roblox-gui-fusion
|
|
3
|
+
description: Fusion 0.3 game UI - shop, inventory, settings screens. Reactive declarative patterns for Roblox.
|
|
4
|
+
last_reviewed: 2026-05-24
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Source patterns: VirtualButFake/fusion-components (MIT), dphfox/Fusion docs -->
|
|
8
|
+
|
|
9
|
+
# Roblox GUI with Fusion
|
|
10
|
+
|
|
11
|
+
## Quick Reference
|
|
12
|
+
|
|
13
|
+
**Framework:** Fusion 0.3 (dphfox/Fusion, MIT). Vendored at `.opencode/vendor/fusion/`.
|
|
14
|
+
|
|
15
|
+
**Require path:** The AI must resolve the Fusion require path based on the project:
|
|
16
|
+
- If `Packages/Fusion` exists (Wally) → `require(ReplicatedStorage.Packages.Fusion)`
|
|
17
|
+
- If `.opencode/vendor/fusion` exists (this plugin) → `require(ReplicatedStorage[".opencode"].vendor.fusion)` or wherever the project root maps in the DataModel
|
|
18
|
+
- If Fusion is elsewhere → match the existing require pattern in the project
|
|
19
|
+
|
|
20
|
+
**When to use this skill:**
|
|
21
|
+
- Building new game UI screens from scratch (shop, inventory, settings, etc.)
|
|
22
|
+
- Any UI with dynamic state (item lists, toggles, selections, animations)
|
|
23
|
+
|
|
24
|
+
**When NOT to use this skill:**
|
|
25
|
+
- Project already has established UI patterns (raw Instance, Roact, Vide) → follow existing patterns instead
|
|
26
|
+
- Simple static HUD with no state → use raw Instance (see `roblox-gui` skill)
|
|
27
|
+
|
|
28
|
+
**Routing logic for the AI:**
|
|
29
|
+
- If the project has existing Fusion code → match its patterns, use these references for architecture only
|
|
30
|
+
- If the project has existing non-Fusion UI → do NOT introduce Fusion, follow what's there
|
|
31
|
+
- If the project has no UI yet (greenfield) → use these references as starting templates, adapt colors/data
|
|
32
|
+
|
|
33
|
+
**Key design rules (framework-agnostic, always apply):**
|
|
34
|
+
- Mobile-first: design for phone, scale up. Touch targets minimum 48x48px.
|
|
35
|
+
- Scale (0-1 proportional) for position/size. Offset only for fixed padding/icons.
|
|
36
|
+
- Container Frame Rule: every logical group gets a Frame with layout modifier inside.
|
|
37
|
+
- UIListLayout/UIGridLayout for auto-arrangement. AutomaticSize on parent.
|
|
38
|
+
- ScreenGui.ResetOnSpawn = false for persistent UI. IgnoreGuiInset = true for fullscreen.
|
|
39
|
+
- Dark palette: off-white text on dark gray (never pure white on pure black).
|
|
40
|
+
- Never use absolute pixel sizes for main containers. UISizeConstraint for min/max bounds.
|
|
41
|
+
- ScrollingFrame: AutomaticCanvasSize. UIListLayout inside for content.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Fusion 0.3 Patterns
|
|
46
|
+
|
|
47
|
+
### Core idioms
|
|
48
|
+
|
|
49
|
+
```luau
|
|
50
|
+
local Fusion = require(path.to.Fusion)
|
|
51
|
+
local scoped = Fusion.scoped
|
|
52
|
+
local peek = Fusion.peek
|
|
53
|
+
local Children = Fusion.Children
|
|
54
|
+
local OnEvent = Fusion.OnEvent
|
|
55
|
+
|
|
56
|
+
-- Create a scope (manages cleanup of all objects created within it)
|
|
57
|
+
local scope = scoped(Fusion)
|
|
58
|
+
|
|
59
|
+
-- Reactive state
|
|
60
|
+
local count = scope:Value(0)
|
|
61
|
+
|
|
62
|
+
-- Derived state (re-computes when dependencies change)
|
|
63
|
+
local label = scope:Computed(function(use)
|
|
64
|
+
return "Count: " .. use(count)
|
|
65
|
+
end)
|
|
66
|
+
|
|
67
|
+
-- Create instances (reactive properties auto-update)
|
|
68
|
+
local gui = scope:New "ScreenGui" {
|
|
69
|
+
Parent = playerGui,
|
|
70
|
+
[Children] = {
|
|
71
|
+
scope:New "TextLabel" {
|
|
72
|
+
Text = label,
|
|
73
|
+
Size = UDim2.fromOffset(200, 50),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
-- Animate any value
|
|
79
|
+
local smoothPos = scope:Spring(position, 25) -- speed 25
|
|
80
|
+
|
|
81
|
+
-- Read without subscribing (in callbacks)
|
|
82
|
+
local currentCount = peek(count)
|
|
83
|
+
|
|
84
|
+
-- Cleanup everything in the scope
|
|
85
|
+
scope:doCleanup()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Component pattern
|
|
89
|
+
|
|
90
|
+
```luau
|
|
91
|
+
local function Button(scope: Fusion.Scope, props: {
|
|
92
|
+
Text: Fusion.UsedAs<string>,
|
|
93
|
+
OnClick: () -> (),
|
|
94
|
+
Color: Fusion.UsedAs<Color3>?,
|
|
95
|
+
})
|
|
96
|
+
local isHovering = scope:Value(false)
|
|
97
|
+
|
|
98
|
+
return scope:New "TextButton" {
|
|
99
|
+
Text = props.Text,
|
|
100
|
+
BackgroundColor3 = scope:Spring(scope:Computed(function(use)
|
|
101
|
+
local base = if props.Color then use(props.Color) else Color3.fromRGB(80, 140, 255)
|
|
102
|
+
return if use(isHovering) then base:Lerp(Color3.new(1,1,1), 0.1) else base
|
|
103
|
+
end), 25),
|
|
104
|
+
[OnEvent "Activated"] = props.OnClick,
|
|
105
|
+
[OnEvent "MouseEnter"] = function() isHovering:set(true) end,
|
|
106
|
+
[OnEvent "MouseLeave"] = function() isHovering:set(false) end,
|
|
107
|
+
[Children] = { scope:New "UICorner" { CornerRadius = UDim.new(0, 6) } },
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### List rendering (ForPairs)
|
|
113
|
+
|
|
114
|
+
```luau
|
|
115
|
+
-- Renders a UI element for each item. Automatically adds/removes as data changes.
|
|
116
|
+
scope:ForPairs(items, function(use, itemScope, index, item)
|
|
117
|
+
return index, itemScope:New "TextLabel" {
|
|
118
|
+
Text = item.Name,
|
|
119
|
+
LayoutOrder = index,
|
|
120
|
+
}
|
|
121
|
+
end)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## References
|
|
127
|
+
|
|
128
|
+
Full production-quality screen implementations are in `references/`:
|
|
129
|
+
|
|
130
|
+
- **shop.luau** - Item grid, currency header, purchase confirmation modal, server-validated buy flow
|
|
131
|
+
- **inventory.luau** - Owned items grid with rarity borders, equip/unequip, detail panel, empty slots
|
|
132
|
+
- **settings-menu.luau** - Tabbed sections, sliders with drag, toggle switches, dropdown selects
|
|
133
|
+
|
|
134
|
+
Each reference is self-contained and demonstrates:
|
|
135
|
+
- Scope-based memory management
|
|
136
|
+
- Component composition (small functions returning instances)
|
|
137
|
+
- Reactive state driving UI updates
|
|
138
|
+
- Spring animations for smooth transitions
|
|
139
|
+
- ForPairs for dynamic lists
|
|
140
|
+
- Modal/overlay patterns
|
|
141
|
+
- Typed props for clear interfaces
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Sources
|
|
146
|
+
|
|
147
|
+
- Fusion: github.com/dphfox/Fusion (MIT, 764★)
|
|
148
|
+
- Fusion docs: elttob.uk/Fusion/latest
|
|
149
|
+
- Component patterns: VirtualButFake/fusion-components (MIT, 31 components)
|
|
150
|
+
- Fusion 0.3 release notes: github.com/dphfox/Fusion/releases/tag/v0.3-beta
|