mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
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:
parent
91543d530d
commit
790647815b
20 changed files with 128 additions and 75 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue