Remove transformations from LayerData (#439)

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube 2021-12-31 03:10:30 +00:00 committed by Keavon Chambers
parent 854d6cc8e4
commit 7ab127c3ae
5 changed files with 89 additions and 91 deletions

View File

@ -193,7 +193,7 @@ impl DocumentMessageHandler {
pub fn with_name(name: String, ipp: &InputPreprocessor) -> Self { pub fn with_name(name: String, ipp: &InputPreprocessor) -> Self {
let mut document = Self { name, ..Self::default() }; let mut document = Self { name, ..Self::default() };
document.graphene_document.root.transform = document.layer_data(&[]).calculate_offset_transform(ipp.viewport_bounds.size() / 2., 0.); document.graphene_document.root.transform = document.movement_handler.calculate_offset_transform(ipp.viewport_bounds.size() / 2.);
document document
} }
@ -497,9 +497,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
fn process_action(&mut self, message: DocumentMessage, ipp: &InputPreprocessor, responses: &mut VecDeque<Message>) { fn process_action(&mut self, message: DocumentMessage, ipp: &InputPreprocessor, responses: &mut VecDeque<Message>) {
use DocumentMessage::*; use DocumentMessage::*;
match message { match message {
Movement(message) => self Movement(message) => self.movement_handler.process_action(message, (&self.graphene_document, ipp), responses),
.movement_handler
.process_action(message, (Self::layer_data_mut_no_borrow_self(&mut self.layer_data, &[]), &self.graphene_document, ipp), responses),
TransformLayers(message) => self TransformLayers(message) => self
.transform_layer_handler .transform_layer_handler
.process_action(message, (&mut self.layer_data, &mut self.graphene_document, ipp), responses), .process_action(message, (&mut self.layer_data, &mut self.graphene_document, ipp), responses),
@ -764,9 +762,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
} }
.into(), .into(),
); );
let root_layerdata = self.layer_data(&[]); let document_transform = &self.movement_handler;
let scale = 0.5 + ASYMPTOTIC_EFFECT + root_layerdata.scale * SCALE_EFFECT; let scale = 0.5 + ASYMPTOTIC_EFFECT + document_transform.scale * SCALE_EFFECT;
let viewport_size = ipp.viewport_bounds.size(); let viewport_size = ipp.viewport_bounds.size();
let viewport_mid = ipp.viewport_bounds.center(); let viewport_mid = ipp.viewport_bounds.center();
let [bounds1, bounds2] = self.graphene_document.visible_layers_bounding_box().unwrap_or([viewport_mid; 2]); let [bounds1, bounds2] = self.graphene_document.visible_layers_bounding_box().unwrap_or([viewport_mid; 2]);
@ -777,9 +775,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
let scrollbar_multiplier = bounds_length - viewport_size; let scrollbar_multiplier = bounds_length - viewport_size;
let scrollbar_size = viewport_size / bounds_length; let scrollbar_size = viewport_size / bounds_length;
let log = root_layerdata.scale.log2(); let log = document_transform.scale.log2();
let ruler_interval = if log < 0. { 100. * 2_f64.powf(-log.ceil()) } else { 100. / 2_f64.powf(log.ceil()) }; let ruler_interval = if log < 0. { 100. * 2_f64.powf(-log.ceil()) } else { 100. / 2_f64.powf(log.ceil()) };
let ruler_spacing = ruler_interval * root_layerdata.scale; let ruler_spacing = ruler_interval * document_transform.scale;
let ruler_origin = self.graphene_document.root.transform.transform_point2(DVec2::ZERO); let ruler_origin = self.graphene_document.root.transform.transform_point2(DVec2::ZERO);

View File

@ -104,7 +104,7 @@ impl DocumentsMessageHandler {
} }
// TODO Fix how this doesn't preserve tab order upon loading new document from file>load // TODO Fix how this doesn't preserve tab order upon loading new document from file>load
fn load_document(&mut self, mut new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque<Message>) { fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque<Message>) {
// Special case when loading a document on an empty page // Special case when loading a document on an empty page
if replace_first_empty && self.active_document().is_unmodified_default() { if replace_first_empty && self.active_document().is_unmodified_default() {
responses.push_back(DocumentsMessage::CloseDocument(self.active_document_id).into()); responses.push_back(DocumentsMessage::CloseDocument(self.active_document_id).into());

View File

@ -2,36 +2,17 @@ use glam::{DAffine2, DVec2};
use graphene::layers::{style::ViewMode, BlendMode, Layer, LayerData as DocumentLayerData, LayerDataType}; use graphene::layers::{style::ViewMode, BlendMode, Layer, LayerData as DocumentLayerData, LayerDataType};
use graphene::LayerId; use graphene::LayerId;
use serde::{ser::SerializeStruct, Deserialize, Serialize}; use serde::{ser::SerializeStruct, Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt; use std::fmt;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Copy)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Copy)]
pub struct LayerData { pub struct LayerData {
pub selected: bool, pub selected: bool,
pub expanded: bool, pub expanded: bool,
pub translation: DVec2,
pub rotation: f64,
pub scale: f64,
} }
impl LayerData { impl LayerData {
pub fn new(expanded: bool) -> LayerData { pub fn new(expanded: bool) -> LayerData {
LayerData { LayerData { selected: false, expanded }
selected: false,
expanded,
translation: DVec2::ZERO,
rotation: 0.,
scale: 1.,
}
}
pub fn calculate_offset_transform(&self, offset: DVec2, snapped_angle: f64) -> DAffine2 {
// TODO: replace with DAffine2::from_scale_angle_translation and fix the errors
let offset_transform = DAffine2::from_translation(offset);
let scale_transform = DAffine2::from_scale(DVec2::new(self.scale, self.scale));
let angle_transform = DAffine2::from_angle(snapped_angle);
let translation_transform = DAffine2::from_translation(self.translation);
scale_transform * offset_transform * angle_transform * translation_transform
} }
} }

View File

@ -1,6 +1,6 @@
use crate::consts::VIEWPORT_ROTATE_SNAP_INTERVAL; use crate::consts::VIEWPORT_ROTATE_SNAP_INTERVAL;
pub use crate::document::layer_panel::*; pub use crate::document::layer_panel::*;
use crate::document::{DocumentMessage, LayerData}; use crate::document::DocumentMessage;
use crate::message_prelude::*; use crate::message_prelude::*;
use crate::{ use crate::{
consts::{VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_WHEEL_RATE}, consts::{VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_WHEEL_RATE},
@ -9,7 +9,7 @@ use crate::{
use graphene::document::Document; use graphene::document::Document;
use graphene::Operation as DocumentOperation; use graphene::Operation as DocumentOperation;
use glam::DVec2; use glam::{DAffine2, DVec2};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::VecDeque; use std::collections::VecDeque;
@ -34,42 +34,67 @@ pub enum MovementMessage {
TranslateCanvasByViewportFraction(DVec2), TranslateCanvasByViewportFraction(DVec2),
} }
#[derive(Debug, Clone, Default, PartialEq)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MovementMessageHandler { pub struct MovementMessageHandler {
translating: bool, translating: bool,
pub translation: DVec2,
rotating: bool, rotating: bool,
pub rotation: f64,
zooming: bool, zooming: bool,
snapping: bool, pub scale: f64,
mouse_pos: ViewportPosition,
snap_rotate: bool, snap_rotate: bool,
mouse_pos: ViewportPosition,
}
impl Default for MovementMessageHandler {
fn default() -> Self {
Self {
scale: 1.,
translating: false,
translation: DVec2::ZERO,
rotating: false,
rotation: 0.,
zooming: false,
snap_rotate: false,
mouse_pos: ViewportPosition::default(),
}
}
} }
impl MovementMessageHandler { impl MovementMessageHandler {
pub fn snapped_angle(&self, layerdata: &LayerData) -> f64 { pub fn snapped_angle(&self) -> f64 {
let increment_radians: f64 = VIEWPORT_ROTATE_SNAP_INTERVAL.to_radians(); let increment_radians: f64 = VIEWPORT_ROTATE_SNAP_INTERVAL.to_radians();
if self.snap_rotate { if self.snap_rotate {
(layerdata.rotation / increment_radians).round() * increment_radians (self.rotation / increment_radians).round() * increment_radians
} else { } else {
layerdata.rotation self.rotation
} }
} }
pub fn calculate_offset_transform(&self, offset: DVec2) -> DAffine2 {
// TODO: replace with DAffine2::from_scale_angle_translation and fix the errors
let offset_transform = DAffine2::from_translation(offset);
let scale_transform = DAffine2::from_scale(DVec2::new(self.scale, self.scale));
let angle_transform = DAffine2::from_angle(self.snapped_angle());
let translation_transform = DAffine2::from_translation(self.translation);
scale_transform * offset_transform * angle_transform * translation_transform
}
fn create_document_transform_from_layerdata(&self, layerdata: &LayerData, viewport_bounds: &ViewportBounds, responses: &mut VecDeque<Message>) { fn create_document_transform(&self, viewport_bounds: &ViewportBounds, responses: &mut VecDeque<Message>) {
let half_viewport = viewport_bounds.size() / 2.; let half_viewport = viewport_bounds.size() / 2.;
let scaled_half_viewport = half_viewport / layerdata.scale; let scaled_half_viewport = half_viewport / self.scale;
responses.push_back( responses.push_back(
DocumentOperation::SetLayerTransform { DocumentOperation::SetLayerTransform {
path: vec![], path: vec![],
transform: layerdata.calculate_offset_transform(scaled_half_viewport, self.snapped_angle(layerdata)).to_cols_array(), transform: self.calculate_offset_transform(scaled_half_viewport).to_cols_array(),
} }
.into(), .into(),
); );
} }
} }
impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreprocessor)> for MovementMessageHandler { impl MessageHandler<MovementMessage, (&Document, &InputPreprocessor)> for MovementMessageHandler {
fn process_action(&mut self, message: MovementMessage, data: (&mut LayerData, &Document, &InputPreprocessor), responses: &mut VecDeque<Message>) { fn process_action(&mut self, message: MovementMessage, data: (&Document, &InputPreprocessor), responses: &mut VecDeque<Message>) {
let (layer_data, document, ipp) = data; let (document, ipp) = data;
use MovementMessage::*; use MovementMessage::*;
match message { match message {
TranslateCanvasBegin => { TranslateCanvasBegin => {
@ -78,18 +103,20 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
} }
RotateCanvasBegin { snap } => { RotateCanvasBegin { snap } => {
self.rotating = true; self.rotating = true;
self.snapping = snap;
self.snap_rotate = snap; self.snap_rotate = snap;
self.mouse_pos = ipp.mouse.position; self.mouse_pos = ipp.mouse.position;
} }
EnableSnapping => self.snapping = true, EnableSnapping => self.snap_rotate = true,
DisableSnapping => self.snapping = false, DisableSnapping => {
self.rotation = self.snapped_angle();
self.snap_rotate = false
}
ZoomCanvasBegin => { ZoomCanvasBegin => {
self.zooming = true; self.zooming = true;
self.mouse_pos = ipp.mouse.position; self.mouse_pos = ipp.mouse.position;
} }
TransformCanvasEnd => { TransformCanvasEnd => {
layer_data.rotation = self.snapped_angle(layer_data); self.rotation = self.snapped_angle();
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.snap_rotate = false; self.snap_rotate = false;
self.translating = false; self.translating = false;
@ -101,9 +128,9 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
let delta = ipp.mouse.position - self.mouse_pos; let delta = ipp.mouse.position - self.mouse_pos;
let transformed_delta = document.root.transform.inverse().transform_vector2(delta); let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
layer_data.translation += transformed_delta; self.translation += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
if self.rotating { if self.rotating {
let half_viewport = ipp.viewport_bounds.size() / 2.; let half_viewport = ipp.viewport_bounds.size() / 2.;
@ -113,53 +140,45 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
start_vec.angle_between(end_vec) start_vec.angle_between(end_vec)
}; };
let snapping = self.snapping; self.rotation += rotation;
layer_data.rotation += rotation;
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.snap_rotate = snapping; responses.push_back(FrontendMessage::SetCanvasRotation { new_radians: self.snapped_angle() }.into());
responses.push_back( self.create_document_transform(&ipp.viewport_bounds, responses);
FrontendMessage::SetCanvasRotation {
new_radians: self.snapped_angle(layer_data),
}
.into(),
);
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses);
} }
if self.zooming { if self.zooming {
let difference = self.mouse_pos.y as f64 - ipp.mouse.position.y as f64; let difference = self.mouse_pos.y as f64 - ipp.mouse.position.y as f64;
let amount = 1. + difference * VIEWPORT_ZOOM_MOUSE_RATE; let amount = 1. + difference * VIEWPORT_ZOOM_MOUSE_RATE;
let new = (layer_data.scale * amount).clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); let new = (self.scale * amount).clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX);
layer_data.scale = new; self.scale = new;
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into()); self.create_document_transform(&ipp.viewport_bounds, responses);
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses);
} }
self.mouse_pos = ipp.mouse.position; self.mouse_pos = ipp.mouse.position;
} }
SetCanvasZoom(new) => { SetCanvasZoom(new) => {
layer_data.scale = new.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); self.scale = new.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX);
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
IncreaseCanvasZoom => { IncreaseCanvasZoom => {
// TODO: Eliminate redundant code by making this call SetCanvasZoom // TODO: Eliminate redundant code by making this call SetCanvasZoom
layer_data.scale = *VIEWPORT_ZOOM_LEVELS.iter().find(|scale| **scale > layer_data.scale).unwrap_or(&layer_data.scale); self.scale = *VIEWPORT_ZOOM_LEVELS.iter().find(|scale| **scale > self.scale).unwrap_or(&self.scale);
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
DecreaseCanvasZoom => { DecreaseCanvasZoom => {
// TODO: Eliminate redundant code by making this call SetCanvasZoom // TODO: Eliminate redundant code by making this call SetCanvasZoom
layer_data.scale = *VIEWPORT_ZOOM_LEVELS.iter().rev().find(|scale| **scale < layer_data.scale).unwrap_or(&layer_data.scale); self.scale = *VIEWPORT_ZOOM_LEVELS.iter().rev().find(|scale| **scale < self.scale).unwrap_or(&self.scale);
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
WheelCanvasZoom => { WheelCanvasZoom => {
// TODO: Eliminate redundant code by making this call SetCanvasZoom // TODO: Eliminate redundant code by making this call SetCanvasZoom
@ -176,13 +195,13 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
let delta = delta_size * (DVec2::splat(0.5) - mouse_fraction); let delta = delta_size * (DVec2::splat(0.5) - mouse_fraction);
let transformed_delta = document.root.transform.inverse().transform_vector2(delta); let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
let new = (layer_data.scale * zoom_factor).clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); let new = (self.scale * zoom_factor).clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX);
layer_data.scale = new; self.scale = new;
layer_data.translation += transformed_delta; self.translation += transformed_delta;
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
WheelCanvasTranslate { use_y_as_x } => { WheelCanvasTranslate { use_y_as_x } => {
let delta = match use_y_as_x { let delta = match use_y_as_x {
@ -190,14 +209,14 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
true => (-ipp.mouse.scroll_delta.y as f64, 0.).into(), true => (-ipp.mouse.scroll_delta.y as f64, 0.).into(),
} * VIEWPORT_SCROLL_RATE; } * VIEWPORT_SCROLL_RATE;
let transformed_delta = document.root.transform.inverse().transform_vector2(delta); let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
layer_data.translation += transformed_delta; self.translation += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
SetCanvasRotation(new) => { SetCanvasRotation(new) => {
layer_data.rotation = new; self.rotation = new;
self.create_document_transform(&ipp.viewport_bounds, responses);
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses);
responses.push_back(FrontendMessage::SetCanvasRotation { new_radians: new }.into()); responses.push_back(FrontendMessage::SetCanvasRotation { new_radians: new }.into());
} }
ZoomCanvasToFitAll => { ZoomCanvasToFitAll => {
@ -212,27 +231,27 @@ impl MessageHandler<MovementMessage, (&mut LayerData, &Document, &InputPreproces
let size = 1. / size; let size = 1. / size;
let new_scale = size.min_element(); let new_scale = size.min_element();
layer_data.translation += center; self.translation += center;
layer_data.scale *= new_scale; self.scale *= new_scale;
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: self.scale }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(FrontendMessage::SetCanvasZoom { new_zoom: layer_data.scale }.into());
responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
} }
TranslateCanvas(delta) => { TranslateCanvas(delta) => {
let transformed_delta = document.root.transform.inverse().transform_vector2(delta); let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
layer_data.translation += transformed_delta; self.translation += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
TranslateCanvasByViewportFraction(delta) => { TranslateCanvasByViewportFraction(delta) => {
let transformed_delta = document.root.transform.inverse().transform_vector2(delta * ipp.viewport_bounds.size()); let transformed_delta = document.root.transform.inverse().transform_vector2(delta * ipp.viewport_bounds.size());
layer_data.translation += transformed_delta; self.translation += transformed_delta;
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
self.create_document_transform_from_layerdata(layer_data, &ipp.viewport_bounds, responses); self.create_document_transform(&ipp.viewport_bounds, responses);
} }
} }
} }

View File

@ -31,7 +31,7 @@ pub struct OverlayMessageHandler {
impl MessageHandler<OverlayMessage, (&mut LayerData, &Document, &InputPreprocessor)> for OverlayMessageHandler { impl MessageHandler<OverlayMessage, (&mut LayerData, &Document, &InputPreprocessor)> for OverlayMessageHandler {
fn process_action(&mut self, message: OverlayMessage, data: (&mut LayerData, &Document, &InputPreprocessor), responses: &mut VecDeque<Message>) { fn process_action(&mut self, message: OverlayMessage, data: (&mut LayerData, &Document, &InputPreprocessor), responses: &mut VecDeque<Message>) {
let (layerdata, document, ipp) = data; let (layer_data, document, ipp) = data;
use OverlayMessage::*; use OverlayMessage::*;
match message { match message {
DispatchOperation(operation) => match self.overlays_graphene_document.handle_operation(&operation) { DispatchOperation(operation) => match self.overlays_graphene_document.handle_operation(&operation) {