use bevy::{prelude::*, ui_widgets::observe};
use jackdaw_feathers::{
button::{self, ButtonProps, ButtonVariant},
separator, tokens,
};
use super::TerrainEditMode;
use crate::{EditorEntity, selection::Selection};
pub(super) fn plugin(app: &mut App) {
app.add_systems(
Update,
(toggle_toolbar_visibility, update_terrain_tool_highlights)
.run_if(in_state(crate::AppState::Editor)),
);
}
#[derive(Component)]
pub struct TerrainToolbar;
#[derive(Component, Clone, Copy, PartialEq, Eq)]
pub enum TerrainToolButton {
Raise,
Lower,
Flatten,
Smooth,
Noise,
Generate,
}
pub fn terrain_toolbar() -> impl Bundle {
(
TerrainToolbar,
EditorEntity,
Node {
flex_direction: FlexDirection::Row,
align_items: AlignItems::Center,
padding: UiRect::axes(px(tokens::SPACING_MD), px(tokens::SPACING_SM)),
column_gap: px(tokens::SPACING_SM),
width: percent(100),
height: px(32.0),
flex_shrink: 0.0,
display: Display::None,
..Default::default()
},
BackgroundColor(tokens::TOOLBAR_BG),
children![
(
Text::new("Terrain"),
TextFont {
font_size: tokens::FONT_SM,
..Default::default()
},
TextColor(tokens::TEXT_SECONDARY),
),
terrain_tool_button("Raise", TerrainToolButton::Raise),
terrain_tool_button("Lower", TerrainToolButton::Lower),
terrain_tool_button("Flatten", TerrainToolButton::Flatten),
terrain_tool_button("Smooth", TerrainToolButton::Smooth),
terrain_tool_button("Noise", TerrainToolButton::Noise),
separator::separator(separator::SeparatorProps::vertical()),
terrain_tool_button("Generate", TerrainToolButton::Generate),
],
)
}
fn terrain_tool_button(label: &str, tool: TerrainToolButton) -> impl Bundle {
(
tool,
button::button(ButtonProps::new(label).with_variant(ButtonVariant::Default)),
observe(
move |_: On<Pointer<Click>>, mut edit_mode: ResMut<TerrainEditMode>| {
let new_mode = match tool {
TerrainToolButton::Raise => {
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Raise)
}
TerrainToolButton::Lower => {
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Lower)
}
TerrainToolButton::Flatten => {
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Flatten)
}
TerrainToolButton::Smooth => {
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Smooth)
}
TerrainToolButton::Noise => {
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Noise)
}
TerrainToolButton::Generate => TerrainEditMode::Generate,
};
if *edit_mode == new_mode {
*edit_mode = TerrainEditMode::None;
} else {
*edit_mode = new_mode;
}
},
),
)
}
fn toggle_toolbar_visibility(
selection: Res<Selection>,
terrains: Query<(), With<jackdaw_jsn::Terrain>>,
mut toolbar: Query<&mut Node, With<TerrainToolbar>>,
mut edit_mode: ResMut<TerrainEditMode>,
) {
if !selection.is_changed() {
return;
}
let should_show = selection.primary().is_some_and(|e| terrains.contains(e));
for mut node in &mut toolbar {
node.display = if should_show {
Display::Flex
} else {
Display::None
};
}
if !should_show && *edit_mode != TerrainEditMode::None {
*edit_mode = TerrainEditMode::None;
}
}
fn update_terrain_tool_highlights(
edit_mode: Res<TerrainEditMode>,
mut buttons: Query<(&TerrainToolButton, &mut BackgroundColor)>,
) {
if !edit_mode.is_changed() {
return;
}
for (button, mut bg) in &mut buttons {
let active = matches!(
(&*edit_mode, button),
(
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Raise),
TerrainToolButton::Raise
) | (
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Lower),
TerrainToolButton::Lower
) | (
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Flatten),
TerrainToolButton::Flatten
) | (
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Smooth),
TerrainToolButton::Smooth
) | (
TerrainEditMode::Sculpt(jackdaw_terrain::SculptTool::Noise),
TerrainToolButton::Noise
) | (TerrainEditMode::Generate, TerrainToolButton::Generate)
);
bg.0 = if active {
tokens::SELECTED_BG
} else {
tokens::TOOLBAR_BUTTON_BG
};
}
}