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.
phichain-compiler
The phichain-compiler crate compiles Phichain charts into a primitive format suitable for gameplay. It performs optimizations like merging child lines, evaluating curve note tracks, and flattening the chart structure.
Installation
Add this to your Cargo.toml:
[ dependencies ]
phichain-compiler = "1.0.0-beta.5"
phichain-chart = "1.0.0-beta.5"
Dependencies
The crate depends on:
phichain-chart (chart data structures)
num 0.4.3 (numerical computations)
anyhow 1.0 (error handling)
nalgebra 0.33.1 (linear algebra for transformations)
Core Function
Compile a Phichain chart into a primitive chart format. The compilation process:
Merges child lines into their parents with proper transformations
Evaluates curve note tracks to generate individual notes
Converts to primitive chart format
use phichain_compiler :: compile;
use phichain_chart :: serialization :: PhichainChart ;
use phichain_chart :: primitive :: PrimitiveChart ;
use std :: fs :: File ;
fn main () -> anyhow :: Result <()> {
// Load chart
let file = File :: open ( "chart.json" ) ? ;
let chart : PhichainChart = serde_json :: from_reader ( file ) ? ;
// Compile to primitive format
let primitive = compile ( chart ) ? ;
// Save compiled chart
let output = File :: create ( "chart.compiled.json" ) ? ;
serde_json :: to_writer_pretty ( output , & primitive ) ? ;
Ok (())
}
Compilation Steps
1. Merge Child Lines
Child lines are merged into their parent lines by applying transformations:
Position offsets are combined
Rotations are accumulated
Events are transformed to parent coordinate space
Notes are repositioned relative to parent
use phichain_chart :: serialization :: { PhichainChart , SerializedLine };
use phichain_chart :: line :: Line ;
use phichain_chart :: beat;
// Before compilation: parent with child line
let parent = SerializedLine :: new (
Line { name : "Parent" . to_string () },
vec! [],
vec! [], // Parent events
vec! [
SerializedLine :: new (
Line { name : "Child" . to_string () },
vec! [], // Child notes
vec! [], // Child events
vec! [],
vec! [],
)
],
vec! [],
);
// After compilation: child merged into parent
// All child transformations are computed relative to parent
2. Evaluate Curve Note Tracks
Curve note tracks define smooth note patterns between two anchor notes. The compiler:
Samples points along the bezier curve
Generates individual notes at each sample point
Interpolates properties (speed, x position) along the curve
Removes the curve track definition
use phichain_chart :: curve_note_track :: CurveNoteTrack ;
use phichain_chart :: note :: { Note , NoteKind };
use phichain_chart :: beat;
// Before compilation: curve track between notes
let from_note = Note :: new ( NoteKind :: Tap , true , beat! ( 0 ), - 1.0 , 1.0 );
let to_note = Note :: new ( NoteKind :: Tap , true , beat! ( 4 ), 1.0 , 1.0 );
// Curve track generates notes along the path
// After compilation: multiple individual notes along the curve
The final primitive chart:
Has a flat line structure (no nesting)
Contains only basic note types
Uses simple transition events
Is optimized for fast rendering and gameplay
The compiled primitive chart format. use phichain_chart :: primitive :: PrimitiveChart ;
pub struct PrimitiveChart {
pub offset : f32 ,
pub bpm_list : BpmList ,
pub lines : Vec < primitive :: line :: Line >,
// Additional metadata fields
}
Complete Example
Compile Chart
Batch Compile
Validate Compilation
use phichain_compiler :: compile;
use phichain_chart :: {
serialization :: PhichainChart ,
primitive :: PrimitiveChart ,
};
use std :: fs :: File ;
use std :: path :: PathBuf ;
fn main () -> anyhow :: Result <()> {
// Load source chart
let input_path = PathBuf :: from ( "charts/mysong/chart.json" );
let file = File :: open ( & input_path ) ? ;
let chart : PhichainChart = serde_json :: from_reader ( file ) ? ;
println! ( "Loaded chart with {} lines" , chart . lines . len ());
// Compile the chart
println! ( "Compiling..." );
let primitive = compile ( chart ) ? ;
println! ( "Compiled to {} flattened lines" , primitive . lines . len ());
// Save compiled chart
let output_path = PathBuf :: from ( "charts/mysong/chart.compiled.json" );
let output = File :: create ( & output_path ) ? ;
serde_json :: to_writer_pretty ( output , & primitive ) ? ;
println! ( "Saved to {}" , output_path . display ());
Ok (())
}
Understanding Compilation
Why Compile?
Phichain charts support advanced features like:
Nested lines - Child lines with relative transformations
Curve note tracks - Smooth note patterns defined by bezier curves
Complex events - Layered transformations and animations
These features make authoring easier but are expensive to compute in real-time. Compilation converts these high-level features into a simple, flat format optimized for gameplay.
Compilation Optimizations
Flattened hierarchy - Eliminates nested line transformations during gameplay
Pre-computed notes - Curve tracks are expanded into individual notes
Simplified events - Complex event chains are resolved
Reduced memory - Compact primitive format uses less memory
Faster parsing - Simple structure for quick deserialization
When to Compile
Before distribution - Ship compiled charts for better performance
Chart validation - Verify charts compile without errors
Performance testing - Test gameplay with optimized charts
Cross-platform - Ensure charts work on all target platforms
Editor preview - Quick preview of compiled output
Advanced Usage
Custom Compilation Pipeline
You can implement custom compilation steps:
use phichain_chart :: serialization :: PhichainChart ;
use phichain_chart :: primitive :: PrimitiveChart ;
fn custom_compile ( mut chart : PhichainChart ) -> anyhow :: Result < PrimitiveChart > {
// 1. Custom preprocessing
preprocess ( & mut chart ) ? ;
// 2. Standard compilation
let mut primitive = phichain_compiler :: compile ( chart ) ? ;
// 3. Custom postprocessing
postprocess ( & mut primitive ) ? ;
Ok ( primitive )
}
fn preprocess ( chart : & mut PhichainChart ) -> anyhow :: Result <()> {
// Add custom logic before compilation
// e.g., normalize BPM, validate chart structure
Ok (())
}
fn postprocess ( chart : & mut PrimitiveChart ) -> anyhow :: Result <()> {
// Add custom logic after compilation
// e.g., optimize note ordering, merge events
Ok (())
}
Error Handling
Compilation can fail for several reasons:
use phichain_compiler :: compile;
use phichain_chart :: serialization :: PhichainChart ;
use std :: fs :: File ;
fn safe_compile ( path : & str ) -> anyhow :: Result <()> {
let file = File :: open ( path )
. map_err ( | e | anyhow :: anyhow! ( "Failed to open file: {}" , e )) ? ;
let chart : PhichainChart = serde_json :: from_reader ( file )
. map_err ( | e | anyhow :: anyhow! ( "Failed to parse chart: {}" , e )) ? ;
let primitive = compile ( chart )
. map_err ( | e | anyhow :: anyhow! ( "Compilation failed: {}" , e )) ? ;
// Use compiled chart
println! ( "Successfully compiled {} lines" , primitive . lines . len ());
Ok (())
}
See Also