Skip to content

Commit 913b936

Browse files
KeavonotdaviesTrueDoctor
authored
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 <[email protected]> Co-authored-by: Dennis Kobert <[email protected]>
1 parent 8336b3e commit 913b936

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+758
-281
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@ members = [
88
]
99

1010
[profile.release.package.graphite-wasm]
11-
opt-level = "s"
11+
opt-level = 3
12+
13+
[profile.dev.package.graphite-wasm]
14+
opt-level = 3
15+
16+
[profile.dev]
17+
opt-level = 3

editor/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ graphite-proc-macros = { path = "../proc-macros" }
1717
glam = { version="0.17", features = ["serde"] }
1818
rand_chacha = "0.3.1"
1919
spin = "0.9.2"
20+
kurbo = { git = "https://github.com/GraphiteEditor/kurbo.git", features = [
21+
"serde",
22+
] }
2023

2124
[dependencies.graphene]
2225
path = "../graphene"

editor/src/communication/dispatcher.rs

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{frontend::FrontendMessageHandler, message_prelude::*, Callback, EditorError};
1+
use crate::{message_prelude::*, EditorError};
22

33
pub use crate::document::DocumentsMessageHandler;
44
pub use crate::input::{InputMapper, InputPreprocessor};
@@ -8,57 +8,54 @@ use crate::global::GlobalMessageHandler;
88
use std::collections::VecDeque;
99

1010
pub struct Dispatcher {
11-
frontend_message_handler: FrontendMessageHandler,
1211
input_preprocessor: InputPreprocessor,
1312
input_mapper: InputMapper,
1413
global_message_handler: GlobalMessageHandler,
1514
tool_message_handler: ToolMessageHandler,
1615
documents_message_handler: DocumentsMessageHandler,
1716
messages: VecDeque<Message>,
17+
pub responses: Vec<FrontendMessage>,
1818
}
1919

