mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-28 19:58:11 +08:00
Only open the node graph panel after drawing a new frame to avoid layout shift interruption (#924)
* Store drag start as document position * Don't open graph whilst drawing * Rename to is_drawing_node_graph_frame Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Keavon Chambers
parent
f51dda5149
commit
df74f6f562
@@ -175,7 +175,8 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
|||||||
}
|
}
|
||||||
#[remain::unsorted]
|
#[remain::unsorted]
|
||||||
NodeGraph(message) => {
|
NodeGraph(message) => {
|
||||||
self.node_graph_handler.process_message(message, (&mut self.document_legacy, ipp), responses);
|
let selected_layers = &mut self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then_some(path.as_slice()));
|
||||||
|
self.node_graph_handler.process_message(message, (&mut self.document_legacy, selected_layers), responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ pub enum NodeGraphMessage {
|
|||||||
SelectNodes {
|
SelectNodes {
|
||||||
nodes: Vec<NodeId>,
|
nodes: Vec<NodeId>,
|
||||||
},
|
},
|
||||||
|
SetDrawing {
|
||||||
|
new_drawing: bool,
|
||||||
|
},
|
||||||
SetInputValue {
|
SetInputValue {
|
||||||
node: NodeId,
|
node: NodeId,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ use crate::messages::layout::utility_types::widgets::button_widgets::{Breadcrumb
|
|||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
|
|
||||||
use document_legacy::document::Document;
|
use document_legacy::document::Document;
|
||||||
use document_legacy::layers::layer_info::LayerDataType;
|
use document_legacy::layers::layer_info::{LayerDataType, LayerDataTypeDiscriminant};
|
||||||
use document_legacy::layers::nodegraph_layer::NodeGraphFrameLayer;
|
use document_legacy::layers::nodegraph_layer::NodeGraphFrameLayer;
|
||||||
|
use document_legacy::LayerId;
|
||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, DocumentNodeMetadata, NodeId, NodeInput, NodeNetwork};
|
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, DocumentNodeMetadata, NodeId, NodeInput, NodeNetwork};
|
||||||
|
|
||||||
@@ -104,6 +105,9 @@ pub struct NodeGraphMessageHandler {
|
|||||||
pub selected_nodes: Vec<graph_craft::document::NodeId>,
|
pub selected_nodes: Vec<graph_craft::document::NodeId>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub widgets: [LayoutGroup; 2],
|
pub widgets: [LayoutGroup; 2],
|
||||||
|
/// Do not allow the node graph window to open or close whilst the user is drawing a node graph frame
|
||||||
|
#[serde(skip)]
|
||||||
|
pub is_drawing_node_graph_frame: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeGraphMessageHandler {
|
impl NodeGraphMessageHandler {
|
||||||
@@ -388,12 +392,17 @@ impl NodeGraphMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageHandler)> for NodeGraphMessageHandler {
|
impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &[LayerId]>)> for NodeGraphMessageHandler {
|
||||||
#[remain::check]
|
#[remain::check]
|
||||||
fn process_message(&mut self, message: NodeGraphMessage, (document, _ipp): (&mut Document, &InputPreprocessorMessageHandler), responses: &mut VecDeque<Message>) {
|
fn process_message(&mut self, message: NodeGraphMessage, (document, selected): (&mut Document, &mut dyn Iterator<Item = &[LayerId]>), responses: &mut VecDeque<Message>) {
|
||||||
#[remain::sorted]
|
#[remain::sorted]
|
||||||
match message {
|
match message {
|
||||||
NodeGraphMessage::CloseNodeGraph => {
|
NodeGraphMessage::CloseNodeGraph => {
|
||||||
|
// Don't close when drawing a node graph frame
|
||||||
|
if self.is_drawing_node_graph_frame {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(_old_layer_path) = self.layer_path.take() {
|
if let Some(_old_layer_path) = self.layer_path.take() {
|
||||||
responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: false }.into());
|
responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: false }.into());
|
||||||
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
||||||
@@ -607,6 +616,11 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
|||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::OpenNodeGraph { layer_path } => {
|
NodeGraphMessage::OpenNodeGraph { layer_path } => {
|
||||||
|
// Don't open when drawing a node graph frame
|
||||||
|
if self.is_drawing_node_graph_frame {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(_old_layer_path) = self.layer_path.replace(layer_path) {
|
if let Some(_old_layer_path) = self.layer_path.replace(layer_path) {
|
||||||
// TODO: Necessary cleanup of old node graph
|
// TODO: Necessary cleanup of old node graph
|
||||||
}
|
}
|
||||||
@@ -671,6 +685,25 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
|||||||
self.update_selection_action_buttons(document, responses);
|
self.update_selection_action_buttons(document, responses);
|
||||||
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
||||||
}
|
}
|
||||||
|
NodeGraphMessage::SetDrawing { new_drawing } => {
|
||||||
|
let selected: Vec<_> = selected.collect();
|
||||||
|
// Check if we stopped drawing a node graph frame
|
||||||
|
if self.is_drawing_node_graph_frame && !new_drawing {
|
||||||
|
// Check if we should open or close the node graph
|
||||||
|
if selected.len() == 1
|
||||||
|
&& document
|
||||||
|
.layer(selected[0])
|
||||||
|
.ok()
|
||||||
|
.filter(|layer| LayerDataTypeDiscriminant::from(&layer.data) == LayerDataTypeDiscriminant::NodeGraphFrame)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
responses.push_back(NodeGraphMessage::OpenNodeGraph { layer_path: selected[0].to_vec() }.into());
|
||||||
|
} else {
|
||||||
|
responses.push_back(NodeGraphMessage::CloseNodeGraph.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.is_drawing_node_graph_frame = new_drawing
|
||||||
|
}
|
||||||
NodeGraphMessage::SetInputValue { node, input_index, value } => {
|
NodeGraphMessage::SetInputValue { node, input_index, value } => {
|
||||||
if let Some(network) = self.get_active_network_mut(document) {
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
if let Some(node) = network.nodes.get_mut(&node) {
|
if let Some(node) = network.nodes.get_mut(&node) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use glam::{DAffine2, DVec2, Vec2Swizzles};
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Resize {
|
pub struct Resize {
|
||||||
pub drag_start: ViewportPosition,
|
drag_start: ViewportPosition,
|
||||||
pub path: Option<Vec<LayerId>>,
|
pub path: Option<Vec<LayerId>>,
|
||||||
snap_manager: SnapManager,
|
snap_manager: SnapManager,
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,14 @@ impl Resize {
|
|||||||
pub fn start(&mut self, responses: &mut VecDeque<Message>, document: &DocumentMessageHandler, mouse_position: DVec2, font_cache: &FontCache) {
|
pub fn start(&mut self, responses: &mut VecDeque<Message>, document: &DocumentMessageHandler, mouse_position: DVec2, font_cache: &FontCache) {
|
||||||
self.snap_manager.start_snap(document, document.bounding_boxes(None, None, font_cache), true, true);
|
self.snap_manager.start_snap(document, document.bounding_boxes(None, None, font_cache), true, true);
|
||||||
self.snap_manager.add_all_document_handles(document, &[], &[], &[]);
|
self.snap_manager.add_all_document_handles(document, &[], &[], &[]);
|
||||||
self.drag_start = self.snap_manager.snap_position(responses, document, mouse_position);
|
let root_transform = document.document_legacy.root.transform;
|
||||||
|
self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, mouse_position));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
root_transform.transform_point2(self.drag_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_transform(
|
pub fn calculate_transform(
|
||||||
@@ -33,7 +40,7 @@ impl Resize {
|
|||||||
ipp: &InputPreprocessorMessageHandler,
|
ipp: &InputPreprocessorMessageHandler,
|
||||||
) -> Option<Message> {
|
) -> Option<Message> {
|
||||||
if let Some(path) = &self.path {
|
if let Some(path) = &self.path {
|
||||||
let mut start = self.drag_start;
|
let mut start = self.viewport_drag_start(document);
|
||||||
|
|
||||||
let stop = self.snap_manager.snap_position(responses, document, ipp.mouse.position);
|
let stop = self.snap_manager.snap_position(responses, document, ipp.mouse.position);
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, u64, &InputPreprocess
|
|||||||
|
|
||||||
// Notify the frontend about the new active tool to be displayed
|
// Notify the frontend about the new active tool to be displayed
|
||||||
tool_data.register_properties(responses, LayoutTarget::ToolShelf);
|
tool_data.register_properties(responses, LayoutTarget::ToolShelf);
|
||||||
|
|
||||||
|
// Ensure the node graph drawing state is reset
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
|
||||||
}
|
}
|
||||||
ToolMessage::DeactivateTools => {
|
ToolMessage::DeactivateTools => {
|
||||||
let tool_data = &mut self.tool_state.tool_data;
|
let tool_data = &mut self.tool_state.tool_data;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ impl Fsm for EllipseToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(Drawing, DragStop) => {
|
(Drawing, DragStop) => {
|
||||||
match shape_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD {
|
match shape_data.viewport_drag_start(document).distance(input.mouse.position) <= DRAG_THRESHOLD {
|
||||||
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
||||||
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ impl Fsm for ImaginateToolFsmState {
|
|||||||
(Ready, DragStart) => {
|
(Ready, DragStart) => {
|
||||||
shape_data.start(responses, document, input.mouse.position, font_cache);
|
shape_data.start(responses, document, input.mouse.position, font_cache);
|
||||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into());
|
||||||
shape_data.path = Some(document.get_path_for_new_layer());
|
shape_data.path = Some(document.get_path_for_new_layer());
|
||||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||||
|
|
||||||
@@ -221,11 +222,12 @@ impl Fsm for ImaginateToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(Drawing, DragStop) => {
|
(Drawing, DragStop) => {
|
||||||
match shape_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD {
|
match shape_data.viewport_drag_start(document).distance(input.mouse.position) <= DRAG_THRESHOLD {
|
||||||
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
||||||
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
|
||||||
shape_data.cleanup(responses);
|
shape_data.cleanup(responses);
|
||||||
|
|
||||||
Ready
|
Ready
|
||||||
@@ -233,6 +235,8 @@ impl Fsm for ImaginateToolFsmState {
|
|||||||
(Drawing, Abort) => {
|
(Drawing, Abort) => {
|
||||||
responses.push_back(DocumentMessage::AbortTransaction.into());
|
responses.push_back(DocumentMessage::AbortTransaction.into());
|
||||||
|
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
|
||||||
|
|
||||||
shape_data.cleanup(responses);
|
shape_data.cleanup(responses);
|
||||||
|
|
||||||
Ready
|
Ready
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ impl Fsm for NodeGraphToolFsmState {
|
|||||||
(Ready, DragStart) => {
|
(Ready, DragStart) => {
|
||||||
shape_data.start(responses, document, input.mouse.position, font_cache);
|
shape_data.start(responses, document, input.mouse.position, font_cache);
|
||||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into());
|
||||||
shape_data.path = Some(document.get_path_for_new_layer());
|
shape_data.path = Some(document.get_path_for_new_layer());
|
||||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||||
|
|
||||||
@@ -186,17 +187,19 @@ impl Fsm for NodeGraphToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(Drawing, DragStop) => {
|
(Drawing, DragStop) => {
|
||||||
match shape_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD {
|
match shape_data.viewport_drag_start(document).distance(input.mouse.position) <= DRAG_THRESHOLD {
|
||||||
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
||||||
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
|
||||||
shape_data.cleanup(responses);
|
shape_data.cleanup(responses);
|
||||||
|
|
||||||
Ready
|
Ready
|
||||||
}
|
}
|
||||||
(Drawing, Abort) => {
|
(Drawing, Abort) => {
|
||||||
responses.push_back(DocumentMessage::AbortTransaction.into());
|
responses.push_back(DocumentMessage::AbortTransaction.into());
|
||||||
|
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
|
||||||
|
|
||||||
shape_data.cleanup(responses);
|
shape_data.cleanup(responses);
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ impl Fsm for RectangleToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(Drawing, DragStop) => {
|
(Drawing, DragStop) => {
|
||||||
match shape_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD {
|
match shape_data.viewport_drag_start(document).distance(input.mouse.position) <= DRAG_THRESHOLD {
|
||||||
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
||||||
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ impl Fsm for ShapeToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(Drawing, DragStop) => {
|
(Drawing, DragStop) => {
|
||||||
match shape_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD {
|
match shape_data.viewport_drag_start(document).distance(input.mouse.position) <= DRAG_THRESHOLD {
|
||||||
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
true => responses.push_back(DocumentMessage::AbortTransaction.into()),
|
||||||
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
false => responses.push_back(DocumentMessage::CommitTransaction.into()),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user