nightshade_api/
hierarchy.rs1use nightshade::ecs::transform::queries::query_descendants;
7use nightshade::ecs::world::{GLOBAL_TRANSFORM, LOCAL_TRANSFORM};
8use nightshade::prelude::*;
9use serde::{Deserialize, Serialize};
10use std::collections::{HashMap, HashSet};
11
12pub fn name(world: &World, entity: Entity) -> String {
14 world
15 .core
16 .get_name(entity)
17 .map(|name| name.0.clone())
18 .filter(|name| !name.is_empty())
19 .unwrap_or_else(|| format!("Entity {}", entity.id))
20}
21
22pub fn set_name(world: &mut World, entity: Entity, name: &str) {
24 world.core.set_name(entity, Name(name.to_string()));
25}
26
27pub fn children(world: &World, entity: Entity) -> Vec<Entity> {
29 let mut found: Vec<Entity> = Vec::new();
30 world
31 .core
32 .query()
33 .with(LOCAL_TRANSFORM)
34 .iter(|candidate, _, _| {
35 if world.core.get_parent(candidate).and_then(|parent| parent.0) == Some(entity) {
36 found.push(candidate);
37 }
38 });
39 found.sort_by_key(|entity| entity.id);
40 found
41}
42
43pub fn descendants(world: &World, entity: Entity) -> Vec<Entity> {
45 query_descendants(world, entity)
46}
47
48pub fn roots(world: &World) -> Vec<Entity> {
50 let mut found: Vec<Entity> = Vec::new();
51 world
52 .core
53 .query()
54 .with(LOCAL_TRANSFORM | GLOBAL_TRANSFORM)
55 .iter(|entity, _, _| {
56 if world
57 .core
58 .get_parent(entity)
59 .and_then(|parent| parent.0)
60 .is_none()
61 {
62 found.push(entity);
63 }
64 });
65 found.sort_by_key(|entity| entity.id);
66 found
67}
68
69#[derive(Clone, PartialEq, Serialize, Deserialize)]
71pub struct SceneRow {
72 pub id: u32,
73 pub name: String,
74 pub depth: u32,
75 pub has_children: bool,
76 pub camera: bool,
77 pub light: bool,
78 pub mesh: bool,
79}
80
81pub fn scene_tree(world: &World) -> Vec<SceneRow> {
84 let mut all: HashSet<Entity> = HashSet::new();
85 world
86 .core
87 .query()
88 .with(LOCAL_TRANSFORM | GLOBAL_TRANSFORM)
89 .iter(|entity, _, _| {
90 all.insert(entity);
91 });
92
93 let mut children_map: HashMap<Entity, Vec<Entity>> = HashMap::new();
94 let mut root_entities: Vec<Entity> = Vec::new();
95 for &entity in &all {
96 let parent = world
97 .core
98 .get_parent(entity)
99 .and_then(|parent| parent.0)
100 .filter(|parent| all.contains(parent));
101 match parent {
102 Some(parent) => children_map.entry(parent).or_default().push(entity),
103 None => root_entities.push(entity),
104 }
105 }
106 root_entities.sort_by_key(|entity| entity.id);
107 for list in children_map.values_mut() {
108 list.sort_by_key(|entity| entity.id);
109 }
110
111 let mut rows = Vec::new();
112 let mut visited: HashSet<Entity> = HashSet::new();
113 let mut stack: Vec<(Entity, u32)> = root_entities
114 .iter()
115 .rev()
116 .map(|entity| (*entity, 0))
117 .collect();
118 while let Some((entity, depth)) = stack.pop() {
119 if !visited.insert(entity) {
120 continue;
121 }
122 let has_children = children_map
123 .get(&entity)
124 .is_some_and(|list| !list.is_empty());
125 rows.push(SceneRow {
126 id: entity.id,
127 name: name(world, entity),
128 depth,
129 has_children,
130 camera: world.core.entity_has_camera(entity),
131 light: world.core.entity_has_light(entity),
132 mesh: world.core.entity_has_render_mesh(entity),
133 });
134 if let Some(list) = children_map.get(&entity) {
135 for child in list.iter().rev() {
136 if !visited.contains(child) {
137 stack.push((*child, depth + 1));
138 }
139 }
140 }
141 }
142 rows
143}