aboutsummaryrefslogtreecommitdiff
path: root/src/tool
diff options
context:
space:
mode:
Diffstat (limited to 'src/tool')
-rw-r--r--src/tool/deletion_tool.rs75
-rw-r--r--src/tool/icon_tool.rs76
-rw-r--r--src/tool/mod.rs86
-rw-r--r--src/tool/polygon_room_tool.rs134
-rw-r--r--src/tool/rect_room_tool.rs80
-rw-r--r--src/tool/selection_tool.rs68
-rw-r--r--src/tool/wall_tool.rs69
7 files changed, 0 insertions, 588 deletions
diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs
deleted file mode 100644
index da2090b..0000000
--- a/src/tool/deletion_tool.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-//! A meta tool for selecting parts of a map and removing them in a single operation.
-//!
-//! The user can draw a rectangle, which currently must have it's side parallel to the x and y-axes
-//! of the world. With the first node placement, the mode is started, while the second placement would
-//! finish the process and delete all elements that are *completely* contained in the rectangle
-//! (partially contained items are not deleted) or abort it, in which case the selection is removed
-//! and nothing is deleted.
-
-use super::Tool;
-use crate::colours::DEFAULT_COLOURS;
-use crate::map::Map;
-use crate::math::{ExactSurface, Rect, Vec2};
-use crate::transform::Transform;
-use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
-
-/// The deletion tool itself.
-pub struct DeletionTool {
- deletion_rect: Option<(Vec2<f64>, Vec2<f64>)>,
-}
-
-impl DeletionTool {
- /// Create a new deletion tool, there should only be one deletion tool and it should be created
- /// by the editor.
- #[allow(clippy::new_without_default)]
- pub fn new() -> Self {
- Self {
- deletion_rect: None,
- }
- }
-}
-
-fn delete_rect((pos1, pos2): (&Vec2<f64>, &Vec2<f64>), map: &mut Map) {
- let bounds = Rect::bounding_rect(*pos1, *pos2);
- map.retain(|e| !bounds.contains_rect(&e.bounding_rect()));
-}
-
-impl Tool for DeletionTool {
- fn deactivate(&mut self) {
- self.deletion_rect = None;
- }
-
- fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
- if let Some((_, ref mut pos2)) = &mut self.deletion_rect {
- *pos2 = *mouse_pos_m;
- }
- }
-
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- if let Some((pos1, pos2)) = self.deletion_rect {
- let rect_px = transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2));
- rld.draw_rectangle_rec(rect_px, DEFAULT_COLOURS.deletion_rect);
- rld.draw_rectangle_lines_ex(rect_px, 4, DEFAULT_COLOURS.deletion_rect_outline);
- }
- }
-
- fn place_single(&mut self, map: &mut Map, mouse_pos_m: &Vec2<f64>) {
- if let Some((pos1, pos2)) = self.deletion_rect {
- delete_rect((&pos1, &pos2), map);
- self.deletion_rect = None;
- } else {
- self.deletion_rect = Some((*mouse_pos_m, *mouse_pos_m));
- }
- }
-
- fn finish(&mut self, map: &mut Map) {
- if let Some((pos1, pos2)) = self.deletion_rect {
- delete_rect((&pos1, &pos2), map);
- self.deletion_rect = None;
- }
- }
-
- fn abort(&mut self) {
- self.deletion_rect = None;
- }
-}
diff --git a/src/tool/icon_tool.rs b/src/tool/icon_tool.rs
deleted file mode 100644
index 8b4afc0..0000000
--- a/src/tool/icon_tool.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-//! Tool for creating icons. For explanation of icons, please see
-//! [the icon module](crate::map::icon).
-
-use crate::config::IconToolBinds;
-use crate::input::Input;
-use crate::map::icon_renderer::IconRenderer;
-use crate::map::{Icon, Map, Mappable};
-use crate::math::Vec2;
-use crate::tool::Tool;
-use crate::transform::Transform;
-use raylib::core::drawing::RaylibDrawHandle;
-use std::rc::Rc;
-
-/// The icon tool itself.
-pub struct IconTool {
- keybindings: IconToolBinds,
- /// Saves whether the IconTool is the currently active tool or not.
- active: bool,
- /// The information of the icon that should be placed / is currently being placed, if it
- /// exists.
- current_icon: Icon,
- renderer: Rc<IconRenderer>,
-}
-
-impl IconTool {
- /// Create a new icon tool that renders icons with the provided icon renderer. There should only
- /// be one instance of the tool for the program, which should be created in the editor.
- pub fn new(keybindings: IconToolBinds, renderer: Rc<IconRenderer>) -> Self {
- Self {
- keybindings,
- active: false,
- current_icon: Icon::new(0, Vec2::default(), 0., renderer.clone()),
- renderer,
- }
- }
-}
-
-impl Tool for IconTool {
- fn activate(&mut self) {
- self.active = true;
- }
-
- fn deactivate(&mut self) {
- self.active = false;
- }
-
- fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
- self.current_icon.position = *mouse_pos_m;
- }
-
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- if self.active {
- self.current_icon.draw(rld, transform);
- }
- }
-
- fn place_single(&mut self, map: &mut Map, _mouse_pos_m: &Vec2<f64>) {
- map.push_icon(self.current_icon.clone());
- }
-
- fn handle_custom_bindings(&mut self, _map: &mut Map, input: &mut Input) {
- if input.poll_global(&self.keybindings.next) {
- self.current_icon.id = (self.current_icon.id + 1) % self.renderer.num_icons();
- }
- if input.poll_global(&self.keybindings.previous) {
- self.current_icon.id =
- (self.current_icon.id + self.renderer.num_icons() - 1) % self.renderer.num_icons();
- }
- if input.poll_global(&self.keybindings.rotate_clockwise) {
- self.current_icon.rotation += 45.;
- }
- if input.poll_global(&self.keybindings.rotate_counterclockwise) {
- self.current_icon.rotation -= 45.;
- }
- }
-}
diff --git a/src/tool/mod.rs b/src/tool/mod.rs
deleted file mode 100644
index b3fae80..0000000
--- a/src/tool/mod.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-//! Tools, which are user interfaces that must be specifically selected in order to do something.
-//!
-//! As stated, a tool is not simply everything that helps a user do something, think of it more as a
-//! mode which must be elected by the user to perform a task on a specific object type or a class of
-//! objects. If instead the operation is defined by the state of the program, it is not a tool, since
-//! the user didn't explicitly ask for this function to be performed, but it is rather an option
-//! that's inherent to the situation the user finds themselves in.
-
-pub mod deletion_tool;
-pub mod icon_tool;
-pub mod polygon_room_tool;
-pub mod rect_room_tool;
-pub mod selection_tool;
-pub mod wall_tool;
-
-pub use deletion_tool::DeletionTool;
-pub use icon_tool::IconTool;
-pub use polygon_room_tool::PolygonRoomTool;
-pub use rect_room_tool::RectRoomTool;
-pub use selection_tool::SelectionTool;
-pub use wall_tool::WallTool;
-
-use crate::input::Input;
-use crate::map::Map;
-use crate::math::Vec2;
-use crate::transform::Transform;
-use raylib::core::drawing::RaylibDrawHandle;
-
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-#[repr(u8)]
-/// The types of tools available in graf karto. For information about the tool itself, please see the
-/// referenced Tool's documentation.
-pub enum ToolType {
- /// See [RectRoomTool] for information on this tool.
- RectRoomTool,
- /// See [PolygonRoomTool] for information on this tool.
- PolygonRoomTool,
- /// See [WallTool] for information on this tool.
- WallTool,
- /// See [IconTool] for information on this tool.
- IconTool,
- /// See [DeletionTool] for information on this tool.
- DeletionTool,
- /// See [SelectionTool] for information on this tool.
- SelectionTool,
- /// Not a real tool but used to know how many tools are available. New tools must be added
- /// above this variant.
- // TODO: Since we now use a hash map in the editor, check if this is still necessary at all.
- NumTools,
-}
-
-/// Base trait for tools. A tool is something that performs a specific action on one or more types of
-/// elements. It must be selected in order to be active. For this reason, the selection tool is a
-/// tool (it must be selected from the toolbox), but the dimension indicator for instance is not,
-/// since it is automatically updated when applicable.
-pub trait Tool {
- /// Code that needs to be called when this Tool is activated or reactivated goes here.
- fn activate(&mut self) {}
- /// Cleanup that needs to be done when the user switches from this tool to something else goes here.
- fn deactivate(&mut self) {}
-
- /// Called on each frame when this tool is active.
- fn update(&mut self, map: &Map, mouse_pos_m: &Vec2<f64>);
-
- /// Draw the contents of this tool.
- // TODO: Maybe make this tool mappable? This might make it easier to make things resizable while
- // it's still being drawn.
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform);
-
- /// Generic keybinding.
- /// Code to place a single node for this tool.
- fn place_single(&mut self, _map: &mut Map, _mouse_pos_m: &Vec2<f64>) {}
-
- /// Generic keybinding.
- /// Code to finish whatever one is doing with this tool currently and trying to apply the
- /// changes to the map data.
- fn finish(&mut self, _map: &mut Map) {}
-
- /// Generic keybinding.
- /// Stop whatever one is doing with this tool and do not apply any changes to the map data.
- fn abort(&mut self) {}
-
- /// If there are any additional keybindings that need to be handled by this tool, these can be
- /// handled here.
- fn handle_custom_bindings(&mut self, _map: &mut Map, _input: &mut Input) {}
-}
diff --git a/src/tool/polygon_room_tool.rs b/src/tool/polygon_room_tool.rs
deleted file mode 100644
index d7c188f..0000000
--- a/src/tool/polygon_room_tool.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-//! Tool to create rooms in the shape of generic polygons.
-
-use super::Tool;
-use crate::colours::DEFAULT_COLOURS;
-use crate::map::Map;
-use crate::math::{self, PolygonGraph, Vec2};
-use crate::transform::Transform;
-use crate::FLOAT_MARGIN;
-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, map: &mut Map) -> bool {
- if self.unfinished_room.is_none() {
- return false;
- }
-
- match self
- .unfinished_room
- .as_ref()
- .unwrap()
- .0
- .clone()
- .bounding_polygon(FLOAT_MARGIN)
- {
- Some(polygon) => {
- map.push_room(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, 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(map);
- }
- } else {
- // Start a new unfinished polygon
- self.unfinished_room = Some((PolygonGraph::new(), *mouse_pos_m));
- }
- }
-
- fn finish(&mut self, map: &mut Map) {
- self.try_push(map);
- }
-
- fn abort(&mut self) {
- self.unfinished_room = None;
- }
-}
diff --git a/src/tool/rect_room_tool.rs b/src/tool/rect_room_tool.rs
deleted file mode 100644
index ec0f0ec..0000000
--- a/src/tool/rect_room_tool.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-//! The rectangle room tool is a specialised tool to create rooms of rectangular shape and with the
-//! sides of the room parallel to the x and y-axes. This is often useful, when a quick room creation
-//! is necessary and the shape of the room does not have to be very special.
-
-use super::Tool;
-use crate::colours::DEFAULT_COLOURS;
-use crate::map::Map;
-use crate::math::{Rect, Vec2};
-use crate::transform::Transform;
-use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
-
-/// The tool to create simple, rectangular rooms.
-pub struct RectRoomTool {
- /// The rectangle that is currently being drawn by the user. Once it is finished, it will be
- /// pushed into the room_rects.
- unfinished_rect: Option<(Vec2<f64>, Vec2<f64>)>,
-}
-
-impl RectRoomTool {
- /// Create a new room tool where no rooms have been drawn yet. Should be created only once per
- /// program instance and by the editor.
- #[allow(clippy::new_without_default)]
- pub fn new() -> Self {
- Self {
- unfinished_rect: None,
- }
- }
-}
-
-impl Tool for RectRoomTool {
- fn deactivate(&mut self) {
- self.unfinished_rect = None;
- }
-
- fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
- if let Some((_, ref mut pos2)) = &mut self.unfinished_rect {
- *pos2 = *mouse_pos_m;
- }
- }
-
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- if let Some((pos1, pos2)) = self.unfinished_rect {
- rld.draw_rectangle_rec(
- transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2)),
- DEFAULT_COLOURS.room_selected,
- );
- }
- }
-
- fn place_single(&mut self, map: &mut Map, mouse_pos_m: &Vec2<f64>) {
- // Try to finish the rectangle if it has been started.
- if let Some((pos1, pos2)) = self.unfinished_rect {
- if pos1 == pos2 {
- warn!("Cannot place rectangle with start and endpoint being the same");
- return;
- }
-
- map.push_room(Rect::bounding_rect(pos1, pos2).into());
- self.unfinished_rect = None;
- } else {
- self.unfinished_rect = Some((*mouse_pos_m, *mouse_pos_m));
- }
- }
-
- fn finish(&mut self, map: &mut Map) {
- if let Some((pos1, pos2)) = self.unfinished_rect {
- if pos1 == pos2 {
- warn!("Cannot place rectangle with start and endpoint being the same");
- return;
- }
-
- map.push_room(Rect::bounding_rect(pos1, pos2).into());
- self.unfinished_rect = None;
- }
- }
-
- fn abort(&mut self) {
- self.unfinished_rect = None;
- }
-}
diff --git a/src/tool/selection_tool.rs b/src/tool/selection_tool.rs
deleted file mode 100644
index 4850a28..0000000
--- a/src/tool/selection_tool.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Selection of items on the map.
-//!
-//! When selecting items on the map, the editor goes into a different mode than when editing a
-//! specific kind of item. Actions that are available for specific types of items become
-//! unavailable, while other actions that make use of the properties to a wide range of items
-//! become available instead.
-//! For this reason, the selection tool can be thought of as a kind of meta tool over tools.
-
-use super::Tool;
-use crate::colours::DEFAULT_COLOURS;
-use crate::map::Map;
-use crate::math::{ExactSurface, Rect, Vec2};
-use crate::transform::Transform;
-use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
-
-/// The selection tool makes it possible to select any item on the map when activated.
-pub struct SelectionTool {
- selection_rect: Option<(Vec2<f64>, Vec2<f64>)>,
-}
-
-impl SelectionTool {
- /// Create a new selection tool. There should be only one such tool per program instance and it
- /// should be created in the editor.
- #[allow(clippy::new_without_default)]
- pub fn new() -> Self {
- Self {
- selection_rect: None,
- }
- }
-}
-
-impl Tool for SelectionTool {
- fn deactivate(&mut self) {
- self.selection_rect = None;
- }
-
- fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
- if let Some((_, ref mut pos2)) = &mut self.selection_rect {
- *pos2 = *mouse_pos_m;
- }
- }
-
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- if let Some((pos1, pos2)) = self.selection_rect {
- let rect_px = transform.rect_m_to_px(&Rect::bounding_rect(pos1, pos2));
- rld.draw_rectangle_rec(rect_px, DEFAULT_COLOURS.selection_rect);
- rld.draw_rectangle_lines_ex(rect_px, 4, DEFAULT_COLOURS.selection_rect_outline);
- }
- }
-
- fn place_single(&mut self, map: &mut Map, mouse_pos_m: &Vec2<f64>) {
- if let Some((pos1, pos2)) = self.selection_rect {
- // Select all items on the map that are inside of the selection rectangle
- let bounds = Rect::bounding_rect(pos1, pos2);
- for element in map.elements_mut() {
- // TODO: Make it possible to do this additively by custom keybinding.
- element.set_selected(bounds.contains_rect(&element.bounding_rect()));
- }
- self.selection_rect = None;
- } else {
- self.selection_rect = Some((*mouse_pos_m, *mouse_pos_m));
- }
- }
-
- fn abort(&mut self) {
- self.selection_rect = None;
- }
-}
diff --git a/src/tool/wall_tool.rs b/src/tool/wall_tool.rs
deleted file mode 100644
index e79d815..0000000
--- a/src/tool/wall_tool.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-//! Tool to create walls. For information about walls, see also
-//! [the wall module](crate::map::wall).
-
-use super::Tool;
-use crate::map::Map;
-use crate::math::{LineSegment, Vec2};
-use crate::transform::Transform;
-use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle};
-use raylib::ffi::{Color, Vector2};
-
-/// The wall tool to create solid barriers a player usually cannot cross.
-pub struct WallTool {
- unfinished_wall: Option<LineSegment<f64>>,
-}
-
-impl WallTool {
- /// Create a new wall tool. There should only be one wall tool per program instance, which should
- /// be created inside of the editor.
- #[allow(clippy::new_without_default)]
- pub fn new() -> Self {
- Self {
- unfinished_wall: None,
- }
- }
-}
-
-impl Tool for WallTool {
- fn deactivate(&mut self) {
- self.unfinished_wall = None;
- }
-
- fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2<f64>) {
- if let Some(ref mut wall) = &mut self.unfinished_wall {
- wall.end = *mouse_pos_m;
- }
- }
-
- fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) {
- if let Some(ref wall) = self.unfinished_wall {
- let start: Vector2 = transform.point_m_to_px(&wall.start).into();
- let end: Vector2 = transform.point_m_to_px(&wall.end).into();
- rld.draw_line_ex(
- start,
- end,
- transform.length_m_to_px(0.1) as f32,
- Color {
- r: 150,
- g: 200,
- b: 150,
- a: 255,
- },
- );
- }
- }
-
- fn place_single(&mut self, map: &mut Map, mouse_pos_m: &Vec2<f64>) {
- if let Some(wall) = self.unfinished_wall.take() {
- // Continue with the next wall straight away.
- self.unfinished_wall = Some(LineSegment::new(wall.end, wall.end));
- map.push_wall(wall);
- } else {
- self.unfinished_wall = Some(LineSegment::new(*mouse_pos_m, *mouse_pos_m));
- }
- }
-
- fn abort(&mut self) {
- self.unfinished_wall = None;
- }
-}