feat: Box brush
This commit is contained in:
parent
caa57922bf
commit
4373e671a0
3 changed files with 88 additions and 35 deletions
|
|
@ -15,10 +15,14 @@ impl<'a> GridManipulationTools<'a> {
|
||||||
};
|
};
|
||||||
self.grid.data[index] = element;
|
self.grid.data[index] = element;
|
||||||
}
|
}
|
||||||
pub fn fill_xyz(&mut self,x1: u32, y1: u32, z1: u32, x2: u32, y2: u32, z2: u32, element: GridElement) {
|
pub fn set_vec(&mut self, vec: UVec3, element: GridElement) {
|
||||||
if x1 > x2 || y1 > y2 || z1 > z2 {
|
let Some(index) = self.grid.indexify(vec) else {
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
|
self.grid.data[index] = element;
|
||||||
|
}
|
||||||
|
pub fn fill_xyz(&mut self,x1: u32, y1: u32, z1: u32, x2: u32, y2: u32, z2: u32, element: GridElement) {
|
||||||
|
let (x1,y1,z1,x2,y2,z2) = (x1.min(x2), y1.min(y2), z1.min(z2), x1.max(x2), y1.max(y2), z1.max(z2));
|
||||||
|
|
||||||
for x in x1..=x2 {
|
for x in x1..=x2 {
|
||||||
for y in y1..=y2 {
|
for y in y1..=y2 {
|
||||||
|
|
@ -27,6 +31,21 @@ impl<'a> GridManipulationTools<'a> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.grid.data[index] = element.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fill_vec(&mut self,vec1: UVec3, vec2: UVec3, element: GridElement) {
|
||||||
|
let (min_corner, max_corner) = (vec1.min(vec2), vec1.max(vec2));
|
||||||
|
|
||||||
|
for x in min_corner.x..=max_corner.x {
|
||||||
|
for y in min_corner.y..=max_corner.y {
|
||||||
|
for z in min_corner.z..=max_corner.z {
|
||||||
|
let Some(index) = self.grid.indexify(UVec3::new(x,y,z)) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
self.grid.data[index] = element.clone();
|
self.grid.data[index] = element.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ impl Plugin for EditorPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, PartialEq, Eq)]
|
#[derive(Default, PartialEq, Eq)]
|
||||||
pub enum Confirmation<T> {
|
pub enum Confirmation<T> {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
|
|
@ -23,6 +23,32 @@ pub enum Confirmation<T> {
|
||||||
Confirmed(T)
|
Confirmed(T)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Confirmation<T> {
|
||||||
|
pub fn from_option(option: &Option<T>) -> Self {
|
||||||
|
match option {
|
||||||
|
Some(item) => Confirmation::Suggestion(item.clone()),
|
||||||
|
None => Confirmation::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn to_option(&self) -> Option<T> {
|
||||||
|
match self {
|
||||||
|
Confirmation::None => None,
|
||||||
|
Confirmation::Suggestion(item) => Some(item.clone()),
|
||||||
|
Confirmation::Confirmed(item) => Some(item.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Clone for Confirmation<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::None => Self::None,
|
||||||
|
Self::Suggestion(arg0) => Self::Suggestion(arg0.clone()),
|
||||||
|
Self::Confirmed(arg0) => Self::Confirmed(arg0.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, PartialEq, Eq,Resource)]
|
#[derive(Default, Clone, PartialEq, Eq,Resource)]
|
||||||
pub struct EditorTool {
|
pub struct EditorTool {
|
||||||
pub block: GridElement,
|
pub block: GridElement,
|
||||||
|
|
@ -34,14 +60,16 @@ pub enum ToolType {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
Paint{ position: Option<UVec3> },
|
Paint{ position: Option<UVec3> },
|
||||||
//Box { first_corner: Confirmation<UVec3>, second_corner: Option<UVec3> }
|
Box { first_corner: Confirmation<UVec3>, second_corner: Option<UVec3> }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Display for ToolType {
|
impl Display for ToolType {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f,"{}",match self {
|
write!(f,"{}",match self {
|
||||||
ToolType::None => "None",
|
ToolType::None => "None",
|
||||||
ToolType::Paint { position: _ } => "Paint"
|
ToolType::Paint { position: _ } => "Paint",
|
||||||
|
ToolType::Box { first_corner: _, second_corner: _ } => "Box",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -51,15 +79,8 @@ impl Display for ToolType {
|
||||||
pub struct ViewCube;
|
pub struct ViewCube;
|
||||||
|
|
||||||
#[derive(Event)]
|
#[derive(Event)]
|
||||||
pub struct ApplyTool{
|
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,
|
||||||
|
|
@ -69,38 +90,50 @@ pub fn calculate_tools(
|
||||||
mut tool: ResMut<EditorTool>,
|
mut tool: ResMut<EditorTool>,
|
||||||
grid: Res<Grid>
|
grid: Res<Grid>
|
||||||
) {
|
) {
|
||||||
let tool_change: ToolType = match tool.kind {
|
// Calculating tile cursor tile placement
|
||||||
|
let mut cursor_position: Option<UVec3> = None;
|
||||||
|
|
||||||
|
for (_, ray) in ray_map.iter() {
|
||||||
|
let Some((_, hit)) = raycast.cast_ray(*ray, &MeshRayCastSettings::default()).first() else {continue;};
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
cursor_position = Some(placement_position.as_ivec3().max(IVec3::ZERO).as_uvec3().min(grid.size-UVec3::ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
let tool_change: ToolType = match tool.kind.clone() {
|
||||||
ToolType::None => ToolType::None,
|
ToolType::None => ToolType::None,
|
||||||
ToolType::Paint { position: _ } => {
|
ToolType::Paint { position: _ } => ToolType::Paint { position: cursor_position },
|
||||||
let mut new_position: Option<UVec3> = None;
|
ToolType::Box { first_corner, second_corner: _ } => {
|
||||||
|
if let Confirmation::Confirmed(_) = first_corner {
|
||||||
for (_, ray) in ray_map.iter() {
|
ToolType::Box { first_corner, second_corner: cursor_position }
|
||||||
let Some((_, hit)) = raycast.cast_ray(*ray, &MeshRayCastSettings::default()).first() else {continue;};
|
} else {
|
||||||
|
ToolType::Box { first_corner: Confirmation::from_option(&cursor_position), second_corner: None }
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ToolType::Paint { position: new_position }
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tool.kind = tool_change;
|
tool.kind = tool_change;
|
||||||
|
|
||||||
|
|
||||||
if mouse_button.just_pressed(MouseButton::Left) {
|
if mouse_button.just_pressed(MouseButton::Left) {
|
||||||
commands.trigger(ApplyTool::new(tool.clone()));
|
commands.trigger(ApplyTool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_tool(params: On<ApplyTool>, mut grid: ResMut<Grid>) {
|
pub fn apply_tool(_params: On<ApplyTool>, mut grid: ResMut<Grid>, mut tool: ResMut<EditorTool>) {
|
||||||
match params.tool.kind {
|
let mut editor = grid.manipulate();
|
||||||
ToolType::None => {},
|
match tool.kind {
|
||||||
ToolType::Paint { position } => {
|
ToolType::Paint { position: Some(position) } => {
|
||||||
let Some(position) = position else { return; };
|
editor.set_vec(position, tool.block);
|
||||||
let index = grid.indexify(position).unwrap();
|
|
||||||
grid.data[index] = params.tool.block;
|
|
||||||
},
|
},
|
||||||
|
ToolType::Box { first_corner: Confirmation::Suggestion(first_corner), second_corner } => {
|
||||||
|
tool.kind = ToolType::Box { first_corner: Confirmation::Confirmed(first_corner), second_corner: second_corner };
|
||||||
|
},
|
||||||
|
ToolType::Box { first_corner: Confirmation::Confirmed(first_corner), second_corner: Some(second_corner) } => {
|
||||||
|
editor.fill_vec(first_corner, second_corner, tool.block);
|
||||||
|
tool.kind = ToolType::Box { first_corner: Confirmation::None, second_corner: None };
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use bevy::prelude::*;
|
||||||
use crate::MAX_FLUID_AMOUNT;
|
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::{EditorTool,ToolType};
|
use crate::view::editor::{EditorTool,ToolType,Confirmation};
|
||||||
|
|
||||||
pub struct UIPlugin;
|
pub struct UIPlugin;
|
||||||
|
|
||||||
|
|
@ -105,7 +105,8 @@ fn editor_tools_column() -> impl Scene {
|
||||||
label("Tools")
|
label("Tools")
|
||||||
ToolLabel,
|
ToolLabel,
|
||||||
tool_button(ToolType::None),
|
tool_button(ToolType::None),
|
||||||
tool_button(ToolType::Paint{position: None})
|
tool_button(ToolType::Paint{position: None}),
|
||||||
|
tool_button(ToolType::Box { first_corner: Confirmation::None, second_corner: None })
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue