aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.rs20
-rw-r--r--src/map_data.rs12
-rw-r--r--src/math/polygon.rs3
-rw-r--r--src/tool/mod.rs3
-rw-r--r--src/tool/polygon_room_tool.rs91
5 files changed, 127 insertions, 2 deletions
diff --git a/src/config.rs b/src/config.rs
index 4e90b21..b4703a2 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -10,6 +10,7 @@ use std::path::Path;
pub struct Config {
pub deletion_keybindings: DeletionToolKeybindings,
pub icon_keybindings: IconToolKeybindings,
+ pub polygon_keybindings: PolygonRoomToolKeybindings,
pub room_keybindings: RoomToolKeybindings,
pub wall_keybindings: WallToolKeybindings,
}
@@ -38,6 +39,14 @@ pub struct IconToolKeybindings {
}
#[derive(Serialize, Deserialize)]
+pub struct PolygonRoomToolKeybindings {
+ pub activation: Button,
+ pub place_node: Button,
+ pub finish: Button,
+ pub abort: Button,
+}
+
+#[derive(Serialize, Deserialize)]
pub struct RoomToolKeybindings {
pub activation: Button,
pub start_draw: Button,
@@ -98,6 +107,12 @@ impl Default for Config {
rotate_counterclockwise: Button::Keyboard(KeyboardKey::Minus),
place: Button::Mouse(MouseButton::Left),
},
+ polygon_keybindings: PolygonRoomToolKeybindings {
+ activation: Button::Keyboard(KeyboardKey::P),
+ place_node: Button::Mouse(MouseButton::Left),
+ finish: Button::Keyboard(KeyboardKey::Enter),
+ abort: Button::Mouse(MouseButton::Right),
+ },
room_keybindings: RoomToolKeybindings {
activation: Button::Keyboard(KeyboardKey::R),
start_draw: Button::Mouse(MouseButton::Left),
@@ -124,6 +139,11 @@ impl ToolKeybindings for IconToolKeybindings {
self.activation
}
}
+impl ToolKeybindings for PolygonRoomToolKeybindings {
+ fn activation_key(&self) -> Button {
+ self.activation
+ }
+}
impl ToolKeybindings for RoomToolKeybindings {
fn activation_key(&self) -> Button {
self.activation
diff --git a/src/map_data.rs b/src/map_data.rs
index e1a9c0b..b17d779 100644
--- a/src/map_data.rs
+++ b/src/map_data.rs
@@ -1,4 +1,4 @@
-use crate::math::{Rect, Vec2};
+use crate::math::{Polygon, Rect, Vec2};
use crate::tool::icon_tool::IconInfo;
use ron::de::from_reader;
use ron::ser::{to_string_pretty, PrettyConfig};
@@ -13,6 +13,7 @@ use std::path::Path;
#[derive(Serialize, Deserialize)]
pub struct MapData {
rooms: Vec<Rect<f32>>,
+ polygons: Vec<Polygon<f32>>,
walls: Vec<(Vec2<f32>, Vec2<f32>)>,
icons: Vec<IconInfo>,
}
@@ -22,6 +23,7 @@ impl MapData {
pub fn new() -> Self {
Self {
rooms: Vec::new(),
+ polygons: Vec::new(),
walls: Vec::new(),
icons: Vec::new(),
}
@@ -40,6 +42,7 @@ impl MapData {
* future)
*/
self.rooms.append(&mut data.rooms);
+ self.polygons.append(&mut data.polygons);
self.walls.append(&mut data.walls);
self.icons.append(&mut data.icons);
@@ -71,6 +74,13 @@ impl MapData {
&mut self.rooms
}
+ pub fn polygons(&self) -> &Vec<Polygon<f32>> {
+ &self.polygons
+ }
+ pub fn polygons_mut(&mut self) -> &mut Vec<Polygon<f32>> {
+ &mut self.polygons
+ }
+
pub fn walls(&self) -> &Vec<(Vec2<f32>, Vec2<f32>)> {
&self.walls
}
diff --git a/src/math/polygon.rs b/src/math/polygon.rs
index 5711049..5cf8104 100644
--- a/src/math/polygon.rs
+++ b/src/math/polygon.rs
@@ -1,9 +1,10 @@
use super::{PolygonGraph, Vec2};
use nalgebra::{ClosedDiv, ClosedMul, ClosedSub, RealField, Scalar};
use num_traits::Zero;
+use serde::{Deserialize, Serialize};
use std::ops::Neg;
-#[derive(Debug)]
+#[derive(Debug, Deserialize, Serialize, PartialEq)]
// TODO: Support polygons with holes
pub struct Polygon<T: Scalar + Copy> {
pub corners: Vec<Vec2<T>>,
diff --git a/src/tool/mod.rs b/src/tool/mod.rs
index e528b8f..f503d2b 100644
--- a/src/tool/mod.rs
+++ b/src/tool/mod.rs
@@ -1,10 +1,12 @@
pub mod deletion_tool;
pub mod icon_tool;
+pub mod polygon_room_tool;
pub mod room_tool;
pub mod wall_tool;
pub use deletion_tool::DeletionTool;
pub use icon_tool::IconTool;
+pub use polygon_room_tool::PolygonRoomTool;
pub use room_tool::RoomTool;
pub use wall_tool::WallTool;
@@ -18,6 +20,7 @@ use raylib::RaylibHandle;
#[repr(u8)]
pub enum ToolType {
RoomTool,
+ PolygonRoomTool,
WallTool,
IconTool,
DeletionTool,
diff --git a/src/tool/polygon_room_tool.rs b/src/tool/polygon_room_tool.rs
new file mode 100644
index 0000000..4aab7f7
--- /dev/null
+++ b/src/tool/polygon_room_tool.rs
@@ -0,0 +1,91 @@
+use super::Tool;
+use crate::button::Button;
+use crate::config::{PolygonRoomToolKeybindings, ToolKeybindings};
+use crate::dimension_indicator::DimensionIndicator;
+use crate::grid::{snap_to_grid, SNAP_SIZE};
+use crate::map_data::MapData;
+use crate::math::{Polygon, Vec2};
+use crate::transform::Transform;
+use raylib::core::drawing::RaylibDrawHandle;
+use raylib::RaylibHandle;
+
+pub struct PolygonRoomTool {
+ keybindings: PolygonRoomToolKeybindings,
+ unfinished_polygon: Option<Vec<Vec2<f32>>>,
+ dimension_indicator: DimensionIndicator,
+}
+
+impl PolygonRoomTool {
+ pub fn new(keybindings: PolygonRoomToolKeybindings) -> Self {
+ Self {
+ keybindings,
+ unfinished_polygon: None,
+ dimension_indicator: DimensionIndicator::new(),
+ }
+ }
+}
+
+impl Tool for PolygonRoomTool {
+ fn activate(&mut self) {}
+
+ fn deactivate(&mut self) {
+ self.unfinished_polygon = None;
+ }
+
+ fn active_update(
+ &mut self,
+ map: &mut MapData,
+ rl: &RaylibHandle,
+ transform: &Transform,
+ mouse_blocked: bool,
+ ) {
+ let mouse_pos_m = transform.point_px_to_m(rl.get_mouse_position().into());
+ let snapped_mouse_pos_m = snap_to_grid(mouse_pos_m, SNAP_SIZE);
+ // Update the position of the node that would be placed into the polygon next.
+ if let Some(ref mut corners) = &mut self.unfinished_polygon {
+ let last_element = corners.len() - 1;
+ corners[last_element] = snapped_mouse_pos_m;
+ self.dimension_indicator.update_dimensions(&corners);
+ }
+
+ if self.keybindings.finish.is_pressed(rl, mouse_blocked)
+ && self.unfinished_polygon.is_some()
+ {
+ // Make sure the polygon is at least a triangle, so it can be drawn.
+ if self.unfinished_polygon.as_ref().unwrap().len() >= 3 {
+ let polygon = Polygon::new(self.unfinished_polygon.take().unwrap());
+ self.dimension_indicator.clear_dimensions();
+ map.polygons_mut().push(polygon);
+ }
+ }
+
+ if self.keybindings.place_node.is_pressed(rl, mouse_blocked) {
+ if let Some(ref mut corners) = self.unfinished_polygon.as_mut() {
+ if snapped_mouse_pos_m == corners[0] {
+ // Make sure the polygon is at least a triangle, so it can be drawn.
+ if corners.len() >= 3 {
+ // The last corner is redundant.
+ corners.pop();
+ let polygon = Polygon::new(self.unfinished_polygon.take().unwrap());
+ self.dimension_indicator.clear_dimensions();
+ map.polygons_mut().push(polygon);
+ }
+ } else {
+ corners.push(snapped_mouse_pos_m);
+ }
+ } else {
+ self.unfinished_polygon = Some(vec![snapped_mouse_pos_m]);
+ }
+ }
+
+ if self.keybindings.abort.is_pressed(rl, false) {
+ self.unfinished_polygon = None;
+ }
+ }
+
+ fn draw(&self, _map: &MapData, _rld: &mut RaylibDrawHandle, _transform: &Transform) {}
+
+ fn activation_key(&self) -> Button {
+ self.keybindings.activation_key()
+ }
+}