Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ivan-1f/phichain/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Lines (also called judgment lines) are the horizontal bars that notes appear on in Phigros. Each line can move, rotate, and change opacity independently through events. Lines can also have child lines for complex animations.

Types

Line

The basic judgment line type.
name
String
required
The display name of the line (default: “Unnamed Line”)

SerializedLine

A line with all its associated data for serialization.
line
Line
required
The base line properties (flattened in JSON)
notes
Vec<Note>
required
All notes attached to this line
events
Vec<LineEvent>
required
Animation events that control the line’s movement and appearance
children
Vec<SerializedLine>
required
Child lines that move relative to this line
curve_note_tracks
Vec<CurveNoteTrack>
required
Curved note tracks (advanced feature)

Line Properties

Lines are controlled through events. The following properties can be animated:
  • X Position: Horizontal position (screen coordinates, 0 = center)
  • Y Position: Vertical position (screen coordinates, 0 = center)
  • Rotation: Rotation angle in degrees
  • Opacity: Visibility from 0.0 (invisible) to 1.0 (fully visible)
  • Speed: Note movement speed multiplier
See the Event documentation for details on controlling these properties.

Creating Lines

use phichain_chart::line::Line;
use phichain_chart::serialization::SerializedLine;

// Create a simple line
let line = Line {
    name: "Main Line".to_string(),
};

// Create with default name
let default_line = Line::default(); // name = "Unnamed Line"

Default Line Events

When creating a SerializedLine with Default::default(), it includes default events for all line properties:
LineEvent { kind: X,        value: constant(0.0),  start: 0, end: 1 }
LineEvent { kind: Y,        value: constant(0.0),  start: 0, end: 1 }
LineEvent { kind: Rotation, value: constant(0.0),  start: 0, end: 1 }
LineEvent { kind: Opacity,  value: constant(0.0),  start: 0, end: 1 }
LineEvent { kind: Speed,    value: constant(10.0), start: 0, end: 1 }
These defaults keep the line at the center with standard speed.

Parent-Child Line Hierarchy

Lines can have child lines that inherit the parent’s transformation:
use phichain_chart::serialization::SerializedLine;
use phichain_chart::line::Line;

// Create parent line
let parent = SerializedLine::new(
    Line { name: "Parent".to_string() },
    vec![],
    vec![
        // Parent moves horizontally
        LineEvent {
            kind: LineEventKind::X,
            start_beat: Beat::ZERO,
            end_beat: Beat::from(4.0),
            value: LineEventValue::transition(-0.5, 0.5, Easing::Linear),
        },
    ],
    vec![
        // Child line rotates while parent moves
        SerializedLine::new(
            Line { name: "Child".to_string() },
            vec![],
            vec![
                LineEvent {
                    kind: LineEventKind::Rotation,
                    start_beat: Beat::ZERO,
                    end_beat: Beat::from(4.0),
                    value: LineEventValue::transition(0.0, 360.0, Easing::Linear),
                },
            ],
            vec![], // child can also have children
            vec![],
        ),
    ],
    vec![],
);

JSON Serialization

{
  "name": "Main Line",
  "notes": [
    {
      "kind": "tap",
      "above": true,
      "beat": [0, 0, 1],
      "x": 0.0,
      "speed": 1.0
    }
  ],
  "events": [
    {
      "kind": "x",
      "start_beat": [0, 0, 1],
      "end_beat": [4, 0, 1],
      "value": {
        "transition": {
          "start": -0.5,
          "end": 0.5,
          "easing": "linear"
        }
      }
    }
  ],
  "children": [],
  "curve_note_tracks": []
}

Working with Lines

let mut line = SerializedLine::default();

// Add a tap note
line.notes.push(Note::new(
    NoteKind::Tap,
    true,
    Beat::from(2.0),
    0.5,
    1.0,
));

// Add a hold note
line.notes.push(Note::new(
    NoteKind::Hold { hold_beat: Beat::from(1.0) },
    false,
    Beat::from(4.0),
    -0.3,
    1.0,
));

Notes

  • Line names don’t need to be unique, but unique names are recommended for easier management
  • Child lines move and rotate relative to their parent’s coordinate system
  • The coordinate system has (0, 0) at the screen center
  • Rotation is measured in degrees, clockwise
  • All notes on a line move together with the line’s transformations

Build docs developers (and LLMs) love