Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
390febb
Added guide lines feature with ruler drag interaction
jsjgdh Jan 15, 2026
9e95d01
Fixed Guide Movement
jsjgdh Jan 16, 2026
30cf143
Added cursor handling for guide dragging
jsjgdh Jan 16, 2026
2b9e692
Removed unneccessary code
jsjgdh Jan 16, 2026
5f1d410
Test
jsjgdh Jan 17, 2026
ca8ec23
Fix guide rotation alignment
jsjgdh Jan 17, 2026
49561a8
Fix guide alignment in case of rotated artboard
jsjgdh Jan 17, 2026
9ac6f79
Fixed offset
jsjgdh Jan 19, 2026
4cf39f8
Color change
jsjgdh Jan 20, 2026
df1672a
Update editor/src/messages/portfolio/document/overlays/guide_overlays.rs
jsjgdh Jan 26, 2026
5cb66eb
Update editor/src/messages/portfolio/document/overlays/guide_overlays.rs
jsjgdh Jan 26, 2026
571ce0d
Changes as per recommendation
jsjgdh Jan 26, 2026
edd35a0
remove unnecessary code
jsjgdh Jan 27, 2026
2aa267e
Name change
jsjgdh May 6, 2026
32754ff
Fix merge conflicts
jsjgdh May 10, 2026
d1c3863
Fix GuideLine message derive macro attribute and Svelte runtime TypeE…
jsjgdh Jul 20, 2026
3e8a8ba
Expose guide line commands via editor_commands macro to EditorWrapper
jsjgdh Jul 20, 2026
c8c1b85
format
jsjgdh Jul 20, 2026
fdc6152
removed unused import
jsjgdh Jul 20, 2026
b81b5ba
Address AI review feedback
jsjgdh Jul 20, 2026
dc2c9ec
Fix isGuideEditor type guard and add onDestroy drag cleanup
jsjgdh Jul 23, 2026
522ad4d
Snapping
jsjgdh Jul 23, 2026
1db5c3c
Ai-Review
jsjgdh Jul 24, 2026
e5731fe
Fix AI review feedback
jsjgdh Jul 25, 2026
163eb65
Fix AI review feedback
jsjgdh Jul 25, 2026
0b4721e
Fix typescript-eslint type assertion error in isGuideEditor
jsjgdh Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions editor/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub const SELECTION_DRAG_ANGLE: f64 = 90.;
pub const LAYER_ORIGIN_CROSS_DIAMETER: f64 = 10.;
pub const LAYER_ORIGIN_CROSS_THICKNESS: f64 = 1.;

// GUIDES
pub const GUIDE_HIT_TOLERANCE: f64 = 5.;

// PIVOT
pub const PIVOT_CROSSHAIR_THICKNESS: f64 = 1.;
pub const PIVOT_CROSSHAIR_LENGTH: f64 = 9.;
Expand Down
2 changes: 2 additions & 0 deletions editor/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl Dispatcher {
menu_bar_message_handler.canvas_tilted = document.document_ptz.tilt() != 0.;
menu_bar_message_handler.canvas_flipped = document.document_ptz.flip;
menu_bar_message_handler.rulers_visible = document.rulers_visible;
menu_bar_message_handler.guide_lines_visible = document.guide_lines_message_handler.guide_lines_visible;
menu_bar_message_handler.node_graph_open = document.is_graph_overlay_open();
menu_bar_message_handler.has_selected_nodes = selected_nodes.selected_nodes().next().is_some();
menu_bar_message_handler.has_selected_layers = selected_nodes.selected_visible_layers(&document.network_interface).next().is_some();
Expand All @@ -297,6 +298,7 @@ impl Dispatcher {
menu_bar_message_handler.canvas_tilted = false;
menu_bar_message_handler.canvas_flipped = false;
menu_bar_message_handler.rulers_visible = false;
menu_bar_message_handler.guide_lines_visible = false;
menu_bar_message_handler.node_graph_open = false;
menu_bar_message_handler.has_selected_nodes = false;
menu_bar_message_handler.has_selected_layers = false;
Expand Down
7 changes: 7 additions & 0 deletions editor/src/messages/menu_bar/menu_bar_message_handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::input_mapper::utility_types::macros::action_shortcut;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::guide_message::GuideLineMessage;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType};
use crate::messages::prelude::*;
use graphene_std::vector::misc::BooleanOperation;
Expand All @@ -11,6 +12,7 @@ pub struct MenuBarMessageHandler {
pub canvas_tilted: bool,
pub canvas_flipped: bool,
pub rulers_visible: bool,
pub guide_lines_visible: bool,
pub node_graph_open: bool,
pub has_selected_nodes: bool,
pub has_selected_layers: bool,
Expand Down Expand Up @@ -635,6 +637,11 @@ impl LayoutHolder for MenuBarMessageHandler {
.tooltip_shortcut(action_shortcut!(PortfolioMessageDiscriminant::ToggleRulers))
.on_commit(|_| PortfolioMessage::ToggleRulers.into())
.disabled(no_active_document),
MenuListEntry::new("Guide Lines")
.label("Guide Lines")
.icon(if self.guide_lines_visible { "CheckboxChecked" } else { "CheckboxUnchecked" })
.on_commit(|_| GuideLineMessage::ToggleGuideLinesVisibility.into())
.disabled(no_active_document),
],
])
.widget_instance(),
Expand Down
32 changes: 30 additions & 2 deletions editor/src/messages/portfolio/document/document_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::collections::{BTreeMap, HashSet};
use document_graph_storage::Registry;
use graph_craft::application_io::resource::{ResourceId, ResourceRegistry, ResourceStorage};

