aboutsummaryrefslogtreecommitdiff
path: root/src/tool
diff options
context:
space:
mode:
authorArne Dußin2020-11-08 16:00:54 +0100
committerArne Dußin2020-11-08 16:00:54 +0100
commite08cb85528e6b72d5f3b2fbeb79b581fa7a4e461 (patch)
tree15b443ce0aa82ae662a544523bd91633aafd011e /src/tool
parentc89592a9de3a9d21082952b8d90584d759ed7ef3 (diff)
downloadgraf_karto-e08cb85528e6b72d5f3b2fbeb79b581fa7a4e461.tar.gz
graf_karto-e08cb85528e6b72d5f3b2fbeb79b581fa7a4e461.zip
Make it so icons can rotate
Diffstat (limited to 'src/tool')
-rw-r--r--src/tool/deletion_tool.rs6
-rw-r--r--src/tool/icon_tool.rs90
2 files changed, 67 insertions, 29 deletions
diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs
index 24d239f..142e0cb 100644
--- a/src/tool/deletion_tool.rs
+++ b/src/tool/deletion_tool.rs
@@ -25,7 +25,9 @@ impl DeletionTool {
map_data
.walls_mut()
.retain(|&(pos1, pos2)| !rect.contains(pos1) || !rect.contains(pos2));
- map_data.icons_mut().retain(|&(_, pos)| !rect.contains(pos));
+ map_data
+ .icons_mut()
+ .retain(|icon| !rect.contains(icon.position));
}
}
@@ -51,7 +53,7 @@ impl Tool for DeletionTool {
}
}
- fn draw(&self, map_data: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) {
+ fn draw(&self, _map_data: &MapData, 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(
diff --git a/src/tool/icon_tool.rs b/src/tool/icon_tool.rs
index 0ff1dc2..89a07e8 100644
--- a/src/tool/icon_tool.rs
+++ b/src/tool/icon_tool.rs
@@ -8,13 +8,13 @@ use raylib::core::texture::Texture2D;
use raylib::ffi::{Color, KeyboardKey, MouseButton};
use raylib::{RaylibHandle, RaylibThread};
use ron::de::from_reader;
-use serde::Deserialize;
+use serde::{Deserialize, Serialize};
use std::fs::{self, File};
pub const ICON_DIR: &'static str = "assets/icons";
#[derive(Deserialize)]
-struct IconInfo {
+struct IconFileInfo {
/// The position the icon should be anchored in pixels. This is the Vector it will be moved by
/// relative to the mouse pointer (to the left and up).
anchor: Vec2<f32>,
@@ -22,14 +22,24 @@ struct IconInfo {
pixels_per_m: f32,
}
+#[derive(Serialize, Deserialize)]
+pub struct IconInfo {
+ /// The id of the icon is the icons position in the currently loaded icon_data vector.
+ pub icon_id: usize,
+ /// The position of the icon on the map, given by the vector in meters.
+ pub position: Vec2<f32>,
+ /// Rotation of the icon texture in degrees.
+ pub rotation: f32,
+}
+
pub struct IconTool {
// TODO: support svg
/// The icon data, containing the image texture and the info for that image texture like the
/// scale the image actually has.
- icon_data: Vec<(Texture2D, IconInfo)>,
- /// The currently active icon, defined by its position in the Vec.
- active_icon: usize,
- current_icon_pos: Option<Vec2<f32>>,
+ icon_data: Vec<(Texture2D, IconFileInfo)>,
+ /// The information of the icon that should be placed / is currently being placed, if it
+ /// exists.
+ current_icon: Option<IconInfo>,
}
impl IconTool {
@@ -70,7 +80,7 @@ impl IconTool {
let mut file = file.path();
file.set_extension("ron");
let ron = File::open(file).expect("Could not read ron file for icon information.");
- let icon_info: IconInfo =
+ let icon_info: IconFileInfo =
from_reader(ron).expect("Could not parse icon info from reader.");
icon_data.push((texture, icon_info));
@@ -78,40 +88,61 @@ impl IconTool {
Self {
icon_data,
- active_icon: 0,
- current_icon_pos: None,
+ current_icon: None,
}
}
}
impl Tool for IconTool {
fn active_update(&mut self, map: &mut MapData, rl: &RaylibHandle, transform: &Transform) {
- // Put the currently active icon to where it would be placed.
- self.current_icon_pos = Some(snap_to_grid(
- transform.point_px_to_m(rl.get_mouse_position().into()),
- 0.5,
- ));
+ // Update the position of the icon that should be drawn to the current mouse position, or
+ // create a new default icon if there was `None`.
+ let snapped_mouse_pos_m =
+ snap_to_grid(transform.point_px_to_m(rl.get_mouse_position().into()), 0.5);
+ self.current_icon = match self.current_icon.take() {
+ Some(mut icon) => {
+ icon.position = snapped_mouse_pos_m;
+ Some(icon)
+ }
+ None => Some(IconInfo {
+ icon_id: 0,
+ position: snapped_mouse_pos_m,
+ rotation: 0.,
+ }),
+ };
- // Activate the next icon when pressing the icon tool key.
- if rl.is_key_pressed(KeyboardKey::KEY_I) {
- self.active_icon = (self.active_icon + 1) % self.icon_data.len();
+ {
+ // Unwrap the current icon, since it is now definitely set, as we are in the active update.
+ let active_icon = self.current_icon.as_mut().unwrap();
+ // Activate the next icon when pressing the icon tool key.
+ if rl.is_key_pressed(KeyboardKey::KEY_I) {
+ active_icon.icon_id = (active_icon.icon_id + 1) % self.icon_data.len();
+ }
+ if rl.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON) {
+ // Rotate the currently active icon by a quarter rotation.
+ active_icon.rotation += 45.;
+ }
}
// Handle placing the icon on the map
if rl.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON) {
- map.icons_mut()
- .push((self.active_icon, self.current_icon_pos.unwrap()));
+ map.icons_mut().push(self.current_icon.take().unwrap());
}
}
fn draw(&self, map: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) {
// Draw all icons that have been placed on the map.
- for (icon, pos) in map.icons() {
- let (texture, info) = &self.icon_data[*icon];
+ for icon in map.icons() {
+ let (texture, info) = &self.icon_data[icon.icon_id];
+ // Round the position to whole pixels to fix rotation problems.
+ let mut position_px =
+ transform.point_m_to_px(icon.position - (info.anchor / info.pixels_per_m));
+ position_px.x = position_px.x as i32 as f32;
+ position_px.y = position_px.y as i32 as f32;
rld.draw_texture_ex(
texture,
- transform.point_m_to_px(*pos - (info.anchor / info.pixels_per_m)),
- 0.,
+ position_px,
+ icon.rotation,
transform.pixels_per_m() / info.pixels_per_m,
Color {
r: 255,
@@ -123,12 +154,17 @@ impl Tool for IconTool {
}
// Draw the icon that would be placed
- if let Some(current_icon_pos) = self.current_icon_pos {
- let (texture, info) = &self.icon_data[self.active_icon];
+ if let Some(current_icon) = &self.current_icon {
+ let (texture, info) = &self.icon_data[current_icon.icon_id];
+ // Round the position to whole pixels to fix rotation problems.
+ let mut position_px =
+ transform.point_m_to_px(current_icon.position - (info.anchor / info.pixels_per_m));
+ position_px.x = position_px.x as i32 as f32;
+ position_px.y = position_px.y as i32 as f32;
rld.draw_texture_ex(
texture,
- transform.point_m_to_px(current_icon_pos - (info.anchor / info.pixels_per_m)),
- 0.,
+ position_px,
+ current_icon.rotation,
transform.pixels_per_m() / info.pixels_per_m,
Color {
r: 120,