1#![allow(dead_code)]
2
3use mittens_engine::engine::{
4 self,
5 ecs::component::{ColorComponent, TransparentCutoutComponent},
6};
7
8pub fn spawn_mms_demo_rig(
16 universe: &mut engine::Universe,
17 cam_pos: [f32; 3],
18) -> engine::ecs::ComponentId {
19 use engine::ecs::component::{
20 BackgroundColorComponent, Camera3DComponent, InputComponent, InputTransformModeComponent,
21 TransformComponent,
22 };
23
24 let bg_color = universe
26 .world
27 .add_component(BackgroundColorComponent::new());
28 let bg_color_c = universe
29 .world
30 .add_component(ColorComponent::rgba(0.02, 0.03, 0.10, 1.0));
31 let _ = universe.world.add_child(bg_color, bg_color_c);
32 universe.add(bg_color);
33
34 let input = universe
36 .world
37 .add_component(InputComponent::new().with_speed(3.0));
38 let input_mode = universe
39 .world
40 .add_component(InputTransformModeComponent::forward_z().with_roll_axis_y());
41 let _ = universe.attach(input, input_mode);
42
43 let cam_transform = universe
44 .world
45 .add_component(TransformComponent::new().with_position(cam_pos[0], cam_pos[1], cam_pos[2]));
46 let _ = universe.attach(input, cam_transform);
47
48 let camera = universe.world.add_component(Camera3DComponent::new());
49 let _ = universe.attach(cam_transform, camera);
50
51 universe.add(input);
52
53 spawn_desktop_camera_controls_hint(universe, cam_transform);
54
55 cam_transform
56}
57
58fn hash_u32(mut x: u32) -> u32 {
59 x ^= x >> 16;
60 x = x.wrapping_mul(0x7feb_352d);
61 x ^= x >> 15;
62 x = x.wrapping_mul(0x846c_a68b);
63 x ^= x >> 16;
64 x
65}
66
67fn rand01(seed: u32) -> f32 {
68 (hash_u32(seed) as f32) / (u32::MAX as f32)
69}
70
71#[derive(Debug, Clone, Copy)]
72pub struct CloudRingParams {
73 pub cloud_count: u32,
74 pub radius: f32,
75 pub center_y: f32,
76 pub puffs_per_cloud: u32,
77 pub angle_jitter: f32,
79 pub high_y_probability: f32,
81 pub high_y_multiplier: f32,
83 pub seed: u32,
85}
86
87impl Default for CloudRingParams {
88 fn default() -> Self {
89 Self {
90 cloud_count: 5,
91 radius: 26.0,
92 center_y: 2.0,
93 puffs_per_cloud: 28,
94 angle_jitter: 0.0,
95 high_y_probability: 0.0,
96 high_y_multiplier: 1.0,
97 seed: 0xC10u32,
98 }
99 }
100}
101
102pub fn spawn_cloud_ring(
106 universe: &mut engine::Universe,
107 bg_root: engine::ecs::ComponentId,
108 p: CloudRingParams,
109) {
110 if p.cloud_count == 0 || p.radius == 0.0 {
111 return;
112 }
113
114 let cube_mesh = universe
115 .render_assets
116 .get_mesh(engine::graphics::BuiltinMeshType::Cube);
117
118 let step = std::f32::consts::TAU / (p.cloud_count as f32);
119 let angle_jitter = p.angle_jitter.clamp(0.0, 1.0);
120 let high_y_probability = p.high_y_probability.clamp(0.0, 1.0);
121
122 for i in 0..p.cloud_count {
123 let seed_i = p.seed ^ i.wrapping_mul(0x9E37_79B9);
124 let jitter = (rand01(seed_i ^ 0xa53a_9d2d) - 0.5) * step * angle_jitter;
125 let a = (i as f32) * step + jitter;
126 let cx = p.radius * a.cos();
127 let cz = p.radius * a.sin();
128
129 let cy = if rand01(seed_i ^ 0x7f4a_7c15) < high_y_probability {
130 p.center_y * p.high_y_multiplier
131 } else {
132 p.center_y
133 };
134
135 let center_tx = universe.world.add_component(
136 engine::ecs::component::TransformComponent::new().with_position(cx, cy, cz),
137 );
138 let _ = universe.attach(bg_root, center_tx);
139
140 let base_seed = seed_i ^ 0x243f_6a88;
141 for puff_i in 0..p.puffs_per_cloud {
142 let seed = base_seed ^ puff_i.wrapping_mul(1_103_515_245);
143
144 let ox = (rand01(seed ^ 0x68bc_21eb) - 0.5) * 9.0;
145 let oy = (rand01(seed ^ 0x02e5_be93) - 0.5) * 4.0;
146 let oz = (rand01(seed ^ 0xa1d3_4f2b) - 0.5) * 9.0;
147
148 let base = 0.7 + rand01(seed ^ 0x9e37_79b9) * 2.8;
149 let sx = base * (0.7 + rand01(seed ^ 0x243f_6a88) * 0.9);
150 let sy = base * (0.6 + rand01(seed ^ 0x85a3_08d3) * 1.0);
151 let sz = base * (0.7 + rand01(seed ^ 0x1319_8a2e) * 0.9);
152
153 let tx = universe.world.add_component(
154 engine::ecs::component::TransformComponent::new()
155 .with_position(ox, oy, oz)
156 .with_scale(sx, sy, sz),
157 );
158 let renderable =
159 universe
160 .world
161 .add_component(engine::ecs::component::RenderableComponent::new(
162 engine::graphics::primitives::Renderable::new(
163 cube_mesh,
164 engine::graphics::primitives::MaterialHandle::TOON_MESH,
165 ),
166 ));
167
168 let t = rand01(seed ^ 0x7f4a_7c15);
169 let r = 0.70 + 0.10 * t;
170 let g = 0.72 + 0.10 * t;
171 let b = 0.80 + 0.12 * t;
172 let color = universe
173 .world
174 .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
175
176 let _ = universe.attach(center_tx, tx);
177 let _ = universe.attach(tx, renderable);
178 let _ = universe.attach(renderable, color);
179 }
180 }
181}
182
183pub fn spawn_desktop_camera_controls_hint(
191 universe: &mut engine::Universe,
192 camera_transform: engine::ecs::ComponentId,
193) -> engine::ecs::ComponentId {
194 use engine::ecs::component::{
195 ColorComponent, EditorComponent, EmissiveComponent, RaycastableComponent, TextComponent,
196 TextureFilteringComponent, TransformComponent,
197 };
198
199 let (cam_pos, cam_rot) = universe
205 .world
206 .get_component_by_id_as::<TransformComponent>(camera_transform)
207 .map(|t| (t.transform.translation, t.transform.rotation))
208 .unwrap_or(([0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]));
209
210 let local_offset = [0.65, 0.25, -1.7];
213
214 let world_offset = mittens_engine::utils::math::quat_rotate_vec3(cam_rot, local_offset);
216 let world_pos = [
217 cam_pos[0] + world_offset[0],
218 cam_pos[1] + world_offset[1],
219 cam_pos[2] + world_offset[2],
220 ];
221
222 let hint_root = universe.world.add_component(
223 TransformComponent::new()
224 .with_position(world_pos[0], world_pos[1], world_pos[2])
225 .with_scale(0.055, 0.055, 1.0),
226 );
227
228 let editor_root = universe.world.add_component(EditorComponent::new());
230 let _ = universe.attach(hint_root, editor_root);
231
232 let text = universe.world.add_component(TextComponent::new(
233 "use wasd/rf/qe\nand right-mouse\nclick and drag\nto move/look",
234 ));
235
236 let raycastable = universe
239 .world
240 .add_component(RaycastableComponent::enabled());
241 let _ = universe.attach(text, raycastable);
242
243 let color = universe
245 .world
246 .add_component(ColorComponent::rgba(0.0, 0.0, 0.0, 1.0));
247 let _ = universe.attach(text, color);
248
249 let emissive = universe.world.add_component(EmissiveComponent::on());
251 let filtering = universe
252 .world
253 .add_component(TextureFilteringComponent::nearest_magnification());
254
255 let cutout = universe
256 .world
257 .add_component(TransparentCutoutComponent::new());
258 let _ = universe.attach(text, cutout);
259
260 let _ = universe.attach(editor_root, text);
261 let _ = universe.attach(text, emissive);
262 let _ = universe.attach(text, filtering);
263
264 universe.add(hint_root);
266
267 hint_root
268}