diff --git a/src/view/editor.rs b/src/view/editor.rs index a865f63..3e5aba7 100644 --- a/src/view/editor.rs +++ b/src/view/editor.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use bevy::prelude::*; use bevy::picking::backend::ray::RayMap; @@ -7,17 +9,41 @@ pub struct EditorPlugin; impl Plugin for EditorPlugin { fn build(&self, app: &mut App) { - app.init_resource::() + app.init_resource::() .add_observer(apply_tool) .add_systems(Update, calculate_tools); } } -#[derive(Default, Clone, PartialEq, Eq,Resource)] -pub enum EditorTools { +#[derive(Default, Clone, PartialEq, Eq)] +pub enum Confirmation { #[default] None, - Paint{ position: UVec3, block: GridElement }, + Suggestion(T), + Confirmed(T) +} + +#[derive(Default, Clone, PartialEq, Eq,Resource)] +pub struct EditorTool { + pub block: GridElement, + pub kind: ToolType +} + +#[derive(Default, Clone, PartialEq, Eq)] +pub enum ToolType { + #[default] + None, + Paint{ position: Option }, + //Box { first_corner: Confirmation, second_corner: Option } +} + +impl Display for ToolType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f,"{}",match self { + ToolType::None => "None", + ToolType::Paint { position: _ } => "Paint" + }) + } } @@ -25,54 +51,56 @@ pub enum EditorTools { pub struct ViewCube; #[derive(Event)] -pub struct ApplyTool(EditorTools); +pub struct ApplyTool{ + pub tool: EditorTool +} + +impl ApplyTool { + pub fn new(tool: EditorTool) -> Self { + Self { tool } + } +} pub fn calculate_tools( mut commands: Commands, mouse_button: Res>, ray_map: Res, mut raycast: MeshRayCast, - mut tool: ResMut, - mut gizmos: Gizmos, + mut tool: ResMut, grid: Res ) { - let new_tool: Option = match tool.clone() { - EditorTools::None => None, - EditorTools::Paint{position: _, block} => { + let tool_change: ToolType = match tool.kind { + ToolType::None => ToolType::None, + ToolType::Paint { position: _ } => { let mut new_position: Option = None; + for (_, ray) in ray_map.iter() { let Some((_, hit)) = raycast.cast_ray(*ray, &MeshRayCastSettings::default()).first() else {continue;}; - let converted_position = (hit.point + 0.51 * hit.normal.normalize()).round(); - gizmos.sphere(converted_position, 0.5, Color::BLACK); - new_position = Some(converted_position.as_ivec3().max(IVec3::ZERO).as_uvec3().min(grid.size-UVec3::ONE)); + + let placement_position = if let GridElement::Air = tool.block { hit.point - 0.51 * hit.normal.normalize() } else { hit.point + 0.51 * hit.normal.normalize() }.round(); + + new_position = Some(placement_position.as_ivec3().max(IVec3::ZERO).as_uvec3().min(grid.size-UVec3::ONE)); } - - new_position.map(|pos|{ - EditorTools::Paint { position: pos , block }} - ) + + ToolType::Paint { position: new_position } }, }; - if let Some(new_tool) = new_tool { - *tool = new_tool; - } + + tool.kind = tool_change; + + if mouse_button.just_pressed(MouseButton::Left) { - match tool.clone() { - EditorTools::None => {}, - EditorTools::Paint { position, block } => { - commands.trigger(ApplyTool(EditorTools::Paint { position, block })); - }, - } + commands.trigger(ApplyTool::new(tool.clone())); } } pub fn apply_tool(params: On, mut grid: ResMut) { - match params.0 { - EditorTools::None => {}, - EditorTools::Paint { position, block } => { - let Some(index) = grid.indexify(position) else { - error!("Grid position {position} is incorrect"); - return;}; - grid.data[index] = block; + match params.tool.kind { + ToolType::None => {}, + ToolType::Paint { position } => { + let Some(position) = position else { return; }; + let index = grid.indexify(position).unwrap(); + grid.data[index] = params.tool.block; }, } } diff --git a/src/view/ui.rs b/src/view/ui.rs index a8093c1..1ec639d 100644 --- a/src/view/ui.rs +++ b/src/view/ui.rs @@ -2,9 +2,10 @@ use bevy::feathers::{FeathersPlugins, containers::*, controls::*, dark_theme::cr use bevy::ui_widgets::{Activate}; use bevy::prelude::*; +use crate::MAX_FLUID_AMOUNT; use crate::grid::{Grid, GridElement}; use crate::simulation::SimulationStatus; -use crate::view::editor::EditorTools; +use crate::view::editor::{EditorTool,ToolType}; pub struct UIPlugin; @@ -56,7 +57,8 @@ fn ui() -> impl Scene { } Children [ debug_column(), - editor_column() + editor_tools_column(), + editor_elements_column(), ] } } @@ -84,7 +86,7 @@ fn debug_column() -> impl Scene { } } -fn editor_column() -> impl Scene { +fn editor_tools_column() -> impl Scene { bsn! { pane() pane_header() @@ -102,24 +104,63 @@ fn editor_column() -> impl Scene { Children [ label("Tools") ToolLabel, - @FeathersButton { - @caption: bsn!{label("None")} - } - on(|_activate: On, mut tool: ResMut, mut label: Single<&mut Text, With>| { - *tool = EditorTools::None; - label.0 = "Current tool: None".to_string(); - }), - @FeathersButton { - @caption: bsn!{label("Paint")} - } - on(|_activate: On, mut tool: ResMut, mut label: Single<&mut Text, With>| { - *tool = EditorTools::Paint { position: UVec3::default(), block: GridElement::Water { amount: 1000 } }; - label.0 = "Current tool: Paint".to_string(); - }), + tool_button(ToolType::None), + tool_button(ToolType::Paint{position: None}) ] } } +fn editor_elements_column() -> impl Scene { + bsn! { + pane() + pane_header() + pane_body() + Node { + display: Display::Flex, + flex_direction: FlexDirection::Column, + align_items: AlignItems::Stretch, + justify_content: JustifyContent::Start, + padding: px(8), + row_gap: px(8), + width: px(256), + min_width: px(256), + } + Children [ + label("Elements"), + element_button(GridElement::Air), + element_button(GridElement::Solid), + element_button(GridElement::Drain), + element_button(GridElement::Water { amount: MAX_FLUID_AMOUNT }), + element_button(GridElement::Source { source_amount: MAX_FLUID_AMOUNT }) + ] + } +} + +fn tool_button(kind: ToolType) -> impl Scene { + bsn! { + @FeathersButton { + @caption: bsn!{ + label(kind.to_string()) + } + } + on(move |_activate: On, mut tool: ResMut, mut label: Single<&mut Text, With>| { + tool.kind = kind.clone(); + label.0 = format!("Current tool: {}",kind.to_string()); + }) + } +} + +fn element_button(element: GridElement) -> impl Scene { + bsn! { + @FeathersButton { + @caption: bsn!{label(element.to_string())} + } + on(move |_activate: On, mut tool: ResMut| { + tool.block = element.clone() + }) + } +} + fn water_amount_label() -> impl Scene { bsn! { Node {