All issues identified across Sections 3.1, 3.2, and 3.3 have been
resolved, verified with unit tests, automated compilation checks under
`-D float_literal_f32_fallback`, and headless SVG export runs.
-
**[angle.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/general/angle.rs)**:
- Implemented `From<f64>` and `From<usize>` for `Degrees`.
- Added unit tests `from_integer` and `from_f64` to verify conversion
accuracy.
-
**[fontsize.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/general/fontsize.rs)**:
- Implemented `From<f64>` for `FontSize`.
- Refactored `FontSize::value(self)` to pass Copy type by value.
- Added unit test `font_size_conversions`.
-
**[general.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/general.rs)**:
- Implemented `From<f64>`, `From<i32>`, and `From<usize>` for
`AnimationSpeed`.
- Added unit test `animation_speed_conversions`.
- Re-exported `macroquad` crate (`pub use macroquad;`) so downstream
code and macro expansions have reliable direct access.
-
**[export.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/export.rs)**:
- Made `parse_svg_export_arg()` public.
- Implemented `run_headless_svg_export<F>(mut build_commands: F,
filename: &str) -> Result<(), ExportError>` that executes commands
using `app.step_animations()`, avoiding all window/GUI dependencies
and never calling `std::process::exit`.
- Updated `handle_svg_export` to delegate to
`run_headless_svg_export`.
-
**[lib.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/lib.rs)**:
- Extracted `pub fn step_animations(&mut self)` from `update(&mut
self)`, allowing command queue draining and tween stepping
headlessly without querying window mouse position or events.
-
**[state.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs)**:
- Changed `TurtleWorld::new()` to initialize camera with
`Camera2D::default()` instead of querying `screen_width()` /
`screen_height()`, eliminating panics when running without a
Macroquad window.
-
**[turtle-lib-macros/src/lib.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib-macros/src/lib.rs)**:
- Added `validate_input` helper providing clean compile diagnostics
with spans for:
- Multiple arguments: `#[turtle_main] functions must take either 0
arguments or a single &mut TurtlePlan`
- Non-unit return types: `#[turtle_main] functions cannot have a
return type`
- Async functions: `#[turtle_main] functions cannot be async`
- Replaced `#[macroquad::main]` wrapper expansion with a native `fn
main()` that inspects CLI arguments first. If `--export-svg` is
present, it runs `run_headless_svg_export` directly and returns
cleanly without opening a window. Otherwise, it launches
`macroquad::Window::new(#window_title, async { ... })`.
- Added 5 unit tests in `turtle-lib-macros` testing signature
validation.
-
**[.vscode/launch.json](file:///home/dietrich/Projekte/Source/turtlers/.vscode/launch.json)**:
- Removed stale references to nonexistent `turtle-example` and
`turtle-ui`.
- Added debug configurations for `turtle-lib` tests,
`turtle-lib-macros` tests, `hello_turtle`, and `breadboard`.
-
**[breadboard.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/breadboard.rs)**:
- Refactored example to use `#[turtle_main("Breadboard")]`.
- Removed `#[cfg(feature = "svg")]` and the early-exit message; the
example now renders directly on screen by default and supports
`--features svg -- --export-svg breadboard.svg`.
-
**[README.md](file:///home/dietrich/Projekte/Source/turtlers/README.md)**:
- Documented optional user-level `~/.cargo/config.toml` mold/lld
fast-linking configuration under "Building and Running".
---
```bash
cargo test --workspace
```
- **Result**: 21 passed (16 in `turtle-lib`, 5 in `turtle-lib-macros`),
34 doctests passed, 0 failed.
```bash
RUSTFLAGS="-D float_literal_f32_fallback" cargo check --workspace
--all-targets --all-features
RUSTFLAGS="-D float_literal_f32_fallback" cargo check --package
turtle-lib --examples --all-features
```
- **Result**: Passed with 0 errors and 0 fallback warnings across all
workspace crates and all 30 examples.
```bash
cargo run --package turtle-lib --example hello_turtle --features svg --
--export-svg hello.svg
cargo run --package turtle-lib --example breadboard --features svg --
--export-svg breadboard.svg
```
- **Result**: Both exported SVG files successfully and exited with code
0 without creating or flashing a graphical window.
```bash
cargo check --package turtle-lib --example breadboard
```
- **Result**: Compiled cleanly with 0 errors when SVG feature is
disabled.
We resolved **Issue 4.3 (Severe Per-Frame Allocation in Rendering
Loop)** by removing the intermediate `MeshData` structure and storing
`macroquad::prelude::Mesh` directly in
[`DrawCommand::Mesh`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs).
[`DrawCommand`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs)
- Dropped `Clone` and `Debug` derives from
[`Turtle`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs#L58)
and
[`DrawCommand`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs#L351),
accommodating Macroquad's `Mesh` which does not implement these
traits.
- Changed
[`DrawCommand::Mesh`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/state.rs#L353)
to the tuple variant `DrawCommand::Mesh(macroquad::prelude::Mesh)`.
- Deleted `struct MeshData` and its `to_mesh` method.
[`tessellation.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs)
- Renamed `build_mesh_data` to
[`build_mesh`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L35)
returning `macroquad::prelude::Mesh { vertices, indices, texture: None
}` directly.
- Updated
[`tessellate_polygon`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L71),
[`tessellate_multi_contour`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L116),
[`tessellate_stroke`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L214),
[`tessellate_circle`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L259),
and
[`tessellate_arc`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tessellation.rs#L308)
to return `Result<Mesh, Box<dyn std::error::Error>>`.
[`drawing.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs)
- In the main drawing loop
([`drawing.rs:36-38`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs#L36-L38)):
```rust
DrawCommand::Mesh(mesh) => {
draw_mesh(mesh);
}
```
Now borrows `&Mesh` directly from the command vector with **0 heap
allocations and 0 vector clones per frame**.
- Updated fill preview ([line
228](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs#L228)),
tween arc/center indicators ([lines 309,
329](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs#L309)),
and turtle shape drawing ([line
349](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/drawing.rs#L349))
to pass `&mesh` directly to `draw_mesh(&mesh)` without vector cloning.
[`execution.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/execution.rs)
- Updated
[`commands.push(DrawCommand::Mesh(mesh))`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/execution.rs#L135)
and
[`tessellate_command`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/execution.rs#L337).
- Updated
[`test_forward_left_forward`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/execution.rs#L487)
to instantiate `mut state` directly without dummy cloning.
---
```bash
cargo test --lib
```
Output:
```
running 10 tests
test circle_geometry::tests::test_circle_left_geometry ... ok
test circle_geometry::tests::test_circle_right_geometry ... ok
test general::angle::tests::degrees_to_radians_roundtrip ... ok
test general::angle::tests::from_integer ... ok
test execution::tests::test_forward_left_forward ... ok
test general::angle::tests::negation ... ok
test tweening::tests::test_animated_mode_pops_to_current_tween ... ok
test tweening::tests::test_instant_mode_drains_queue ... ok
test
tweening::tests::test_instant_mode_respects_batch_limit_and_retains_pending
... ok
test tweening::tests::test_streaming_append_commands_does_not_accumulate
... ok
test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered
out; finished in 0.00s
```
All targets verified with `cargo check --all-targets` and `cargo clippy
--lib`.
In
[`TweenController`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs),
commands are currently accumulated in `queue: CommandQueue` (which wraps
a `Vec<TurtleCommand>`). When commands execute in `update()`, an
internal `cursor: usize` increments, but executed commands are never
removed. In streaming and threaded applications (such as
[`examples/clock_threaded.rs`](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/examples/clock_threaded.rs)),
new commands are appended continuously, causing `queue` to grow
unboundedly over time and exhaust memory.
We will replace `queue: CommandQueue` and `cursor: usize` with `queue:
std::collections::VecDeque<TurtleCommand>` inside `TweenController`.
Consumed commands will be removed immediately using `pop_front()`,
completely freeing memory as commands complete.
> [!NOTE]
> All design decisions were aligned during the `/grill-me` session:
> - `TweenController` will internally store
`std::collections::VecDeque<TurtleCommand>` and consume items via
`pop_front()`.
> - `self.cursor` is eliminated entirely.
> - `CommandQueue` remains the public API container for passing
batches of commands into `TweenController::new` and
`TweenController::append_commands`.
> - `TurtleCommand::Reset` retains its normal semantics (clearing
drawings and parameters without clearing future queued commands), as
continuous `pop_front()` already discards consumed commands.
> - Standard `VecDeque` capacity behavior is maintained (no
auto-shrinking) to prevent reallocation jitter in streaming scenarios.
[tweening.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/tweening.rs)
- Import `std::collections::VecDeque`.
- Update `TweenController` struct definition:
- Replace `queue: CommandQueue` and `cursor: usize` with `queue:
VecDeque<TurtleCommand>`.
- In `TweenController::new`:
- Initialize `queue` using `queue.into_iter().collect()`.
- Remove `cursor` initialization.
- In `TweenController::append_commands`:
- Extend `self.queue` directly from `new_queue: CommandQueue`.
- In `TweenController::update`:
- **Instant mode**: Replace `while let Some(command) =
self.queue.get(self.cursor).cloned()` with `while let Some(command)
= self.queue.pop_front()`, removing `self.cursor += 1` and
unnecessary command cloning.
- **Animated mode**: Replace `if let Some(command) =
self.queue.get(self.cursor).cloned()` with `if let Some(command) =
self.queue.pop_front()`, removing `self.cursor += 1` and unnecessary
command cloning.
- In `TweenController::is_complete`:
- Update check to `self.current_tween.is_none() &&
self.queue.is_empty()`.
- Add unit tests in `#[cfg(test)] mod tests`:
- Verify queue drains to 0 length in Instant mode.
- Verify queue drains in Animated mode with multiple frames.
- Verify streaming `append_commands` calls continuously drain and do
not accumulate.
- Verify `is_complete()` transitions correctly.
---
[commands.rs](file:///home/dietrich/Projekte/Source/turtlers/turtle-lib/src/commands.rs)
- Update doc comments referencing `TweenController`'s cursor to reflect
the queue consumption model.
- Run `cargo test -p turtle-lib --lib tweening` to execute the new unit
tests.
- Run `cargo test -p turtle-lib` to ensure all existing tests in
`turtle-lib` continue to pass.
- Run `cargo check --examples` to ensure all examples (including
`clock_threaded.rs`) compile cleanly.
- Review memory behavior or run `examples/clock_threaded.rs` in debug to
confirm streaming updates run smoothly.