-
Notifications
You must be signed in to change notification settings - Fork 1
Movement Options
Note that the order of operation is always as they are listed here, regardless in which order you specify them.
If you want a different order or run a single operation multiple times, you need to run the tool multiple times, or use multiple lines in a action.txt
preset file.
All operations support filtering options to apply to certain types only.
See the measurement system in the glossary for more details regarding the expected format of parameters.
One of the following: (mutually exclusive)
-
-p<x,y,t>
/--pivot=<x,y,t>
--note-pivot=<note_type>
--relative
Usually scaling, rotating and outsetting will be done in respect to the center of grid, ie rotation will be done around it and scaling/outsetting will be away from it or towards it.
When you specify a pivot, instead everything will revolve around that point.
Note that time coordinate of the pivot is only relevant when you are scaling in time and can usually be 0.
When using --note-pivot
, before any operations are applied the pivot position is set to the first note of the given note type.
When you specify --relative
, the outcome depends on the type of object you are using it on:
- For single notes, the only operation that has an apparent effect is offset.
Because how would you move a single note away from itself or rotate it around itself? - For rails, the start of each rail will be used as pivot for the other nodes of that rail.
- For walls:
- scale / outset will have no effect (just as with single notes above)
- rotation will rotate the wall around its center (just like you can do in the editor)
-
offset will be relative to the wall rotation (ie offset of
1,0,0
will move the wall in the direction that "right" would be when the wall is upright).
(relative mode is mostly useful for single objects, it will wreck complex patterns since each object is treated individually)
Technical note: Pivot operations are implemented as result = operation(input - pivot) + pivot
-s<x,y,t>
or --scale=<x,y,t>
This option multiplies all coordinates (individually) by the given coordinates. Note that this does not affect the size of the walls, only their positions.
Note: Scaling time is done relative to start of selection (unless using pivot/relative). On export, the start of the selection is moved to the first element (wall or note) (unless you use the --keep-alignment
post-processing option). Note that a scale of 2 means the pattern gets 2x longer, and does not double the speed (You'd use 1/2 for that).
If you just want to rescale to a different BPM, see --bpm
Technical note: This is implemented as result = input * scale
- Increase the size of a pattern by 50% (=150% or x1.5) horizontally and vertically:
--scale=1.5,150%,1
- Mirror everything on the X-axis (without swapping note colors):
--scale=-1,1,1
- Squish rails flat onto the X-axis:
--scale=0,1,1 --relative
- Move everything to the same Y coordinate of
+2
:--scale=1,0,1 --pivot=1,0,1
- Halve length of pattern in time:
--scale=1,1,1/2
- Reverse pattern in time:
--scale=1,1,-1
-r<degrees>
or --rotate=<degrees>
This option rotates all positions around the center of the grid (unless using pivot/relative). It will also change the angle of walls to match. Not much else to it.
Technical note: This is implemented as result = dot_product(input, rotation_matrix(angle))
- Rotate 45 degrees counterclockwise:
--rotate=45
- Rotate 90 degrees clockwise:
--rotate=-90
- Rotate 15 degrees counterclockwise around the bottom right corner:
--rotate=45 --pivot=8,-6,0
- Rotate rail/wall by 180 degrees around itself:
--rotate=180 --relative
--wall-rotate=<degrees>
You may want to decouple the wall rotation from the overall pattern rotation, which this allows you to do.
The wall rotation is applied after the regular rotation.
- Rotate walls by 9 degrees around itself:
--wall-rotate=90
(equivalent to--filter=walls --rotate=90 --relative
) - Rotate pattern by 30 degrees, but keep the wall orientation:
--rotate=30 --wall-rotate=-30
-o<x,y,t>
or --offset=<x,y,t>
Moves everything, in positions and/or time. Also not much to this one. Note that pivot/relative does not affect offsetting.
Technical note: This is implemented as result = input + offset
- Move everything up by one grid square:
--offset=0,1,0
- Move everything left by half a grid square:
--offset=-1/2,0,0
- Move everything 1/4 of a beat later:
--offset=0,0,1/4
- Move everything 2 seconds later:
--offset=0,0,2s
- Fix certain wall types being lower in the game than they are in the editor:
--filter slides --offset=0,2.1,0 --keep-alignment
(This is included asexport_walls.txt
, along with an undo)
--outset=<distance>
While offsetting will move by a fixed distance and in a fixed direction for everything, and scaling will change both distance and direction to be -well- scaled by their position and angle, outsetting will only change the direction, but keep the distance static.
A positive value will move it away from the center (unless using pivot/relative), while a negative value will move towards it.
Note: a high enough negative value may result in the position being moved across the pivot and to the other side.
Technical note: This is implemented as result = input + normalize(input) * outset
- Move everything half a grid square closer to the center:
--outset=-1/2
- Move all rails nodes away by one grid square from the rail start:
--outset=1 --relative
- Move all rails nodes away by one grid square from the top center of the grid:
--outset=1 --pivot=0,6,0
-c<count>
/ --stack-count=<count>
or --stack-duration=<beats>
/ --stack-duration=<seconds>s
While by default the objects would be moved to the new positions, stacking instead creates a number of copies. This is an extremely powerful tool and can create complex patterns extremely fast.
And it gets even more powerful when used with --connect-singles
(but that must be done in a following call, since connecting is a preprocessing operation) to make rails more flexible than --spiral
would allow.
Technical note: This is implemented as stacked = do_movement(stacked or initial), add stacked to output
for each stack
- Creates 4 additional copies (so there will be 5 patterns in total), which rotate by 30 degrees and move 1/4 of a beat later per stack (see the following images):
--rotate=30 --offset=0,0,1/4 --stack-count=4
Input | Result |
---|---|
Either --offset-along=<target note type>
or --rotate-with=<target note type>
(also requires offset in time)
These option make the movement track existing notes and rails of a target type/color. Both options are mutually exclusive, and --rotate-with
also respects a pivot. --relative
is not supported.
This works by looking for a target note at the start of the selection, and then again after the time offset.
When there is no note or rail node for the second, the position is interpolated if possible. Both positions are used to calculate the movement for all moved objects. This complex patterns (e.g. wall art) from becoming distorted, but may look weird if you stack objects that are not aligned to the start of the section.
When stacking, the movement is recalculated for each stacking.
Note: You likely want to exclude the target type/color via Filtering, ie by doing --filter=<other_type> --rotate-with=<target_type>
if you want to affect a certain type or --filter=<target> --invert-filter --rotate-with=<target>
to affect everything except the target.
- Creates 4 additional copies of the center wall, offsetting along the green single-handed rail and move 1/4 of a beat later per stack (see the following):
--filter=center --offset=0,0,1/4 --stack-count=4 --offset-along=single
Note that the walls just shift with the rail, but do not rotate. - Creates 4 additional copies of everything that isn't green single-handed, rotating with the green single-handed rail and move 1/4 of a beat later per stack (see the following):
--filter=single --invert-filter --offset=0,0,1/4 --stack-count=4 --rotate-with=single
Note that the walls both rotate and move in/outward with the rail, aligned to the default pivot (grid center)
Input | Offsetting along rail | Rotating with rail |
---|---|---|
--autostack
or --autostack=<mode>
Instead of manually specifying offset, rotation, etc, you can let the tool determine this by itself based on the first pair of objects in the selection (before filtering). Values that are not calculated can also be specified manually if you are feeling fancy (may result in weird results tho).
The following modes are supported:
-
OFFSET
(default): this just looks at the positions and continues in a straight line, leading to linear patterns.
Calculates: offset, wall-rotate -
SPIRAL
(only possible if the detected pair is walls): Attempts to find a pivot point such that wall rotation lines up with position rotation. This typically leads to perfectly cylindrical spiral patterns.
Calculates: offset, pivot, rotation -
OUTSET
: instead of looking at absolute position, this looks at distance and direction from center (or pivot) and continues that, typically leading to conical patterns (ie expanding spirals).
Calculates: offset, outset, rotate, wall-rotate -
SCALE
: similar toOUTSET
, but instead of using the absolute change in distance, uses the relative change. This results in exponentially expanding funnels, so avoid using with large changes.
Calculates: offset, scale, wall-rotate
- Continue the pattern for a full beat:
--autostack <mode> --stack-duration=1
Input | OFFSET |
SPIRAL |
OUTSET |
SCALE |
---|---|---|---|---|
--offset-random=<min_x>:<max_x>,<min_y>:<max_y>
or --offset-random=<max_x>,<max_y>
(can be given multiple times in the same command)
This generates a random offset between the specified minimum and maximum for X and Y (evenly distributed). When no minimum is specified, the negative maximum is used. This offset is either generated once (not for each individual object) when not stacking or once per stacked copy after stacking and without affecting the following stacks.
When specified multiple times, it will "fairly" choose one of the areas (based on their size) to pick the offset.
Technical note: This is implemented as stacked = do_movement(stacked or initial_input), add (stacked + random_offset) to output
- Creates 32 additional copies (so there will be 33 patterns in total), which move 1/4 of a beat later per stack and are randomly distributed between -20 and +20 in X and 0 and +5 in Y (see the following images):
--offset-random=20,0:5 --offset=0,0,1/4 --stack-count=32
Input | Result |
---|---|
- Randomly stack something on either side of the playspace (start with a centered pattern, randomly offset it -20 to -10 or +10 to +20):
--offset-random=-20:-10,0 --offset-random=10:20,0 --offset=0,0,1/4 --stack-count=32
--rotate-random=<min_ang>:<max_ang>
or --rotate-random=<max_ang>
(can be given multiple times in the same command)
This generates a random angle between the specified minimum and maximum (evenly distributed). When no minimum is specified, the negative maximum is used. This angle is either generated once (not for each individual object) when not stacking or once per stacked copy after stacking and without affecting the following stacks.
When specified multiple times, it will "fairly" choose one of the areas (based on their size) to pick the offset.
Technical note: This is implemented as stacked = do_movement(stacked or initial_input), add rotate(stacked, random_angle) to output
- Randomly rotate something while stacking, either close to horizontally or close to vertically (0°±10° or 90°±10°):
--rotate-random=-10:+10 --rotate-random=80:100 --offset=0,0,1/4 --stack-count=32
Quick Links: Home | Installation | Glossary | Companion
- Pre-Processing: Change BPM, Delete Everything Not Matching Filter, Connect Single Notes Into Rails, Merge Rails, Change Note Type, Swap Hands, Change Wall Type
- Rails: Interpolate, Shorten Rails, Spiral, Spikes
- Movement: Scaling, Rotate, Offset, Outset, Stacking, Following Notes, Auto-Stacking, Random Offset, Random Rotation
- Post-Processing, Create parallel patterns, Split Rails, Convert Rails Into Single Notes, Snap to Rails, Keep Selection Alignment
- Miscellaneous: Use Original JSON, Filtering