Curve Slides
Sketch curved slides, air slides, and air-crush paths.
The Curve utility helps you sketch width-agnostic slide paths before
turning them into notes. The usual workflow is to draw a path as a curve, then materialize it as a
Slide, AirSlide, or
AirCrush. For hand-built notes and joints, start with
Notes.
from margrete_rpc import Margrete
from margrete_rpc.chart.util import Curve
m = Margrete()
with m.open_edit() as tx:
slide = (
Curve(t=(0, 0), x=0)
.to(t=(1, 0), x=12, ease_x="in_out_sine")
.to_slide(w=4)
.clamp()
)
tx.chart.notes.append(slide)Mental model
A Curve stores Waypoint values with:
| Field | Meaning |
|---|---|
t | Tick or Position tuple. |
x | Lane position. |
h | Air height. |
ease_x | Easing used for lane movement into this waypoint. |
ease_h | Easing used for height movement into this waypoint. |
The first waypoint anchors the curve, so its easing values do not affect the path. h is preserved when you
materialize a ground slide, but it only has visible effect on air-slide and air-crush paths.
Add legs with to(...). Each target time must be later than
the current end of the curve.
from margrete_rpc.chart.util import Curve
path = (
Curve(t=(0, 0), x=2, h=60)
.to(t=(0, 2), x=12, h=120, ease_x="out_cubic", ease_h="in_sine")
.to(t=(1, 0), x=4, h=80, ease_x="in_cubic", ease_h="out_sine")
)Positions are resolved the same way as note constructors. Inside with m.open_edit() blocks, tuple positions
use the chart's time signatures. See Time & Position for the full timing model.
Materialize notes
Use to_slide() for ground slides. The w value is applied
to every generated joint.
from margrete_rpc.chart.util import Curve
slide = (
Curve(t=(0, 0), x=0)
.to(t=(0, 2), x=8, ease_x="out_quad")
.to(t=(1, 0), x=4, ease_x="in_quad")
.to_slide(w=4)
)Use to_air_slide() when the generated path should live in
the air lane. Pass h= on the curve start and on legs where height should change.
from margrete_rpc.chart.notes import Tap
from margrete_rpc.chart.util import Curve
air_slide = (
Curve(t=(0, 0), x=4, h=60)
.to(t=(0, 2), x=10, h=120, ease_x="in_out_sine", ease_h="out_quad")
.to(t=(1, 0), x=6, h=80, ease_x="in_out_sine", ease_h="in_quad")
.to_air_slide(w=4)
)
parent = Tap(t=air_slide.t, x=air_slide.x, w=air_slide.w).add_air(air_slide)Use to_air_crush() for air-crush traces. gap accepts
either raw ticks or a division tuple such as (1, 16).
from margrete_rpc.chart.util import Curve
crush = (
Curve(t=(0, 0), x=2, h=80)
.to(t=(1, 0), x=14, h=120, ease_x="out_expo", ease_h="in_out_sine")
.to_air_crush(w=2, gap=(1, 16), color="blue")
)Curve samples eased legs into integer waypoints. Linear legs stay compact, while curved legs get enough
control points to reproduce the sketched motion after conversion to notes.
ease_x and ease_h accept built-in easing names, Easing
objects, or custom callables. See Easings for the full list and custom easing rules.
Inspect and compose
Call points() to preview the quantized path before creating
a note.
path = Curve(t=(0, 0), x=0).to(t=(1, 0), x=12, ease_x="in_out_sine")
for point in path.points():
print(point.t, point.x, point.h)Use at(tick) to evaluate a curve at a specific tick. This
is useful for building derived paths that follow or cross another path.
path = Curve(t=0, x=0, h=80).to(t=960, x=12, h=120)
mid = path.at(480)
print(mid.x, mid.h)Use then() or + to join curves. If the second curve
starts at the first curve's end tick, the shared point is de-duplicated.
from margrete_rpc.chart.util import Curve
out = Curve(t=(0, 0), x=0).to(t=(0, 2), x=12, ease_x="out_cubic")
back = Curve(t=(0, 2), x=12).to(t=(1, 0), x=4, ease_x="in_cubic")
slide = (out + back).to_slide(w=4)Use Curve.from_note() when you want to load an existing
long note as a curve, compose it, then materialize again.
from margrete_rpc.chart.util import Curve
path = Curve.from_note(existing_slide)
for point in path.waypoints[1:]:
point.ease_x = "out_cubic"
copy = path.to_slide(w=existing_slide.w)Width is intentionally dropped because Curve is width-agnostic.