Correct snapping offsets after canvas transformation when using snap-reliant tools (#1370)
* fix: pen, spline tool incorrect snap offsets - re-render snapping offsets if canvas transformed during line draw * [wip]feat: add CanvasTransformed global message * [wip]fix: synchronize line tool snap offsets * fix: update offsets for shape tools on canvas transform * chore: remove unneeded function parameter * [wip]fix: use line tool at canvas level * refactor: revert line tool changes
This commit is contained in:
parent
2377240d07
commit
1c11ebcc4e
|
|
@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
|||
#[impl_message(Message, BroadcastMessage, TriggerEvent)]
|
||||
pub enum BroadcastEvent {
|
||||
DocumentIsDirty,
|
||||
CanvasTransformed,
|
||||
ToolAbort,
|
||||
SelectionChanged,
|
||||
WorkingColorChanged,
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPre
|
|||
TransformCanvasEnd => {
|
||||
self.tilt = self.snapped_angle();
|
||||
self.zoom = self.snapped_scale();
|
||||
responses.add(BroadcastEvent::CanvasTransformed);
|
||||
responses.add(BroadcastEvent::DocumentIsDirty);
|
||||
responses.add(ToolMessage::UpdateCursor);
|
||||
responses.add(ToolMessage::UpdateHints);
|
||||
|
|
@ -225,6 +226,7 @@ impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPre
|
|||
let transformed_delta = document.root.transform.inverse().transform_vector2(delta);
|
||||
|
||||
self.pan += transformed_delta;
|
||||
responses.add(BroadcastEvent::CanvasTransformed);
|
||||
responses.add(BroadcastEvent::DocumentIsDirty);
|
||||
self.create_document_transform(&ipp.viewport_bounds, responses);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ impl Resize {
|
|||
self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, input.mouse.position));
|
||||
}
|
||||
|
||||
/// Recalculates snap targets without snapping the starting position.
|
||||
pub fn recalculate_snaps(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, render_data: &RenderData) {
|
||||
self.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true);
|
||||
self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
|
||||
}
|
||||
|
||||
/// Calculate the drag start position in viewport space.
|
||||
pub fn viewport_drag_start(&self, document: &DocumentMessageHandler) -> DVec2 {
|
||||
let root_transform = document.document_legacy.root.transform;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ pub enum EllipseOptionsUpdate {
|
|||
pub enum EllipseToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
#[remain::unsorted]
|
||||
WorkingColorChanged,
|
||||
|
|
@ -165,6 +167,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for Ellipse
|
|||
impl ToolTransition for EllipseTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(EllipseToolMessage::CanvasTransformed.into()),
|
||||
tool_abort: Some(EllipseToolMessage::Abort.into()),
|
||||
working_color_changed: Some(EllipseToolMessage::WorkingColorChanged.into()),
|
||||
..Default::default()
|
||||
|
|
@ -209,6 +212,10 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
if let ToolMessage::Ellipse(event) = event {
|
||||
match (self, event) {
|
||||
(Drawing, CanvasTransformed) => {
|
||||
tool_data.data.recalculate_snaps(document, input, render_data);
|
||||
self
|
||||
}
|
||||
(Ready, DragStart) => {
|
||||
shape_data.start(responses, document, input, render_data);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ impl Default for LineOptions {
|
|||
pub enum LineToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
DocumentIsDirty,
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
#[remain::unsorted]
|
||||
WorkingColorChanged,
|
||||
|
|
@ -140,6 +144,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for LineToo
|
|||
impl ToolTransition for LineTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(LineToolMessage::CanvasTransformed.into()),
|
||||
tool_abort: Some(LineToolMessage::Abort.into()),
|
||||
working_color_changed: Some(LineToolMessage::WorkingColorChanged.into()),
|
||||
..Default::default()
|
||||
|
|
@ -219,7 +224,6 @@ impl Fsm for LineToolFsmState {
|
|||
tool_data.snap_manager.cleanup(responses);
|
||||
input.mouse.finish_transaction(tool_data.drag_start, responses);
|
||||
tool_data.path = None;
|
||||
|
||||
Ready
|
||||
}
|
||||
(Drawing, Abort) => {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ impl Default for PenOptions {
|
|||
pub enum PenToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
DocumentIsDirty,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
|
@ -193,6 +195,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PenTool
|
|||
impl ToolTransition for PenTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(PenToolMessage::CanvasTransformed.into()),
|
||||
document_dirty: Some(PenToolMessage::DocumentIsDirty.into()),
|
||||
tool_abort: Some(PenToolMessage::Abort.into()),
|
||||
selection_changed: Some(PenToolMessage::SelectionChanged.into()),
|
||||
|
|
@ -589,6 +592,10 @@ impl Fsm for PenToolFsmState {
|
|||
|
||||
if let ToolMessage::Pen(event) = event {
|
||||
match (self, event) {
|
||||
(_, PenToolMessage::CanvasTransformed) => {
|
||||
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true);
|
||||
self
|
||||
}
|
||||
(_, PenToolMessage::DocumentIsDirty) => {
|
||||
// When the document has moved / needs to be redraw, re-render the overlays
|
||||
// TODO the overlay system should probably receive this message instead of the tool
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ impl Default for PolygonOptions {
|
|||
pub enum PolygonToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
#[remain::unsorted]
|
||||
WorkingColorChanged,
|
||||
|
|
@ -205,6 +207,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for Polygon
|
|||
impl ToolTransition for PolygonTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(PolygonToolMessage::CanvasTransformed.into()),
|
||||
tool_abort: Some(PolygonToolMessage::Abort.into()),
|
||||
working_color_changed: Some(PolygonToolMessage::WorkingColorChanged.into()),
|
||||
..Default::default()
|
||||
|
|
@ -249,6 +252,10 @@ impl Fsm for PolygonToolFsmState {
|
|||
|
||||
if let ToolMessage::Polygon(event) = event {
|
||||
match (self, event) {
|
||||
(Drawing, CanvasTransformed) => {
|
||||
tool_data.data.recalculate_snaps(document, input, render_data);
|
||||
self
|
||||
}
|
||||
(Ready, DragStart) => {
|
||||
polygon_data.start(responses, document, input, render_data);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ pub enum RectangleOptionsUpdate {
|
|||
pub enum RectangleToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
#[remain::unsorted]
|
||||
WorkingColorChanged,
|
||||
|
|
@ -164,6 +166,7 @@ impl ToolMetadata for RectangleTool {
|
|||
impl ToolTransition for RectangleTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(RectangleToolMessage::CanvasTransformed.into()),
|
||||
tool_abort: Some(RectangleToolMessage::Abort.into()),
|
||||
working_color_changed: Some(RectangleToolMessage::WorkingColorChanged.into()),
|
||||
..Default::default()
|
||||
|
|
@ -208,6 +211,10 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
if let ToolMessage::Rectangle(event) = event {
|
||||
match (self, event) {
|
||||
(Drawing, CanvasTransformed) => {
|
||||
tool_data.data.recalculate_snaps(document, input, render_data);
|
||||
self
|
||||
}
|
||||
(Ready, DragStart) => {
|
||||
shape_data.start(responses, document, input, render_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ impl Default for SplineOptions {
|
|||
pub enum SplineToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
CanvasTransformed,
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
#[remain::unsorted]
|
||||
WorkingColorChanged,
|
||||
|
|
@ -178,6 +180,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for SplineT
|
|||
impl ToolTransition for SplineTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: Some(SplineToolMessage::CanvasTransformed.into()),
|
||||
tool_abort: Some(SplineToolMessage::Abort.into()),
|
||||
working_color_changed: Some(SplineToolMessage::WorkingColorChanged.into()),
|
||||
..Default::default()
|
||||
|
|
@ -219,6 +222,10 @@ impl Fsm for SplineToolFsmState {
|
|||
|
||||
if let ToolMessage::Spline(event) = event {
|
||||
match (self, event) {
|
||||
(_, CanvasTransformed) => {
|
||||
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true);
|
||||
self
|
||||
}
|
||||
(Ready, DragStart) => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for TextToo
|
|||
impl ToolTransition for TextTool {
|
||||
fn event_to_message_map(&self) -> EventToMessageMap {
|
||||
EventToMessageMap {
|
||||
canvas_transformed: None,
|
||||
document_dirty: Some(TextToolMessage::DocumentIsDirty.into()),
|
||||
tool_abort: Some(TextToolMessage::Abort.into()),
|
||||
selection_changed: Some(TextToolMessage::DocumentIsDirty.into()),
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ impl DocumentToolData {
|
|||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct EventToMessageMap {
|
||||
pub canvas_transformed: Option<ToolMessage>,
|
||||
pub document_dirty: Option<ToolMessage>,
|
||||
pub selection_changed: Option<ToolMessage>,
|
||||
pub tool_abort: Option<ToolMessage>,
|
||||
|
|
@ -189,6 +190,7 @@ pub trait ToolTransition {
|
|||
};
|
||||
|
||||
let event_to_tool_map = self.event_to_message_map();
|
||||
subscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed);
|
||||
subscribe_message(event_to_tool_map.document_dirty, BroadcastEvent::DocumentIsDirty);
|
||||
subscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort);
|
||||
subscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged);
|
||||
|
|
@ -206,6 +208,7 @@ pub trait ToolTransition {
|
|||
};
|
||||
|
||||
let event_to_tool_map = self.event_to_message_map();
|
||||
unsubscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed);
|
||||
unsubscribe_message(event_to_tool_map.document_dirty, BroadcastEvent::DocumentIsDirty);
|
||||
unsubscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort);
|
||||
unsubscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged);
|
||||
|
|
|
|||
Loading…
Reference in New Issue