Implement anchor and handle point rendering with the Path Tool (#353)

* Implement Path Tool

* Draw a red rectangle where the first point on the shape is

* Correctly render anchors, handles, and connecting lines

* Fix drain() which can panic

* Refactor frontend messages to work as return values not callbacks

* Reduce the number of unnecessary frontend updates

* Fix stack overflow by using a loop

* Group Document Render calls and put them at the end

* Speed hacks for dirtification

* Add performance

* Bunch folder changed updates

* Add triggers to redraw overlays to movement_handler

* Polish the pixel-perfect rendering of vector manipulators

* Restore scrollbars that were disabled

* Cleanup

* WIP Add shape outline rendering

* Fix compiling

* Add outlines to selected shapes

* Fix outlines rendering over handles and anchors

* Fix dirtification

* Add a comment

* Address code review feedback

* Formatting

* Small tweaks

Co-authored-by: Oliver Davies <oliver@psyfer.io>
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Keavon Chambers
2021-08-29 00:10:54 -07:00
committed by GitHub
parent 8336b3e809
commit 913b9365e2
41 changed files with 759 additions and 282 deletions

View File

@@ -7,13 +7,14 @@ use super::{
use crate::message_prelude::*;
use crate::tool::ToolType;
use serde::{Deserialize, Serialize};
use std::fmt::Write;
const NUDGE_AMOUNT: f64 = 1.;
const SHIFT_NUDGE_AMOUNT: f64 = 10.;
#[impl_message(Message, InputMapper)]
#[derive(PartialEq, Clone, Debug, Hash)]
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
pub enum InputMapperMessage {
PointerMove,
MouseScroll,
@@ -172,14 +173,16 @@ impl Default for Mapping {
// Fill
entry! {action=FillMessage::MouseDown, key_down=Lmb},
// Tool Actions
entry! {action=ToolMessage::SelectTool(ToolType::Fill), key_down=KeyF},
entry! {action=ToolMessage::SelectTool(ToolType::Rectangle), key_down=KeyM},
entry! {action=ToolMessage::SelectTool(ToolType::Ellipse), key_down=KeyE},
entry! {action=ToolMessage::SelectTool(ToolType::Select), key_down=KeyV},
entry! {action=ToolMessage::SelectTool(ToolType::Line), key_down=KeyL},
entry! {action=ToolMessage::SelectTool(ToolType::Pen), key_down=KeyP},
entry! {action=ToolMessage::SelectTool(ToolType::Shape), key_down=KeyY},
entry! {action=ToolMessage::SelectTool(ToolType::Eyedropper), key_down=KeyI},
entry! {action=ToolMessage::ActivateTool(ToolType::Select), key_down=KeyV},
entry! {action=ToolMessage::ActivateTool(ToolType::Eyedropper), key_down=KeyI},
entry! {action=ToolMessage::ActivateTool(ToolType::Fill), key_down=KeyF},
entry! {action=ToolMessage::ActivateTool(ToolType::Path), key_down=KeyA},
entry! {action=ToolMessage::ActivateTool(ToolType::Pen), key_down=KeyP},
entry! {action=ToolMessage::ActivateTool(ToolType::Line), key_down=KeyL},
entry! {action=ToolMessage::ActivateTool(ToolType::Rectangle), key_down=KeyM},
entry! {action=ToolMessage::ActivateTool(ToolType::Ellipse), key_down=KeyE},
entry! {action=ToolMessage::ActivateTool(ToolType::Shape), key_down=KeyY},
// Colors
entry! {action=ToolMessage::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]},
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
// Editor Actions
@@ -300,7 +303,7 @@ impl InputMapper {
let mut actions = actions
.into_iter()
.flatten()
.filter(|a| !matches!(*a, MessageDiscriminant::Tool(ToolMessageDiscriminant::SelectTool) | MessageDiscriminant::Global(_)));
.filter(|a| !matches!(*a, MessageDiscriminant::Tool(ToolMessageDiscriminant::ActivateTool) | MessageDiscriminant::Global(_)));
self.mapping
.key_down
.iter()

View File

@@ -7,9 +7,10 @@ use bitflags::bitflags;
#[doc(inline)]
pub use graphene::DocumentResponse;
use serde::{Deserialize, Serialize};
#[impl_message(Message, InputPreprocessor)]
#[derive(PartialEq, Clone, Debug)]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum InputPreprocessorMessage {
MouseDown(EditorMouseState, ModifierKeys),
MouseUp(EditorMouseState, ModifierKeys),
@@ -21,7 +22,7 @@ pub enum InputPreprocessorMessage {
}
bitflags! {
#[derive(Default)]
#[derive(Default, Serialize, Deserialize)]
#[repr(transparent)]
pub struct ModifierKeys: u8 {
const CONTROL = 0b0000_0001;

View File

@@ -1,11 +1,12 @@
use bitflags::bitflags;
use glam::DVec2;
use serde::{Deserialize, Serialize};
// Origin is top left
pub type ViewportPosition = DVec2;
pub type EditorPosition = DVec2;
#[derive(PartialEq, Clone, Debug, Default)]
#[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)]
pub struct ViewportBounds {
pub top_left: DVec2,
pub bottom_right: DVec2,
@@ -28,7 +29,7 @@ impl ViewportBounds {
}
}
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ScrollDelta {
pub x: i32,
pub y: i32,
@@ -47,7 +48,7 @@ impl ScrollDelta {
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq)]
#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct MouseState {
pub position: ViewportPosition,
pub mouse_keys: MouseKeys,
@@ -77,7 +78,7 @@ impl MouseState {
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq)]
#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct EditorMouseState {
pub editor_position: EditorPosition,
pub mouse_keys: MouseKeys,
@@ -116,7 +117,7 @@ impl EditorMouseState {
}
bitflags! {
#[derive(Default)]
#[derive(Default, Serialize, Deserialize)]
#[repr(transparent)]
pub struct MouseKeys: u8 {
const LEFT = 0b0000_0001;