turtle/.github/copilot-instructions.md

6.3 KiB

Turtle Graphics Library - AI Agent Instructions

Project Overview

Rust workspace with turtle graphics implementations. Primary focus: turtle-lib-macroquad - lightweight library using Macroquad + Lyon for GPU-accelerated rendering.

Workspace Structure

turtle/
├── turtle-lib-macroquad/        # MAIN LIBRARY - Macroquad + Lyon (focus here)
├── turtle-lib-macroquad-macros/ # Proc macro for turtle_main
├── turtle-lib/                  # Legacy Bevy 0.17.1 implementation (maintenance only)
├── turtle-example/              # Legacy examples
└── turtle-ui/                   # UI components

Architecture (turtle-lib-macroquad)

Core Design Pattern: Command Queue + Tweening

  • Builder API (TurtlePlan) accumulates commands
  • Command Queue stores execution plan
  • Tween Controller interpolates between states for animation
  • Lyon Tessellation converts all primitives to GPU meshes

Key Files

src/
├── lib.rs           - Public API, TurtleApp (main loop), re-exports
├── builders.rs      - Fluent API traits (forward/right/etc chain)
├── commands.rs      - TurtleCommand enum (Move/Turn/Circle/etc)
├── execution.rs     - Execute commands, update state
├── tweening.rs      - Animation interpolation, speed control
├── drawing.rs       - Render Lyon meshes with Macroquad
├── tessellation.rs  - Lyon integration (polygons/strokes/fills/arcs)
├── state.rs         - TurtleState, TurtleWorld, FillState
└── circle_geometry.rs - Arc/circle math

Critical Concepts

1. Consolidated Commands (reduces duplication):

  • Move(distance) - negative = backward
  • Turn(angle) - positive = right, negative = left (degrees)
  • Circle{radius, angle, steps, direction} - unified left/right

2. Fill System (multi-contour with holes):

  • FillState tracks Vec<Vec<Vec2>> (multiple contours)
  • pen_up() closes current contour, pen_down() opens new
  • Lyon's EvenOdd fill rule auto-detects holes
  • Example: Donut = outer circle + inner circle (2 contours)

3. Speed Modes:

  • < 999: Animated with tweening
  • >= 999: Instant execution
  • Controlled via SetSpeed commands (dynamic switching)

4. Lyon Tessellation Pipeline: All drawing → Lyon → GPU mesh → Macroquad rendering

  • ~410 lines eliminated vs manual triangulation
  • Functions: tessellate_polygon/stroke/circle/arc/multi_contour

Developer Workflows

Building & Testing

# Main library
cargo build --package turtle-lib-macroquad
cargo test --package turtle-lib-macroquad
cargo clippy --package turtle-lib-macroquad -- -Wclippy::pedantic \
  -Aclippy::cast_precision_loss -Aclippy::cast_sign_loss -Aclippy::cast_possible_truncation

# Run examples (15+ examples available)
cargo run --package turtle-lib-macroquad --example hello_turtle
cargo run --package turtle-lib-macroquad --example yinyang
cargo run --package turtle-lib-macroquad --example cheese_macro

Macro Crate

cargo build --package turtle-lib-macroquad-macros

Code Quality Standards

  • Clippy pedantic mode enabled
  • Cast warnings allowed for graphics math
  • All examples must build warning-free
  • Use #[must_use] on builder methods

Project-Specific Patterns

1. The turtle_main Macro (PREFERRED for examples)

Simplest way to create turtle programs:

use turtle_lib_macroquad::*;

#[turtle_main("Window Title")]
fn draw(turtle: &mut TurtlePlan) {
    turtle.forward(100.0).right(90.0);
}

Generates: window setup + render loop + quit handling (ESC/Q)

2. Import Convention

Only need: use turtle_lib_macroquad::*;

  • Re-exports: vec2, RED/BLUE/GREEN/etc, all turtle types
  • No use macroquad::prelude::* needed (causes unused warnings)

3. Builder Chain Pattern

let mut t = create_turtle();
t.forward(100).right(90)
 .set_pen_color(BLUE)
 .circle_left(50.0, 360.0, 36)
 .begin_fill()
 .end_fill();
let app = TurtleApp::new().with_commands(t.build());

4. Multi-Contour Fill Example

turtle.begin_fill();
turtle.circle_left(100.0, 360.0, 72);  // Outer circle
turtle.pen_up();  // Closes contour
turtle.goto(vec2(0.0, -30.0));
turtle.pen_down(); // Opens new contour
turtle.circle_left(30.0, 360.0, 36);   // Inner (becomes hole)
turtle.end_fill(); // EvenOdd rule creates donut

5. Manual Setup (advanced control)

#[macroquad::main("Custom")]
async fn main() {
    let mut turtle = create_turtle();
    // ... drawing code ...
    let mut app = TurtleApp::new().with_commands(turtle.build());
    
    loop {
        clear_background(WHITE);
        app.update();
        app.render();
        next_frame().await;
    }
}

Common Tasks

Adding New Turtle Command

  1. Add variant to TurtleCommand enum in commands.rs
  2. Implement builder method in builders.rs (chain with self)
  3. Add execution logic in execution.rs
  4. Update tessellation/rendering if needed

Adding Example

  • Prefer turtle_main macro for simplicity
  • Use only use turtle_lib_macroquad::*;
  • Keep examples focused (one concept each)
  • See examples/hello_turtle.rs for minimal template

Debugging Lyon Issues

  • Enable tracing: RUST_LOG=turtle_lib_macroquad=debug cargo run
  • Check tessellation.rs for Lyon API usage
  • EvenOdd fill rule: holes must have opposite winding

Dependencies & Integration

Main Dependencies

  • macroquad = "0.4" - Window/rendering framework
  • lyon = "1.0" - Tessellation (fills, strokes, circles)
  • tween = "2.1.0" - Animation easing
  • tracing = "0.1" - Optional logging (zero overhead when unused)

Proc Macro Crate

  • Separate crate required by Rust (proc-macro = true)
  • Uses syn, quote, proc-macro2
  • Generates full macroquad app boilerplate

What NOT to Do

  • Don't add use macroquad::prelude::* in examples when not required
  • Don't manually triangulate - use Lyon functions
  • Don't add commands for Forward/Backward separately (use Move)
  • Don't modify turtle-lib (Bevy) unless specifically needed
  • Don't create summary/comparison docs unless requested

Key Documentation Files

  • README.md - Main API docs
  • turtle-lib-macroquad/README.md - Library-specific docs
  • turtle-lib-macroquad-macros/README.md - Macro docs

Response Style

  • Be concise, no extensive summaries
  • No emojis in technical responses
  • Focus on code solutions over explanations
  • Use bullet points for lists
  • Reference specific files when helpful