1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Raylib-backed renderer for the [Cotis](https://crates.io/crates/cotis) UI ecosystem.
//!
//! `cotis-raylib` implements Cotis's `CotisRenderer` and `CotisRendererAsync` traits
//! (from `cotis::renders`) on top of [raylib](https://crates.io/crates/raylib) 6.x.
//! It is the primary render backend used by `cotis-layout` examples.
//!
//! # Quick start
//!
//! For interactive applications, create a [`crate::renderer::RaylibRender`] and wire it into
//! `CotisApp` (from `cotis::cotis_app`) with a layout manager and pipe:
//!
//! ```rust,ignore
//! use cotis::cotis_app::CotisApp;
//! use cotis_layout::preamble::CotisLayoutManager;
//! use cotis_pipes::cotis_layout_pipes::CotisLayoutToRenderListPipeForGenerics;
//! use cotis_raylib::prelude::RaylibRender;
//! use cotis_utils::math::Dimensions;
//!
//! let renderer = RaylibRender::auto_start();
//! let manager = CotisLayoutManager::new(Dimensions::new(1000.0, 800.0));
//! let mut app = CotisApp::new(renderer, manager, CotisLayoutToRenderListPipeForGenerics);
//! // app.compute_frame(...);
//! // while !app.render().window_should_close() { ... }
//! ```
//!
//! Shipped examples use [`crate::renderer::RaylibRender`] directly (not `RayTestRender` from the
//! `test_render` module). Run from the repository root:
//!
//! ```text
//! cargo run -p cotis-raylib --example basic_example
//! ```
//!
//! # Recommended imports
//!
//! Use [`prelude`] for the common entry-point types:
//!
//! ```rust,no_run
//! use cotis_raylib::prelude::{PathBasedImage, RaylibRender, RayRenderHandle};
//! ```
//!
//! # Rendering model
//!
//! [`crate::renderer::RaylibRender`] draws two kinds of command streams:
//!
//! - [`cotis_defaults::render_commands::render_t_list::RenderTList`] — typed heterogeneous command lists
//! produced by layout pipes. Images are preloaded into the renderer cache before drawing.
//! - [`Box<dyn crate::drawables::RaylibDrawable>`] — custom drawables; implement
//! [`crate::drawables::RaylibDrawable`] for types not covered by `cotis-defaults` commands.
//!
//! Extend drawing with [`crate::drawables::RaylibDrawable::scale_by`] (used by `RayTestRender` when the
//! `test-render` feature is enabled) and [`crate::drawables::RaylibDrawable::preload_generic_images`]
//! for path-based images.
//!
//! # Images
//!
//! Path-based assets use [`crate::cotis_defaults_images::PathBasedImage`] (or `JPEGImage`, `PNGImage`,
//! `SVGImage` from `cotis_defaults::generic_image`).
//! [`crate::renderer::RaylibRender::translate_generic_image`] loads textures into an internal cache
//! keyed by file path. `SVGImage` is a semantic path tag only — raylib loads raster data from the path;
//! true vector SVG rendering is not implemented.
//!
//! # Fonts
//!
//! Call [`crate::renderer::RaylibRender::load_font_and_keep`] or
//! [`crate::renderer::RaylibRender::load_font_ex_and_keep`] at startup.
//! The returned ID (0-based, assigned in load order) is stored in `TextConfig::font_id`
//! (`cotis_defaults::element_configs::text_config::TextConfig`).
//! Additional pixel sizes are loaded lazily at the start of each frame.
//!
//! # Features
//!
//! | Feature | Effect |
//! |---------|--------|
//! | `test-render` | Exposes the `test_render` module for scaled/headless-style testing. |
//! | `complex-color` | Enables gradient and layered fills (requires `cotis-defaults/complex_color`). |
//!
//! # Thread safety
//!
//! The raylib handle is wrapped in `Arc<Mutex<RayRenderHandle>>` ([`crate::renderer::RayRenderHandle`])
//! so it can be shared for input polling. `RaylibThread` (from the `raylib` crate) is owned by
//! [`crate::renderer::RaylibRender`] and must be used for drawing on the thread that created the window.
//! All mutex locks **panic** if the mutex is poisoned.
//!
//! # When to use `RayTestRender`
//!
//! With the `test-render` feature, `RayTestRender` wraps [`crate::renderer::RaylibRender`] to render at a logical resolution while keeping a smaller physical
//! window (`dimensions / scale`). Use it for CI snapshots and headless-style tests — not as the default
//! for interactive applications.
/// Scaled rendering wrapper for tests (requires `test-render` feature).