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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! `bevy_symbios_texture` — procedural texture generation for Bevy.
//!
//! # Crate split
//!
//! The pure, Bevy-free generation core lives in the [`symbios_texture`] crate
//! (every generator module, its `Config`/`Generator` types, the
//! [`TextureGenerator`] trait, the [`TextureMap`] pipeline, [`ToroidalNoise`],
//! the [`sprite`]/[`surface`] kits, the per-config genetics, and the
//! registry). This wrapper re-exports that core wholesale and adds the
//! Bevy-coupled layer: the [`SymbiosTexturePlugin`], the async generation
//! pool, the `bevy` `Image` upload adapters, the
//! [`TextureCache`] resource, the procedural-material builder, and the egui
//! UI. The public API is unchanged across the split.
//!
//! # Generators
//!
//! **Tileable surface textures** (bark, rock, ground, brick, plank, concrete,
//! metal, shingle, pavers, stucco, ashlar, cobblestone, thatch, marble,
//! corrugated, asphalt, wainscoting, encaustic, fabric, sand, snow, ice,
//! lava, moss, lichen, cactus skin): wrap seamlessly via toroidal 4-D noise
//! mapping. Upload with [`map_to_images`] to get repeat-wrapping samplers.
//! `lava` additionally produces an emissive (glow) map.
//!
//! **Alpha-masked cards** (leaf, twig, window, stained_glass, iron_grille,
//! chain_link, log_end): produce silhouettes with per-pixel alpha that must
//! not tile. Upload with [`map_to_images_card`] to get clamp-to-edge
//! samplers.
//!
//! **Sprite atlases** — particle sprites (soft_disc, spark, snowflake,
//! puff, ring, petal, shard, flame, flower) and foliage billboards
//! (leaf_sprite, grass tuft, frond, reed, needle, broadleaf): alpha-silhouette
//! cards for billboards. Each can bake a `variant_rows × variant_cols`
//! atlas where every cell renders a per-cell-seeded variant of the same
//! config — one bake gives a particle system per-particle shape variety via
//! random atlas frames; the foliage billboards default to a single `1 × 1`
//! card. Shared conventions live in [`sprite`]; upload with
//! [`map_to_images_card`].
//!
//! # Architecture
//! Every generator implements [`TextureGenerator`], which produces a
//! [`TextureMap`] (raw pixel buffers for albedo, normal, roughness/ORM, and
//! an optional emissive map).
//!
//! Seamless tiling for surface textures is guaranteed by the [`ToroidalNoise`]
//! wrapper, which maps 2-D UV coordinates to a 4-D torus so noise wraps at
//! every edge with no seam.
//!
//! Both upload functions generate a full mipmap chain with type-correct
//! averaging: sRGB-linear averaging for albedo, renormalized averaging for
//! normal maps, and direct linear averaging for ORM maps.
//!
//! # Plugin & async generation
//! [`SymbiosTexturePlugin`] registers the polling systems and applies an
//! [`AsyncTextureConfig`] to a private rayon thread pool dedicated to
//! texture generation. Spawn [`async_gen::PendingTexture`] components to
//! offload work; the result lands on the entity as
//! [`async_gen::TextureReady`].
//!
//! # Procedural materials
//! [`build_procedural_material_async`] is a one-shot helper that returns a
//! `Handle<StandardMaterial>` immediately and patches the generated textures
//! in once the background task completes. Pair with an optional
//! [`TextureCache`] resource to avoid regenerating identical configs.
//!
//! # Animated parameters
//! [`AnimatedProceduralMaterial`] drives time-varying texture parameters by
//! re-evaluating a closure each frame, regenerating only when the
//! fingerprint of the resulting [`TextureConfig`] changes (with a
//! configurable wall-clock cooldown).
//!
//! # Genetics
//! All config types implement `symbios_genetics::Genotype` (see [`genetics`]),
//! making them compatible with evolutionary search algorithms such as
//! `SimpleGA`, `Nsga2`, and `MapElites` from the `symbios-genetics` crate.
//!
//! [`TextureCache`]: cache::TextureCache
//! [`TextureConfig`]: material::TextureConfig
// Re-export the entire Bevy-free core so the public module paths
// (`bevy_symbios_texture::ashlar`, `::sprite`, `::genetics`, …) and every
// pure `Config`/`Generator`/helper type are preserved exactly. The wrapper's
// own `generator` module below shadows the core's `generator` in this glob
// (it re-exports the core items and adds the Bevy upload adapters), so
// `bevy_symbios_texture::generator` is the merged view.
pub use *;
// Bevy-coupled modules kept in the wrapper.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ToroidalNoise;
pub use ;
pub use ;
pub use ;
use *;
/// Bevy plugin — registers the async-generation polling system and applies
/// the [`AsyncTextureConfig`] to the private texture-generation thread pool.
///
/// Construct via [`Default`] for the standard [`DEFAULT_POOL_THREADS`] cap,
/// or set [`SymbiosTexturePlugin::config`] explicitly for custom pool sizing:
///
/// ```rust,ignore
/// app.add_plugins(SymbiosTexturePlugin {
/// config: AsyncTextureConfig { pool_threads: 0 }, // auto = cores / 2
/// });
/// ```
///
/// The pool configuration is applied at plugin-build time and frozen on the
/// first generation request — re-adding the plugin with a different config
/// after a task has been dispatched has no effect.