use crate::types::{GraphNode, LabelSettings, LabelVisibilityIndicator, NodeLabel, SearchState};
use bevy::prelude::*;
pub fn setup_ui(commands: &mut Commands) {
commands.spawn((
Text::new("Controls:\nArrows: Pan camera\nShift+Arrows: Orbit view\n+/- or Scroll: Zoom\nLeft drag: Orbit\nRight drag: Pan\nL: Show all labels\n/: Search nodes\nESC: Close search\nQ: Exit"),
TextFont {
font_size: 16.0,
..default()
},
TextColor(Color::WHITE),
Node {
position_type: PositionType::Absolute,
top: Val::Px(10.0),
left: Val::Px(10.0),
..default()
},
));
commands.spawn((
Text::new(""),
TextFont {
font_size: 20.0,
..default()
},
TextColor(Color::srgba(1.0, 1.0, 0.0, 0.8)),
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(10.0),
left: Val::Px(10.0),
..default()
},
LabelVisibilityIndicator,
));
}
pub fn create_node_labels(
mut commands: Commands,
node_query: Query<(Entity, &GraphNode), Added<GraphNode>>,
) {
for (node_entity, graph_node) in &node_query {
commands.spawn((
Text::new(graph_node.name.clone()),
TextFont {
font_size: 20.0,
..default()
},
TextColor(Color::WHITE),
Node {
position_type: PositionType::Absolute,
..default()
},
NodeLabel { node_entity },
Visibility::Hidden, ));
}
}
pub fn toggle_label_visibility(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut label_settings: ResMut<LabelSettings>,
mut indicator_query: Query<&mut Text, With<LabelVisibilityIndicator>>,
search_state: Res<SearchState>,
) {
if search_state.active {
return;
}
if keyboard_input.just_pressed(KeyCode::KeyL) {
label_settings.show_all_labels = !label_settings.show_all_labels;
if let Ok(mut text) = indicator_query.single_mut() {
text.0 = if label_settings.show_all_labels {
"Showing all labels".to_string()
} else {
String::new()
};
}
}
}
pub fn update_node_label_positions(
camera_query: Query<(&Camera, &GlobalTransform)>,
node_query: Query<&GlobalTransform, With<GraphNode>>,
mut label_query: Query<(&mut Node, &mut Visibility, &mut TextColor, &NodeLabel)>,
label_settings: Res<LabelSettings>,
) {
let Ok((camera, camera_transform)) = camera_query.single() else {
return;
};
for (mut node_style, mut visibility, mut text_color, label) in &mut label_query {
let Ok(node_transform) = node_query.get(label.node_entity) else {
continue;
};
let distance = camera_transform
.translation()
.distance(node_transform.translation());
if label_settings.show_all_labels || distance <= label_settings.visibility_distance {
*visibility = Visibility::Visible;
let alpha = if label_settings.show_all_labels {
1.0
} else {
let fade_start = label_settings.visibility_distance * 0.7;
if distance < fade_start {
1.0
} else {
1.0 - ((distance - fade_start)
/ (label_settings.visibility_distance - fade_start))
}
};
text_color.0 = Color::srgba(1.0, 1.0, 1.0, alpha.clamp(0.0, 1.0));
} else {
*visibility = Visibility::Hidden;
}
if let Ok(viewport_position) =
camera.world_to_viewport(camera_transform, node_transform.translation())
{
node_style.left = Val::Px(viewport_position.x);
node_style.top = Val::Px(viewport_position.y);
}
}
}