use crate::ecs::EditorWorld;
use nightshade::ecs::lines::components::{Line, Lines};
use nightshade::ecs::world::{GLOBAL_TRANSFORM, LINES, SKIN, VISIBILITY};
use nightshade::prelude::*;
use std::collections::HashSet;
pub fn update(editor_world: &mut EditorWorld, world: &mut World) {
if !editor_world.resources.skeleton_debug.enabled {
if let Some(entity) = editor_world.resources.skeleton_debug.entity
&& let Some(data) = world.core.get_lines(entity)
&& !data.lines.is_empty()
{
world
.core
.set_lines(entity, Lines::new_always_on_top(Vec::new()));
}
return;
}
let entity = ensure_debug_entity(editor_world, world);
let lines = build_skeleton_lines(world, &editor_world.resources.skeleton_debug);
world
.core
.set_lines(entity, Lines::new_always_on_top(lines));
}
fn ensure_debug_entity(editor_world: &mut EditorWorld, world: &mut World) -> Entity {
if let Some(entity) = editor_world.resources.skeleton_debug.entity
&& world.core.entity_has_components(entity, LINES)
{
return entity;
}
let entity = spawn_entities(world, LINES | VISIBILITY | GLOBAL_TRANSFORM, 1)[0];
world
.core
.set_lines(entity, Lines::new_always_on_top(Vec::new()));
world
.core
.set_visibility(entity, Visibility { visible: true });
world
.core
.set_global_transform(entity, GlobalTransform::default());
editor_world
.resources
.editor_scene
.register_scaffolding(entity);
editor_world.resources.skeleton_debug.entity = Some(entity);
entity
}
fn build_skeleton_lines(world: &World, settings: &crate::ecs::SkeletonDebugState) -> Vec<Line> {
let skin_owners: Vec<Entity> = world.core.query_entities(SKIN).collect();
let mut lines = Vec::new();
for owner in skin_owners {
let Some(skin) = world.core.get_skin(owner) else {
continue;
};
if skin.joints.is_empty() {
continue;
}
let joint_set: HashSet<Entity> = skin.joints.iter().copied().collect();
for &joint_entity in &skin.joints {
let Some(joint_transform) = world.core.get_global_transform(joint_entity) else {
continue;
};
let joint_position = joint_transform.translation();
push_joint_cross(
&mut lines,
joint_position,
settings.joint_size,
settings.joint_color,
);
let Some(parent) = world
.core
.get_parent(joint_entity)
.and_then(|parent| parent.0)
else {
continue;
};
if !joint_set.contains(&parent) {
continue;
}
let Some(parent_transform) = world.core.get_global_transform(parent) else {
continue;
};
lines.push(Line {
start: parent_transform.translation(),
end: joint_position,
color: settings.bone_color,
});
}
}
lines
}
fn push_joint_cross(lines: &mut Vec<Line>, position: Vec3, size: f32, color: Vec4) {
let half = size * 0.5;
lines.push(Line {
start: position - Vec3::new(half, 0.0, 0.0),
end: position + Vec3::new(half, 0.0, 0.0),
color,
});
lines.push(Line {
start: position - Vec3::new(0.0, half, 0.0),
end: position + Vec3::new(0.0, half, 0.0),
color,
});
lines.push(Line {
start: position - Vec3::new(0.0, 0.0, half),
end: position + Vec3::new(0.0, 0.0, half),
color,
});
}