Margrete RPC
Advanced

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:

FieldMeaning
tTick or Position tuple.
xLane position.
hAir height.
ease_xEasing used for lane movement into this waypoint.
ease_hEasing 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.

On this page