turtle/.github/copilot-instructions.md

201 lines
6.3 KiB
Markdown

# 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
```bash
# 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
```bash
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:
```rust
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
```rust
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
```rust
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)
```rust
#[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