use super::utility_types::guide::GuideLinesState;
use super::utility_types::network_interface::NodeNetworkInterface;
use super::utility_types::network_interface::storage_metadata::{StorageMetadataView, collect_network_view_settings};

Expand All @@ -20,6 +21,10 @@ pub struct DocumentHistory {
legacy_undo_stack: VecDeque<NodeNetworkInterface>,
/// Stack of document network snapshots for future history states.
legacy_redo_stack: VecDeque<NodeNetworkInterface>,
/// Guide-line state paired with each legacy undo snapshot.
guide_undo_stack: VecDeque<GuideLinesState>,
/// Guide-line state paired with each legacy redo snapshot.
guide_redo_stack: VecDeque<GuideLinesState>,
/// The `Gdd` working copy: owns the CRDT `Session` and mirrors edits to disk. `None` until the mount
/// future built by `load_document` resolves.
#[derivative(Debug = "ignore")]
Expand All @@ -34,29 +39,52 @@ impl DocumentHistory {
Self::push_capped(&mut self.legacy_undo_stack, snapshot);
}

/// Push a guide-line snapshot alongside the most recent undo network snapshot.
pub fn push_guide_undo(&mut self, guide_state: GuideLinesState) {
Self::push_capped(&mut self.guide_undo_stack, guide_state);
}

/// Push a snapshot onto the redo stack, evicting the oldest entry past the history cap.
pub fn push_redo(&mut self, snapshot: NodeNetworkInterface) {
Self::push_capped(&mut self.legacy_redo_stack, snapshot);
}

/// Push a guide-line snapshot alongside the most recent redo network snapshot.
pub fn push_guide_redo(&mut self, guide_state: GuideLinesState) {
Self::push_capped(&mut self.guide_redo_stack, guide_state);
}

/// Pop the most recent undo snapshot, or `None` when the stack is empty.
pub fn pop_undo(&mut self) -> Option<NodeNetworkInterface> {
self.legacy_undo_stack.pop_back()
}

/// Pop the guide-line snapshot paired with the most recent undo entry.
pub fn pop_guide_undo(&mut self) -> Option<GuideLinesState> {
self.guide_undo_stack.pop_back()
}

/// Pop the most recent redo snapshot, or `None` when the stack is empty.
pub fn pop_redo(&mut self) -> Option<NodeNetworkInterface> {
self.legacy_redo_stack.pop_back()
}

/// Pop the guide-line snapshot paired with the most recent redo entry.
pub fn pop_guide_redo(&mut self) -> Option<GuideLinesState> {
self.guide_redo_stack.pop_back()
}

/// Drop the most recently pushed undo snapshot (used to cancel a transaction that ended up unmodified).
pub fn discard_last_undo(&mut self) {
#[must_use]
pub fn discard_last_undo(&mut self) -> Option<GuideLinesState> {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
self.legacy_undo_stack.pop_back();
self.guide_undo_stack.pop_back()
}

/// Clear the redo stack, called when a fresh edit invalidates the redo future.
pub fn clear_redo(&mut self) {
self.legacy_redo_stack.clear();
self.guide_redo_stack.clear();
}

/// Add the resources referenced by every snapshot in both history stacks into `resources`, so
Expand Down Expand Up @@ -258,7 +286,7 @@ impl DocumentHistory {
}
}

fn push_capped(stack: &mut VecDeque<NodeNetworkInterface>, snapshot: NodeNetworkInterface) {
fn push_capped<T>(stack: &mut VecDeque<T>, snapshot: T) {
stack.push_back(snapshot);
if stack.len() > crate::consts::MAX_UNDO_HISTORY_LEN {
stack.pop_front();
Expand Down
3 changes: 3 additions & 0 deletions editor/src/messages/portfolio/document/document_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::sync::Arc;
use super::utility_types::misc::{GroupFolderType, SnappingState};
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::data_panel::DataPanelMessage;
use crate::messages::portfolio::document::guide_message::GuideLineMessage;
use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, OverlaysType};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GridSnapping};
Expand Down Expand Up @@ -41,6 +42,8 @@ pub enum DocumentMessage {
DataPanel(DataPanelMessage),
#[child]
Resource(ResourceMessage),
#[child]
GuideLine(GuideLineMessage),

// Messages
AlignSelectedLayers {
Expand Down
Loading
Loading