20+
const GROUP_MESSAGES: &[MessageDiscriminant] = &[
21+
MessageDiscriminant::Documents(DocumentsMessageDiscriminant::Document(DocumentMessageDiscriminant::RenderDocument)),
22+
MessageDiscriminant::Documents(DocumentsMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
23+
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateLayer),
24+
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::ExpandFolder),
25+
MessageDiscriminant::Tool(ToolMessageDiscriminant::SelectedLayersChanged),
26+
];
27+
2028
impl Dispatcher {
2129
pub fn handle_message<T: Into<Message>>(&mut self, message: T) -> Result<(), EditorError> {
22-
let message = message.into();
30+
self.messages.push_back(message.into());
31+
2332
use Message::*;
24-
if !(matches!(
25-
message,
26-
Message::InputPreprocessor(_)
27-
| Message::InputMapper(_)
28-
| Message::Documents(DocumentsMessage::Document(DocumentMessage::RenderDocument))
29-
| Message::Frontend(FrontendMessage::UpdateCanvas { .. })
30-
| Message::Frontend(FrontendMessage::UpdateScrollbars { .. })
31-
| Message::Frontend(FrontendMessage::SetCanvasZoom { .. })
32-
| Message::Frontend(FrontendMessage::SetCanvasRotation { .. })
33-
) || MessageDiscriminant::from(&message).local_name().ends_with("MouseMove"))
34-
{
35-
log::trace!("Message: {:?}", message);
36-
//log::trace!("Hints:{:?}", self.input_mapper.hints(self.collect_actions()));
37-
}
38-
match message {
39-
NoOp => (),
40-
Documents(message) => self.documents_message_handler.process_action(message, &self.input_preprocessor, &mut self.messages),
41-
Global(message) => self.global_message_handler.process_action(message, (), &mut self.messages),
42-
Tool(message) => self
43-
.tool_message_handler
44-
.process_action(message, (self.documents_message_handler.active_document(), &self.input_preprocessor), &mut self.messages),
45-
Frontend(message) => self.frontend_message_handler.process_action(message, (), &mut self.messages),
46-
InputPreprocessor(message) => self.input_preprocessor.process_action(message, (), &mut self.messages),
47-
InputMapper(message) => {
48-
let actions = self.collect_actions();
49-
self.input_mapper.process_action(message, (&self.input_preprocessor, actions), &mut self.messages)
33+
while let Some(message) = self.messages.pop_front() {
34+
if GROUP_MESSAGES.contains(&message.to_discriminant()) && self.messages.contains(&message) {
35+
continue;
36+
}
37+
log_message(&message);
38+
match message {
39+
NoOp => (),
40+
Documents(message) => self.documents_message_handler.process_action(message, &self.input_preprocessor, &mut self.messages),
41+
Global(message) => self.global_message_handler.process_action(message, (), &mut self.messages),
42+
Tool(message) => self
43+
.tool_message_handler
44+
.process_action(message, (self.documents_message_handler.active_document(), &self.input_preprocessor), &mut self.messages),
45+
Frontend(message) => self.responses.push(message),
46+
InputPreprocessor(message) => self.input_preprocessor.process_action(message, (), &mut self.messages),
47+
InputMapper(message) => {
48+
let actions = self.collect_actions();
49+
self.input_mapper.process_action(message, (&self.input_preprocessor, actions), &mut self.messages)
50+
}
5051
}
51-
}
52-
if let Some(message) = self.messages.pop_front() {
53-
self.handle_message(message)?;
5452
}
5553
Ok(())
5654
}
5755

5856
pub fn collect_actions(&self) -> ActionList {
5957
//TODO: reduce the number of heap allocations
6058
let mut list = Vec::new();
61-
list.extend(self.frontend_message_handler.actions());
6259
list.extend(self.input_preprocessor.actions());
6360
list.extend(self.input_mapper.actions());
6461
list.extend(self.global_message_handler.actions());
@@ -67,24 +64,36 @@ impl Dispatcher {
6764
list
6865
}
6966

70-
pub fn new(callback: Callback) -> Dispatcher {
67+
pub fn new() -> Dispatcher {
7168
Dispatcher {
72-
frontend_message_handler: FrontendMessageHandler::new(callback),
7369
input_preprocessor: InputPreprocessor::default(),
7470
global_message_handler: GlobalMessageHandler::new(),
7571
input_mapper: InputMapper::default(),
7672
documents_message_handler: DocumentsMessageHandler::default(),
7773
tool_message_handler: ToolMessageHandler::default(),
7874
messages: VecDeque::new(),
75+
responses: vec![],
7976
}
8077
}
8178
}
8279

80+
fn log_message(message: &Message) {
81+
use Message::*;
82+
if log::max_level() == log::LevelFilter::Trace
83+
&& !(matches!(
84+
message,
85+
InputPreprocessor(_) | Frontend(FrontendMessage::SetCanvasZoom { .. }) | Frontend(FrontendMessage::SetCanvasRotation { .. })
86+
) || MessageDiscriminant::from(message).local_name().ends_with("MouseMove"))
87+
{
88+
log::trace!("Message: {:?}", message);
89+
//log::trace!("Hints:{:?}", self.input_mapper.hints(self.collect_actions()));
90+
}
91+
}
92+
8393
#[cfg(test)]
8494
mod test {
8595
use crate::{document::DocumentMessageHandler, message_prelude::*, misc::test_utils::EditorTestUtils, Editor};
8696
use graphene::{color::Color, Operation};
87-
use log::info;
8897

8998
fn init_logger() {
9099
let _ = env_logger::builder().is_test(true).try_init();
@@ -95,9 +104,7 @@ mod test {
95104
/// 2. A blue shape
96105
/// 3. A green ellipse
97106
fn create_editor_with_three_layers() -> Editor {
98-
let mut editor = Editor::new(Box::new(|e| {
99-
info!("Got frontend message: {:?}", e);
100-
}));
107+
let mut editor = Editor::new();
101108

102109
editor.select_primary_color(Color::RED);
103110
editor.draw_rect(100., 200., 300., 400.);

editor/src/communication/message.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::message_prelude::*;
22
use graphite_proc_macros::*;
3+
use serde::{Deserialize, Serialize};
34
use std::{
45
collections::hash_map::DefaultHasher,
56
hash::{Hash, Hasher},
@@ -16,7 +17,7 @@ where
1617
}
1718

1819
#[impl_message]
19-
#[derive(Clone, Debug, PartialEq)]
20+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2021
pub enum Message {
2122
NoOp,
2223
#[child]

editor/src/consts.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use graphene::color::Color;
2+
13
// VIEWPORT
24
pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = 1. / 600.;
35
pub const VIEWPORT_ZOOM_MOUSE_RATE: f64 = 1. / 400.;
@@ -13,12 +15,15 @@ pub const VIEWPORT_SCROLL_RATE: f64 = 0.6;
1315

1416
pub const VIEWPORT_ROTATE_SNAP_INTERVAL: f64 = 15.;
1517

18+
// SELECT TOOL
19+
pub const SELECTION_TOLERANCE: f64 = 1.;
20+
21+
// PATH TOOL
22+
pub const VECTOR_MANIPULATOR_ANCHOR_MARKER_SIZE: f64 = 5.;
23+
1624
// LINE TOOL
1725
pub const LINE_ROTATE_SNAP_ANGLE: f64 = 15.;
1826

19-
// SELECT TOOL
20-
pub const SELECTION_TOLERANCE: f64 = 1.0;
21-
2227
// SCROLLBARS
2328
pub const SCROLLBAR_SPACING: f64 = 0.1;
2429
pub const ASYMPTOTIC_EFFECT: f64 = 0.5;
@@ -27,3 +32,6 @@ pub const SCALE_EFFECT: f64 = 0.5;
2732
pub const DEFAULT_DOCUMENT_NAME: &str = "Untitled Document";
2833
pub const FILE_SAVE_SUFFIX: &str = ".graphite";
2934
pub const FILE_EXPORT_SUFFIX: &str = ".svg";
35+
36+
// COLORS
37+
pub const COLOR_ACCENT: Color = Color::from_unsafe(0x00 as f32 / 255., 0xA8 as f32 / 255., 0xFF as f32 / 255.);

0 commit comments

Comments
 (0)