Fix misc errors and cleanup after rebases

This commit is contained in:
Adam
2025-09-09 16:53:07 -07:00
parent c994cdeced
commit 4c92c48cc3
25 changed files with 206 additions and 436 deletions

View File

@@ -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);

View File

@@ -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.;

View File

@@ -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"];

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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 } => {

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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,
}
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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}")
}
}

View File

@@ -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)]

View File

@@ -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,

View File

@@ -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 {