Compare commits

...

2 Commits

Author SHA1 Message Date
a3cad7d1bc update the README.md 2025-10-24 17:29:40 +02:00
8128c212ae fix unused variable warning 2025-10-24 17:29:06 +02:00
4 changed files with 87 additions and 144 deletions

114
README.md
View File

@ -17,9 +17,32 @@ A modern turtle graphics library for Rust built on [Macroquad](https://macroquad
- 🐢 **Multiple Turtle Shapes**: Triangle, classic turtle, circle, square, arrow, and custom shapes
- 🔍 **Structured Logging**: Optional `tracing` integration for debugging (zero overhead when disabled)
- 💨 **Lightweight**: Fast compilation and runtime
- 📤 **SVG Export**: Export drawings to SVG format with viewBox and padding (feature-gated)
## Quick Start
The simplest example to draw a square:
```rust
//! Minimal turtle example - just 10 lines!
//!
//! This is the simplest possible turtle program using the macro.
use turtle_lib::*;
#[turtle_main]
fn hello() {
turtle.set_pen_color(BLUE);
for _ in 0..4 {
turtle.forward(100.0);
turtle.right(90.0);
}
}
```
The turtle starts at the center of the window, facing right (0 degrees). The above code draws a blue square.
The `turtle_main` macro sets up the Macroquad window, turtle initialization, and main loop for you. It expands to code similar to this:
```rust
use macroquad::prelude::*;
use turtle_lib::*;
@ -108,7 +131,7 @@ plan.forward(100).right(90).forward(50);
### Execution Modes
Speed is now controlled via commands, allowing dynamic switching during execution:
Speed controlled via commands, allowing dynamic switching during execution:
```rust
let mut plan = create_turtle();
@ -124,32 +147,15 @@ plan.pen_down();
plan.forward(200);
plan.right(90);
// Create app (no speed parameter needed)
// Create app
let app = TurtleApp::new().with_commands(plan.build());
```
**Speed Modes:**
- **Speed < 999**: Animated mode with smooth tweening
- **Speed >= 999**: Instant mode (no animation)
- **Speed >= 999**: Instant mode (no animation) the bigger the number the more segments will be added per frame.
- Default speed is 100.0 if not specified
### Animation Loop
```rust
loop {
clear_background(WHITE);
app.update(); // Update animation state
app.render(); // Draw to screen
if app.is_complete() {
// All commands executed
}
next_frame().await
}
```
## Debugging and Logging
The library uses [`tracing`](https://docs.rs/tracing) for structured diagnostic logging. This is completely optional - if you don't set up a subscriber, there's zero overhead.
@ -177,6 +183,48 @@ RUST_LOG=turtle_lib=trace cargo run
**See the complete example**: [`examples/logging_example.rs`](turtle-lib/examples/logging_example.rs) demonstrates initialization, log levels, filtering, and example output.
## SVG Export
Export your turtle drawings to SVG format for use in web applications, vector graphics editors, or further processing.
### Enabling SVG Export
Add the `svg` feature to enable SVG export functionality:
```bash
cargo run --example export_svg --features svg
```
### Usage
```rust
use turtle_lib::*;
// Create your drawing
let mut plan = create_turtle();
plan.forward(100).right(90).forward(100);
// Create app
let mut app = TurtleApp::new().with_commands(plan.build());
// Export to SVG
app.export_drawing("drawing.svg", export::DrawingFormat::Svg)?;
```
### Features
- **Complete Primitive Support**: Lines, circles, arcs, polygons, and fills
- **Automatic viewBox**: Includes 20px padding around the entire drawing
- **Color and Styling**: Preserves colors, pen width, and fill colors
- **Multi-Contour Fills**: Exports complex fills with holes using SVG paths
- **Text Support**: Exports text elements with positioning
### Example
See [`examples/export_svg.rs`](turtle-lib/examples/export_svg.rs) for a complete example that draws various shapes and exports them to SVG.
The exported SVG can be opened in any web browser or vector graphics application.
## Examples
Run examples with:
@ -188,6 +236,9 @@ cargo run --example yinyang
cargo run --example stern
cargo run --example nikolaus
# SVG export example (requires --features svg)
cargo run --example export_svg --features svg
# Logging example - shows how to enable debug output
cargo run --example logging_example
RUST_LOG=turtle_lib=debug cargo run --example logging_example
@ -210,15 +261,18 @@ RUST_LOG=turtle_lib=debug cargo run --example logging_example
- **fill_circle_test.rs**: Circle fills with different angles
- **fill_instant_test.rs**: Quick fill test in instant mode
#### Export
- **export_svg.rs**: Demonstrates SVG export functionality (requires `--features svg`)
#### Debugging
- **logging_example.rs**: Demonstrates how to enable and use tracing/logging output
## Why Lyon?
- Automatic hole detection via EvenOdd fill rule
- Handles any self-intersecting path
- GPU-accelerated rendering
- Standards-compliant (matches SVG, HTML Canvas)
- Handles any self-intersecting path
### Basic Fill
```rust
@ -283,15 +337,6 @@ turtle-lib/src/
└── general/ - Type definitions (Angle, Length, etc.)
```
### Design Principles
- **State Management**: Clean separation between turtle state and world state
- **Command Queue**: Commands queued and executed with optional tweening
- **Consolidated Commands**: Unified commands reduce duplication (Move, Turn, Circle)
- **Dynamic Speed Control**: Speed managed via SetSpeed commands for flexibility
- **Tweening System**: Smooth interpolation with easing functions
- **Unified Lyon Rendering**: All drawing operations use GPU-accelerated Lyon tessellation
## Workspace Structure
```
@ -309,8 +354,14 @@ cargo check
# Run specific example
cargo run --example yinyang
# Run SVG export example (requires svg feature)
cargo run --example export_svg --features svg
# Build release version
cargo build --release
# Build with SVG support
cargo build --features svg
```
## Development Status
@ -329,7 +380,8 @@ cargo build --release
- **EvenOdd fill rule** for complex self-intersecting paths
- **Live fill preview** during animation with progressive rendering
- **Multi-contour support** - pen_up/pen_down manage contours
- **Command consolidation**
- **Command consolidation**
- **SVG Export** - Export drawings to SVG with viewBox and padding (feature-gated)
## What's New

View File

@ -3,111 +3,3 @@
The main turtle graphics library built on Macroquad with Lyon tessellation.
**See the [main README](../README.md) for complete documentation.**
## Features
**Complete Lyon Integration** - All drawing operations use GPU-optimized tessellation
- Unified rendering pipeline for lines, arcs, circles, and fills
- ~410 lines of code eliminated through architectural simplification
- Consistent high-quality rendering across all primitives
**Multi-Contour Fill System** - Advanced fill capabilities with automatic hole detection
- EvenOdd fill rule for complex shapes with holes (like cheese or yin-yang symbols)
- `pen_up()` closes current contour, `pen_down()` opens next contour
- Progressive fill preview during animations
- Support for self-intersecting paths
**Smooth Animation** - Tweening system with live rendering
- Configurable speed control
- Frame-rate independent animation
- Live fill preview during circle/arc drawing
## Quick Start
### Using the `turtle_main` Macro (Recommended for Beginners)
The easiest way to create turtle programs is with the `turtle_main` macro:
```rust
use macroquad::prelude::*;
use turtle_lib::*;
#[turtle_main("My First Drawing")]
fn my_drawing(turtle: &mut TurtlePlan) {
turtle.set_pen_color(RED);
turtle.forward(100.0);
turtle.right(90.0);
turtle.forward(100.0);
}
```
The macro automatically handles:
- Window creation and setup
- Turtle initialization
- Rendering loop
- Quit handling (ESC or Q keys)
### Manual Setup (For Advanced Use)
For more control over the application loop:
```rust
use macroquad::prelude::*;
use turtle_lib::*;
#[macroquad::main("Turtle")]
async fn main() {
let mut turtle = create_turtle();
turtle.forward(100.0).right(90.0);
let mut app = TurtleApp::new().with_commands(turtle.build());
loop {
clear_background(WHITE);
app.update();
app.render();
next_frame().await;
}
}
```
## Quick Examples
All examples now use the `turtle_main` macro for simplicity:
```bash
# Run from this directory
cargo run --example hello_turtle # Minimal 10-line example
cargo run --example macro_demo # Simple square with macro
cargo run --example square # Basic square drawing
cargo run --example shapes # Different turtle shapes
cargo run --example yinyang # Multi-contour fills with holes
cargo run --example koch # Recursive fractals
cargo run --example fill_demo # Fill with holes (donut)
cargo run --example cheese_macro # Cheese example using macro
cargo run --example fill_advanced # Complex shapes (manual setup)
```
Most examples use `turtle_main` for simplicity. A few keep manual setup for custom UI or logging.
## Architecture Highlights
### Rendering Pipeline
All drawing operations → Lyon tessellation → GPU mesh rendering
### DrawCommand Enum
Simplified from 5 variants to 1:
- `Mesh(MeshData)` - unified variant for all drawing operations
### Fill System
- `FillState` tracks multiple contours (completed + current)
- Pen state management automatically handles contour creation
- EvenOdd tessellation provides automatic hole detection
See [LYON_COMPLETE.md](LYON_COMPLETE.md) and [MULTI_CONTOUR_FILLS.md](MULTI_CONTOUR_FILLS.md) for implementation details.
## Status
**Stable** - Lyon integration complete, multi-contour fills working, all examples passing.
See [../README.md](../README.md) for full API documentation and project status.

View File

@ -28,7 +28,7 @@ pub fn render_world(world: &TurtleWorld) {
for turtle in &world.turtles {
for cmd in &turtle.commands {
match cmd {
DrawCommand::Mesh { data, source } => {
DrawCommand::Mesh { data, source: _ } => {
// Rendering wie bisher
draw_mesh(&data.to_mesh());
// Hier könnte man das source für Debug/Export loggen
@ -39,7 +39,7 @@ pub fn render_world(world: &TurtleWorld) {
heading,
font_size,
color,
source,
source: _,
} => {
draw_text_command(text, *position, *heading, *font_size, *color);
// Hier könnte man das source für Debug/Export loggen
@ -80,7 +80,7 @@ pub fn render_world_with_tweens(world: &TurtleWorld, zoom_level: f32) {
for turtle in &world.turtles {
for cmd in &turtle.commands {
match cmd {
DrawCommand::Mesh { data, source } => {
DrawCommand::Mesh { data, source: _ } => {
draw_mesh(&data.to_mesh());
}
DrawCommand::Text {
@ -89,7 +89,7 @@ pub fn render_world_with_tweens(world: &TurtleWorld, zoom_level: f32) {
heading,
font_size,
color,
source,
source: _,
} => {
draw_text_command(text, *position, *heading, *font_size, *color);
}

View File

@ -5,7 +5,6 @@ pub mod svg_export {
use crate::commands::TurtleCommand;
use crate::export::{DrawingExporter, ExportError};
use crate::state::{DrawCommand, TurtleWorld};
use macroquad::prelude::Vec2;
use std::fs::File;
use svg::{
node::element::{Circle, Line, Polygon, Text as SvgText},