1use crate::runner::{
9 DRAW_CUBE_POOL, DRAW_LINES_POOL, DRAW_MATERIAL, DRAW_SPHERE_POOL, lookup_named, register_named,
10};
11use nightshade::prelude::nalgebra_glm::Quat;
12use nightshade::prelude::*;
13
14pub fn draw_cube(world: &mut World, position: Vec3, scale: Vec3, color: [f32; 4]) {
16 push_instance(
17 world,
18 DRAW_CUBE_POOL,
19 InstanceTransform::new(position, Quat::identity(), scale),
20 color,
21 );
22}
23
24pub fn draw_sphere(world: &mut World, position: Vec3, radius: f32, color: [f32; 4]) {
26 push_instance(
27 world,
28 DRAW_SPHERE_POOL,
29 InstanceTransform::new(
30 position,
31 Quat::identity(),
32 Vec3::new(radius, radius, radius),
33 ),
34 color,
35 );
36}
37
38pub fn draw_line(world: &mut World, start: Vec3, end: Vec3, color: [f32; 4]) {
40 let Some(entity) = lookup_named(world, DRAW_LINES_POOL) else {
41 return;
42 };
43 if let Some(lines) = world.core.get_lines_mut(entity) {
44 lines.push(Line {
45 start,
46 end,
47 color: Vec4::new(color[0], color[1], color[2], color[3]),
48 });
49 }
50}
51
52pub fn draw_text_3d(world: &mut World, text: &str, position: Vec3) {
57 for (index, name) in TEXT_POOL_NAMES.iter().enumerate() {
58 match lookup_named(world, name) {
59 Some(entity) => {
60 let parked = world
61 .core
62 .get_local_transform(entity)
63 .is_some_and(|transform| transform.translation.y < PARKED_THRESHOLD);
64 if parked || index == TEXT_POOL_NAMES.len() - 1 {
65 crate::text::set_text(world, entity, text);
66 crate::placement::set_position(world, entity, position);
67 return;
68 }
69 }
70 None => {
71 let entity = crate::text::spawn_label(world, text, position);
72 world.core.add_components(entity, NAME);
73 world.core.set_name(entity, Name(name.to_string()));
74 register_named(world, name, entity);
75 return;
76 }
77 }
78 }
79}
80
81pub fn spawn_lines(world: &mut World, lines: Vec<Line>) -> Entity {
84 let entity = spawn_entities(world, LINES | VISIBILITY | GLOBAL_TRANSFORM, 1)[0];
85 world.core.set_lines(entity, Lines::new(lines));
86 entity
87}
88
89fn push_instance(
90 world: &mut World,
91 pool_name: &str,
92 transform: InstanceTransform,
93 color: [f32; 4],
94) {
95 let Some(entity) = lookup_named(world, pool_name) else {
96 return;
97 };
98 if let Some(instanced) = world.core.get_instanced_mesh_mut(entity) {
99 instanced.add_instance(transform);
100 let index = instanced.instance_count() - 1;
101 instanced.set_instance_tint(index, color);
102 }
103}
104
105pub(crate) fn initialize_draw_pools(world: &mut World) {
106 crate::scene::ensure_primitive_mesh(world, "Cube");
107 crate::scene::ensure_primitive_mesh(world, "Sphere");
108
109 material_registry_insert(
110 &mut world.resources.assets.material_registry,
111 DRAW_MATERIAL.to_string(),
112 Material::default(),
113 );
114 if let Some((index, _)) = registry_lookup_index(
115 &world.resources.assets.material_registry.registry,
116 DRAW_MATERIAL,
117 ) {
118 registry_add_reference(
119 &mut world.resources.assets.material_registry.registry,
120 index,
121 );
122 }
123
124 let cube_pool = spawn_instanced_mesh_with_material(world, "Cube", Vec::new(), DRAW_MATERIAL);
125 world
126 .core
127 .set_name(cube_pool, Name(DRAW_CUBE_POOL.to_string()));
128 register_named(world, DRAW_CUBE_POOL, cube_pool);
129 let sphere_pool =
130 spawn_instanced_mesh_with_material(world, "Sphere", Vec::new(), DRAW_MATERIAL);
131 world
132 .core
133 .set_name(sphere_pool, Name(DRAW_SPHERE_POOL.to_string()));
134 register_named(world, DRAW_SPHERE_POOL, sphere_pool);
135
136 let lines_pool = spawn_entities(world, LINES | NAME | VISIBILITY | GLOBAL_TRANSFORM, 1)[0];
137 world
138 .core
139 .set_name(lines_pool, Name(DRAW_LINES_POOL.to_string()));
140 world.core.set_lines(lines_pool, Lines::new(Vec::new()));
141 register_named(world, DRAW_LINES_POOL, lines_pool);
142}
143
144pub(crate) fn clear_draw_pools(world: &mut World) {
145 for pool_name in [DRAW_CUBE_POOL, DRAW_SPHERE_POOL] {
146 if let Some(entity) = lookup_named(world, pool_name)
147 && let Some(instanced) = world.core.get_instanced_mesh_mut(entity)
148 && instanced.instance_count() > 0
149 {
150 instanced.clear_instances();
151 }
152 }
153 if let Some(entity) = lookup_named(world, DRAW_LINES_POOL)
154 && let Some(lines) = world.core.get_lines_mut(entity)
155 && !lines.lines.is_empty()
156 {
157 lines.clear();
158 }
159 for name in TEXT_POOL_NAMES.iter() {
160 let Some(entity) = lookup_named(world, name) else {
161 break;
162 };
163 let used = world
164 .core
165 .get_local_transform(entity)
166 .is_some_and(|transform| transform.translation.y > PARKED_THRESHOLD);
167 if used {
168 crate::placement::set_position(world, entity, Vec3::new(0.0, -100000.0, 0.0));
169 }
170 }
171}
172
173const PARKED_THRESHOLD: f32 = -90000.0;
174
175const TEXT_POOL_NAMES: [&str; 64] = [
176 "api::draw::text::0",
177 "api::draw::text::1",
178 "api::draw::text::2",
179 "api::draw::text::3",
180 "api::draw::text::4",
181 "api::draw::text::5",
182 "api::draw::text::6",
183 "api::draw::text::7",
184 "api::draw::text::8",
185 "api::draw::text::9",
186 "api::draw::text::10",
187 "api::draw::text::11",
188 "api::draw::text::12",
189 "api::draw::text::13",
190 "api::draw::text::14",
191 "api::draw::text::15",
192 "api::draw::text::16",
193 "api::draw::text::17",
194 "api::draw::text::18",
195 "api::draw::text::19",
196 "api::draw::text::20",
197 "api::draw::text::21",
198 "api::draw::text::22",
199 "api::draw::text::23",
200 "api::draw::text::24",
201 "api::draw::text::25",
202 "api::draw::text::26",
203 "api::draw::text::27",
204 "api::draw::text::28",
205 "api::draw::text::29",
206 "api::draw::text::30",
207 "api::draw::text::31",
208 "api::draw::text::32",
209 "api::draw::text::33",
210 "api::draw::text::34",
211 "api::draw::text::35",
212 "api::draw::text::36",
213 "api::draw::text::37",
214 "api::draw::text::38",
215 "api::draw::text::39",
216 "api::draw::text::40",
217 "api::draw::text::41",
218 "api::draw::text::42",
219 "api::draw::text::43",
220 "api::draw::text::44",
221 "api::draw::text::45",
222 "api::draw::text::46",
223 "api::draw::text::47",
224 "api::draw::text::48",
225 "api::draw::text::49",
226 "api::draw::text::50",
227 "api::draw::text::51",
228 "api::draw::text::52",
229 "api::draw::text::53",
230 "api::draw::text::54",
231 "api::draw::text::55",
232 "api::draw::text::56",
233 "api::draw::text::57",
234 "api::draw::text::58",
235 "api::draw::text::59",
236 "api::draw::text::60",
237 "api::draw::text::61",
238 "api::draw::text::62",
239 "api::draw::text::63",
240];