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::prelude::*;
|
||||||
use bevy::picking::backend::ray::RayMap;
|
use bevy::picking::backend::ray::RayMap;
|
||||||
|
|
||||||
|
|
@ -7,17 +9,41 @@ pub struct EditorPlugin;
|
||||||
|
|
||||||
impl Plugin for EditorPlugin {
|
impl Plugin for EditorPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<EditorTools>()
|
app.init_resource::<EditorTool>()
|
||||||
.add_observer(apply_tool)
|
.add_observer(apply_tool)
|
||||||
.add_systems(Update, calculate_tools);
|
.add_systems(Update, calculate_tools);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, PartialEq, Eq,Resource)]
|
#[derive(Default, Clone, PartialEq, Eq)]
|
||||||
pub enum EditorTools {
|
pub enum Confirmation<T> {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
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;
|
pub struct ViewCube;
|
||||||
|
|
||||||
#[derive(Event)]
|
#[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(
|
pub fn calculate_tools(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mouse_button: Res<ButtonInput<MouseButton>>,
|
mouse_button: Res<ButtonInput<MouseButton>>,
|
||||||
ray_map: Res<RayMap>,
|
ray_map: Res<RayMap>,
|
||||||
mut raycast: MeshRayCast,
|
mut raycast: MeshRayCast,
|
||||||
mut tool: ResMut<EditorTools>,
|
mut tool: ResMut<EditorTool>,
|
||||||
mut gizmos: Gizmos,
|
|
||||||
grid: Res<Grid>
|
grid: Res<Grid>
|
||||||
) {
|
) {
|
||||||
let new_tool: Option<EditorTools> = match tool.clone() {
|
let tool_change: ToolType = match tool.kind {
|
||||||
EditorTools::None => None,
|
ToolType::None => ToolType::None,
|
||||||
EditorTools::Paint{position: _, block} => {
|
ToolType::Paint { position: _ } => {
|
||||||
let mut new_position: Option<UVec3> = None;
|
let mut new_position: Option<UVec3> = None;
|
||||||
|
|
||||||
for (_, ray) in ray_map.iter() {
|
for (_, ray) in ray_map.iter() {
|
||||||
let Some((_, hit)) = raycast.cast_ray(*ray, &MeshRayCastSettings::default()).first() else {continue;};
|
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);
|
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(converted_position.as_ivec3().max(IVec3::ZERO).as_uvec3().min(grid.size-UVec3::ONE));
|
|
||||||
|
new_position = Some(placement_position.as_ivec3().max(IVec3::ZERO).as_uvec3().min(grid.size-UVec3::ONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
new_position.map(|pos|{
|
ToolType::Paint { position: new_position }
|
||||||
EditorTools::Paint { position: pos , block }}
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let Some(new_tool) = new_tool {
|
|
||||||
*tool = new_tool;
|
tool.kind = tool_change;
|
||||||
}
|
|
||||||
|
|
||||||
if mouse_button.just_pressed(MouseButton::Left) {
|
if mouse_button.just_pressed(MouseButton::Left) {
|
||||||
match tool.clone() {
|
commands.trigger(ApplyTool::new(tool.clone()));
|
||||||
EditorTools::None => {},
|
|
||||||
EditorTools::Paint { position, block } => {
|
|
||||||
commands.trigger(ApplyTool(EditorTools::Paint { position, block }));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_tool(params: On<ApplyTool>, mut grid: ResMut<Grid>) {
|
pub fn apply_tool(params: On<ApplyTool>, mut grid: ResMut<Grid>) {
|
||||||
match params.0 {
|
match params.tool.kind {
|
||||||
EditorTools::None => {},
|
ToolType::None => {},
|
||||||
EditorTools::Paint { position, block } => {
|
ToolType::Paint { position } => {
|
||||||
let Some(index) = grid.indexify(position) else {
|
let Some(position) = position else { return; };
|
||||||
error!("Grid position {position} is incorrect");
|
let index = grid.indexify(position).unwrap();
|
||||||
return;};
|
grid.data[index] = params.tool.block;
|
||||||
grid.data[index] = block;
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ use bevy::feathers::{FeathersPlugins, containers::*, controls::*, dark_theme::cr
|
||||||
use bevy::ui_widgets::{Activate};
|
use bevy::ui_widgets::{Activate};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::MAX_FLUID_AMOUNT;
|
||||||
use crate::grid::{Grid, GridElement};
|
use crate::grid::{Grid, GridElement};
|
||||||
use crate::simulation::SimulationStatus;
|
use crate::simulation::SimulationStatus;
|
||||||
use crate::view::editor::EditorTools;
|
use crate::view::editor::{EditorTool,ToolType};
|
||||||
|
|
||||||
pub struct UIPlugin;
|
pub struct UIPlugin;
|
||||||
|
|
||||||
|
|
@ -56,7 +57,8 @@ fn ui() -> impl Scene {
|
||||||
}
|
}
|
||||||
Children [
|
Children [
|
||||||
debug_column(),
|
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! {
|
bsn! {
|
||||||
pane()
|
pane()
|
||||||
pane_header()
|
pane_header()
|
||||||
|
|
@ -102,24 +104,63 @@ fn editor_column() -> impl Scene {
|
||||||
Children [
|
Children [
|
||||||
label("Tools")
|
label("Tools")
|
||||||
ToolLabel,
|
ToolLabel,
|
||||||
@FeathersButton {
|
tool_button(ToolType::None),
|
||||||
@caption: bsn!{label("None")}
|
tool_button(ToolType::Paint{position: 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();
|
|
||||||
}),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
fn water_amount_label() -> impl Scene {
|
||||||
bsn! {
|
bsn! {
|
||||||
Node {
|
Node {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue