use crate::ecs::generational_registry::registry_entry_by_name_mut;
use crate::prelude::*;
use super::GizmoState;
use super::lifecycle::{hide_entities, set_entity_visible_recursive, show_entities};
pub fn check_gizmo_axis_hit(
world: &World,
gizmo: &GizmoState,
picked_entity: Entity,
) -> Option<Vec3> {
let axes = [
(
gizmo.axis_entities.x_axis,
nalgebra_glm::vec3(1.0, 0.0, 0.0),
),
(
gizmo.axis_entities.y_axis,
nalgebra_glm::vec3(0.0, 1.0, 0.0),
),
(
gizmo.axis_entities.z_axis,
nalgebra_glm::vec3(0.0, 0.0, 1.0),
),
];
for (axis_entity, axis_vec) in axes.iter() {
if let Some(entity) = axis_entity
&& (picked_entity == *entity || is_child_of(world, picked_entity, *entity))
{
return Some(*axis_vec);
}
}
if let Some(center_entity) = gizmo.axis_entities.center_cube
&& (picked_entity == center_entity || is_child_of(world, picked_entity, center_entity))
{
return Some(nalgebra_glm::vec3(1.0, 1.0, 1.0));
}
let planes = [
(
gizmo.axis_entities.xy_plane,
nalgebra_glm::vec3(1.1, 1.1, 0.0),
),
(
gizmo.axis_entities.yz_plane,
nalgebra_glm::vec3(0.0, 1.1, 1.1),
),
(
gizmo.axis_entities.xz_plane,
nalgebra_glm::vec3(1.1, 0.0, 1.1),
),
];
for (plane_entity, plane_vec) in planes.iter() {
if let Some(entity) = plane_entity
&& (picked_entity == *entity || is_child_of(world, picked_entity, *entity))
{
return Some(*plane_vec);
}
}
None
}
fn is_child_of(world: &World, child: Entity, parent: Entity) -> bool {
let mut current = child;
while let Some(parent_comp) = world.core.get_parent(current) {
if let Some(parent_entity) = parent_comp.0 {
if parent_entity == parent {
return true;
}
current = parent_entity;
} else {
break;
}
}
false
}
fn set_entity_material_color(world: &mut World, entity: Entity, color: [f32; 4]) {
if let Some(material_ref) = world.core.get_material_ref(entity) {
let name = material_ref.name.clone();
if let Some(material) =
registry_entry_by_name_mut(&mut world.resources.material_registry.registry, &name)
{
material.base_color = color;
world
.resources
.mesh_render_state
.mark_material_dirty(entity);
}
}
}
pub fn highlight_gizmo_axis(world: &mut World, gizmo: &GizmoState, axis: Option<Vec3>) {
let axis_entities = &gizmo.axis_entities;
let axes = [
(axis_entities.x_axis, [0.7, 0.0, 0.0, 1.0]),
(axis_entities.y_axis, [0.0, 0.7, 0.0, 1.0]),
(axis_entities.z_axis, [0.0, 0.0, 0.7, 1.0]),
];
let highlighted_axis = axis.and_then(|a| {
if a.x > 0.5 && a.y < 0.1 && a.z < 0.1 {
Some(0)
} else if a.y > 0.5 && a.x < 0.1 && a.z < 0.1 {
Some(1)
} else if a.z > 0.5 && a.x < 0.1 && a.y < 0.1 {
Some(2)
} else {
None
}
});
let center_highlighted = axis.is_some_and(|a| a.x > 0.9 && a.y > 0.9 && a.z > 0.9);
let (xy_highlighted, yz_highlighted, xz_highlighted) =
axis.map_or((false, false, false), |a| {
if a.x > 1.05 && a.y > 1.05 {
(true, false, false)
} else if a.y > 1.05 && a.z > 1.05 {
(false, true, false)
} else if a.x > 1.05 && a.z > 1.05 {
(false, false, true)
} else {
(false, false, false)
}
});
for (index, (axis_entity, color)) in axes.iter().enumerate() {
if let Some(entity) = axis_entity {
let is_highlighted = Some(index) == highlighted_axis;
let base_color = if is_highlighted {
[1.0, 1.0, 0.0, 1.0]
} else {
*color
};
let children: Vec<Entity> =
crate::ecs::transform::queries::query_children(world, *entity);
for child in children {
set_entity_material_color(world, child, base_color);
}
}
}
if let Some(center_entity) = axis_entities.center_cube {
let color = if center_highlighted {
[1.0, 1.0, 0.0, 1.0]
} else {
[0.6, 0.6, 0.6, 1.0]
};
set_entity_material_color(world, center_entity, color);
}
if let Some(xy_plane) = axis_entities.xy_plane {
let color = if xy_highlighted {
[1.0, 1.0, 0.0, 0.7]
} else {
[0.4, 0.4, 0.0, 0.4]
};
set_entity_material_color(world, xy_plane, color);
}
if let Some(yz_plane) = axis_entities.yz_plane {
let color = if yz_highlighted {
[1.0, 1.0, 0.0, 0.7]
} else {
[0.0, 0.4, 0.4, 0.4]
};
set_entity_material_color(world, yz_plane, color);
}
if let Some(xz_plane) = axis_entities.xz_plane {
let color = if xz_highlighted {
[1.0, 1.0, 0.0, 0.7]
} else {
[0.4, 0.0, 0.4, 0.4]
};
set_entity_material_color(world, xz_plane, color);
}
}
#[derive(Clone, Copy)]
pub enum GizmoDragMode {
None,
Axis(Vec3),
Plane(Vec3),
Free,
}
pub fn set_gizmo_drag_visibility(world: &mut World, gizmo: &GizmoState, drag_mode: GizmoDragMode) {
let axis_entities = &gizmo.axis_entities;
match drag_mode {
GizmoDragMode::None => {
if let Some(x_axis) = axis_entities.x_axis {
set_entity_visible_recursive(world, x_axis, true);
}
if let Some(y_axis) = axis_entities.y_axis {
set_entity_visible_recursive(world, y_axis, true);
}
if let Some(z_axis) = axis_entities.z_axis {
set_entity_visible_recursive(world, z_axis, true);
}
if let Some(xy_plane) = axis_entities.xy_plane {
set_entity_visible_recursive(world, xy_plane, true);
}
if let Some(yz_plane) = axis_entities.yz_plane {
set_entity_visible_recursive(world, yz_plane, true);
}
if let Some(xz_plane) = axis_entities.xz_plane {
set_entity_visible_recursive(world, xz_plane, true);
}
if let Some(center_cube) = axis_entities.center_cube {
set_entity_visible_recursive(world, center_cube, true);
}
if let Some(x_line) = axis_entities.x_axis_line {
hide_entities(world, &[x_line]);
}
if let Some(y_line) = axis_entities.y_axis_line {
hide_entities(world, &[y_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
hide_entities(world, &[z_line]);
}
}
GizmoDragMode::Axis(axis) => {
let mut all_parts = Vec::new();
if let Some(x_axis) = axis_entities.x_axis {
all_parts.push(x_axis);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, x_axis,
));
}
if let Some(y_axis) = axis_entities.y_axis {
all_parts.push(y_axis);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, y_axis,
));
}
if let Some(z_axis) = axis_entities.z_axis {
all_parts.push(z_axis);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, z_axis,
));
}
if let Some(xy_plane) = axis_entities.xy_plane {
all_parts.push(xy_plane);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, xy_plane,
));
}
if let Some(yz_plane) = axis_entities.yz_plane {
all_parts.push(yz_plane);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, yz_plane,
));
}
if let Some(xz_plane) = axis_entities.xz_plane {
all_parts.push(xz_plane);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world, xz_plane,
));
}
if let Some(center_cube) = axis_entities.center_cube {
all_parts.push(center_cube);
all_parts.extend(crate::ecs::transform::queries::query_descendants(
world,
center_cube,
));
}
hide_entities(world, &all_parts);
if let Some(x_line) = axis_entities.x_axis_line {
hide_entities(world, &[x_line]);
}
if let Some(y_line) = axis_entities.y_axis_line {
hide_entities(world, &[y_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
hide_entities(world, &[z_line]);
}
if axis.x > 0.5 {
if let Some(x_axis) = axis_entities.x_axis {
let mut to_show = vec![x_axis];
to_show.extend(crate::ecs::transform::queries::query_descendants(
world, x_axis,
));
show_entities(world, &to_show);
}
if let Some(x_line) = axis_entities.x_axis_line {
show_entities(world, &[x_line]);
}
} else if axis.y > 0.5 {
if let Some(y_axis) = axis_entities.y_axis {
let mut to_show = vec![y_axis];
to_show.extend(crate::ecs::transform::queries::query_descendants(
world, y_axis,
));
show_entities(world, &to_show);
}
if let Some(y_line) = axis_entities.y_axis_line {
show_entities(world, &[y_line]);
}
} else if axis.z > 0.5 {
if let Some(z_axis) = axis_entities.z_axis {
let mut to_show = vec![z_axis];
to_show.extend(crate::ecs::transform::queries::query_descendants(
world, z_axis,
));
show_entities(world, &to_show);
}
if let Some(z_line) = axis_entities.z_axis_line {
show_entities(world, &[z_line]);
}
}
}
GizmoDragMode::Plane(normal) => {
if let Some(center_cube) = axis_entities.center_cube {
set_entity_visible_recursive(world, center_cube, false);
}
if let Some(x_line) = axis_entities.x_axis_line {
hide_entities(world, &[x_line]);
}
if let Some(y_line) = axis_entities.y_axis_line {
hide_entities(world, &[y_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
hide_entities(world, &[z_line]);
}
if normal.z > 0.5 {
if let Some(xy_plane) = axis_entities.xy_plane {
set_entity_visible_recursive(world, xy_plane, true);
}
if let Some(yz_plane) = axis_entities.yz_plane {
set_entity_visible_recursive(world, yz_plane, false);
}
if let Some(xz_plane) = axis_entities.xz_plane {
set_entity_visible_recursive(world, xz_plane, false);
}
if let Some(x_axis) = axis_entities.x_axis {
set_entity_visible_recursive(world, x_axis, true);
}
if let Some(y_axis) = axis_entities.y_axis {
set_entity_visible_recursive(world, y_axis, true);
}
if let Some(z_axis) = axis_entities.z_axis {
set_entity_visible_recursive(world, z_axis, false);
}
if let Some(x_line) = axis_entities.x_axis_line {
show_entities(world, &[x_line]);
}
if let Some(y_line) = axis_entities.y_axis_line {
show_entities(world, &[y_line]);
}
} else if normal.x > 0.5 {
if let Some(yz_plane) = axis_entities.yz_plane {
set_entity_visible_recursive(world, yz_plane, true);
}
if let Some(xy_plane) = axis_entities.xy_plane {
set_entity_visible_recursive(world, xy_plane, false);
}
if let Some(xz_plane) = axis_entities.xz_plane {
set_entity_visible_recursive(world, xz_plane, false);
}
if let Some(y_axis) = axis_entities.y_axis {
set_entity_visible_recursive(world, y_axis, true);
}
if let Some(z_axis) = axis_entities.z_axis {
set_entity_visible_recursive(world, z_axis, true);
}
if let Some(x_axis) = axis_entities.x_axis {
set_entity_visible_recursive(world, x_axis, false);
}
if let Some(y_line) = axis_entities.y_axis_line {
show_entities(world, &[y_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
show_entities(world, &[z_line]);
}
} else {
if let Some(xz_plane) = axis_entities.xz_plane {
set_entity_visible_recursive(world, xz_plane, true);
}
if let Some(xy_plane) = axis_entities.xy_plane {
set_entity_visible_recursive(world, xy_plane, false);
}
if let Some(yz_plane) = axis_entities.yz_plane {
set_entity_visible_recursive(world, yz_plane, false);
}
if let Some(x_axis) = axis_entities.x_axis {
set_entity_visible_recursive(world, x_axis, true);
}
if let Some(z_axis) = axis_entities.z_axis {
set_entity_visible_recursive(world, z_axis, true);
}
if let Some(y_axis) = axis_entities.y_axis {
set_entity_visible_recursive(world, y_axis, false);
}
if let Some(x_line) = axis_entities.x_axis_line {
show_entities(world, &[x_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
show_entities(world, &[z_line]);
}
}
}
GizmoDragMode::Free => {
if let Some(x_line) = axis_entities.x_axis_line {
hide_entities(world, &[x_line]);
}
if let Some(y_line) = axis_entities.y_axis_line {
hide_entities(world, &[y_line]);
}
if let Some(z_line) = axis_entities.z_axis_line {
hide_entities(world, &[z_line]);
}
if let Some(x_axis) = axis_entities.x_axis {
set_entity_visible_recursive(world, x_axis, false);
}
if let Some(y_axis) = axis_entities.y_axis {
set_entity_visible_recursive(world, y_axis, false);
}
if let Some(z_axis) = axis_entities.z_axis {
set_entity_visible_recursive(world, z_axis, false);
}
if let Some(xy_plane) = axis_entities.xy_plane {
set_entity_visible_recursive(world, xy_plane, false);
}
if let Some(yz_plane) = axis_entities.yz_plane {
set_entity_visible_recursive(world, yz_plane, false);
}
if let Some(xz_plane) = axis_entities.xz_plane {
set_entity_visible_recursive(world, xz_plane, false);
}
if let Some(center_cube) = axis_entities.center_cube {
set_entity_visible_recursive(world, center_cube, true);
}
}
}
}