reduce exposed internal functions and fields

This commit is contained in:
Franz Dietrich 2026-05-16 15:31:10 +02:00
parent cd589b2513
commit a7570911d8
9 changed files with 103 additions and 94 deletions

View File

@ -10,11 +10,11 @@ pub enum CircleDirection {
} }
/// Encapsulates all geometry for a circular arc /// Encapsulates all geometry for a circular arc
pub struct CircleGeometry { pub(crate) struct CircleGeometry {
pub center: Vec2, pub(crate) center: Vec2,
pub radius: f32, pub(crate) radius: f32,
pub start_angle_from_center: f32, // radians pub(crate) start_angle_from_center: f32, // radians
pub direction: CircleDirection, pub(crate) direction: CircleDirection,
} }
impl CircleGeometry { impl CircleGeometry {

View File

@ -76,7 +76,7 @@ pub struct TurtleCommandSender {
/// ///
/// Paired with `TurtleCommandSender` via `turtle_command_channel()`. /// Paired with `TurtleCommandSender` via `turtle_command_channel()`.
/// Automatically managed by `TurtleApp::process_commands()`. /// Automatically managed by `TurtleApp::process_commands()`.
pub struct TurtleCommandReceiver { pub(crate) struct TurtleCommandReceiver {
turtle_id: usize, turtle_id: usize,
rx: Receiver<CommandQueue>, rx: Receiver<CommandQueue>,
} }
@ -212,7 +212,7 @@ impl TurtleCommandReceiver {
/// # } /// # }
/// ``` /// ```
#[must_use] #[must_use]
pub fn turtle_command_channel( pub(crate) fn turtle_command_channel(
turtle_id: usize, turtle_id: usize,
buffer_size: usize, buffer_size: usize,
) -> (TurtleCommandSender, TurtleCommandReceiver) { ) -> (TurtleCommandSender, TurtleCommandReceiver) {

View File

@ -13,7 +13,7 @@ use macroquad::prelude::*;
use tween::CubicInOut; use tween::CubicInOut;
/// Render the entire turtle world /// Render the entire turtle world
pub fn render_world(world: &TurtleWorld) { pub(crate) fn render_world(world: &TurtleWorld) {
// Update camera zoom based on current screen size to prevent stretching // Update camera zoom based on current screen size to prevent stretching
let camera = Camera2D { let camera = Camera2D {
zoom: vec2(1.0 / screen_width() * 2.0, 1.0 / screen_height() * 2.0), zoom: vec2(1.0 / screen_width() * 2.0, 1.0 / screen_height() * 2.0),
@ -61,7 +61,7 @@ pub fn render_world(world: &TurtleWorld) {
/// Render the turtle world with active tween visualization /// Render the turtle world with active tween visualization
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub fn render_world_with_tweens(world: &TurtleWorld, zoom_level: f32) { pub(crate) fn render_world_with_tweens(world: &TurtleWorld, zoom_level: f32) {
// Update camera zoom based on current screen size to prevent stretching // Update camera zoom based on current screen size to prevent stretching
// Apply user zoom level by dividing by it (smaller zoom value = more zoomed in) // Apply user zoom level by dividing by it (smaller zoom value = more zoomed in)
let camera = Camera2D { let camera = Camera2D {
@ -386,7 +386,7 @@ fn draw_tween_arc(
} }
/// Draw the turtle shape /// Draw the turtle shape
pub fn draw_turtle(turtle_params: &TurtleParams) { pub(crate) fn draw_turtle(turtle_params: &TurtleParams) {
let rotated_vertices = turtle_params.shape.rotated_vertices(turtle_params.heading); let rotated_vertices = turtle_params.shape.rotated_vertices(turtle_params.heading);
if turtle_params.shape.filled { if turtle_params.shape.filled {

View File

@ -12,7 +12,7 @@ use crate::general::AnimationSpeed;
/// Execute side effects for commands that don't involve movement /// Execute side effects for commands that don't involve movement
/// Returns true if the command was handled (caller should skip movement processing) /// Returns true if the command was handled (caller should skip movement processing)
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub fn execute_command_side_effects(command: &TurtleCommand, state: &mut Turtle) -> bool { pub(crate) fn execute_command_side_effects(command: &TurtleCommand, state: &mut Turtle) -> bool {
match command { match command {
TurtleCommand::BeginFill => { TurtleCommand::BeginFill => {
if state.filling.is_some() { if state.filling.is_some() {
@ -159,7 +159,7 @@ pub fn execute_command_side_effects(command: &TurtleCommand, state: &mut Turtle)
/// Record fill vertices after movement commands have updated state /// Record fill vertices after movement commands have updated state
#[tracing::instrument] #[tracing::instrument]
pub fn record_fill_vertices_after_movement( pub(crate) fn record_fill_vertices_after_movement(
command: &TurtleCommand, command: &TurtleCommand,
start_state: &TurtleParams, start_state: &TurtleParams,
state: &mut Turtle, state: &mut Turtle,
@ -200,7 +200,7 @@ pub fn record_fill_vertices_after_movement(
/// Execute a single turtle command, updating state and adding draw commands /// Execute a single turtle command, updating state and adding draw commands
#[tracing::instrument] #[tracing::instrument]
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub fn execute_command(command: &TurtleCommand, state: &mut Turtle) { pub(crate) fn execute_command(command: &TurtleCommand, state: &mut Turtle) {
// Try to execute as side-effect-only command first // Try to execute as side-effect-only command first
if execute_command_side_effects(command, state) { if execute_command_side_effects(command, state) {
return; // Command fully handled return; // Command fully handled
@ -346,7 +346,11 @@ pub fn execute_command(command: &TurtleCommand, state: &mut Turtle) {
} }
/// Execute command on a specific turtle by ID /// Execute command on a specific turtle by ID
pub fn execute_command_with_id(command: &TurtleCommand, turtle_id: usize, world: &mut TurtleWorld) { pub(crate) fn execute_command_with_id(
command: &TurtleCommand,
turtle_id: usize,
world: &mut TurtleWorld,
) {
// Clone turtle state to avoid borrow checker issues // Clone turtle state to avoid borrow checker issues
if let Some(turtle) = world.get_turtle(turtle_id) { if let Some(turtle) = world.get_turtle(turtle_id) {
let mut state = turtle.clone(); let mut state = turtle.clone();
@ -359,7 +363,7 @@ pub fn execute_command_with_id(command: &TurtleCommand, turtle_id: usize, world:
} }
/// Add drawing command for a completed tween /// Add drawing command for a completed tween
pub fn add_draw_for_completed_tween( pub(crate) fn add_draw_for_completed_tween(
command: &TurtleCommand, command: &TurtleCommand,
start_state: &TurtleParams, start_state: &TurtleParams,
end_state: &mut TurtleParams, end_state: &mut TurtleParams,

View File

@ -17,7 +17,7 @@ pub enum DrawingFormat {
// Weitere Formate wie Png, Pdf, ... // Weitere Formate wie Png, Pdf, ...
} }
pub trait DrawingExporter { pub(crate) trait DrawingExporter {
/// Export the drawing to the specified format and filename /// Export the drawing to the specified format and filename
/// ///
/// # Errors /// # Errors
@ -26,7 +26,7 @@ pub trait DrawingExporter {
fn export(&self, world: &TurtleWorld, filename: &str) -> Result<(), ExportError>; fn export(&self, world: &TurtleWorld, filename: &str) -> Result<(), ExportError>;
} }
pub fn parse_svg_export_arg() -> Option<String> { pub(crate) fn parse_svg_export_arg() -> Option<String> {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let mut i = 1; let mut i = 1;
while i < args.len() { while i < args.len() {

View File

@ -34,9 +34,9 @@
//! async fn main() { //! async fn main() {
//! let mut plan = create_turtle_plan(); //! let mut plan = create_turtle_plan();
//! plan.forward(100.0).right(90.0).forward(100.0); //! plan.forward(100.0).right(90.0).forward(100.0);
//! //!
//! let mut app = TurtleApp::new().with_commands(plan.build()); //! let mut app = TurtleApp::new().with_commands(plan.build());
//! //!
//! loop { //! loop {
//! clear_background(WHITE); //! clear_background(WHITE);
//! app.update(); //! app.update();
@ -46,30 +46,28 @@
//! } //! }
//! ``` //! ```
pub mod builders; pub(crate) mod builders;
pub mod circle_geometry; pub(crate) mod circle_geometry;
pub mod commands; pub(crate) mod commands;
pub mod commands_channel; pub(crate) mod commands_channel;
pub mod drawing; pub(crate) mod drawing;
pub mod execution; pub(crate) mod execution;
pub mod general; pub(crate) mod general;
pub mod shapes; pub(crate) mod shapes;
pub mod state; pub(crate) mod state;
pub mod tessellation; pub(crate) mod tessellation;
pub mod tweening; pub(crate) mod tweening;
// Re-export commonly used types // Re-export commonly used types
pub use builders::{CurvedMovement, DirectionalMovement, Turnable, TurtlePlan, WithCommands}; pub use builders::{CurvedMovement, DirectionalMovement, Turnable, TurtlePlan, WithCommands};
pub use commands::{CommandQueue, TurtleCommand}; pub use commands::{CommandQueue, TurtleCommand};
pub use commands_channel::{turtle_command_channel, TurtleCommandReceiver, TurtleCommandSender}; pub use commands_channel::TurtleCommandSender;
pub use general::{Angle, AnimationSpeed, Color, Coordinate, Length, Precision}; pub use general::{Angle, AnimationSpeed, Color, Coordinate, Length, Precision};
pub use shapes::{ShapeType, TurtleShape}; pub use shapes::{ShapeType, TurtleShape};
pub use state::{DrawCommand, Turtle, TurtleWorld};
pub use tweening::TweenController;
pub mod export; pub mod export;
#[cfg(feature = "svg")] #[cfg(feature = "svg")]
pub mod export_svg; pub(crate) mod export_svg;
// Re-export the turtle_main macro // Re-export the turtle_main macro
pub use turtle_lib_macros::turtle_main; pub use turtle_lib_macros::turtle_main;
@ -79,6 +77,9 @@ pub use macroquad::prelude::{
vec2, BLACK, BLUE, DARKGRAY, GOLD, GREEN, ORANGE, PURPLE, RED, WHITE, YELLOW, vec2, BLACK, BLUE, DARKGRAY, GOLD, GREEN, ORANGE, PURPLE, RED, WHITE, YELLOW,
}; };
use crate::commands_channel::TurtleCommandReceiver;
use crate::state::TurtleWorld;
use crate::tweening::TweenController;
use macroquad::prelude::*; use macroquad::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
@ -386,12 +387,12 @@ impl TurtleApp {
/// Get reference to the world state /// Get reference to the world state
#[must_use] #[must_use]
pub fn world(&self) -> &TurtleWorld { pub(crate) fn world(&self) -> &TurtleWorld {
&self.world &self.world
} }
/// Get mutable reference to the world state /// Get mutable reference to the world state
pub fn world_mut(&mut self) -> &mut TurtleWorld { pub(crate) fn world_mut(&mut self) -> &mut TurtleWorld {
&mut self.world &mut self.world
} }
} }

View File

@ -8,33 +8,33 @@ use macroquad::prelude::*;
/// State during active fill operation /// State during active fill operation
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FillState { pub(crate) struct FillState {
/// Starting position of the fill /// Starting position of the fill
pub start_position: Coordinate, pub(crate) start_position: Coordinate,
/// All contours collected so far. Each contour is a separate closed path. /// All contours collected so far. Each contour is a separate closed path.
/// The first contour is the outer boundary, subsequent contours are holes. /// The first contour is the outer boundary, subsequent contours are holes.
pub contours: Vec<Vec<Coordinate>>, pub(crate) contours: Vec<Vec<Coordinate>>,
/// Current contour being built (vertices for the active `pen_down` segment) /// Current contour being built (vertices for the active `pen_down` segment)
pub current_contour: Vec<Coordinate>, pub(crate) current_contour: Vec<Coordinate>,
/// Fill color (cached from when `begin_fill` was called) /// Fill color (cached from when `begin_fill` was called)
pub fill_color: Color, pub(crate) fill_color: Color,
} }
/// Parameters that define a turtle's visual state /// Parameters that define a turtle's visual state
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TurtleParams { pub(crate) struct TurtleParams {
pub position: Vec2, pub(crate) position: Vec2,
pub heading: f32, pub(crate) heading: f32,
pub pen_down: bool, pub(crate) pen_down: bool,
pub pen_width: f32, pub(crate) pen_width: f32,
pub color: Color, pub(crate) color: Color,
pub fill_color: Option<Color>, pub(crate) fill_color: Option<Color>,
pub visible: bool, pub(crate) visible: bool,
pub shape: crate::shapes::TurtleShape, pub(crate) shape: crate::shapes::TurtleShape,
pub speed: AnimationSpeed, pub(crate) speed: AnimationSpeed,
} }
impl Default for TurtleParams { impl Default for TurtleParams {
@ -56,18 +56,18 @@ impl Default for TurtleParams {
/// State of a single turtle /// State of a single turtle
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Turtle { pub(crate) struct Turtle {
pub turtle_id: usize, pub(crate) turtle_id: usize,
pub params: TurtleParams, pub(crate) params: TurtleParams,
// Fill tracking // Fill tracking
pub filling: Option<FillState>, pub(crate) filling: Option<FillState>,
// Drawing commands created by this turtle // Drawing commands created by this turtle
pub commands: Vec<DrawCommand>, pub(crate) commands: Vec<DrawCommand>,
// Animation controller for this turtle // Animation controller for this turtle
pub tween_controller: TweenController, pub(crate) tween_controller: TweenController,
} }
impl Default for Turtle { impl Default for Turtle {
@ -259,9 +259,9 @@ impl Turtle {
/// Cached mesh data that can be cloned and converted to Mesh when needed /// Cached mesh data that can be cloned and converted to Mesh when needed
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MeshData { pub(crate) struct MeshData {
pub vertices: Vec<macroquad::prelude::Vertex>, pub(crate) vertices: Vec<macroquad::prelude::Vertex>,
pub indices: Vec<u16>, pub(crate) indices: Vec<u16>,
} }
impl MeshData { impl MeshData {
@ -278,19 +278,19 @@ impl MeshData {
/// Drawable elements in the world /// Drawable elements in the world
/// All drawing is done via Lyon-tessellated meshes for consistency and quality /// All drawing is done via Lyon-tessellated meshes for consistency and quality
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TurtleSource { pub(crate) struct TurtleSource {
pub command: crate::commands::TurtleCommand, pub(crate) command: crate::commands::TurtleCommand,
pub color: Color, pub(crate) color: Color,
pub fill_color: Color, pub(crate) fill_color: Color,
pub pen_width: f32, pub(crate) pen_width: f32,
pub start_position: Vec2, pub(crate) start_position: Vec2,
pub end_position: Vec2, pub(crate) end_position: Vec2,
pub start_heading: f32, pub(crate) start_heading: f32,
pub contours: Option<Vec<Vec<crate::general::Coordinate>>>, pub(crate) contours: Option<Vec<Vec<crate::general::Coordinate>>>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum DrawCommand { pub(crate) enum DrawCommand {
/// Pre-tessellated mesh data (lines, arcs, circles, polygons - all use this) /// Pre-tessellated mesh data (lines, arcs, circles, polygons - all use this)
Mesh { Mesh {
data: MeshData, data: MeshData,
@ -308,11 +308,11 @@ pub enum DrawCommand {
} }
/// The complete turtle world containing all drawing state /// The complete turtle world containing all drawing state
pub struct TurtleWorld { pub(crate) struct TurtleWorld {
/// All turtles in the world (indexed by turtle ID) /// All turtles in the world (indexed by turtle ID)
pub turtles: Vec<Turtle>, pub(crate) turtles: Vec<Turtle>,
pub camera: Camera2D, pub(crate) camera: Camera2D,
pub background_color: Color, pub(crate) background_color: Color,
} }
impl TurtleWorld { impl TurtleWorld {

View File

@ -14,26 +14,30 @@ use macroquad::prelude::*;
/// Convert macroquad Vec2 to Lyon Point /// Convert macroquad Vec2 to Lyon Point
#[must_use] #[must_use]
pub fn to_lyon_point(v: Vec2) -> Point { pub(crate) fn to_lyon_point(v: Vec2) -> Point {
point(v.x, v.y) point(v.x, v.y)
} }
/// Convert Lyon Point to macroquad Vec2 /// Convert Lyon Point to macroquad Vec2
#[allow(dead_code)] #[allow(dead_code)]
#[must_use] #[must_use]
pub fn to_macroquad_vec2(p: Point) -> Vec2 { pub(crate) fn to_macroquad_vec2(p: Point) -> Vec2 {
vec2(p.x, p.y) vec2(p.x, p.y)
} }
/// Simple vertex type for Lyon tessellation /// Simple vertex type for Lyon tessellation
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct SimpleVertex { pub(crate) struct SimpleVertex {
pub position: [f32; 2], pub(crate) position: [f32; 2],
} }
/// Build mesh data from Lyon tessellation /// Build mesh data from Lyon tessellation
#[must_use] #[must_use]
pub fn build_mesh_data(vertices: &[SimpleVertex], indices: &[u16], color: Color) -> MeshData { pub(crate) fn build_mesh_data(
vertices: &[SimpleVertex],
indices: &[u16],
color: Color,
) -> MeshData {
let verts: Vec<Vertex> = vertices let verts: Vec<Vertex> = vertices
.iter() .iter()
.map(|v| Vertex { .map(|v| Vertex {
@ -62,7 +66,7 @@ pub fn build_mesh_data(vertices: &[SimpleVertex], indices: &[u16], color: Color)
/// # Errors /// # Errors
/// ///
/// Returns an error if no vertices are provided or if tessellation fails. /// Returns an error if no vertices are provided or if tessellation fails.
pub fn tessellate_polygon( pub(crate) fn tessellate_polygon(
vertices: &[Vec2], vertices: &[Vec2],
color: Color, color: Color,
) -> Result<MeshData, Box<dyn std::error::Error>> { ) -> Result<MeshData, Box<dyn std::error::Error>> {
@ -107,7 +111,7 @@ pub fn tessellate_polygon(
/// # Errors /// # Errors
/// ///
/// Returns an error if no contours are provided or if tessellation fails. /// Returns an error if no contours are provided or if tessellation fails.
pub fn tessellate_multi_contour( pub(crate) fn tessellate_multi_contour(
contours: &[Vec<Vec2>], contours: &[Vec<Vec2>],
color: Color, color: Color,
) -> Result<MeshData, Box<dyn std::error::Error>> { ) -> Result<MeshData, Box<dyn std::error::Error>> {
@ -203,7 +207,7 @@ pub fn tessellate_multi_contour(
/// # Errors /// # Errors
/// ///
/// Returns an error if no vertices are provided or if tessellation fails. /// Returns an error if no vertices are provided or if tessellation fails.
pub fn tessellate_stroke( pub(crate) fn tessellate_stroke(
vertices: &[Vec2], vertices: &[Vec2],
color: Color, color: Color,
width: f32, width: f32,
@ -249,7 +253,7 @@ pub fn tessellate_stroke(
/// # Errors /// # Errors
/// ///
/// Returns an error if tessellation fails. /// Returns an error if tessellation fails.
pub fn tessellate_circle( pub(crate) fn tessellate_circle(
center: Vec2, center: Vec2,
radius: f32, radius: f32,
color: Color, color: Color,
@ -295,7 +299,7 @@ pub fn tessellate_circle(
/// ///
/// Returns an error if tessellation fails. /// Returns an error if tessellation fails.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn tessellate_arc( pub(crate) fn tessellate_arc(
center: Vec2, center: Vec2,
radius: f32, radius: f32,
start_angle_degrees: f32, start_angle_degrees: f32,

View File

@ -45,22 +45,22 @@ impl From<TweenVec2> for Vec2 {
/// Controls tweening of turtle commands /// Controls tweening of turtle commands
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct TweenController { pub(crate) struct TweenController {
queue: CommandQueue, queue: CommandQueue,
current_tween: Option<CommandTween>, current_tween: Option<CommandTween>,
speed: AnimationSpeed, speed: AnimationSpeed,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CommandTween { pub(crate) struct CommandTween {
pub turtle_id: usize, pub(crate) turtle_id: usize,
pub command: TurtleCommand, pub(crate) command: TurtleCommand,
pub start_time: f64, pub(crate) start_time: f64,
pub duration: f64, pub(crate) duration: f64,
pub start_params: TurtleParams, pub(crate) start_params: TurtleParams,
pub target_params: TurtleParams, pub(crate) target_params: TurtleParams,
pub current_position: Vec2, pub(crate) current_position: Vec2,
pub current_heading: f32, pub(crate) current_heading: f32,
position_tweener: Tweener<TweenVec2, f64, CubicInOut>, position_tweener: Tweener<TweenVec2, f64, CubicInOut>,
heading_tweener: Tweener<f32, f64, CubicInOut>, heading_tweener: Tweener<f32, f64, CubicInOut>,
pen_width_tweener: Tweener<f32, f64, CubicInOut>, pen_width_tweener: Tweener<f32, f64, CubicInOut>,