mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Fix misc errors and cleanup after rebases
This commit is contained in:
@@ -50,6 +50,7 @@ impl Editor {
|
||||
open: active_document.graph_view_overlay_open,
|
||||
in_selected_network: &active_document.selection_network_path == breadcrumb_network_path,
|
||||
previewed_node,
|
||||
thumbnails: active_document.node_graph_handler.thumbnails.clone()
|
||||
};
|
||||
let opacity = active_document.graph_fade_artwork_percentage;
|
||||
let node_graph_overlay_node = generate_node_graph_overlay(node_graph_render_data, opacity);
|
||||
|
||||
@@ -4,7 +4,7 @@ pub const EXPORTS_TO_TOP_EDGE_PIXEL_GAP: u32 = 72;
|
||||
pub const EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP: u32 = 120;
|
||||
pub const IMPORTS_TO_TOP_EDGE_PIXEL_GAP: u32 = 72;
|
||||
pub const IMPORTS_TO_LEFT_EDGE_PIXEL_GAP: u32 = 120;
|
||||
pub const TOOLTIP_DELAY: u32 = 800;
|
||||
pub const INPUT_TOOLTIP_DELAY: u64 = 800;
|
||||
|
||||
// VIEWPORT
|
||||
pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.;
|
||||
|
||||
@@ -59,6 +59,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
|
||||
const DEBUG_MESSAGE_BLOCK_LIST: &[MessageDiscriminant] = &[
|
||||
MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(EventMessageDiscriminant::AnimationFrame)),
|
||||
MessageDiscriminant::Animation(AnimationMessageDiscriminant::IncrementFrameCounter),
|
||||
MessageDiscriminant::Defer(DeferMessageDiscriminant::CheckDeferredMessages),
|
||||
];
|
||||
// TODO: Find a way to combine these with the list above. We use strings for now since these are the standard variant names used by multiple messages. But having these also type-checked would be best.
|
||||
const DEBUG_MESSAGE_ENDING_BLOCK_LIST: &[&str] = &["PointerMove", "PointerOutsideViewport", "Overlays", "Draw", "CurrentTime", "Time"];
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
ops::Bound,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
#[derive(ExtractField)]
|
||||
pub struct DeferMessageContext<'a> {
|
||||
pub portfolio: &'a PortfolioMessageHandler,
|
||||
pub time: Instant,
|
||||
pub time: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, ExtractField)]
|
||||
@@ -17,7 +13,7 @@ pub struct DeferMessageHandler {
|
||||
after_graph_run: HashMap<DocumentId, Vec<(u64, Message)>>,
|
||||
after_viewport_resize: Vec<Message>,
|
||||
current_graph_submission_id: u64,
|
||||
after_time_elapsed: BTreeMap<Instant, Message>,
|
||||
after_time_elapsed: BTreeMap<u64, Message>,
|
||||
}
|
||||
|
||||
#[message_handler_data]
|
||||
@@ -58,11 +54,11 @@ impl MessageHandler<DeferMessage, DeferMessageContext<'_>> for DeferMessageHandl
|
||||
}
|
||||
}
|
||||
DeferMessage::RequestDeferredMessage { timeout, message } => {
|
||||
self.after_time_elapsed.insert(context.time + timeout, *message);
|
||||
self.after_time_elapsed.insert(context.time + timeout.as_millis() as u64, *message);
|
||||
}
|
||||
DeferMessage::CheckDeferredMessages => {
|
||||
let after_current_time = self.after_time_elapsed.split_off((Bound::Unbounded, Bound::Excluded(context.time)));
|
||||
for (_, message) in std::mem::replace(self.after_time_elapsed, after_current_time) {
|
||||
let after_current_time = self.after_time_elapsed.split_off(&context.time);
|
||||
for (_, message) in std::mem::replace(&mut self.after_time_elapsed, after_current_time) {
|
||||
responses.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,10 +175,6 @@ pub enum FrontendMessage {
|
||||
#[serde(rename = "exportIndex")]
|
||||
index: Option<usize>,
|
||||
},
|
||||
UpdateLayerWidths {
|
||||
#[serde(rename = "layerWidths")]
|
||||
layer_widths: HashMap<NodeId, u32>,
|
||||
},
|
||||
UpdateDialogButtons {
|
||||
#[serde(rename = "layoutTarget")]
|
||||
layout_target: LayoutTarget,
|
||||
@@ -269,7 +265,6 @@ pub enum FrontendMessage {
|
||||
UpdateMouseCursor {
|
||||
cursor: MouseCursorIcon,
|
||||
},
|
||||
RequestNativeNodeGraphRender,
|
||||
UpdateNativeNodeGraphSVG {
|
||||
#[serde(rename = "svgString")]
|
||||
svg_string: String,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo;
|
||||
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
|
||||
use crate::messages::prelude::*;
|
||||
use glam::DVec2;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(ExtractField)]
|
||||
pub struct InputPreprocessorMessageContext {
|
||||
@@ -14,7 +14,7 @@ pub struct InputPreprocessorMessageContext {
|
||||
#[derive(Debug, Default, ExtractField)]
|
||||
pub struct InputPreprocessorMessageHandler {
|
||||
pub frame_time: FrameTimeInfo,
|
||||
pub time: Instant,
|
||||
pub time: u64,
|
||||
pub keyboard: KeyStates,
|
||||
pub mouse: MouseState,
|
||||
pub viewport_bounds: ViewportBounds,
|
||||
@@ -43,6 +43,7 @@ impl MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContext> f
|
||||
.into(),
|
||||
],
|
||||
});
|
||||
responses.add(NodeGraphMessage::UpdateNodeGraphTopRight);
|
||||
}
|
||||
InputPreprocessorMessage::DoubleClick { editor_mouse_state, modifier_keys } => {
|
||||
self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses);
|
||||
@@ -114,7 +115,7 @@ impl MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContext> f
|
||||
}
|
||||
InputPreprocessorMessage::CurrentTime { timestamp } => {
|
||||
responses.add(AnimationMessage::SetTime { time: timestamp as f64 });
|
||||
self.time = Instant::from(timestamp);
|
||||
self.time = timestamp;
|
||||
self.frame_time.advance_timestamp(Duration::from_millis(timestamp));
|
||||
}
|
||||
InputPreprocessorMessage::WheelScroll { editor_mouse_state, modifier_keys } => {
|
||||
|
||||
@@ -476,6 +476,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(DocumentMessage::ZoomCanvasToFitAll);
|
||||
responses.add(NodeGraphMessage::UpdateNodeGraphTopRight);
|
||||
}
|
||||
DocumentMessage::Escape => {
|
||||
if self.node_graph_handler.drag_start.is_some() {
|
||||
@@ -504,6 +505,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
}
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(DocumentMessage::PTZUpdate);
|
||||
responses.add(NodeGraphMessage::UpdateNodeGraphTopRight);
|
||||
}
|
||||
DocumentMessage::FlipSelectedLayers { flip_axis } => {
|
||||
let scale = match flip_axis {
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::messages::input_mapper::utility_types::input_keyboard::Key;
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{ImportOrExport, InputConnector, NodeTemplate, OutputConnector};
|
||||
use crate::messages::prelude::*;
|
||||
use glam::IVec2;
|
||||
use glam::{DVec2, IVec2};
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{NodeId, NodeInput};
|
||||
use graph_craft::proto::GraphErrors;
|
||||
@@ -112,6 +112,7 @@ pub enum NodeGraphMessage {
|
||||
PointerOutsideViewport {
|
||||
shift: Key,
|
||||
},
|
||||
UpdateNodeGraphTopRight,
|
||||
ShakeNode,
|
||||
RemoveImport {
|
||||
import_index: usize,
|
||||
@@ -215,7 +216,9 @@ pub enum NodeGraphMessage {
|
||||
SetLockedOrVisibilitySideEffects {
|
||||
node_ids: Vec<NodeId>,
|
||||
},
|
||||
TryDisplayTooltip,
|
||||
TryDisplayTooltip {
|
||||
initial_position: DVec2,
|
||||
},
|
||||
UpdateBoxSelection,
|
||||
UpdateImportsExports,
|
||||
UpdateLayerPanel,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::utility_types::{BoxSelection, ContextMenuInformation, DragStart};
|
||||
use super::{document_node_definitions, node_properties};
|
||||
use crate::consts::{GRID_SIZE, TOOLTIP_DELAY};
|
||||
use crate::consts::*;
|
||||
use crate::messages::input_mapper::utility_types::macros::action_keys;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::document_message_handler::navigation_controls;
|
||||
@@ -30,6 +30,7 @@ use graphene_std::*;
|
||||
use kurbo::{DEFAULT_ACCURACY, Shape};
|
||||
use renderer::Quad;
|
||||
use std::cmp::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, ExtractField)]
|
||||
pub struct NodeGraphMessageContext<'a> {
|
||||
@@ -1149,19 +1150,21 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
.unwrap_or_else(|| modify_import_export.reorder_imports_exports.input_ports().count() + 1),
|
||||
);
|
||||
responses.add(FrontendMessage::UpdateExportReorderIndex { index: self.end_index });
|
||||
} else if !self.hovering_input && !self.hovering_output {
|
||||
} else if !self.hovering_input && !self.hovering_output && !self.hovering_node {
|
||||
if network_interface.input_connector_from_click(ipp.mouse.position, breadcrumb_network_path).is_some() {
|
||||
self.hovering_input = true;
|
||||
responses.add(DeferMessage::RequestDeferredMessage {
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip.into()),
|
||||
timeout: Duration::from_millis(TOOLTIP_DELAY),
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip { initial_position: ipp.mouse.position }.into()),
|
||||
timeout: Duration::from_millis(INPUT_TOOLTIP_DELAY),
|
||||
});
|
||||
}
|
||||
if network_interface.output_connector_from_click(ipp.mouse.position, breadcrumb_network_path).is_some() {
|
||||
self.hovering_output = true;
|
||||
} else if network_interface.output_connector_from_click(ipp.mouse.position, breadcrumb_network_path).is_some() {
|
||||
responses.add(DeferMessage::RequestDeferredMessage {
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip.into()),
|
||||
timeout: Duration::from_millis(TOOLTIP_DELAY),
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip { initial_position: ipp.mouse.position }.into()),
|
||||
timeout: Duration::from_millis(INPUT_TOOLTIP_DELAY),
|
||||
})
|
||||
} else if network_interface.node_from_click(ipp.mouse.position, breadcrumb_network_path).is_some() {
|
||||
responses.add(DeferMessage::RequestDeferredMessage {
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip { initial_position: ipp.mouse.position }.into()),
|
||||
timeout: Duration::from_millis(INPUT_TOOLTIP_DELAY),
|
||||
})
|
||||
}
|
||||
} else if self.hovering_input {
|
||||
@@ -1174,16 +1177,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
self.hovering_output = false;
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: None, text: String::new() });
|
||||
}
|
||||
} else if !self.hovering_node {
|
||||
if network_interface.node_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
self.hovering_node = true;
|
||||
responses.add(DeferMessage::RequestDeferredMessage {
|
||||
message: Box::new(NodeGraphMessage::TryDisplayTooltip.into()),
|
||||
timeout: Duration::from_millis(TOOLTIP_DELAY),
|
||||
})
|
||||
}
|
||||
} else if self.hovering_node {
|
||||
if !network_interface.node_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
if !network_interface.node_from_click(ipp.mouse.position, breadcrumb_network_path).is_some() {
|
||||
self.hovering_node = false;
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: None, text: String::new() });
|
||||
}
|
||||
@@ -1449,6 +1444,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
self.auto_panning.stop(&messages, responses);
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::UpdateNodeGraphTopRight => {
|
||||
network_interface.set_node_graph_width(ipp.viewport_bounds.size().x, breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
}
|
||||
NodeGraphMessage::ShakeNode => {
|
||||
let Some(drag_start) = &self.drag_start else {
|
||||
log::error!("Drag start should be initialized when shaking a node");
|
||||
@@ -1849,8 +1848,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
responses.add(NodeGraphMessage::SetVisibility { node_id, visible });
|
||||
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids: vec![node_id] });
|
||||
}
|
||||
NodeGraphMessage::TryDisplayTooltip => {
|
||||
if let Some(input) = network_interface.input_connector_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
NodeGraphMessage::TryDisplayTooltip { initial_position } => {
|
||||
if initial_position != ipp.mouse.position {
|
||||
return;
|
||||
} else if let Some(input) = network_interface.input_connector_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
let text = network_interface.input_tooltip_text(&input, breadcrumb_network_path);
|
||||
if let Some(position) = network_interface.input_position(&input, breadcrumb_network_path) {
|
||||
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
|
||||
@@ -1862,6 +1863,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
y: position.y as i32,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: Some(xy), text });
|
||||
self.hovering_input = true;
|
||||
}
|
||||
} else if let Some(output) = network_interface.output_connector_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
let text = network_interface.output_tooltip_text(&output, breadcrumb_network_path);
|
||||
@@ -1876,25 +1878,29 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
y: position.y as i32,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: Some(xy), text });
|
||||
self.hovering_output = true;
|
||||
}
|
||||
} else if let Some(node_id) = network_interface.node_from_click(ipp.mouse.position, breadcrumb_network_path) {
|
||||
let text = network_interface.node_tooltip_text(&node_id, breadcrumb_network_path);
|
||||
if let Some(position) = network_interface.position(&node_id, breadcrumb_network_path) {
|
||||
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
|
||||
return;
|
||||
};
|
||||
let position = network_metadata
|
||||
.persistent_metadata
|
||||
.navigation_metadata
|
||||
.node_graph_to_viewport
|
||||
.transform_point2(DVec2::new(position.x as f64 * 24., position.y as f64 * 24.));
|
||||
let Some(position) = network_interface.position(&node_id, breadcrumb_network_path) else {
|
||||
log::error!("Could not get position from node: {node_id}");
|
||||
return;
|
||||
};
|
||||
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
|
||||
return;
|
||||
};
|
||||
let position = network_metadata
|
||||
.persistent_metadata
|
||||
.navigation_metadata
|
||||
.node_graph_to_viewport
|
||||
.transform_point2(DVec2::new(position.x as f64 * 24., position.y as f64 * 24.));
|
||||
|
||||
let xy = FrontendXY {
|
||||
x: position.x as i32,
|
||||
y: position.y as i32,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: Some(xy), text });
|
||||
}
|
||||
let xy = FrontendXY {
|
||||
x: position.x as i32,
|
||||
y: position.y as i32,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateTooltip { position: Some(xy), text });
|
||||
self.hovering_node = true;
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::SetPinned { node_id, pinned } => {
|
||||
@@ -2655,6 +2661,9 @@ impl Default for NodeGraphMessageHandler {
|
||||
reordering_import: None,
|
||||
end_index: None,
|
||||
thumbnails: HashMap::new(),
|
||||
hovering_input: false,
|
||||
hovering_output: false,
|
||||
hovering_node: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,185 +1,6 @@
|
||||
use graph_craft::document::NodeId;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::resolved_types::TypeSource;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub enum FrontendGraphDataType {
|
||||
#[default]
|
||||
General,
|
||||
Number,
|
||||
Artboard,
|
||||
Graphic,
|
||||
Raster,
|
||||
Vector,
|
||||
Color,
|
||||
Gradient,
|
||||
Typography,
|
||||
}
|
||||
|
||||
impl FrontendGraphDataType {
|
||||
pub fn from_type(input: &Type) -> Self {
|
||||
match TaggedValue::from_type_or_none(input) {
|
||||
TaggedValue::U32(_)
|
||||
| TaggedValue::U64(_)
|
||||
| TaggedValue::F32(_)
|
||||
| TaggedValue::F64(_)
|
||||
| TaggedValue::DVec2(_)
|
||||
| TaggedValue::F64Array4(_)
|
||||
| TaggedValue::VecF64(_)
|
||||
| TaggedValue::VecDVec2(_)
|
||||
| TaggedValue::DAffine2(_) => Self::Number,
|
||||
TaggedValue::Artboard(_) => Self::Artboard,
|
||||
TaggedValue::Graphic(_) => Self::Graphic,
|
||||
TaggedValue::Raster(_) => Self::Raster,
|
||||
TaggedValue::Vector(_) => Self::Vector,
|
||||
TaggedValue::Color(_) => Self::Color,
|
||||
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) | TaggedValue::GradientTable(_) => Self::Gradient,
|
||||
TaggedValue::String(_) => Self::Typography,
|
||||
_ => Self::General,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn displayed_type(type_source: &TypeSource) -> Self {
|
||||
match type_source.compiled_nested_type() {
|
||||
Some(nested_type) => Self::from_type(&nested_type),
|
||||
None => Self::General,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendXY {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendGraphInput {
|
||||
#[serde(rename = "dataType")]
|
||||
pub data_type: FrontendGraphDataType,
|
||||
#[serde(rename = "resolvedType")]
|
||||
pub resolved_type: String,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
/// Either "nothing", "import index {index}", or "{node name} output {output_index}".
|
||||
#[serde(rename = "connectedToString")]
|
||||
pub connected_to: String,
|
||||
/// Used to render the upstream node once this node is rendered
|
||||
#[serde(rename = "connectedToNode")]
|
||||
pub connected_to_node: Option<NodeId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendGraphOutput {
|
||||
#[serde(rename = "dataType")]
|
||||
pub data_type: FrontendGraphDataType,
|
||||
pub name: String,
|
||||
#[serde(rename = "resolvedType")]
|
||||
pub resolved_type: String,
|
||||
pub description: String,
|
||||
/// If connected to an export, it is "export index {index}".
|
||||
/// If connected to a node, it is "{node name} input {input_index}".
|
||||
#[serde(rename = "connectedTo")]
|
||||
pub connected_to: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendExport {
|
||||
pub port: FrontendGraphInput,
|
||||
pub wire: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendExports {
|
||||
/// If the primary export is not visible, then it is None.
|
||||
pub exports: Vec<Option<FrontendExport>>,
|
||||
#[serde(rename = "previewWire")]
|
||||
pub preview_wire: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendImport {
|
||||
pub port: FrontendGraphOutput,
|
||||
pub wires: Vec<String>,
|
||||
}
|
||||
|
||||
// Metadata that is common to nodes and layers
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNodeMetadata {
|
||||
#[serde(rename = "nodeId")]
|
||||
pub node_id: NodeId,
|
||||
// TODO: Remove and replace with popup manager system
|
||||
#[serde(rename = "canBeLayer")]
|
||||
pub can_be_layer: bool,
|
||||
#[serde(rename = "displayName")]
|
||||
pub display_name: String,
|
||||
pub selected: bool,
|
||||
// Used to get the description, which is stored in a global hashmap
|
||||
pub reference: Option<String>,
|
||||
// Reduces opacity of node/hidden eye icon
|
||||
pub visible: bool,
|
||||
// The svg string for each input
|
||||
// pub wires: Vec<Option<String>>,
|
||||
pub errors: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNode {
|
||||
// pub position: FrontendNodePosition,
|
||||
pub position: FrontendXY,
|
||||
pub inputs: Vec<Option<FrontendGraphInput>>,
|
||||
pub outputs: Vec<Option<FrontendGraphOutput>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendLayer {
|
||||
#[serde(rename = "bottomInput")]
|
||||
pub bottom_input: FrontendGraphInput,
|
||||
#[serde(rename = "sideInput")]
|
||||
pub side_input: Option<FrontendGraphInput>,
|
||||
pub output: FrontendGraphOutput,
|
||||
// pub position: FrontendLayerPosition,
|
||||
pub position: FrontendXY,
|
||||
pub locked: bool,
|
||||
#[serde(rename = "chainWidth")]
|
||||
pub chain_width: u32,
|
||||
#[serde(rename = "layerHasLeftBorderGap")]
|
||||
pub layer_has_left_border_gap: bool,
|
||||
#[serde(rename = "primaryInputConnectedToLayer")]
|
||||
pub primary_input_connected_to_layer: bool,
|
||||
#[serde(rename = "primaryOutputConnectedToLayer")]
|
||||
pub primary_output_connected_to_layer: bool,
|
||||
}
|
||||
|
||||
// // Should be an enum but those are hard to serialize/deserialize to TS
|
||||
// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
// pub struct FrontendNodePosition {
|
||||
// pub absolute: Option<FrontendXY>,
|
||||
// pub chain: Option<bool>,
|
||||
// }
|
||||
|
||||
// // Should be an enum but those are hard to serialize/deserialize to TS
|
||||
// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
// pub struct FrontendLayerPosition {
|
||||
// pub absolute: Option<FrontendXY>,
|
||||
// pub stack: Option<u32>,
|
||||
// }
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNodeOrLayer {
|
||||
pub node: Option<FrontendNode>,
|
||||
pub layer: Option<FrontendLayer>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNodeToRender {
|
||||
pub metadata: FrontendNodeMetadata,
|
||||
#[serde(rename = "nodeOrLayer")]
|
||||
pub node_or_layer: FrontendNodeOrLayer,
|
||||
//TODO: Remove
|
||||
pub wires: Vec<(String, bool, FrontendGraphDataType)>,
|
||||
}
|
||||
use graphene_std::uuid::NodeId;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNodeType {
|
||||
|
||||
@@ -2675,6 +2675,16 @@ impl NodeNetworkInterface {
|
||||
self.unload_modify_import_export(network_path);
|
||||
}
|
||||
|
||||
pub fn set_node_graph_width(&mut self, node_graph_width: f64, network_path: &[NodeId]) {
|
||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
||||
log::error!("Could not get nested network in set_transform");
|
||||
return;
|
||||
};
|
||||
network_metadata.persistent_metadata.navigation_metadata.node_graph_width = node_graph_width;
|
||||
self.unload_import_export_ports(network_path);
|
||||
self.unload_modify_import_export(network_path);
|
||||
}
|
||||
|
||||
pub fn vector_modify(&mut self, node_id: &NodeId, modification_type: VectorModificationType) {
|
||||
let Some(node) = self.network_mut(&[]).unwrap().nodes.get_mut(node_id) else {
|
||||
log::error!("Could not get node in vector_modification");
|
||||
@@ -5853,7 +5863,7 @@ pub enum LayerClickTargetTypes {
|
||||
// Preview,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct NavigationMetadata {
|
||||
/// The current pan, and zoom state of the viewport's view of the node graph.
|
||||
/// Ensure `DocumentMessage::UpdateDocumentTransform` is called when the pan, zoom, or transform changes.
|
||||
@@ -5861,21 +5871,10 @@ pub struct NavigationMetadata {
|
||||
// TODO: Remove and replace with calculate_offset_transform from the node_graph_ptz. This will be difficult since it requires both the navigation message handler and the IPP
|
||||
/// Transform from node graph space to viewport space.
|
||||
pub node_graph_to_viewport: DAffine2,
|
||||
/// Top right of the node graph in viewport space
|
||||
// TODO: Eventually replace with footprint
|
||||
/// The width of the node graph in viewport space
|
||||
#[serde(default)]
|
||||
pub node_graph_top_right: DVec2,
|
||||
}
|
||||
|
||||
impl Default for NavigationMetadata {
|
||||
fn default() -> NavigationMetadata {
|
||||
// Default PTZ and transform
|
||||
NavigationMetadata {
|
||||
node_graph_ptz: PTZ::default(),
|
||||
node_graph_to_viewport: DAffine2::IDENTITY,
|
||||
// TODO: Eventually replace with footprint
|
||||
node_graph_top_right: DVec2::ZERO,
|
||||
}
|
||||
}
|
||||
pub node_graph_width: f64,
|
||||
}
|
||||
|
||||
// PartialEq required by message handlers
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use glam::{DVec2, IVec2};
|
||||
use graph_craft::proto::GraphErrors;
|
||||
use graphene_std::uuid::NodeId;
|
||||
use graphene_std::{
|
||||
node_graph_overlay::types::{
|
||||
FrontendExport, FrontendExports, FrontendGraphInput, FrontendGraphOutput, FrontendImport, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendNodeToRender,
|
||||
FrontendXY,
|
||||
},
|
||||
uuid::NodeId,
|
||||
};
|
||||
use kurbo::BezPath;
|
||||
|
||||
use crate::{
|
||||
consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP},
|
||||
messages::portfolio::document::{
|
||||
node_graph::utility_types::{
|
||||
FrontendExport, FrontendExports, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendImport, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer,
|
||||
FrontendNodeToRender, FrontendXY,
|
||||
},
|
||||
utility_types::{
|
||||
network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector, Previewing},
|
||||
wires::{GraphWireStyle, build_vector_wire},
|
||||
},
|
||||
messages::portfolio::document::utility_types::{
|
||||
network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector, Previewing},
|
||||
wires::{GraphWireStyle, build_vector_wire},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -123,7 +123,7 @@ impl NodeNetworkInterface {
|
||||
(
|
||||
wire,
|
||||
self.wire_is_thick(&InputConnector::node(node_id, input_index), network_path),
|
||||
FrontendGraphDataType::displayed_type(&self.input_type(&InputConnector::node(node_id, input_index), network_path)),
|
||||
self.input_type(&InputConnector::node(node_id, input_index), network_path).displayed_type(),
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -210,8 +210,12 @@ impl NodeNetworkInterface {
|
||||
}
|
||||
}
|
||||
};
|
||||
let connected = self
|
||||
.outward_wires(network_path)
|
||||
.and_then(|outward_wires| outward_wires.get(output_connector))
|
||||
.is_some_and(|downstream| downstream.len() > 0);
|
||||
let data_type = output_type.displayed_type();
|
||||
Some(FrontendGraphOutput { data_type, name })
|
||||
Some(FrontendGraphOutput { data_type, name, connected })
|
||||
}
|
||||
|
||||
pub fn chain_width(&self, node_id: &NodeId, network_path: &[NodeId]) -> u32 {
|
||||
@@ -386,19 +390,18 @@ impl NodeNetworkInterface {
|
||||
let import_top_left = DVec2::new(top_left_inner_bound.x.min(bounding_box_top_left.x), top_left_inner_bound.y.min(bounding_box_top_left.y));
|
||||
let rounded_import_top_left = DVec2::new((import_top_left.x / 24.).round() * 24., (import_top_left.y / 24.).round() * 24.);
|
||||
|
||||
let viewport_top_right = network_metadata.persistent_metadata.navigation_metadata.node_graph_top_right;
|
||||
let target_viewport_top_right = DVec2::new(
|
||||
viewport_top_right.x - EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP as f64,
|
||||
viewport_top_right.y + EXPORTS_TO_TOP_EDGE_PIXEL_GAP as f64,
|
||||
);
|
||||
let viewport_width = network_metadata.persistent_metadata.navigation_metadata.node_graph_width;
|
||||
|
||||
let target_viewport_top_right = DVec2::new(viewport_width - EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP as f64, EXPORTS_TO_TOP_EDGE_PIXEL_GAP as f64);
|
||||
|
||||
// An offset from the right edge in viewport pixels
|
||||
let node_graph_pixel_offset_top_right = node_graph_to_viewport.inverse().transform_point2(target_viewport_top_right);
|
||||
|
||||
// A 5x5 grid offset from the right corner
|
||||
let node_graph_grid_space_offset_top_right = node_graph_to_viewport.inverse().transform_point2(viewport_top_right) + DVec2::new(-5. * GRID_SIZE as f64, 4. * GRID_SIZE as f64);
|
||||
let node_graph_grid_space_offset_top_right = node_graph_to_viewport.inverse().transform_point2(DVec2::new(viewport_width, 0.)) + DVec2::new(-5. * GRID_SIZE as f64, 4. * GRID_SIZE as f64);
|
||||
|
||||
// The inner bound of the export is the highest/furthest right of the two offsets
|
||||
// The inner bound of the export is the highest/furthest right of the two offsets.
|
||||
// When zoomed out this keeps it a constant grid space away from the edge, but when zoomed in it prevents the exports from getting too far in
|
||||
let top_right_inner_bound = DVec2::new(
|
||||
node_graph_pixel_offset_top_right.x.max(node_graph_grid_space_offset_top_right.x),
|
||||
node_graph_pixel_offset_top_right.y.min(node_graph_grid_space_offset_top_right.y),
|
||||
@@ -561,6 +564,6 @@ impl NodeNetworkInterface {
|
||||
return String::new();
|
||||
};
|
||||
|
||||
format!("{display_name}\nReference: {reference}\n\n{description}")
|
||||
format!("{display_name}\n\nReference: {reference:?}\n\n{description}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use glam::{DVec2, IVec2};
|
||||
use graphene_std::vector::misc::dvec2_to_point;
|
||||
use graphene_std::{node_graph_overlay::types::FrontendGraphDataType, vector::misc::dvec2_to_point};
|
||||
use kurbo::{BezPath, DEFAULT_ACCURACY, Line, Point, Shape};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
|
||||
@@ -562,7 +562,7 @@ struct PathToolData {
|
||||
saved_selection_before_handle_drag: HashMap<LayerNodeIdentifier, (HashSet<ManipulatorPointId>, HashSet<SegmentId>)>,
|
||||
handle_drag_toggle: bool,
|
||||
saved_points_before_anchor_convert_smooth_sharp: HashMap<LayerNodeIdentifier, Vec<ManipulatorPointId>>,
|
||||
last_click_time: Instant,
|
||||
last_click_time: u64,
|
||||
dragging_state: DraggingState,
|
||||
angle: f64,
|
||||
pivot_gizmo: PivotGizmo,
|
||||
|
||||
@@ -12,6 +12,7 @@ use graphene_std::text::FontCache;
|
||||
use graphene_std::transform::Footprint;
|
||||
use graphene_std::vector::Vector;
|
||||
use graphene_std::wasm_application_io::RenderOutputType;
|
||||
use graphene_std::Graphic;
|
||||
use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta;
|
||||
|
||||
mod runtime_io;
|
||||
@@ -121,14 +122,7 @@ impl NodeGraphExecutor {
|
||||
|
||||
/// Update the cached network if necessary.
|
||||
fn update_node_graph(&mut self, document: &mut DocumentMessageHandler, node_to_inspect: Option<NodeId>, ignore_hash: bool) -> Result<(), String> {
|
||||
let mut network = document.network_interface.document_network().clone();
|
||||
if let Some(mut node_graph_overlay_node) = document.node_graph_handler.node_graph_overlay.clone() {
|
||||
let node_graph_overlay_id = NodeId::new();
|
||||
let new_export = NodeInput::node(node_graph_overlay_id, 0);
|
||||
let old_export = std::mem::replace(&mut network.exports[0], new_export);
|
||||
node_graph_overlay_node.inputs[0] = old_export;
|
||||
network.nodes.insert(node_graph_overlay_id, node_graph_overlay_node);
|
||||
}
|
||||
let network = document.network_interface.document_network().clone();
|
||||
let network_hash = network.current_hash();
|
||||
// Refresh the graph when it changes or the inspect node changes
|
||||
if network_hash != self.node_graph_hash || self.previous_node_to_inspect != node_to_inspect || ignore_hash {
|
||||
|
||||
Reference in New Issue
Block a user