-
Notifications
You must be signed in to change notification settings - Fork 0
Timeline Commands Reference
Command type IDs are defined in TimelineCommandFactory.Create(). Each command serializes to JSON in timeline.json with a "type" field matching these IDs.
- Input simulation
- Flow control
- CopyScript
- Screenshots
- Studio / scene
- Pose
- Variables & logic
- VNGE
- Other
- Adding new commands
| Type ID | Command | Purpose |
|---|---|---|
simulate_key |
SimulateKeyCommand | Send key combo (Ctrl+A, F5, etc.) |
simulate_mouse |
SimulateMouseCommand | Mouse button click |
move_mouse |
MoveMouseCommand | Move cursor to position |
scroll |
ScrollCommand | Mouse wheel scroll |
| Type ID | Command | Purpose |
|---|---|---|
pause |
PauseCommand | Wait for duration |
loop |
LoopCommand | Repeat section |
checkpoint |
CheckpointCommand | Mark checkpoint |
jump |
JumpToCheckpointCommand | Jump to checkpoint |
confirm |
ConfirmCommand | Wait for user confirm |
resolve_on_issue |
ResolveOnIssueCommand | Branch on issue flag |
resolve_on_count |
ResolveOnCountCommand | Branch on counter |
sub_timeline |
SubTimelineCommand | Run nested timeline |
sub_timeline_param |
SubTimelineParamCommand | Sub-timeline with params |
sub_if |
SubBlockIfCommand | Start of a block-if (main timeline or sub-timeline) |
sub_elseif |
SubBlockElseIfCommand | Additional conditional branch |
sub_else |
SubBlockElseCommand | Default branch |
sub_endif |
SubBlockEndIfCommand | End of the block-if |
return |
ReturnCommand | Return from sub-timeline |
label |
LabelCommand | Label marker |
A structural if / else if* / else / end construct that works on the main timeline and inside sub-timelines (the add buttons live in the Subtimeline category). Blocks may be repeated and nested freely. Unlike the checkpoint-based while, these branch by position in the list rather than by jumping to a named checkpoint.
Rules
- Every
sub_ifmust be balanced by a matchingsub_endif(End If is mandatory). Between them: any number ofsub_elseif, then at most onesub_else. Order within a block must beIf→Else If* →Else→End If. Nested blocks are matched by depth like brackets. - Violations are shown on the offending row and block Start.
- The conditions in
sub_if/sub_elseifbehave exactly like thewhilecommand (same operands, operators,Not). -
sub_elseandsub_endifhave no condition.
Execution
-
Iftrue → run the commands directly below it; when the block reaches the next same-level marker (Else If/Else), jump to its matchingEnd If. -
Iffalse → evaluate eachElse Ifin turn; the first true one runs its block. If none match, theElseblock runs. - After a taken branch finishes, execution continues after
End If.
Example "CheckMood" (works the same on the main timeline or in a sub-timeline)
1. Set mood = "happy" (normal command)
2. If mood == "happy"
3. Pose Apply "smile"
4. Else If mood == "sad"
5. Pose Apply "cry"
6. Else
7. Pose Apply "neutral"
8. End If
9. Screenshot (runs after the block)
-
mood = "happy"→ 1 → 2 (true) → 3 → jump to 8 → 9 -
mood = "sad"→ 1 → 2 (false) → 4 (true) → 5 → jump to 8 → 9 -
mood = "angry"→ 1 → 2 (false) → 4 (false) → 6 (else) → 7 → 8 → 9
| Type ID | Command | Purpose |
|---|---|---|
start_tracking |
StartTrackingCommand | Start file tracking |
stop_tracking |
StopTrackingCommand | Stop tracking |
copy_rename |
CopyRenameCommand | Copy/rename tracked files |
clear_tracked |
ClearTrackedFilesCommand | Clear tracked list |
set_source_path |
SetSourcePathCommand | Set source path |
set_destination_path |
SetDestinationPathCommand | Set destination |
set_name_pattern |
SetNamePatternCommand | Set rename pattern |
set_rule_counter |
SetCounterRuleCommand | Counter rule |
set_rule_list |
SetListRuleCommand | List rule |
set_rule_batch |
SetBatchRuleCommand | Batch rule |
| Type ID | Command | Purpose |
|---|---|---|
screenshot |
ScreenshotCommand | Take screenshot |
wait_screenshot |
WaitForScreenshotCommand | Wait for screenshot plugin |
wait_empty_screenshots |
WaitForEmptyScreenshotsCommand | Wait until queue empty |
screenshot_alpha |
ScreenshotAlphaModeCommand | Alpha mode |
screenshot_resolution |
ScreenshotResolutionCommand | Resolution |
screenshot_save_path |
ScreenshotSavePathCommand | Save path |
screenshot_alt_path_var |
ScreenshotAltPathVarCommand | Alt path variable |
| Type ID | Command | Purpose |
|---|---|---|
clothing_state |
ClothingStateCommand | Clothing on/off states |
accessory_state |
AccessoryStateCommand | Accessory states |
gdc_wardrobe_state |
GdcWardrobeStateCommand | Enable/disable all GDC Wardrobe layers |
outfit_rotate |
OutfitRotateCommand | Rotate outfit |
outfit_by_name |
OutfitByNameCommand | Select outfit by name |
set_camera_by_name |
SetCameraByNameCommand | Select camera |
select_object_by_name |
SelectObjectByNameCommand | Select workspace object |
set_object_visible_by_name |
SetObjectVisibleByNameCommand | Toggle visibility |
replace_chara_card |
ReplaceCharaCardCommand | Load chara from UserData/chara/
|
load_coordinate_card |
LoadCoordinateCardCommand | Load coordinate card |
pose_library |
PoseLibraryCommand | Pose library interaction |
sound |
SoundCommand | Play sound |
clothing_state/accessory_stateapply the chosen state directly to the currently selected character(s) viaOCIChar(clothing:SetClothesStateAll/SetClothesState; accessory:ShowAccessory). The Anim/Attitude manipulate panel does not need to be open, and the state is applied to every selected character. If no character is selected, the command does nothing and logs a warning.
gdc_wardrobe_stateenables (On) or disables (Off) all layers of the GDC Wardrobe plugin at once. Each GDC layer is a GameObject on the character namedGDCLayer_*; the plugin's per-layer toggle just callsSetActiveon it, so the command does the same directly on every such GameObject (across all characters, including currently inactive ones). The GDC window does not need to be open, but it also won't refresh its own checkboxes when toggled this way.
| Type ID | Command | Purpose |
|---|---|---|
pose_apply |
PoseApplyCommand | Apply a Pose Browser pose by path (interpolatable). Optionally target a single character by name |
pose_apply_group |
PoseApplyGroupCommand | Apply a Pose Browser pose group by path. Optionally target a set of characters by name |
Path for
pose_applyis the pose file's path relative tostudio/pose(e.g.MyFolder/cool pose.png); an absolute path also works. Path forpose_apply_groupis the group name (the group id also works). Both are obtained via the Copy path button in the Pose Browser (on a pose or on a group). Requires the Pose Browser plugin to be installed.
pose_apply: with Character off it applies to the workspace selection; with Character on it looks up the single scene character with the given (interpolatable) name and applies the pose to that character.pose_apply_group: with Characters off it applies to the workspace selection; with Characters on the character set comes either from a list variable (whose items are character names) or from an inline list edited in the command. Names are resolved to scene characters. The Pose Browser priority list is applied in all cases.
| Type ID | Command | Purpose |
|---|---|---|
set |
SetVariableCommand | Set variable |
set_string |
SetStringCommand | Set string variable |
set_integer |
SetIntegerCommand | Set integer |
get |
GetVariableCommand | Read variable |
calc |
CalcCommand | Arithmetic |
if |
WhileCommand | Conditional jump to checkpoint (do-while loop) |
str_replace |
StrReplaceCommand | String replace |
str_split |
StrSplitCommand | Split a string into a list variable |
list |
ListCommand | List operations |
range |
RangeCommand | Cycle a variable through a set of numbers/ranges |
Condition operators (used by
whileand the block-if commands):==,≠,<,≤,>,≥, plus three membership operators where the right field is a variable name (a list, a dict, or a string holding arangeexpression):
∈F— left equals the first element (list) / first number (range).∈L— left equals the last element (list) / last number (range).in— left is contained in the right: any element of a list, any number of a range, or a key or value of a dict. |set_list| SetListCommand | Set list variable | |list_insert| ListInsertCommand | Insert list item | |list_remove| ListRemoveCommand | Remove list item | |list_apply_dict| ListApplyDictCommand | Apply dict to list | |dict_set| DictSetCommand | Dictionary set | |dict_get| DictGetCommand | Dictionary get |
listdrives a string variable from a list of values (an inline list or a list variable). A mode button selects the behaviour: next (default, advance through the values cycling), rev (advance from last to first), first (always the first value), last (always the last value), get (read the value at a specific index), length (store the number of items as a number). In get mode the source is always a list variable (the inline-list option is hidden); an extra Idx field gives the index (interpolatable) and a 1-based toggle switches between 0-based (default) and 1-based indexing; an out-of-range index is skipped with a warning. length works on an empty list too (stores0).
rangedrives a variable from a sequence of numbers each time it runs. The sequence comes from an interpolatable text field of comma-separated single numbers and/or inclusive ranges:1-10,1,2,3,5,1-3,6,1-10,12,14-20. A descending range like5-1counts down. A mode button selects the behaviour:
- next (default) — write the next value, cycling.
1-5→1, 2, 3, 4, 5, 1, …(stored asint).- rev — like next but from the last value to the first.
1-5→5, 4, 3, 2, 1, 5, …(int).- first — always the first value of the whole range (
int).- last — always the last value of the whole range (
int).- list — write the whole expanded range into a list variable, e.g.
1-3,6→[1, 2, 3, 6].The target variable is created if it doesn't exist yet (an
intfor next/rev/first/last, a list for list mode).
str_splitsplits a Source string by a Separator and writes the parts into a List var (created if absent). Source and separator both support interpolation (e.g.{myVar}). An empty separator yields a single-element list containing the whole source. Pairs naturally withlistin get mode to read individual parts.
| Type ID | Command | Purpose |
|---|---|---|
vnge_scene_next |
VngeSceneNextCommand | Next scene |
vnge_scene_prev |
VngeScenePrevCommand | Previous scene |
vnge_next_scene |
VngeNextSceneCommand | Next scene alt |
vnge_prev_scene |
VngePrevSceneCommand | Prev scene alt |
vnge_load_scene |
VngeLoadSceneByIndexCommand | Load scene by index |
| Type ID | Command | Purpose |
|---|---|---|
video_record |
VideoRecordCommand | Video recording |
get_fashion |
GetFashionCommand | FashionLine data |
display |
DisplayCommand | Open/close a floating window showing a variable's live value |
displaytakes a variable name (typestring,int, orbool) and a mode button: open (default) or close. In open mode it opens a movable, resizable window with the variable name (top) and its current value (large, below); the value updates live while the timeline runs. Each window has a close button and a pin button (top-right) — pinning persists that window's position/size for the variable across runs and sessions. Opening a window for a variable that already has one is a no-op. In close mode it closes the window for that variable. All Display windows also close automatically when the timeline ends.Instead of a variable name you can enter an override token. Currently supported:
%TIME— elapsed run time of the timeline, formattedHH:MM:SS.Overrides are defined in
DisplayOverrides.cs; add an entry there to extend the set.
See .cursor/skills/create-timeline-command/ in the repository:
- Create
src/Timeline/YourCommand.csextendingTimelineCommand - Register type ID in
TimelineCommandFactory.cs - Add UI in
ActionTimelineWindowif needed
Navigation: ← Timeline · Timeline commands · Next: SearchBarManager →
- Overview
- Folders & library
- Search, filters & sort
- Grid & selection
- Pose groups
- Multi-character apply
- Pose stash
- Pose items
- Import/export ZIP
- Thumbnails
- Options & data