Upgrade to the Rust 2024 edition (#2367)

* Update to rust 2024 edition

* Fixes

* Clean up imports

* Cargo fmt again

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2025-03-12 17:29:12 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent 927d7dd9b2
commit beb1c6ae64
253 changed files with 980 additions and 1371 deletions
@@ -5,17 +5,15 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GridSnapping};
use crate::messages::portfolio::utility_types::PanelType;
use crate::messages::prelude::*;
use glam::DAffine2;
use graph_craft::document::NodeId;
use graphene_core::Color;
use graphene_core::raster::BlendMode;
use graphene_core::raster::Image;
use graphene_core::vector::style::ViewMode;
use graphene_core::Color;
use graphene_std::renderer::ClickTarget;
use graphene_std::transform::Footprint;
use glam::DAffine2;
#[impl_message(Message, PortfolioMessage, Document)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum DocumentMessage {
@@ -2,10 +2,10 @@ use super::node_graph::document_node_definitions;
use super::node_graph::utility_types::Transform;
use super::overlays::utility_types::Pivot;
use super::utility_types::error::EditorError;
use super::utility_types::misc::{GroupFolderType, SnappingOptions, SnappingState, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS};
use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS, SnappingOptions, SnappingState};
use super::utility_types::network_interface::{self, NodeNetworkInterface, TransactionStatus};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes};
use crate::application::{generate_uuid, GRAPHITE_GIT_COMMIT_HASH};
use crate::application::{GRAPHITE_GIT_COMMIT_HASH, generate_uuid};
use crate::consts::{ASYMPTOTIC_EFFECT, COLOR_OVERLAY_GRAY, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL};
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
@@ -24,17 +24,15 @@ use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
use crate::messages::tool::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor;
use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::vector::style::ViewMode;
use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{path_bool_lib, PointId};
use glam::{DAffine2, DVec2, IVec2};
use graphene_std::vector::{PointId, path_bool_lib};
pub struct DocumentMessageData<'a> {
pub document_id: DocumentId,
@@ -1497,7 +1495,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
impl DocumentMessageHandler {
/// Runs an intersection test with all layers and a viewport space quad
pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
let document_quad = document_to_viewport.inverse() * viewport_quad;
@@ -1505,12 +1503,12 @@ impl DocumentMessageHandler {
}
/// Runs an intersection test with all layers and a viewport space quad; ignoring artboards
pub fn intersect_quad_no_artboards<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_quad_no_artboards<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.intersect_quad(viewport_quad, ipp).filter(|layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
}
/// Runs an intersection test with all layers and a viewport space subpath
pub fn intersect_polygon<'a>(&'a self, mut viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_polygon<'a>(&'a self, mut viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
viewport_polygon.apply_transform(document_to_viewport.inverse());
@@ -1518,7 +1516,7 @@ impl DocumentMessageHandler {
}
/// Runs an intersection test with all layers and a viewport space subpath; ignoring artboards
pub fn intersect_polygon_no_artboards<'a>(&'a self, viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_polygon_no_artboards<'a>(&'a self, viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.intersect_polygon(viewport_polygon, ipp).filter(|layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
}
@@ -1562,7 +1560,7 @@ impl DocumentMessageHandler {
}
/// Find all of the layers that were clicked on from a viewport space location
pub fn click_xray(&self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
pub fn click_xray(&self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'_> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
let point = document_to_viewport.inverse().transform_point2(ipp.mouse.position);
ClickXRayIter::new(&self.network_interface, XRayTarget::Point(point))
@@ -1584,7 +1582,7 @@ impl DocumentMessageHandler {
}
/// Find layers under the location in viewport space that was clicked, listed by their depth in the layer tree hierarchy.
pub fn click_list<'a>(&'a self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn click_list<'a>(&'a self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.click_xray(ipp)
.filter(move |&layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
.skip_while(|&layer| layer == LayerNodeIdentifier::ROOT_PARENT)
@@ -2,20 +2,18 @@ use super::utility_types::TransformIn;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate;
use crate::messages::prelude::*;
use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::NodeId;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::brush_stroke::BrushStroke;
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::PointId;
use graphene_core::vector::VectorModificationType;
use graphene_core::vector::brush_stroke::BrushStroke;
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::{Artboard, Color};
use glam::{DAffine2, DVec2, IVec2};
#[impl_message(Message, DocumentMessage, GraphOperation)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum GraphOperationMessage {
@@ -5,16 +5,14 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface, OutputConnector};
use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers;
use crate::messages::prelude::*;
use glam::{DAffine2, DVec2};
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
use graphene_core::renderer::Quad;
use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke};
use graphene_core::Color;
use graphene_std::vector::convert_usvg_path;
use glam::{DAffine2, DVec2};
#[derive(Debug, Clone)]
struct ArtboardInfo {
input_node: NodeInput,
@@ -262,10 +260,9 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
// Modify upstream connections
for outward_wire in &artboard.1.output_nodes {
let input = NodeInput::node(artboard_data[artboard.0].merge_node, 0);
let input_connector = if let Some(artboard_info) = artboard_data.get(&outward_wire.node_id().unwrap_or_default()) {
InputConnector::node(artboard_info.merge_node, outward_wire.input_index())
} else {
*outward_wire
let input_connector = match artboard_data.get(&outward_wire.node_id().unwrap_or_default()) {
Some(artboard_info) => InputConnector::node(artboard_info.merge_node, outward_wire.input_index()),
_ => *outward_wire,
};
responses.add(NodeGraphMessage::SetInput { input_connector, input });
}
@@ -1,10 +1,9 @@
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface};
use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::vector::PointId;
/// Convert an affine transform into the tuple `(scale, angle, translation, shear)` assuming `shear.y = 0`.
pub fn compute_scale_angle_translation_shear(transform: DAffine2) -> (DVec2, f64, DVec2, DVec2) {
@@ -89,11 +88,7 @@ pub fn get_current_transform(inputs: &[NodeInput]) -> DAffine2 {
/// Extract the current normalized pivot from the layer
pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 {
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() {
pivot
} else {
DVec2::splat(0.5)
}
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) }
}
/// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png)
@@ -3,22 +3,20 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions:
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector};
use crate::messages::prelude::*;
use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::concrete;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::brush_stroke::BrushStroke;
use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::{PointId, VectorModificationType};
use graphene_core::{Artboard, Color};
use graphene_std::vector::{VectorData, VectorDataTable};
use graphene_std::GraphicGroupTable;
use glam::{DAffine2, DVec2, IVec2};
use graphene_std::vector::{VectorData, VectorDataTable};
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum TransformIn {
@@ -82,10 +80,9 @@ impl<'a> ModifyInputsContext<'a> {
if current_index == insert_index {
break;
}
let next_node_in_stack_id =
network_interface
.input_from_connector(&post_node_input_connector, &[])
.and_then(|input_from_connector| if let NodeInput::Node { node_id, .. } = input_from_connector { Some(node_id) } else { None });
let next_node_in_stack_id = network_interface
.input_from_connector(&post_node_input_connector, &[])
.and_then(|input_from_connector| if let NodeInput::Node { node_id, .. } = input_from_connector { Some(node_id) } else { None });
if let Some(next_node_in_stack_id) = next_node_in_stack_id {
// Only increment index for layer nodes
@@ -1,6 +1,5 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::prelude::*;
use glam::DVec2;
#[impl_message(Message, DocumentMessage, Navigation)]
@@ -10,10 +10,8 @@ use crate::messages::portfolio::document::utility_types::misc::PTZ;
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
use graph_craft::document::NodeId;
use glam::{DAffine2, DVec2};
use graph_craft::document::NodeId;
pub struct NavigationMessageData<'a> {
pub network_interface: &'a mut NodeNetworkInterface,
@@ -8,12 +8,12 @@ use crate::messages::portfolio::document::utility_types::network_interface::{
use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::Message;
use crate::node_graph_executor::NodeGraphExecutor;
use glam::DVec2;
use graph_craft::ProtoNodeIdentifier;
use graph_craft::concrete;
use graph_craft::document::value::*;
use graph_craft::document::*;
use graph_craft::imaginate_input::ImaginateSamplingMethod;
use graph_craft::ProtoNodeIdentifier;
use graphene_core::raster::brush_cache::BrushCache;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlue, RedGreenBlueAlpha};
@@ -22,12 +22,10 @@ use graphene_core::transform::Footprint;
use graphene_core::vector::VectorDataTable;
use graphene_core::*;
use graphene_std::wasm_application_io::WasmEditorApi;
#[cfg(feature = "gpu")]
use wgpu_executor::{Bindgroup, CommandBuffer, PipelineLayout, ShaderHandle, ShaderInputFrame, WgpuShaderInput};
use glam::DVec2;
use once_cell::sync::Lazy;
use std::collections::{HashMap, HashSet, VecDeque};
#[cfg(feature = "gpu")]
use wgpu_executor::{Bindgroup, CommandBuffer, PipelineLayout, ShaderHandle, ShaderInputFrame, WgpuShaderInput};
pub struct NodePropertiesContext<'a> {
pub persistent_data: &'a PersistentData,
@@ -52,10 +50,9 @@ impl NodePropertiesContext<'_> {
log::error!("Could not get input properties row in call_widget_override");
return Vec::new();
};
if let Some(tooltip) = &input_properties_row.input_data.get("tooltip").and_then(|tooltip| tooltip.as_str()) {
layout_group.into_iter().map(|widget| widget.with_tooltip(*tooltip)).collect::<Vec<_>>()
} else {
layout_group
match &input_properties_row.input_data.get("tooltip").and_then(|tooltip| tooltip.as_str()) {
Some(tooltip) => layout_group.into_iter().map(|widget| widget.with_tooltip(*tooltip)).collect::<Vec<_>>(),
_ => layout_group,
}
})
.map_err(|error| {
@@ -3,7 +3,6 @@ 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 graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
@@ -15,13 +15,11 @@ use crate::messages::portfolio::document::utility_types::network_interface::{
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry};
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::proto::GraphErrors;
use graphene_core::*;
use renderer::Quad;
use glam::{DAffine2, DVec2, IVec2};
use std::cmp::Ordering;
#[derive(Debug)]
@@ -1141,11 +1139,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let mut node_wires = Vec::new();
let mut stack_wires = Vec::new();
for wire in overlapping_wires {
if is_stack_wire(&wire) {
stack_wires.push(wire)
} else {
node_wires.push(wire)
}
if is_stack_wire(&wire) { stack_wires.push(wire) } else { node_wires.push(wire) }
}
// Auto convert node to layer when inserting on a single stack wire
@@ -2068,26 +2062,23 @@ impl NodeGraphMessageHandler {
.iter()
.flat_map(|(wire_end, node)| node.inputs.iter().filter(|input| input.is_exposed()).enumerate().map(move |(index, input)| (input, wire_end, index)))
.filter_map(|(input, &wire_end, wire_end_input_index)| {
if let NodeInput::Node {
node_id: wire_start,
output_index: wire_start_output_index,
// TODO: add ui for lambdas
lambda: _,
} = *input
{
Some(FrontendNodeWire {
match *input {
NodeInput::Node {
node_id: wire_start,
output_index: wire_start_output_index,
// TODO: add ui for lambdas
lambda: _,
} => Some(FrontendNodeWire {
wire_start: OutputConnector::node(wire_start, wire_start_output_index),
wire_end: InputConnector::node(wire_end, wire_end_input_index),
dashed: false,
})
} else if let NodeInput::Network { import_index, .. } = *input {
Some(FrontendNodeWire {
}),
NodeInput::Network { import_index, .. } => Some(FrontendNodeWire {
wire_start: OutputConnector::Import(import_index),
wire_end: InputConnector::node(wire_end, wire_end_input_index),
dashed: false,
})
} else {
None
}),
_ => None,
}
})
.collect::<Vec<_>>();
@@ -2281,16 +2272,12 @@ impl NodeGraphMessageHandler {
let mut current_network = network_interface.nested_network(&current_network_path).unwrap();
let mut subgraph_names = vec!["Document".to_string()];
for node_id in breadcrumb_network_path {
if let Some(node) = current_network.nodes.get(node_id) {
if let Some(network) = node.implementation.get_network() {
current_network = network;
};
subgraph_names.push(network_interface.frontend_display_name(node_id, &current_network_path));
current_network_path.push(*node_id)
} else {
// Could not get node in network in breadcrumb_network_path
return None;
let node = current_network.nodes.get(node_id)?;
if let Some(network) = node.implementation.get_network() {
current_network = network;
};
subgraph_names.push(network_interface.frontend_display_name(node_id, &current_network_path));
current_network_path.push(*node_id)
}
Some(subgraph_names)
}
@@ -1,16 +1,16 @@
#![allow(clippy::too_many_arguments)]
use super::document_node_definitions::{NodePropertiesContext, NODE_OVERRIDES};
use super::document_node_definitions::{NODE_OVERRIDES, NodePropertiesContext};
use super::utility_types::FrontendGraphDataType;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::prelude::*;
use dyn_any::DynAny;
use glam::{DAffine2, DVec2, IVec2, UVec2};
use graph_craft::Type;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod};
use graph_craft::Type;
use graphene_core::raster::curve::Curve;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::{
@@ -22,25 +22,20 @@ use graphene_core::vector::misc::CentroidType;
use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
use graphene_std::application_io::TextureFrameTable;
use graphene_std::transform::Footprint;
use graphene_std::vector::VectorDataTable;
use graphene_std::vector::misc::BooleanOperation;
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
use graphene_std::vector::VectorDataTable;
use graphene_std::{GraphicGroupTable, RasterFrame};
use glam::{DAffine2, DVec2, IVec2, UVec2};
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
let widget = TextLabel::new(text).widget_holder();
vec![LayoutGroup::Row { widgets: vec![widget] }]
}
fn optionally_update_value<T>(value: impl Fn(&T) -> Option<TaggedValue> + 'static + Send + Sync, node_id: NodeId, input_index: usize) -> impl Fn(&T) -> Message + 'static + Send + Sync {
move |input_value: &T| {
if let Some(value) = value(input_value) {
NodeGraphMessage::SetInputValue { node_id, input_index, value }.into()
} else {
Message::NoOp
}
move |input_value: &T| match value(input_value) {
Some(value) => NodeGraphMessage::SetInputValue { node_id, input_index, value }.into(),
_ => Message::NoOp,
}
}
@@ -177,68 +172,78 @@ pub(crate) fn property_from_type(
Some(x) if x == TypeId::of::<CellularDistanceFunction>() => cellular_distance_function(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<CellularReturnType>() => cellular_return_type(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<DomainWarpType>() => domain_warp_type(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![DropdownInput::new(vec![vec![
MenuListEntry::new("Relative")
.label("Relative")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)),
MenuListEntry::new("Absolute")
.label("Absolute")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)),
]])
.widget_holder()]
Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Relative")
.label("Relative")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)),
MenuListEntry::new("Absolute")
.label("Absolute")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)),
]])
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<LineCap>() => line_cap_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<LineJoin>() => line_join_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<FillType>() => vec![DropdownInput::new(vec![vec![
MenuListEntry::new("Solid")
.label("Solid")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)),
MenuListEntry::new("Gradient")
.label("Gradient")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)),
]])
.widget_holder()]
Some(x) if x == TypeId::of::<FillType>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Solid")
.label("Solid")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)),
MenuListEntry::new("Gradient")
.label("Gradient")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)),
]])
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<GradientType>() => vec![DropdownInput::new(vec![vec![
MenuListEntry::new("Linear")
.label("Linear")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)),
MenuListEntry::new("Radial")
.label("Radial")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
]])
.widget_holder()]
Some(x) if x == TypeId::of::<GradientType>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Linear")
.label("Linear")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)),
MenuListEntry::new("Radial")
.label("Radial")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
]])
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<BooleanOperation>() => boolean_operation_radio_buttons(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<CentroidType>() => centroid_widget(document_node, node_id, index),
Some(x) if x == TypeId::of::<LuminanceCalculation>() => luminance_calculation(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![DropdownInput::new(
ImaginateSamplingMethod::list()
.into_iter()
.map(|method| {
vec![MenuListEntry::new(format!("{:?}", method)).label(method.to_string()).on_update(update_value(
move |_| TaggedValue::ImaginateSamplingMethod(method),
node_id,
index,
))]
})
.collect(),
)
.widget_holder()]
Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![
DropdownInput::new(
ImaginateSamplingMethod::list()
.into_iter()
.map(|method| {
vec![MenuListEntry::new(format!("{:?}", method)).label(method.to_string()).on_update(update_value(
move |_| TaggedValue::ImaginateSamplingMethod(method),
node_id,
index,
))]
})
.collect(),
)
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![DropdownInput::new(
ImaginateMaskStartingFill::list()
.into_iter()
.map(|fill| {
vec![MenuListEntry::new(format!("{:?}", fill)).label(fill.to_string()).on_update(update_value(
move |_| TaggedValue::ImaginateMaskStartingFill(fill),
node_id,
index,
))]
})
.collect(),
)
.widget_holder()]
Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![
DropdownInput::new(
ImaginateMaskStartingFill::list()
.into_iter()
.map(|fill| {
vec![MenuListEntry::new(format!("{:?}", fill)).label(fill.to_string()).on_update(update_value(
move |_| TaggedValue::ImaginateMaskStartingFill(fill),
node_id,
index,
))]
})
.collect(),
)
.widget_holder(),
]
.into(),
_ => {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, true);
@@ -313,7 +318,7 @@ pub fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Bool(x)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Bool(x)) = input.as_non_exposed_value() {
widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
checkbox_input
@@ -342,7 +347,7 @@ pub fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Footprint(footprint)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Footprint(footprint)) = input.as_non_exposed_value() {
let top_left = footprint.transform.transform_point2(DVec2::ZERO);
let bounds = footprint.scale();
let oversample = footprint.resolution.as_dvec2() / bounds;
@@ -752,7 +757,7 @@ pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::RedGreenBlue(mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RedGreenBlue(mode)) = input.as_non_exposed_value() {
let calculation_modes = [RedGreenBlue::Red, RedGreenBlue::Green, RedGreenBlue::Blue];
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@@ -779,7 +784,7 @@ pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::RedGreenBlueAlpha(mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RedGreenBlueAlpha(mode)) = input.as_non_exposed_value() {
let calculation_modes = [RedGreenBlueAlpha::Red, RedGreenBlueAlpha::Green, RedGreenBlueAlpha::Blue, RedGreenBlueAlpha::Alpha];
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@@ -807,7 +812,7 @@ pub fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, n
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::NoiseType(noise_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::NoiseType(noise_type)) = input.as_non_exposed_value() {
let entries = NoiseType::list()
.iter()
.map(|noise_type| {
@@ -833,7 +838,7 @@ pub fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::FractalType(fractal_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::FractalType(fractal_type)) = input.as_non_exposed_value() {
let entries = FractalType::list()
.iter()
.map(|fractal_type| {
@@ -859,7 +864,7 @@ pub fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CellularDistanceFunction(cellular_distance_function)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CellularDistanceFunction(cellular_distance_function)) = input.as_non_exposed_value() {
let entries = CellularDistanceFunction::list()
.iter()
.map(|cellular_distance_function| {
@@ -888,7 +893,7 @@ pub fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CellularReturnType(cellular_return_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CellularReturnType(cellular_return_type)) = input.as_non_exposed_value() {
let entries = CellularReturnType::list()
.iter()
.map(|cellular_return_type| {
@@ -914,7 +919,7 @@ pub fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::DomainWarpType(domain_warp_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::DomainWarpType(domain_warp_type)) = input.as_non_exposed_value() {
let entries = DomainWarpType::list()
.iter()
.map(|domain_warp_type| {
@@ -940,7 +945,7 @@ pub fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, n
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::BlendMode(blend_mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::BlendMode(blend_mode)) = input.as_non_exposed_value() {
let entries = BlendMode::list_svg_subset()
.iter()
.map(|category| {
@@ -973,7 +978,7 @@ pub fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, inde
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LuminanceCalculation(calculation)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LuminanceCalculation(calculation)) = input.as_non_exposed_value() {
let calculation_modes = LuminanceCalculation::list();
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@@ -1001,7 +1006,7 @@ pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: No
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::BooleanOperation(calculation)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::BooleanOperation(calculation)) = input.as_non_exposed_value() {
let operations = BooleanOperation::list();
let icons = BooleanOperation::icons();
let mut entries = Vec::with_capacity(operations.len());
@@ -1030,7 +1035,7 @@ pub fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usi
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LineCap(line_cap)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LineCap(line_cap)) = input.as_non_exposed_value() {
let entries = [("Butt", LineCap::Butt), ("Round", LineCap::Round), ("Square", LineCap::Square)]
.into_iter()
.map(|(name, val)| {
@@ -1055,7 +1060,7 @@ pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LineJoin(line_join)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LineJoin(line_join)) = input.as_non_exposed_value() {
let entries = [("Miter", LineJoin::Miter), ("Bevel", LineJoin::Bevel), ("Round", LineJoin::Round)]
.into_iter()
.map(|(name, val)| {
@@ -1101,7 +1106,7 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
.on_commit(commit_value)
.widget_holder(),
),
TaggedValue::GradientStops(ref x) => widgets.push(
TaggedValue::GradientStops(x) => widgets.push(
color_button
.value(FillChoice::Gradient(x.clone()))
.on_update(update_value(
@@ -1143,7 +1148,7 @@ pub fn centroid_widget(document_node: &DocumentNode, node_id: NodeId, index: usi
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CentroidType(centroid_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CentroidType(centroid_type)) = input.as_non_exposed_value() {
let entries = vec![
RadioEntryData::new("area")
.label("Area")
@@ -1223,13 +1228,10 @@ pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesCo
let document_node = get_document_node(node_id, context)?;
// This is safe since the node is a proto node and the implementation cannot be changed.
let randomize_index = 5;
Ok(
if let Some(&TaggedValue::Bool(randomize_enabled)) = &document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
randomize_enabled
} else {
false
},
)
Ok(match document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
Some(TaggedValue::Bool(randomize_enabled)) => *randomize_enabled,
_ => false,
})
}
pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
@@ -1244,10 +1246,9 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
// Monochrome
let monochrome_index = 1;
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true);
let is_monochrome = if let Some(&TaggedValue::Bool(monochrome_choice)) = &document_node.inputs[monochrome_index].as_value() {
monochrome_choice
} else {
false
let is_monochrome = match document_node.inputs[monochrome_index].as_value() {
Some(TaggedValue::Bool(monochrome_choice)) => *monochrome_choice,
_ => false,
};
// Output channel choice
@@ -1277,11 +1278,12 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
output_channel.extend([RadioInput::new(entries).selected_index(Some(choice as u32)).widget_holder()]);
};
let is_output_channel = if let Some(&TaggedValue::RedGreenBlue(choice)) = &document_node.inputs[output_channel_index].as_value() {
choice
} else {
warn!("Channel Mixer node properties panel could not be displayed.");
return vec![];
let is_output_channel = match &document_node.inputs[output_channel_index].as_value() {
Some(TaggedValue::RedGreenBlue(choice)) => choice,
_ => {
warn!("Channel Mixer node properties panel could not be displayed.");
return vec![];
}
};
// Channel values
@@ -1376,11 +1378,12 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
colors.extend([DropdownInput::new(entries).selected_index(Some(choice as u32)).widget_holder()]);
}
let colors_choice_index = if let Some(&TaggedValue::SelectiveColorChoice(choice)) = &document_node.inputs[colors_index].as_value() {
choice
} else {
warn!("Selective Color node properties panel could not be displayed.");
return vec![];
let colors_choice_index = match &document_node.inputs[colors_index].as_value() {
Some(TaggedValue::SelectiveColorChoice(choice)) => choice,
_ => {
warn!("Selective Color node properties panel could not be displayed.");
return vec![];
}
};
// CMYK
@@ -1409,7 +1412,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::RelativeAbsolute(relative_or_absolute)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RelativeAbsolute(relative_or_absolute)) = input.as_non_exposed_value() {
let entries = vec![
RadioEntryData::new("relative")
.label("Relative")
@@ -1495,7 +1498,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Bool(is_individual)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Bool(is_individual)) = input.as_non_exposed_value() {
// Values
let Some(input) = document_node.inputs.get(corner_radius_index) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
@@ -2216,7 +2219,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
let mut widgets_first_row = start_widgets(document_node, node_id, fill_index, "Fill", FrontendGraphDataType::General, true);
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), Some(&TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), &Some(&TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
&document_node.inputs[fill_index].as_value(),
&document_node.inputs[backup_color_index].as_value(),
&document_node.inputs[backup_gradient_index].as_value(),
@@ -1,8 +1,7 @@
use graph_craft::document::value::TaggedValue;
use graph_craft::document::NodeId;
use graphene_core::Type;
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, OutputConnector, TypeSource};
use graph_craft::document::NodeId;
use graph_craft::document::value::TaggedValue;
use graphene_core::Type;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum FrontendGraphDataType {
@@ -2,11 +2,9 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::misc::{GridSnapping, GridType};
use crate::messages::prelude::*;
use glam::DVec2;
use graphene_core::raster::color::Color;
use graphene_core::renderer::Quad;
use glam::DVec2;
use graphene_std::vector::style::FillChoice;
fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, spacing: DVec2) {
@@ -211,7 +209,7 @@ pub fn grid_overlay(document: &DocumentMessageHandler, overlay_context: &mut Ove
pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
let mut widgets = Vec::new();
fn update_val<I>(grid: &GridSnapping, update: impl Fn(&mut GridSnapping, &I)) -> impl Fn(&I) -> Message {
fn update_val<I, F: Fn(&mut GridSnapping, &I)>(grid: &GridSnapping, update: F) -> impl Fn(&I) -> Message + use<I, F> {
let grid = grid.clone();
move |input: &I| {
let mut grid = grid.clone();
@@ -220,7 +218,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
}
}
let update_origin = |grid, update: fn(&mut GridSnapping) -> Option<&mut f64>| {
update_val::<NumberInput>(grid, move |grid, val| {
update_val::<NumberInput, _>(grid, move |grid, val| {
if let Some(val) = val.value {
if let Some(update) = update(grid) {
*update = val;
@@ -229,7 +227,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
})
};
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
update_val::<ColorInput>(grid, move |grid, color| {
update_val::<ColorInput, _>(grid, move |grid, color| {
if let FillChoice::Solid(color) = color.value {
if let Some(update_color) = update(grid) {
*update_color = color;
@@ -238,7 +236,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
})
};
let update_display = |grid, update: fn(&mut GridSnapping) -> Option<&mut bool>| {
update_val::<CheckboxInput>(grid, move |grid, checkbox| {
update_val::<CheckboxInput, _>(grid, move |grid, checkbox| {
if let Some(update) = update(grid) {
*update = checkbox.checked;
}
@@ -1,4 +1,4 @@
use super::utility_types::{empty_provider, OverlayProvider};
use super::utility_types::{OverlayProvider, empty_provider};
use crate::messages::prelude::*;
#[impl_message(Message, DocumentMessage, Overlays)]
@@ -2,12 +2,10 @@ use super::utility_types::{DrawHandles, OverlayContext};
use crate::consts::HIDE_HANDLE_DISTANCE;
use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerState, ShapeState};
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler};
use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{PointId, SegmentId};
use bezier_rs::{Bezier, BezierHandles};
use glam::{DAffine2, DVec2};
use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{PointId, SegmentId};
use wasm_bindgen::JsCast;
pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> {
@@ -4,14 +4,12 @@ use crate::consts::{
COMPASS_ROSE_RING_INNER_DIAMETER, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
};
use crate::messages::prelude::Message;
use bezier_rs::{Bezier, Subpath};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use core::borrow::Borrow;
use core::f64::consts::{FRAC_PI_2, TAU};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use std::collections::HashMap;
use wasm_bindgen::JsValue;
@@ -1,7 +1,6 @@
use graph_craft::document::NodeId;
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::node_graph_executor::NodeGraphExecutor;
use graph_craft::document::NodeId;
pub struct PropertiesPanelMessageHandlerData<'a> {
pub network_interface: &'a mut NodeNetworkInterface,
@@ -1,5 +1,4 @@
use super::network_interface::NodeTemplate;
use graph_craft::document::NodeId;
#[repr(u8)]
@@ -1,14 +1,12 @@
use super::network_interface::NodeNetworkInterface;
use crate::messages::portfolio::document::graph_operation::transform_utils;
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
use super::network_interface::NodeNetworkInterface;
use glam::{DAffine2, DVec2};
use graph_craft::document::NodeId;
use graphene_core::renderer::ClickTarget;
use graphene_core::renderer::Quad;
use graphene_core::transform::Footprint;
use graphene_std::vector::{PointId, VectorData};
use glam::{DAffine2, DVec2};
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;
@@ -1,5 +1,4 @@
use graphene_core::raster::color::Color;
use thiserror::Error;
/// The error type used by the Graphite editor.
@@ -1,8 +1,6 @@
use crate::consts::COLOR_OVERLAY_GRAY;
use graphene_core::raster::Color;
use glam::DVec2;
use graphene_core::raster::Color;
use std::fmt;
#[repr(transparent)]
@@ -3,21 +3,21 @@ use super::misc::PTZ;
use super::nodes::SelectedNodes;
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};
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
use crate::messages::portfolio::document::node_graph::document_node_definitions::{resolve_document_node_type, DocumentNodeDefinition};
use crate::messages::portfolio::document::node_graph::document_node_definitions::{DocumentNodeDefinition, resolve_document_node_type};
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput};
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::tool_messages::tool_prelude::NumberInputMode;
use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork};
use graph_craft::{concrete, Type};
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork};
use graph_craft::{Type, concrete};
use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::transform::Footprint;
use graphene_std::vector::{PointId, VectorData, VectorModificationType};
use interpreted_executor::{dynamic_executor::ResolvedDocumentNodeTypes, node_registry::NODE_REGISTRY};
use glam::{DAffine2, DVec2, IVec2};
use serde_json::{json, Value};
use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypes;
use interpreted_executor::node_registry::NODE_REGISTRY;
use serde_json::{Value, json};
use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::{DefaultHasher, Hash, Hasher};
@@ -656,11 +656,7 @@ impl NodeNetworkInterface {
// For example a node input of (Footprint) -> VectorData would not be compatible with () -> VectorData
node_io.inputs[iterator_index].clone().nested_type() == input_type || node_io.inputs[iterator_index] == input_type
});
if valid_implementation {
node_io.inputs.get(*input_index).cloned()
} else {
None
}
if valid_implementation { node_io.inputs.get(*input_index).cloned() } else { None }
})
.collect::<Vec<_>>()
}
@@ -1339,7 +1335,7 @@ impl NodeNetworkInterface {
/// Layers excluding ones that are children of other layers in the list.
// TODO: Cache this
pub fn shallowest_unique_layers(&self, network_path: &[NodeId]) -> impl Iterator<Item = LayerNodeIdentifier> {
pub fn shallowest_unique_layers(&self, network_path: &[NodeId]) -> impl Iterator<Item = LayerNodeIdentifier> + use<> {
let mut sorted_layers = if let Some(selected_nodes) = self.selected_nodes_in_nested_network(network_path) {
selected_nodes
.selected_layers(self.document_metadata())
@@ -2528,10 +2524,9 @@ impl NodeNetworkInterface {
}
}
let number_of_outputs = if let DocumentNodeImplementation::Network(network) = &document_node.implementation {
network.exports.len()
} else {
1
let number_of_outputs = match &document_node.implementation {
DocumentNodeImplementation::Network(network) => network.exports.len(),
_ => 1,
};
// If the node does not have a primary output, shift all ports down a row
let mut output_row_count = if !node_metadata.persistent_metadata.has_primary_output { 1 } else { 0 };
@@ -2682,11 +2677,7 @@ impl NodeNetworkInterface {
let Some(downstream_node_id) = downstream_node_connectors.iter().find_map(|input_connector| {
if let InputConnector::Node { node_id, input_index } = input_connector {
let downstream_input_index = if self.is_layer(node_id, network_path) { 1 } else { 0 };
if *input_index == downstream_input_index {
Some(node_id)
} else {
None
}
if *input_index == downstream_input_index { Some(node_id) } else { None }
} else {
None
}
@@ -2933,11 +2924,7 @@ impl NodeNetworkInterface {
log::error!("Could not get node_metadata for node {node_id}");
return None;
};
if !node_metadata.persistent_metadata.is_layer() {
Some(*node_id)
} else {
None
}
if !node_metadata.persistent_metadata.is_layer() { Some(*node_id) } else { None }
})
.or_else(|| clicked_nodes.into_iter().next())
}
@@ -3168,13 +3155,10 @@ impl NodeNetworkInterface {
// Only load structure if there is a root node
let Some(root_node) = self.root_node(&[]) else { return };
let Some(first_root_layer) = self.upstream_flow_back_from_nodes(vec![root_node.node_id], &[], FlowType::PrimaryFlow).find_map(|node_id| {
if self.is_layer(&node_id, &[]) {
Some(LayerNodeIdentifier::new(node_id, self, &[]))
} else {
None
}
}) else {
let Some(first_root_layer) = self
.upstream_flow_back_from_nodes(vec![root_node.node_id], &[], FlowType::PrimaryFlow)
.find_map(|node_id| if self.is_layer(&node_id, &[]) { Some(LayerNodeIdentifier::new(node_id, self, &[])) } else { None })
else {
return;
};
// Should refer to output node
@@ -3329,7 +3313,7 @@ impl NodeNetworkInterface {
};
{
let mut value = node.inputs.get_mut(1).and_then(|input| input.as_value_mut());
let Some(TaggedValue::VectorModification(ref mut modification)) = value.as_deref_mut() else {
let Some(TaggedValue::VectorModification(modification)) = value.as_deref_mut() else {
panic!("Path node does not have modification input");
};
@@ -3846,10 +3830,9 @@ impl NodeNetworkInterface {
}
}
let previous_metadata = if let NodeInput::Node { node_id, .. } = &previous_input {
self.position(node_id, network_path).map(|position| (*node_id, position))
} else {
None
let previous_metadata = match &previous_input {
NodeInput::Node { node_id, .. } => self.position(node_id, network_path).map(|position| (*node_id, position)),
_ => None,
};
let Some(network) = self.network_mut(network_path) else {
@@ -4701,14 +4684,17 @@ impl NodeNetworkInterface {
log::error!("Could not get node_metadata for node {node_id}");
return;
};
if let NodeTypePersistentMetadata::Layer(layer_metadata) = &mut node_metadata.persistent_metadata.node_type_metadata {
if layer_metadata.position == LayerPosition::Stack(y_offset) {
return;
match &mut node_metadata.persistent_metadata.node_type_metadata {
NodeTypePersistentMetadata::Layer(layer_metadata) => {
if layer_metadata.position == LayerPosition::Stack(y_offset) {
return;
}
layer_metadata.position = LayerPosition::Stack(y_offset);
self.transaction_modified();
}
_ => {
log::error!("Could not set stack position for non layer node {node_id}");
}
layer_metadata.position = LayerPosition::Stack(y_offset);
self.transaction_modified();
} else {
log::error!("Could not set stack position for non layer node {node_id}");
}
}
@@ -5128,16 +5114,12 @@ impl NodeNetworkInterface {
stack_dependents_with_position.sort_unstable_by(|a, b| {
a.1.signum().cmp(&b.1.signum()).then_with(|| {
// If the node has a positive offset, then it is shifted up, so shift the top nodes first
if a.1.signum() == 1 {
a.2.cmp(&b.2)
} else {
b.2.cmp(&a.2)
}
if a.1.signum() == 1 { a.2.cmp(&b.2) } else { b.2.cmp(&a.2) }
})
});
// Try shift every node that is offset from its original position
for (node_id, mut offset, _) in stack_dependents_with_position.iter() {
for &(ref node_id, mut offset, _) in stack_dependents_with_position.iter() {
while offset != 0 {
if self.check_collision_with_stack_dependents(node_id, -offset.signum(), network_path).is_empty() {
self.vertical_shift_with_push(node_id, -offset.signum(), &mut HashSet::new(), network_path);
@@ -5302,6 +5284,7 @@ impl NodeNetworkInterface {
self.transaction_modified();
} else if let LayerPosition::Stack(y_offset) = &mut layer_metadata.position {
let shifted_y_offset = *y_offset as i32 + shift.y;
// A layer can only be shifted to a positive y_offset
if shifted_y_offset < 0 {
log::error!(
@@ -5312,6 +5295,7 @@ impl NodeNetworkInterface {
if shift.x != 0 {
log::error!("Stack layer {node_id} cannot be shifted horizontally.");
}
let new_y_offset = shifted_y_offset.max(0) as u32;
if *y_offset == new_y_offset {
return;
@@ -1,8 +1,6 @@
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use super::network_interface::NodeNetworkInterface;
use graph_craft::document::{NodeId, NodeNetwork};
use serde::ser::SerializeStruct;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)]
@@ -7,13 +7,11 @@ use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::utility_types::ToolType;
use glam::{DAffine2, DMat2, DVec2};
use graphene_core::renderer::Quad;
use graphene_core::vector::ManipulatorPointId;
use graphene_core::vector::VectorModificationType;
use graphene_std::vector::{HandleId, PointId};
use glam::{DAffine2, DMat2, DVec2};
use std::collections::{HashMap, VecDeque};
use std::f64::consts::PI;
@@ -136,11 +134,7 @@ impl Axis {
return (target, false);
}
if local {
(Axis::Both, false)
} else {
(self, true)
}
if local { (Axis::Both, false) } else { (self, true) }
}
}
@@ -167,11 +161,7 @@ impl Translation {
}
};
let displacement = transform.inverse().transform_vector2(displacement);
if increment_mode {
displacement.round()
} else {
displacement
}
if increment_mode { displacement.round() } else { displacement }
}
#[must_use]
@@ -259,11 +249,7 @@ impl Default for Scale {
impl Scale {
pub fn to_f64(self, increment: bool) -> f64 {
let factor = if let Some(value) = self.typed_factor { value } else { self.dragged_factor };
if increment {
(factor / SCALE_INCREMENT).round() * SCALE_INCREMENT
} else {
factor
}
if increment { (factor / SCALE_INCREMENT).round() * SCALE_INCREMENT } else { factor }
}
pub fn to_dvec(self, increment_mode: bool) -> DVec2 {