Chained commands
Two commands you'll find yourself wanting:
AnchorAll: anchor everything currently selected.RecolorAll: recolor everything currently selected.
You don't have to choose. props:RunCommand lets one command call another.
The basics
return {
Arguments = {},
Run = function(props)
-- Run AnchorAll using AnchorAll's *current* argument values.
props:RunCommand("AnchorAll")
-- Run Recolor with explicit arg overrides.
props:RunCommand("Recolor", { Color = "Bright red" })
end,
}
RunCommand is synchronous. The next line doesn't execute until the inner command's Run (and its OnExecuted) have finished. Whatever the inner Run returned is RunCommand's return value.
Undo behavior
Inner RunCommand calls bypass their own ChangeHistoryService recording. The outer command's recording (assuming AutoRecordChanges = true) covers everything.
What this means in practice:
-- Outer command, opens recording
Run = function(props)
props:RunCommand("AnchorAll") -- inner: NO new recording, joins outer
props:RunCommand("RecolorAll") -- inner: same, joins outer
-- All three operations are one undo step.
end,
If you set AutoRecordChanges = false on the outer and want each inner step to be its own undo step, you'll need to call them differently, manually wrapping each in your own ChangeHistoryService:TryBeginRecording block. But that's an unusual setup; most chains want the single-undo behavior.
Argument inheritance
RunCommand("Name") (with no second argument) uses whatever argument values are currently set on Name: the values the user entered into its UI, or the persisted attribute values from the last session.
RunCommand("Name", { ... }) uses your overrides for any keys you provide; missing keys fall back to the current values. This lets you partially override:
-- Run Recolor with the user's current Anchor setting,
-- but force the Color regardless of what's typed in the field.
props:RunCommand("Recolor", { Color = "Black" })
The override is call-scoped. The persisted argument values on the Recolor command are not changed.
"Macro" command pattern
A common shape: a command that chains together several others to do a complete workflow:
return {
Description = "Anchor everything, recolor to gray, lock further edits.",
Tags = { "macro" },
Arguments = {},
Run = function(props)
props:RunCommand("AnchorAll")
props:RunCommand("Recolor", { Color = "Medium stone grey" })
props:RunCommand("LockSelection")
end,
}
The macro doesn't need its own arguments, it just sequences the underlying commands. Treat macros as the "high-level recipe" that your "low-level building blocks" plug into.
Switching the active sidebar selection
RunCommand runs a command but doesn't change which command is visible in the sidebar. To switch the user's active view:
props:ViewCommand("Recolor")
This is useful in two patterns:
- "Continue" buttons: a button argument that runs some prep work and then takes the user to the next command in a flow.
- Undo-then-show: when a command finishes, navigate to a related command so the user can iterate without searching.
ViewCommand does not run the command, it just selects it. Combine with RunCommand if you want both:
props:RunCommand("AnchorAll")
props:ViewCommand("Recolor")