feat: Split tool type and tool struct, added tool element selection
This commit is contained in:
parent
dd0f3d883e
commit
2ae8f20e85
2 changed files with 117 additions and 48 deletions
|
|
@ -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::<EditorTools>()
|
||||
app.init_resource::<EditorTool>()
|
||||
.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<T> {
|
||||
#[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<UVec3> },
|
||||
//Box { first_corner: Confirmation<UVec3>, second_corner: Option<UVec3> }
|
||||
}
|
||||
|
||||
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<ButtonInput<MouseButton>>,
|
||||
ray_map: Res<RayMap>,
|
||||
mut raycast: MeshRayCast,
|
||||
mut tool: ResMut<EditorTools>,
|
||||
mut gizmos: Gizmos,
|
||||
mut tool: ResMut<EditorTool>,
|
||||
grid: Res<Grid>
|
||||
) {
|
||||
let new_tool: Option<EditorTools> = 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<UVec3> = 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<ApplyTool>, mut grid: ResMut<Grid>) {
|
||||
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;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Activate>, mut tool: ResMut<EditorTools>, mut label: Single<&mut Text, With<ToolLabel>>| {
|
||||
*tool = EditorTools::None;
|
||||
label.0 = "Current tool: None".to_string();
|
||||
}),
|
||||
@FeathersButton {
|
||||
@caption: bsn!{label("Paint")}
|
||||
}
|
||||
on(|_activate: On<Activate>, mut tool: ResMut<EditorTools>, mut label: Single<&mut Text, With<ToolLabel>>| {
|
||||
*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<Activate>, mut tool: ResMut<EditorTool>, mut label: Single<&mut Text, With<ToolLabel>>| {
|
||||
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<Activate>, mut tool: ResMut<EditorTool>| {
|
||||
tool.block = element.clone()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn water_amount_label() -> impl Scene {
|
||||
bsn! {
|
||||
Node {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue