aboutsummaryrefslogtreecommitdiff
path: root/src/client/tool/polygon_room_tool.rs
diff options
context:
space:
mode:
authorArne Dußin2021-01-27 14:01:50 +0100
committerArne Dußin2021-02-02 22:16:15 +0100
commitf92e9f6f07b1e3834c2ca58ce3510734819d08e4 (patch)
tree20e3d3afce342a56ae98f6c20491482ccd2b5c6b /src/client/tool/polygon_room_tool.rs
parentc60a6d07efb120724b308e29e8e70f27c87c952d (diff)
downloadgraf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.tar.gz
graf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.zip
Rework graf karto to fit the client/server structure
Diffstat (limited to 'src/client/tool/polygon_room_tool.rs')
-rw-r--r--src/client/tool/polygon_room_tool.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/client/tool/polygon_room_tool.rs b/src/client/tool/polygon_room_tool.rs
new file mode 100644
index 0000000..63456cc
--- /dev/null
+++ b/src/client/tool/polygon_room_tool.rs
@@ -0,0 +1,141 @@
+//! Tool to create rooms in the shape of generic polygons.
+
+use super::Tool;
+use crate::client::colours::DEFAULT_COLOURS;
+use crate::client::map::Map;
+use crate::client::transform::Transform;
+use crate::client::FLOAT_MARGIN;
+use crate::math::{self, PolygonGraph, Vec2};
+use crate::net::{Cargo, Connection};
+use crate::world::Room;
+use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
+
+/// The tool itself.
+pub struct PolygonRoomTool {
+ unfinished_room: Option<(PolygonGraph<f64>, Vec2<f64>)>,
+ last_mouse_pos_m: Vec2<f64>,
+}
+
+impl PolygonRoomTool {
+ /// Create a new polygon room tool. There should be only one instance and it should be created
+ /// in the editor.
+ #[allow(clippy::new_without_default)]
+ pub fn new() -> Self {
+ Self {
+ unfinished_room: None,
+ last_mouse_pos_m: Vec2::new(0., 0.),
+ }
+ }
+
+ /* Helper function to try and finish the currently drawn polygon. If successful, it will add it
+ * to the map, clear the currently drawn polygon and return bool. Otherwise it will leave the
+ * unfinished polygon as is and return false without pushing anything.
+ */
+ fn try_push(&mut self, server: &Connection<Cargo>) -> bool {
+ if self.unfinished_room.is_none() {
+ return false;
+ }
+
+ match self
+ .unfinished_room
+ .as_ref()
+ .unwrap()
+ .0
+ .clone()
+ .bounding_polygon(FLOAT_MARGIN)
+ {
+ Some(polygon) => {
+ server.send(Cargo::AddRoom(Room::new(polygon)));
+ self.unfinished_room = None;
+ true
+ }
+ None => false,
+ }
+ }
+}
+
+impl Tool for PolygonRoomTool {
+ fn deactivate(&mut self) {
+ self.unfinished_room = None;
+ }
+
+ fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
+ // Update the last mouse position that was seen for later use.
+ self.last_mouse_pos_m = *mouse_pos_m;
+ }
+
+ fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
+ if let Some((graph, last_node)) = &self.unfinished_room {
+ /* To turn the graph into a polygon, we need a copy, might as well do
+ * it now, so we can add the working corner to it.
+ */
+ let mut graph = graph.clone();
+
+ // Add the current mouse position as the next position if possible.
+ graph.add_edge(&last_node, &self.last_mouse_pos_m);
+
+ if graph.num_nodes() <= 1 {
+ // Only able to draw a point
+ rld.draw_circle_v(
+ transform.point_m_to_px(&self.last_mouse_pos_m),
+ transform.length_m_to_px(0.1) as f32,
+ DEFAULT_COLOURS.room_selected,
+ );
+ } else if let Some(polygon) = graph.clone().bounding_polygon(FLOAT_MARGIN) {
+ let triangles = math::triangulate(polygon, FLOAT_MARGIN);
+ for triangle in triangles {
+ let triangle: [Vec2<f64>; 3] = triangle.into();
+ rld.draw_triangle(
+ transform.point_m_to_px(&triangle[0]),
+ transform.point_m_to_px(&triangle[1]),
+ transform.point_m_to_px(&triangle[2]),
+ DEFAULT_COLOURS.room_selected,
+ )
+ }
+ } else {
+ // For some reason the polygon creation failed. Draw lines for the edges instead.
+ for edge in graph.edge_iter() {
+ rld.draw_line_ex(
+ transform.point_m_to_px(&edge.start),
+ transform.point_m_to_px(&edge.end),
+ transform.length_m_to_px(0.1) as f32,
+ DEFAULT_COLOURS.room_selected,
+ );
+ }
+ }
+ }
+ }
+
+ fn place_single(
+ &mut self,
+ _map: &mut Map,
+ server: &Connection<Cargo>,
+ mouse_pos_m: &Vec2<f64>,
+ ) {
+ if let Some((ref mut graph, ref mut last_placed)) = &mut self.unfinished_room {
+ // If the corner already exists in the polygon, try to finish and push it after adding the
+ // next edge.
+ let try_finish = graph.has_node(&mouse_pos_m);
+
+ // Add an edge from the last corner to the currently active position if possible.
+ if graph.add_edge(last_placed, &mouse_pos_m) {
+ *last_placed = *mouse_pos_m;
+ }
+
+ if try_finish {
+ self.try_push(server);
+ }
+ } else {
+ // Start a new unfinished polygon
+ self.unfinished_room = Some((PolygonGraph::new(), *mouse_pos_m));
+ }
+ }
+
+ fn finish(&mut self, _map: &mut Map, server: &Connection<Cargo>) {
+ self.try_push(server);
+ }
+
+ fn abort(&mut self) {
+ self.unfinished_room = None;
+ }
+}