Refactor ViewportPosition from u32 (UVec2) to f64 (DVec2) (#345)

* Refactor ViewportPosition from u32 (UVec2) to f64 (DVec2)

* Fix pseudo_hash call

* Replace hash function with proper function for uuid generation

* Cargo fmt

Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Keavon Chambers 2021-08-14 02:45:24 -07:00 committed by GitHub
parent 91543d530d
commit 790647815b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 128 additions and 75 deletions

48
Cargo.lock generated
View file

@ -98,7 +98,9 @@ dependencies = [
"graphite-graphene",
"graphite-proc-macros",
"log",
"rand_chacha",
"serde",
"spin",
"thiserror",
]
@ -187,6 +189,15 @@ version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "lock_api"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
@ -202,6 +213,12 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro2"
version = "1.0.27"
@ -220,6 +237,22 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
[[package]]
name = "regex"
version = "1.5.4"
@ -249,6 +282,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.126"
@ -280,6 +319,15 @@ dependencies = [
"serde",
]
[[package]]
name = "spin"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5"
dependencies = [
"lock_api",
]
[[package]]
name = "syn"
version = "1.0.73"

View file

@ -15,6 +15,8 @@ thiserror = "1.0.24"
serde = { version = "1.0", features = ["derive"] }
graphite-proc-macros = { path = "../proc-macros" }
glam = { version="0.17", features = ["serde"] }
rand_chacha = "0.3.1"
spin = "0.9.2"
[dependencies.graphene]
path = "../graphene"

View file

@ -100,11 +100,11 @@ mod test {
}));
editor.select_primary_color(Color::RED);
editor.draw_rect(100, 200, 300, 400);
editor.draw_rect(100., 200., 300., 400.);
editor.select_primary_color(Color::BLUE);
editor.draw_shape(10, 1200, 1300, 400);
editor.draw_shape(10., 1200., 1300., 400.);
editor.select_primary_color(Color::GREEN);
editor.draw_ellipse(104, 1200, 1300, 400);
editor.draw_ellipse(104., 1200., 1300., 400.);
editor
}
@ -278,7 +278,7 @@ mod test {
editor.handle_message(DocumentMessage::SelectLayers(vec![vec![rect_id], vec![ellipse_id]])).unwrap();
editor.handle_message(DocumentsMessage::CopySelectedLayers).unwrap();
editor.handle_message(DocumentMessage::DeleteSelectedLayers).unwrap();
editor.draw_rect(0, 800, 12, 200);
editor.draw_rect(0., 800., 12., 200.);
editor.handle_message(DocumentsMessage::PasteLayers { path: vec![], insert_index: -1 }).unwrap();
editor.handle_message(DocumentsMessage::PasteLayers { path: vec![], insert_index: -1 }).unwrap();
@ -303,7 +303,7 @@ mod test {
/// - create rect, shape and ellipse
/// - select ellipse and rect
/// - move them down and back up again
fn move_seletion() {
fn move_selection() {
init_logger();
let mut editor = create_editor_with_three_layers();

View file

@ -1,16 +1,20 @@
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
pub mod dispatcher;
pub mod message;
use crate::message_prelude::*;
pub use dispatcher::*;
use rand_chacha::{
rand_core::{RngCore, SeedableRng},
ChaCha20Rng,
};
use spin::Mutex;
pub use crate::input::InputPreprocessor;
use std::collections::VecDeque;
pub type ActionList = Vec<Vec<MessageDiscriminant>>;
static RNG: Mutex<Option<ChaCha20Rng>> = Mutex::new(None);
// TODO: Add Send + Sync requirement
// Use something like rw locks for synchronization
pub trait MessageHandlerData {}
@ -25,12 +29,10 @@ where
fn actions(&self) -> ActionList;
}
pub fn generate_hash<'a>(messages: impl IntoIterator<Item = &'a Message>, ipp: &InputPreprocessor, document_hash: u64) -> u64 {
let mut s = DefaultHasher::new();
document_hash.hash(&mut s);
ipp.hash(&mut s);
for message in messages {
message.pseudo_hash().hash(&mut s);
pub fn generate_uuid() -> u64 {
let mut lock = RNG.lock();
if lock.is_none() {
*lock = Some(ChaCha20Rng::seed_from_u64(0));
}
s.finish()
lock.as_mut().map(ChaCha20Rng::next_u64).unwrap()
}

View file

@ -242,7 +242,7 @@ impl DocumentMessageHandler {
}
/// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain
/// any actual data, but ratfolderch as visibility and names of the layers.
/// any actual data, but rather attributes such as visibility and names of the layers.
pub fn layer_panel(&mut self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, EditorError> {
let folder = self.document.folder(path)?;
let paths: Vec<Vec<LayerId>> = folder.layer_ids.iter().map(|id| [path, &[*id]].concat()).collect();
@ -284,7 +284,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
CommitTransaction => self.document_backup = None,
ExportDocument => {
let bbox = self.document.visible_layers_bounding_box().unwrap_or([DVec2::ZERO, ipp.viewport_size.as_f64()]);
let bbox = self.document.visible_layers_bounding_box().unwrap_or([DVec2::ZERO, ipp.viewport_size]);
let size = bbox[1] - bbox[0];
let name = match self.name.ends_with(FILE_SAVE_SUFFIX) {
true => self.name.clone().replace(FILE_SAVE_SUFFIX, FILE_EXPORT_SUFFIX),

View file

@ -32,7 +32,7 @@ pub enum MovementMessage {
ZoomCanvasToFitAll,
}
#[derive(Debug, Clone, Hash, Default, PartialEq)]
#[derive(Debug, Clone, Default, PartialEq)]
pub struct MovementMessageHandler {
translating: bool,
rotating: bool,
@ -43,7 +43,7 @@ pub struct MovementMessageHandler {
impl MovementMessageHandler {
fn create_document_transform_from_layerdata(&self, layerdata: &LayerData, viewport_size: &ViewportPosition, responses: &mut VecDeque<Message>) {
let half_viewport = viewport_size.as_f64() / 2.;
let half_viewport = *viewport_size / 2.;
let scaled_half_viewport = half_viewport / layerdata.scale;
responses.push_back(
DocumentOperation::SetLayerTransform {
@ -64,7 +64,6 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
self.translating = true;
self.mouse_pos = ipp.mouse.position;
}
RotateCanvasBegin { snap } => {
self.rotating = true;
self.snapping = snap;
@ -86,17 +85,17 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
}
MouseMove => {
if self.translating {
let delta = ipp.mouse.position.as_f64() - self.mouse_pos.as_f64();
let delta = ipp.mouse.position - self.mouse_pos;
let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
layerdata.translation += transformed_delta;
self.create_document_transform_from_layerdata(layerdata, &ipp.viewport_size, responses);
}
if self.rotating {
let half_viewport = ipp.viewport_size.as_f64() / 2.;
let half_viewport = ipp.viewport_size / 2.;
let rotation = {
let start_vec = self.mouse_pos.as_f64() - half_viewport;
let end_vec = ipp.mouse.position.as_f64() - half_viewport;
let start_vec = self.mouse_pos - half_viewport;
let end_vec = ipp.mouse.position - half_viewport;
start_vec.angle_between(end_vec)
};
@ -140,8 +139,8 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
}
WheelCanvasZoom => {
let scroll = ipp.mouse.scroll_delta.scroll_delta();
let mouse = ipp.mouse.position.as_f64();
let viewport_size = ipp.viewport_size.as_f64();
let mouse = ipp.mouse.position;
let viewport_size = ipp.viewport_size;
let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE;
if ipp.mouse.scroll_delta.y > 0 {
zoom_factor = 1. / zoom_factor
@ -177,7 +176,7 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
let pos1 = document.root.transform.inverse().transform_point2(pos1);
let pos2 = document.root.transform.inverse().transform_point2(pos2);
let v1 = document.root.transform.inverse().transform_point2(DVec2::ZERO);
let v2 = document.root.transform.inverse().transform_point2(ipp.viewport_size.as_f64());
let v2 = document.root.transform.inverse().transform_point2(ipp.viewport_size);
let center = v1.lerp(v2, 0.5) - pos1.lerp(pos2, 0.5);
let size = (pos2 - pos1) / (v2 - v1);

View file

@ -30,7 +30,7 @@ bitflags! {
}
}
#[derive(Debug, Default, Hash)]
#[derive(Debug, Default)]
pub struct InputPreprocessor {
pub keyboard: KeyStates,
pub mouse: MouseState,
@ -81,7 +81,7 @@ impl MessageHandler<InputPreprocessorMessage, ()> for InputPreprocessor {
responses.push_back(
graphene::Operation::TransformLayer {
path: vec![],
transform: glam::DAffine2::from_translation((size.as_f64() - self.viewport_size.as_f64()) / 2.).to_cols_array(),
transform: glam::DAffine2::from_translation((size - self.viewport_size) / 2.).to_cols_array(),
}
.into(),
);
@ -141,7 +141,7 @@ mod test {
#[test]
fn process_action_mouse_move_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
let message = InputPreprocessorMessage::MouseMove((4, 809).into(), ModifierKeys::ALT);
let message = InputPreprocessorMessage::MouseMove((4., 809.).into(), ModifierKeys::ALT);
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);

View file

@ -1,8 +1,8 @@
use bitflags::bitflags;
use glam::DVec2;
// origin is top left
pub type ViewportPosition = glam::UVec2;
// Origin is top left
pub type ViewportPosition = DVec2;
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
pub struct ScrollDelta {
@ -23,7 +23,7 @@ impl ScrollDelta {
}
}
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
#[derive(Debug, Copy, Clone, Default, PartialEq)]
pub struct MouseState {
pub position: ViewportPosition,
pub mouse_keys: MouseKeys,
@ -31,17 +31,18 @@ pub struct MouseState {
}
impl MouseState {
pub fn new() -> MouseState {
pub fn new() -> Self {
Self::default()
}
pub fn from_pos(x: u32, y: u32) -> MouseState {
MouseState {
pub fn from_pos(x: f64, y: f64) -> Self {
Self {
position: (x, y).into(),
mouse_keys: MouseKeys::default(),
scroll_delta: ScrollDelta::default(),
}
}
pub fn from_u8_pos(keys: u8, position: ViewportPosition) -> Self {
let mouse_keys = MouseKeys::from_bits(keys).expect("invalid modifier keys");
Self {

View file

@ -50,7 +50,7 @@ impl Editor {
}
pub mod message_prelude {
pub use crate::communication::generate_hash;
pub use crate::communication::generate_uuid;
pub use crate::communication::message::{AsMessage, Message, MessageDiscriminant};
pub use crate::communication::{ActionList, MessageHandler};
pub use crate::document::{DocumentMessage, DocumentMessageDiscriminant};

View file

@ -11,35 +11,35 @@ use graphene::color::Color;
/// A set of utility functions to make the writing of editor test more declarative
pub trait EditorTestUtils {
fn draw_rect(&mut self, x1: u32, y1: u32, x2: u32, y2: u32);
fn draw_shape(&mut self, x1: u32, y1: u32, x2: u32, y2: u32);
fn draw_ellipse(&mut self, x1: u32, y1: u32, x2: u32, y2: u32);
fn draw_rect(&mut self, x1: f64, y1: f64, x2: f64, y2: f64);
fn draw_shape(&mut self, x1: f64, y1: f64, x2: f64, y2: f64);
fn draw_ellipse(&mut self, x1: f64, y1: f64, x2: f64, y2: f64);
/// Select given tool and drag it from (x1, y1) to (x2, y2)
fn drag_tool(&mut self, typ: ToolType, x1: u32, y1: u32, x2: u32, y2: u32);
fn move_mouse(&mut self, x: u32, y: u32);
fn drag_tool(&mut self, typ: ToolType, x1: f64, y1: f64, x2: f64, y2: f64);
fn move_mouse(&mut self, x: f64, y: f64);
fn mousedown(&mut self, state: MouseState);
fn mouseup(&mut self, state: MouseState);
fn lmb_mousedown(&mut self, x: u32, y: u32);
fn lmb_mousedown(&mut self, x: f64, y: f64);
fn input(&mut self, message: InputPreprocessorMessage);
fn select_tool(&mut self, typ: ToolType);
fn select_primary_color(&mut self, color: Color);
}
impl EditorTestUtils for Editor {
fn draw_rect(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) {
fn draw_rect(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) {
self.drag_tool(ToolType::Rectangle, x1, y1, x2, y2);
}
fn draw_shape(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) {
fn draw_shape(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) {
self.drag_tool(ToolType::Shape, x1, y1, x2, y2);
}
fn draw_ellipse(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) {
fn draw_ellipse(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) {
self.drag_tool(ToolType::Ellipse, x1, y1, x2, y2);
}
fn drag_tool(&mut self, typ: ToolType, x1: u32, y1: u32, x2: u32, y2: u32) {
fn drag_tool(&mut self, typ: ToolType, x1: f64, y1: f64, x2: f64, y2: f64) {
self.select_tool(typ);
self.move_mouse(x1, y1);
self.lmb_mousedown(x1, y1);
@ -51,7 +51,7 @@ impl EditorTestUtils for Editor {
});
}
fn move_mouse(&mut self, x: u32, y: u32) {
fn move_mouse(&mut self, x: f64, y: f64) {
self.input(InputPreprocessorMessage::MouseMove((x, y).into(), ModifierKeys::default()));
}
@ -63,7 +63,7 @@ impl EditorTestUtils for Editor {
self.handle_message(InputPreprocessorMessage::MouseUp(state, ModifierKeys::default())).unwrap()
}
fn lmb_mousedown(&mut self, x: u32, y: u32) {
fn lmb_mousedown(&mut self, x: f64, y: f64) {
self.mousedown(MouseState {
position: (x, y).into(),
mouse_keys: MouseKeys::LEFT,

View file

@ -58,7 +58,7 @@ impl Fsm for EllipseToolFsmState {
fn transition(
self,
event: ToolMessage,
document: &DocumentMessageHandler,
_document: &DocumentMessageHandler,
tool_data: &DocumentToolData,
data: &mut Self::ToolData,
input: &InputPreprocessor,
@ -72,7 +72,7 @@ impl Fsm for EllipseToolFsmState {
(Ready, DragStart) => {
shape_data.drag_start = input.mouse.position;
responses.push_back(DocumentMessage::StartTransaction.into());
shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
shape_data.path = Some(vec![generate_uuid()]);
responses.push_back(DocumentMessage::DeselectAllLayers.into());
responses.push_back(

View file

@ -19,7 +19,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
let mouse_pos = data.2.mouse.position;
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
let quad = Quad::from_box([mouse_pos.as_f64() - tolerance, mouse_pos.as_f64() + tolerance]);
let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]);
if let Some(path) = data.0.document.intersects_quad_root(quad).last() {
if let Ok(layer) = data.0.document.layer(path) {

View file

@ -17,7 +17,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Fill {
fn process_action(&mut self, _action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
let mouse_pos = data.2.mouse.position;
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
let quad = Quad::from_box([mouse_pos.as_f64() - tolerance, mouse_pos.as_f64() + tolerance]);
let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]);
if let Some(path) = data.0.document.intersects_quad_root(quad).last() {
responses.push_back(

View file

@ -59,7 +59,7 @@ impl Fsm for LineToolFsmState {
fn transition(
self,
event: ToolMessage,
document: &DocumentMessageHandler,
_document: &DocumentMessageHandler,
tool_data: &DocumentToolData,
data: &mut Self::ToolData,
input: &InputPreprocessor,
@ -72,7 +72,7 @@ impl Fsm for LineToolFsmState {
(Ready, DragStart) => {
data.drag_start = input.mouse.position;
responses.push_back(DocumentMessage::StartTransaction.into());
data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
data.path = Some(vec![generate_uuid()]);
responses.push_back(DocumentMessage::DeselectAllLayers.into());
responses.push_back(
@ -122,8 +122,8 @@ impl Fsm for LineToolFsmState {
}
fn generate_transform(data: &mut LineToolData, lock: bool, snap: bool, center: bool) -> Message {
let mut start = data.drag_start.as_f64();
let stop = data.drag_current.as_f64();
let mut start = data.drag_start;
let stop = data.drag_current;
let dir = stop - start;

View file

@ -65,7 +65,7 @@ impl Fsm for PenToolFsmState {
responses: &mut VecDeque<Message>,
) -> Self {
let transform = document.document.root.transform;
let pos = transform.inverse() * DAffine2::from_translation(input.mouse.position.as_f64());
let pos = transform.inverse() * DAffine2::from_translation(input.mouse.position);
use PenMessage::*;
use PenToolFsmState::*;
@ -74,7 +74,7 @@ impl Fsm for PenToolFsmState {
(Ready, DragStart) => {
responses.push_back(DocumentMessage::StartTransaction.into());
responses.push_back(DocumentMessage::DeselectAllLayers.into());
data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
data.path = Some(vec![generate_uuid()]);
data.points.push(pos);
data.next_point = pos;

View file

@ -58,7 +58,7 @@ impl Fsm for RectangleToolFsmState {
fn transition(
self,
event: ToolMessage,
document: &DocumentMessageHandler,
_document: &DocumentMessageHandler,
tool_data: &DocumentToolData,
data: &mut Self::ToolData,
input: &InputPreprocessor,
@ -72,7 +72,7 @@ impl Fsm for RectangleToolFsmState {
(Ready, DragStart) => {
shape_data.drag_start = input.mouse.position;
responses.push_back(DocumentMessage::StartTransaction.into());
shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
shape_data.path = Some(vec![generate_uuid()]);
responses.push_back(DocumentMessage::DeselectAllLayers.into());
responses.push_back(

View file

@ -11,8 +11,8 @@ pub struct Resize {
}
impl Resize {
pub fn calculate_transform(&self, center: Key, lock_ratio: Key, ipp: &InputPreprocessor) -> Option<Message> {
let mut start = self.drag_start.as_f64();
let stop = ipp.mouse.position.as_f64();
let mut start = self.drag_start;
let stop = ipp.mouse.position;
let mut size = stop - start;
if ipp.keyboard.get(lock_ratio as usize) {

View file

@ -79,9 +79,9 @@ impl SelectToolData {
fn selection_box(&self) -> [DVec2; 2] {
if self.drag_current == self.drag_start {
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
[self.drag_start.as_f64() - tolerance, self.drag_start.as_f64() + tolerance]
[self.drag_start - tolerance, self.drag_start + tolerance]
} else {
[self.drag_start.as_f64(), self.drag_current.as_f64()]
[self.drag_start, self.drag_current]
}
}
}
@ -122,7 +122,7 @@ impl Fsm for SelectToolFsmState {
Dragging
} else {
responses.push_back(DocumentMessage::DeselectAllLayers.into());
data.box_id = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
data.box_id = Some(vec![generate_uuid()]);
responses.push_back(
Operation::AddBoundingBox {
path: data.box_id.clone().unwrap(),
@ -139,7 +139,7 @@ impl Fsm for SelectToolFsmState {
responses.push_back(
Operation::TransformLayerInViewport {
path: path.clone(),
transform: DAffine2::from_translation(input.mouse.position.as_f64() - data.drag_current.as_f64()).to_cols_array(),
transform: DAffine2::from_translation(input.mouse.position - data.drag_current).to_cols_array(),
}
.into(),
);
@ -149,8 +149,8 @@ impl Fsm for SelectToolFsmState {
}
(DrawingBox, MouseMove) => {
data.drag_current = input.mouse.position;
let start = data.drag_start.as_f64();
let size = data.drag_current.as_f64() - start;
let start = data.drag_start;
let size = data.drag_current - start;
responses.push_back(
Operation::SetLayerTransformInViewport {

View file

@ -58,7 +58,7 @@ impl Fsm for ShapeToolFsmState {
fn transition(
self,
event: ToolMessage,
document: &DocumentMessageHandler,
_document: &DocumentMessageHandler,
tool_data: &DocumentToolData,
data: &mut Self::ToolData,
input: &InputPreprocessor,
@ -72,7 +72,7 @@ impl Fsm for ShapeToolFsmState {
(Ready, DragStart) => {
shape_data.drag_start = input.mouse.position;
responses.push_back(DocumentMessage::StartTransaction.into());
shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
shape_data.path = Some(vec![generate_uuid()]);
responses.push_back(DocumentMessage::DeselectAllLayers.into());
data.sides = match tool_data.tool_options.get(&ToolType::Shape) {
Some(&ToolOptions::Shape {

View file

@ -107,7 +107,7 @@ pub fn close_all_documents_with_confirmation() -> Result<(), JsValue> {
// TODO: Call event when the panels are resized
/// Viewport resized
#[wasm_bindgen]
pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> {
pub fn viewport_resize(new_width: f64, new_height: f64) -> Result<(), JsValue> {
let ev = InputPreprocessorMessage::ViewportResize((new_width, new_height).into());
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
}
@ -115,8 +115,9 @@ pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> {
// TODO: When a mouse button is down that started in the viewport, this should trigger even when the mouse is outside the viewport (or even the browser window if the browser supports it)
/// Mouse movement within the screenspace bounds of the viewport
#[wasm_bindgen]
pub fn on_mouse_move(x: u32, y: u32, modifiers: u8) -> Result<(), JsValue> {
pub fn on_mouse_move(x: f64, y: f64, modifiers: u8) -> Result<(), JsValue> {
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
// TODO: Convert these screenspace viewport coordinates to canvas coordinates based on the current zoom and pan
let ev = InputPreprocessorMessage::MouseMove((x, y).into(), mods);
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
@ -133,7 +134,7 @@ pub fn on_mouse_scroll(delta_x: i32, delta_y: i32, delta_z: i32, modifiers: u8)
/// A mouse button depressed within screenspace the bounds of the viewport
#[wasm_bindgen]
pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
pub fn on_mouse_down(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
let ev = InputPreprocessorMessage::MouseDown(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods);
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
@ -141,7 +142,7 @@ pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<()
/// A mouse button released
#[wasm_bindgen]
pub fn on_mouse_up(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
pub fn on_mouse_up(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
let ev = InputPreprocessorMessage::MouseUp(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods);
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)