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-13 01:29:12 +01:00 committed by GitHub
parent 927d7dd9b2
commit beb1c6ae64
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
253 changed files with 980 additions and 1371 deletions

View file

@ -2,9 +2,9 @@
name = "graphite-editor" name = "graphite-editor"
publish = false publish = false
version = "0.0.0" version = "0.0.0"
rust-version = "1.82" rust-version = "1.85"
authors = ["Graphite Authors <contact@graphite.rs>"] authors = ["Graphite Authors <contact@graphite.rs>"]
edition = "2021" edition = "2024"
readme = "../README.md" readme = "../README.md"
homepage = "https://graphite.rs" homepage = "https://graphite.rs"
repository = "https://github.com/GraphiteEditor/Graphite" repository = "https://github.com/GraphiteEditor/Graphite"

View file

@ -1,6 +1,5 @@
use crate::dispatcher::Dispatcher; use crate::dispatcher::Dispatcher;
use crate::messages::prelude::*; use crate::messages::prelude::*;
pub use graphene_core::uuid::*; pub use graphene_core::uuid::*;
// TODO: serialize with serde to save the current editor state // TODO: serialize with serde to save the current editor state

View file

@ -303,11 +303,7 @@ impl Dispatcher {
fn create_indents(queues: &[VecDeque<Message>]) -> String { fn create_indents(queues: &[VecDeque<Message>]) -> String {
String::from_iter(queues.iter().enumerate().skip(1).map(|(index, queue)| { String::from_iter(queues.iter().enumerate().skip(1).map(|(index, queue)| {
if index == queues.len() - 1 { if index == queues.len() - 1 {
if queue.is_empty() { if queue.is_empty() { "└── " } else { "├── " }
"└── "
} else {
"├── "
}
} else if queue.is_empty() { } else if queue.is_empty() {
" " " "
} else { } else {

View file

@ -25,7 +25,7 @@
/// ``` /// ```
/// ///
macro_rules! actions { macro_rules! actions {
($($v:expr),* $(,)?) => {{ ($($v:expr_2021),* $(,)?) => {{
vec![$(vec![$v.into()]),*] vec![$(vec![$v.into()]),*]
}}; }};
@ -42,7 +42,7 @@ macro_rules! actions {
/// } /// }
/// ``` /// ```
macro_rules! advertise_actions { macro_rules! advertise_actions {
($($v:expr),* $(,)?) => { ($($v:expr_2021),* $(,)?) => {
fn actions(&self) -> $crate::utility_traits::ActionList { fn actions(&self) -> $crate::utility_traits::ActionList {
actions!($($v),*) actions!($($v),*)
} }

View file

@ -1,9 +1,7 @@
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graph_craft::document::NodeId;
use glam::{IVec2, UVec2}; use glam::{IVec2, UVec2};
use graph_craft::document::NodeId;
/// A dialog to allow users to set some initial options about a new document. /// A dialog to allow users to set some initial options about a new document.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]

View file

@ -26,16 +26,18 @@ impl LayoutHolder for ComingSoonDialog {
if let Some(issue) = self.issue { if let Some(issue) = self.issue {
let row2 = vec![TextLabel::new("But you can help build it! Visit its issue:").widget_holder()]; let row2 = vec![TextLabel::new("But you can help build it! Visit its issue:").widget_holder()];
let row3 = vec![TextButton::new(format!("GitHub Issue #{issue}")) let row3 = vec![
.icon(Some("Website".into())) TextButton::new(format!("GitHub Issue #{issue}"))
.flush(true) .icon(Some("Website".into()))
.on_update(move |_| { .flush(true)
FrontendMessage::TriggerVisitLink { .on_update(move |_| {
url: format!("https://github.com/GraphiteEditor/Graphite/issues/{issue}"), FrontendMessage::TriggerVisitLink {
} url: format!("https://github.com/GraphiteEditor/Graphite/issues/{issue}"),
.into() }
}) .into()
.widget_holder()]; })
.widget_holder(),
];
rows.push(LayoutGroup::Row { widgets: row2 }); rows.push(LayoutGroup::Row { widgets: row2 });
rows.push(LayoutGroup::Row { widgets: row3 }); rows.push(LayoutGroup::Row { widgets: row3 });

View file

@ -32,11 +32,13 @@ impl LayoutHolder for DemoArtworkDialog {
.flat_map(|chunk| { .flat_map(|chunk| {
fn make_dialog(name: &str, filename: &str) -> Message { fn make_dialog(name: &str, filename: &str) -> Message {
DialogMessage::CloseDialogAndThen { DialogMessage::CloseDialogAndThen {
followups: vec![FrontendMessage::TriggerFetchAndOpenDocument { followups: vec![
name: name.to_string(), FrontendMessage::TriggerFetchAndOpenDocument {
filename: filename.to_string(), name: name.to_string(),
} filename: filename.to_string(),
.into()], }
.into(),
],
} }
.into() .into()
} }

View file

@ -10,8 +10,7 @@ pub use about_graphite_dialog::AboutGraphiteDialog;
pub use close_all_documents_dialog::CloseAllDocumentsDialog; pub use close_all_documents_dialog::CloseAllDocumentsDialog;
pub use close_document_dialog::CloseDocumentDialog; pub use close_document_dialog::CloseDocumentDialog;
pub use coming_soon_dialog::ComingSoonDialog; pub use coming_soon_dialog::ComingSoonDialog;
pub use demo_artwork_dialog::ARTWORK;
pub use demo_artwork_dialog::DemoArtworkDialog; pub use demo_artwork_dialog::DemoArtworkDialog;
pub use error_dialog::ErrorDialog; pub use error_dialog::ErrorDialog;
pub use licenses_dialog::LicensesDialog; pub use licenses_dialog::LicensesDialog;
pub use demo_artwork_dialog::ARTWORK;

View file

@ -6,7 +6,6 @@ use crate::messages::portfolio::document::node_graph::utility_types::{
use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer}; use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::utility_types::HintData; use crate::messages::tool::utility_types::HintData;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use graphene_core::text::Font; use graphene_core::text::Font;

View file

@ -1,5 +1,4 @@
use crate::messages::portfolio::utility_types::Platform; use crate::messages::portfolio::utility_types::Platform;
use std::sync::OnceLock; use std::sync::OnceLock;
pub static GLOBAL_PLATFORM: OnceLock<Platform> = OnceLock::new(); pub static GLOBAL_PLATFORM: OnceLock<Platform> = OnceLock::new();

View file

@ -3,7 +3,6 @@ use super::utility_types::misc::Mapping;
use crate::messages::input_mapper::utility_types::input_keyboard::{self, Key}; use crate::messages::input_mapper::utility_types::input_keyboard::{self, Key};
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use std::fmt::Write; use std::fmt::Write;
pub struct InputMapperMessageData<'a> { pub struct InputMapperMessageData<'a> {

View file

@ -11,7 +11,6 @@ use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate; use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate;
use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys; use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
use glam::DVec2; use glam::DVec2;
impl From<MappingVariant> for Mapping { impl From<MappingVariant> for Mapping {

View file

@ -1,8 +1,6 @@
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bitflags::bitflags; use bitflags::bitflags;
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign};

View file

@ -1,6 +1,5 @@
use crate::consts::DRAG_THRESHOLD; use crate::consts::DRAG_THRESHOLD;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bitflags::bitflags; use bitflags::bitflags;
use glam::DVec2; use glam::DVec2;
use std::collections::VecDeque; use std::collections::VecDeque;

View file

@ -24,7 +24,7 @@ macro_rules! modifiers {
/// Each handler adds or removes actions in the form of message discriminants. Here, we tie an input condition (such as a hotkey) to an action's full message. /// Each handler adds or removes actions in the form of message discriminants. Here, we tie an input condition (such as a hotkey) to an action's full message.
/// When an action is currently available, and the user enters that input, the action's message is dispatched on the message bus. /// When an action is currently available, and the user enters that input, the action's message is dispatched on the message bus.
macro_rules! entry { macro_rules! entry {
($input:expr; $(modifiers=[$($modifier:ident),*],)? $(refresh_keys=[$($refresh:ident),* $(,)?],)? action_dispatch=$action_dispatch:expr$(,)?) => { ($input:expr_2021; $(modifiers=[$($modifier:ident),*],)? $(refresh_keys=[$($refresh:ident),* $(,)?],)? action_dispatch=$action_dispatch:expr_2021$(,)?) => {
&[&[ &[&[
// Cause the `action_dispatch` message to be sent when the specified input occurs. // Cause the `action_dispatch` message to be sent when the specified input occurs.
MappingEntry { MappingEntry {
@ -72,7 +72,7 @@ macro_rules! entry {
/// (key_up, key_down, double_click, wheel_scroll, pointer_move) /// (key_up, key_down, double_click, wheel_scroll, pointer_move)
/// ``` /// ```
macro_rules! mapping { macro_rules! mapping {
[$($entry:expr),* $(,)?] => {{ [$($entry:expr_2021),* $(,)?] => {{
let mut key_up = KeyMappingEntries::key_array(); let mut key_up = KeyMappingEntries::key_array();
let mut key_down = KeyMappingEntries::key_array(); let mut key_down = KeyMappingEntries::key_array();
let mut key_up_no_repeat = KeyMappingEntries::key_array(); let mut key_up_no_repeat = KeyMappingEntries::key_array();
@ -107,7 +107,7 @@ macro_rules! mapping {
/// Constructs an `ActionKeys` macro with a certain `Action` variant, conveniently wrapped in `Some()`. /// Constructs an `ActionKeys` macro with a certain `Action` variant, conveniently wrapped in `Some()`.
macro_rules! action_keys { macro_rules! action_keys {
($action:expr) => { ($action:expr_2021) => {
Some(crate::messages::input_mapper::utility_types::misc::ActionKeys::Action($action.into())) Some(crate::messages::input_mapper::utility_types::misc::ActionKeys::Action($action.into()))
}; };
} }

View file

@ -1,9 +1,8 @@
use super::input_keyboard::{all_required_modifiers_pressed, Key, KeysGroup, LayoutKeysGroup}; use super::input_keyboard::{Key, KeysGroup, LayoutKeysGroup, all_required_modifiers_pressed};
use crate::messages::input_mapper::key_mapping::MappingVariant; use crate::messages::input_mapper::key_mapping::MappingVariant;
use crate::messages::input_mapper::utility_types::input_keyboard::{KeyStates, NUMBER_OF_KEYS}; use crate::messages::input_mapper::utility_types::input_keyboard::{KeyStates, NUMBER_OF_KEYS};
use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS; use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use core::time::Duration; use core::time::Duration;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -1,7 +1,6 @@
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ViewportBounds}; use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ViewportBounds};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use core::time::Duration; use core::time::Duration;
#[impl_message(Message, InputPreprocessor)] #[impl_message(Message, InputPreprocessor)]

View file

@ -3,7 +3,6 @@ use crate::messages::input_mapper::utility_types::input_mouse::{MouseButton, Mou
use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo; use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo;
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::DVec2; use glam::DVec2;
pub struct InputPreprocessorMessageData { pub struct InputPreprocessorMessageData {

View file

@ -1,11 +1,9 @@
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup; use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use graphene_core::text::Font; use graphene_core::text::Font;
use graphene_std::vector::style::{FillChoice, GradientStops}; use graphene_std::vector::style::{FillChoice, GradientStops};
use serde_json::Value; use serde_json::Value;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]

View file

@ -6,7 +6,6 @@ use crate::application::generate_uuid;
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup; use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
use crate::messages::input_mapper::utility_types::misc::ActionKeys; use crate::messages::input_mapper::utility_types::misc::ActionKeys;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use std::sync::Arc; use std::sync::Arc;
#[repr(transparent)] #[repr(transparent)]
@ -348,11 +347,7 @@ impl LayoutGroup {
val.clone_from(&tooltip); val.clone_from(&tooltip);
} }
} }
if is_col { if is_col { Self::Column { widgets } } else { Self::Row { widgets } }
Self::Column { widgets }
} else {
Self::Row { widgets }
}
} }
/// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so. /// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so.

View file

@ -2,12 +2,10 @@ use crate::messages::input_mapper::utility_types::misc::ActionKeys;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType;
use crate::messages::tool::tool_messages::tool_prelude::WidgetCallback; use crate::messages::tool::tool_messages::tool_prelude::WidgetCallback;
use derivative::*;
use graphene_std::vector::style::FillChoice; use graphene_std::vector::style::FillChoice;
use graphite_proc_macros::WidgetBuilder; use graphite_proc_macros::WidgetBuilder;
use derivative::*;
#[derive(Clone, Default, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)] #[derive(Clone, Default, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
#[derivative(Debug, PartialEq)] #[derivative(Debug, PartialEq)]
pub struct IconButton { pub struct IconButton {

View file

@ -1,11 +1,10 @@
use crate::messages::input_mapper::utility_types::misc::ActionKeys; use crate::messages::input_mapper::utility_types::misc::ActionKeys;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use graphene_core::{raster::curve::Curve, Color};
use graphite_proc_macros::WidgetBuilder;
use derivative::*; use derivative::*;
use glam::DVec2; use glam::DVec2;
use graphene_core::Color;
use graphene_core::raster::curve::Curve;
use graphite_proc_macros::WidgetBuilder;
#[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)] #[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
#[derivative(Debug, PartialEq)] #[derivative(Debug, PartialEq)]

View file

@ -1,10 +1,9 @@
use super::input_widgets::InvisibleStandinInput;
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup; use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
use crate::messages::input_mapper::utility_types::misc::ActionKeys; use crate::messages::input_mapper::utility_types::misc::ActionKeys;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use super::input_widgets::InvisibleStandinInput;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Default, specta::Type)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Default, specta::Type)]
pub struct MenuBarEntryChildren(pub Vec<Vec<MenuBarEntry>>); pub struct MenuBarEntryChildren(pub Vec<Vec<MenuBarEntry>>);

View file

@ -1,5 +1,4 @@
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphite_proc_macros::*; use graphite_proc_macros::*;
#[impl_message] #[impl_message]

View file

@ -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::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GridSnapping};
use crate::messages::portfolio::utility_types::PanelType; use crate::messages::portfolio::utility_types::PanelType;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::DAffine2;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::Color;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::Image; use graphene_core::raster::Image;
use graphene_core::vector::style::ViewMode; use graphene_core::vector::style::ViewMode;
use graphene_core::Color;
use graphene_std::renderer::ClickTarget; use graphene_std::renderer::ClickTarget;
use graphene_std::transform::Footprint; use graphene_std::transform::Footprint;
use glam::DAffine2;
#[impl_message(Message, PortfolioMessage, Document)] #[impl_message(Message, PortfolioMessage, Document)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum DocumentMessage { pub enum DocumentMessage {

View file

@ -2,10 +2,10 @@ use super::node_graph::document_node_definitions;
use super::node_graph::utility_types::Transform; use super::node_graph::utility_types::Transform;
use super::overlays::utility_types::Pivot; use super::overlays::utility_types::Pivot;
use super::utility_types::error::EditorError; 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::network_interface::{self, NodeNetworkInterface, TransactionStatus};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes}; 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::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::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*; 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::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::ToolType; use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork}; use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::vector::style::ViewMode; use graphene_core::vector::style::ViewMode;
use graphene_std::renderer::{ClickTarget, Quad}; use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{path_bool_lib, PointId}; use graphene_std::vector::{PointId, path_bool_lib};
use glam::{DAffine2, DVec2, IVec2};
pub struct DocumentMessageData<'a> { pub struct DocumentMessageData<'a> {
pub document_id: DocumentId, pub document_id: DocumentId,
@ -1497,7 +1495,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
impl DocumentMessageHandler { impl DocumentMessageHandler {
/// Runs an intersection test with all layers and a viewport space quad /// 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_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
let document_quad = document_to_viewport.inverse() * viewport_quad; 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 /// 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(), &[])) 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 /// 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); 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()); 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 /// 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(), &[])) 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 /// 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 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); let point = document_to_viewport.inverse().transform_point2(ipp.mouse.position);
ClickXRayIter::new(&self.network_interface, XRayTarget::Point(point)) 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. /// 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) self.click_xray(ipp)
.filter(move |&layer| !self.network_interface.is_artboard(&layer.to_node(), &[])) .filter(move |&layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
.skip_while(|&layer| layer == LayerNodeIdentifier::ROOT_PARENT) .skip_while(|&layer| layer == LayerNodeIdentifier::ROOT_PARENT)

View file

@ -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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate; use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig}; 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::PointId;
use graphene_core::vector::VectorModificationType; 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 graphene_core::{Artboard, Color};
use glam::{DAffine2, DVec2, IVec2};
#[impl_message(Message, DocumentMessage, GraphOperation)] #[impl_message(Message, DocumentMessage, GraphOperation)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum GraphOperationMessage { pub enum GraphOperationMessage {

View file

@ -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::network_interface::{InputConnector, NodeNetworkInterface, OutputConnector};
use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers; use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::{DAffine2, DVec2};
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::text::{Font, TypesettingConfig}; use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke}; use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke};
use graphene_core::Color;
use graphene_std::vector::convert_usvg_path; use graphene_std::vector::convert_usvg_path;
use glam::{DAffine2, DVec2};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct ArtboardInfo { struct ArtboardInfo {
input_node: NodeInput, input_node: NodeInput,
@ -262,10 +260,9 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
// Modify upstream connections // Modify upstream connections
for outward_wire in &artboard.1.output_nodes { for outward_wire in &artboard.1.output_nodes {
let input = NodeInput::node(artboard_data[artboard.0].merge_node, 0); 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()) { let input_connector = match artboard_data.get(&outward_wire.node_id().unwrap_or_default()) {
InputConnector::node(artboard_info.merge_node, outward_wire.input_index()) Some(artboard_info) => InputConnector::node(artboard_info.merge_node, outward_wire.input_index()),
} else { _ => *outward_wire,
*outward_wire
}; };
responses.add(NodeGraphMessage::SetInput { input_connector, input }); responses.add(NodeGraphMessage::SetInput { input_connector, input });
} }

View file

@ -1,10 +1,9 @@
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface}; use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface};
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2}; 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`. /// 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) { 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 /// Extract the current normalized pivot from the layer
pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 { pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 {
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) }
pivot
} else {
DVec2::splat(0.5)
}
} }
/// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png) /// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png)

View file

@ -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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector}; use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::concrete; use graph_craft::concrete;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig}; use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::brush_stroke::BrushStroke; use graphene_core::vector::brush_stroke::BrushStroke;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::{PointId, VectorModificationType}; use graphene_core::vector::{PointId, VectorModificationType};
use graphene_core::{Artboard, Color}; use graphene_core::{Artboard, Color};
use graphene_std::vector::{VectorData, VectorDataTable};
use graphene_std::GraphicGroupTable; use graphene_std::GraphicGroupTable;
use graphene_std::vector::{VectorData, VectorDataTable};
use glam::{DAffine2, DVec2, IVec2};
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)] #[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum TransformIn { pub enum TransformIn {
@ -82,10 +80,9 @@ impl<'a> ModifyInputsContext<'a> {
if current_index == insert_index { if current_index == insert_index {
break; break;
} }
let next_node_in_stack_id = let next_node_in_stack_id = network_interface
network_interface .input_from_connector(&post_node_input_connector, &[])
.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 });
.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 { if let Some(next_node_in_stack_id) = next_node_in_stack_id {
// Only increment index for layer nodes // Only increment index for layer nodes

View file

@ -1,6 +1,5 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::DVec2; use glam::DVec2;
#[impl_message(Message, DocumentMessage, Navigation)] #[impl_message(Message, DocumentMessage, Navigation)]

View file

@ -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::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
use graph_craft::document::NodeId;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graph_craft::document::NodeId;
pub struct NavigationMessageData<'a> { pub struct NavigationMessageData<'a> {
pub network_interface: &'a mut NodeNetworkInterface, pub network_interface: &'a mut NodeNetworkInterface,

View file

@ -8,12 +8,12 @@ use crate::messages::portfolio::document::utility_types::network_interface::{
use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::Message; use crate::messages::prelude::Message;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use glam::DVec2;
use graph_craft::ProtoNodeIdentifier;
use graph_craft::concrete; use graph_craft::concrete;
use graph_craft::document::value::*; use graph_craft::document::value::*;
use graph_craft::document::*; use graph_craft::document::*;
use graph_craft::imaginate_input::ImaginateSamplingMethod; use graph_craft::imaginate_input::ImaginateSamplingMethod;
use graph_craft::ProtoNodeIdentifier;
use graphene_core::raster::brush_cache::BrushCache; use graphene_core::raster::brush_cache::BrushCache;
use graphene_core::raster::image::ImageFrameTable; use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlue, RedGreenBlueAlpha}; 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::vector::VectorDataTable;
use graphene_core::*; use graphene_core::*;
use graphene_std::wasm_application_io::WasmEditorApi; 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 once_cell::sync::Lazy;
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet, VecDeque};
#[cfg(feature = "gpu")]
use wgpu_executor::{Bindgroup, CommandBuffer, PipelineLayout, ShaderHandle, ShaderInputFrame, WgpuShaderInput};
pub struct NodePropertiesContext<'a> { pub struct NodePropertiesContext<'a> {
pub persistent_data: &'a PersistentData, pub persistent_data: &'a PersistentData,
@ -52,10 +50,9 @@ impl NodePropertiesContext<'_> {
log::error!("Could not get input properties row in call_widget_override"); log::error!("Could not get input properties row in call_widget_override");
return Vec::new(); return Vec::new();
}; };
if let Some(tooltip) = &input_properties_row.input_data.get("tooltip").and_then(|tooltip| tooltip.as_str()) { match &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<_>>() Some(tooltip) => layout_group.into_iter().map(|widget| widget.with_tooltip(*tooltip)).collect::<Vec<_>>(),
} else { _ => layout_group,
layout_group
} }
}) })
.map_err(|error| { .map_err(|error| {

View file

@ -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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{ImportOrExport, InputConnector, NodeTemplate, OutputConnector}; use crate::messages::portfolio::document::utility_types::network_interface::{ImportOrExport, InputConnector, NodeTemplate, OutputConnector};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::IVec2; use glam::IVec2;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};

View file

@ -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::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::proto::GraphErrors; use graph_craft::proto::GraphErrors;
use graphene_core::*; use graphene_core::*;
use renderer::Quad; use renderer::Quad;
use glam::{DAffine2, DVec2, IVec2};
use std::cmp::Ordering; use std::cmp::Ordering;
#[derive(Debug)] #[derive(Debug)]
@ -1141,11 +1139,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let mut node_wires = Vec::new(); let mut node_wires = Vec::new();
let mut stack_wires = Vec::new(); let mut stack_wires = Vec::new();
for wire in overlapping_wires { for wire in overlapping_wires {
if is_stack_wire(&wire) { if is_stack_wire(&wire) { stack_wires.push(wire) } else { node_wires.push(wire) }
stack_wires.push(wire)
} else {
node_wires.push(wire)
}
} }
// Auto convert node to layer when inserting on a single stack wire // Auto convert node to layer when inserting on a single stack wire
@ -2068,26 +2062,23 @@ impl NodeGraphMessageHandler {
.iter() .iter()
.flat_map(|(wire_end, node)| node.inputs.iter().filter(|input| input.is_exposed()).enumerate().map(move |(index, input)| (input, wire_end, index))) .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)| { .filter_map(|(input, &wire_end, wire_end_input_index)| {
if let NodeInput::Node { match *input {
node_id: wire_start, NodeInput::Node {
output_index: wire_start_output_index, node_id: wire_start,
// TODO: add ui for lambdas output_index: wire_start_output_index,
lambda: _, // TODO: add ui for lambdas
} = *input lambda: _,
{ } => Some(FrontendNodeWire {
Some(FrontendNodeWire {
wire_start: OutputConnector::node(wire_start, wire_start_output_index), wire_start: OutputConnector::node(wire_start, wire_start_output_index),
wire_end: InputConnector::node(wire_end, wire_end_input_index), wire_end: InputConnector::node(wire_end, wire_end_input_index),
dashed: false, dashed: false,
}) }),
} else if let NodeInput::Network { import_index, .. } = *input { NodeInput::Network { import_index, .. } => Some(FrontendNodeWire {
Some(FrontendNodeWire {
wire_start: OutputConnector::Import(import_index), wire_start: OutputConnector::Import(import_index),
wire_end: InputConnector::node(wire_end, wire_end_input_index), wire_end: InputConnector::node(wire_end, wire_end_input_index),
dashed: false, dashed: false,
}) }),
} else { _ => None,
None
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -2281,16 +2272,12 @@ impl NodeGraphMessageHandler {
let mut current_network = network_interface.nested_network(&current_network_path).unwrap(); let mut current_network = network_interface.nested_network(&current_network_path).unwrap();
let mut subgraph_names = vec!["Document".to_string()]; let mut subgraph_names = vec!["Document".to_string()];
for node_id in breadcrumb_network_path { for node_id in breadcrumb_network_path {
if let Some(node) = current_network.nodes.get(node_id) { let node = current_network.nodes.get(node_id)?;
if let Some(network) = node.implementation.get_network() { if let Some(network) = node.implementation.get_network() {
current_network = 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;
}; };
subgraph_names.push(network_interface.frontend_display_name(node_id, &current_network_path));
current_network_path.push(*node_id)
} }
Some(subgraph_names) Some(subgraph_names)
} }

View file

@ -1,16 +1,16 @@
#![allow(clippy::too_many_arguments)] #![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 super::utility_types::FrontendGraphDataType;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector; use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use dyn_any::DynAny; use dyn_any::DynAny;
use glam::{DAffine2, DVec2, IVec2, UVec2};
use graph_craft::Type;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod}; use graph_craft::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod};
use graph_craft::Type;
use graphene_core::raster::curve::Curve; use graphene_core::raster::curve::Curve;
use graphene_core::raster::image::ImageFrameTable; use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::{ use graphene_core::raster::{
@ -22,25 +22,20 @@ use graphene_core::vector::misc::CentroidType;
use graphene_core::vector::style::{GradientType, LineCap, LineJoin}; use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
use graphene_std::application_io::TextureFrameTable; use graphene_std::application_io::TextureFrameTable;
use graphene_std::transform::Footprint; use graphene_std::transform::Footprint;
use graphene_std::vector::VectorDataTable;
use graphene_std::vector::misc::BooleanOperation; use graphene_std::vector::misc::BooleanOperation;
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops}; use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
use graphene_std::vector::VectorDataTable;
use graphene_std::{GraphicGroupTable, RasterFrame}; use graphene_std::{GraphicGroupTable, RasterFrame};
use glam::{DAffine2, DVec2, IVec2, UVec2};
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> { pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
let widget = TextLabel::new(text).widget_holder(); let widget = TextLabel::new(text).widget_holder();
vec![LayoutGroup::Row { widgets: vec![widget] }] 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 { 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| { move |input_value: &T| match value(input_value) {
if let Some(value) = value(input_value) { Some(value) => NodeGraphMessage::SetInputValue { node_id, input_index, value }.into(),
NodeGraphMessage::SetInputValue { node_id, input_index, value }.into() _ => Message::NoOp,
} else {
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::<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::<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::<DomainWarpType>() => domain_warp_type(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![DropdownInput::new(vec![vec![ Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![
MenuListEntry::new("Relative") DropdownInput::new(vec![vec![
.label("Relative") MenuListEntry::new("Relative")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)), .label("Relative")
MenuListEntry::new("Absolute") .on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)),
.label("Absolute") MenuListEntry::new("Absolute")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)), .label("Absolute")
]]) .on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)),
.widget_holder()] ]])
.widget_holder(),
]
.into(), .into(),
Some(x) if x == TypeId::of::<LineCap>() => line_cap_widget(document_node, node_id, index, name, true), 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::<LineJoin>() => line_join_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<FillType>() => vec![DropdownInput::new(vec![vec![ Some(x) if x == TypeId::of::<FillType>() => vec![
MenuListEntry::new("Solid") DropdownInput::new(vec![vec![
.label("Solid") MenuListEntry::new("Solid")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)), .label("Solid")
MenuListEntry::new("Gradient") .on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)),
.label("Gradient") MenuListEntry::new("Gradient")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)), .label("Gradient")
]]) .on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)),
.widget_holder()] ]])
.widget_holder(),
]
.into(), .into(),
Some(x) if x == TypeId::of::<GradientType>() => vec![DropdownInput::new(vec![vec![ Some(x) if x == TypeId::of::<GradientType>() => vec![
MenuListEntry::new("Linear") DropdownInput::new(vec![vec![
.label("Linear") MenuListEntry::new("Linear")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)), .label("Linear")
MenuListEntry::new("Radial") .on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)),
.label("Radial") MenuListEntry::new("Radial")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)), .label("Radial")
]]) .on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
.widget_holder()] ]])
.widget_holder(),
]
.into(), .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::<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::<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::<LuminanceCalculation>() => luminance_calculation(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![DropdownInput::new( Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![
ImaginateSamplingMethod::list() DropdownInput::new(
.into_iter() ImaginateSamplingMethod::list()
.map(|method| { .into_iter()
vec![MenuListEntry::new(format!("{:?}", method)).label(method.to_string()).on_update(update_value( .map(|method| {
move |_| TaggedValue::ImaginateSamplingMethod(method), vec![MenuListEntry::new(format!("{:?}", method)).label(method.to_string()).on_update(update_value(
node_id, move |_| TaggedValue::ImaginateSamplingMethod(method),
index, node_id,
))] index,
}) ))]
.collect(), })
) .collect(),
.widget_holder()] )
.widget_holder(),
]
.into(), .into(),
Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![DropdownInput::new( Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![
ImaginateMaskStartingFill::list() DropdownInput::new(
.into_iter() ImaginateMaskStartingFill::list()
.map(|fill| { .into_iter()
vec![MenuListEntry::new(format!("{:?}", fill)).label(fill.to_string()).on_update(update_value( .map(|fill| {
move |_| TaggedValue::ImaginateMaskStartingFill(fill), vec![MenuListEntry::new(format!("{:?}", fill)).label(fill.to_string()).on_update(update_value(
node_id, move |_| TaggedValue::ImaginateMaskStartingFill(fill),
index, node_id,
))] index,
}) ))]
.collect(), })
) .collect(),
.widget_holder()] )
.widget_holder(),
]
.into(), .into(),
_ => { _ => {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, true); 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![]; 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(&[ widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(),
checkbox_input 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![]; 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 top_left = footprint.transform.transform_point2(DVec2::ZERO);
let bounds = footprint.scale(); let bounds = footprint.scale();
let oversample = footprint.resolution.as_dvec2() / bounds; 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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 calculation_modes = [RedGreenBlue::Red, RedGreenBlue::Green, RedGreenBlue::Blue];
let mut entries = Vec::with_capacity(calculation_modes.len()); let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes { 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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 calculation_modes = [RedGreenBlueAlpha::Red, RedGreenBlueAlpha::Green, RedGreenBlueAlpha::Blue, RedGreenBlueAlpha::Alpha];
let mut entries = Vec::with_capacity(calculation_modes.len()); let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes { 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = NoiseType::list()
.iter() .iter()
.map(|noise_type| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = FractalType::list()
.iter() .iter()
.map(|fractal_type| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = CellularDistanceFunction::list()
.iter() .iter()
.map(|cellular_distance_function| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = CellularReturnType::list()
.iter() .iter()
.map(|cellular_return_type| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = DomainWarpType::list()
.iter() .iter()
.map(|domain_warp_type| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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() let entries = BlendMode::list_svg_subset()
.iter() .iter()
.map(|category| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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 calculation_modes = LuminanceCalculation::list();
let mut entries = Vec::with_capacity(calculation_modes.len()); let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes { 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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 operations = BooleanOperation::list();
let icons = BooleanOperation::icons(); let icons = BooleanOperation::icons();
let mut entries = Vec::with_capacity(operations.len()); 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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)] let entries = [("Butt", LineCap::Butt), ("Round", LineCap::Round), ("Square", LineCap::Square)]
.into_iter() .into_iter()
.map(|(name, val)| { .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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)] let entries = [("Miter", LineJoin::Miter), ("Bevel", LineJoin::Bevel), ("Round", LineJoin::Round)]
.into_iter() .into_iter()
.map(|(name, val)| { .map(|(name, val)| {
@ -1101,7 +1106,7 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
.on_commit(commit_value) .on_commit(commit_value)
.widget_holder(), .widget_holder(),
), ),
TaggedValue::GradientStops(ref x) => widgets.push( TaggedValue::GradientStops(x) => widgets.push(
color_button color_button
.value(FillChoice::Gradient(x.clone())) .value(FillChoice::Gradient(x.clone()))
.on_update(update_value( .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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] }; 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![ let entries = vec![
RadioEntryData::new("area") RadioEntryData::new("area")
.label("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)?; 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. // This is safe since the node is a proto node and the implementation cannot be changed.
let randomize_index = 5; let randomize_index = 5;
Ok( Ok(match document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
if let Some(&TaggedValue::Bool(randomize_enabled)) = &document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) { Some(TaggedValue::Bool(randomize_enabled)) => *randomize_enabled,
randomize_enabled _ => false,
} else { })
false
},
)
} }
pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { 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 // Monochrome
let monochrome_index = 1; let monochrome_index = 1;
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true); 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() { let is_monochrome = match document_node.inputs[monochrome_index].as_value() {
monochrome_choice Some(TaggedValue::Bool(monochrome_choice)) => *monochrome_choice,
} else { _ => false,
false
}; };
// Output channel choice // 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()]); 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() { let is_output_channel = match &document_node.inputs[output_channel_index].as_value() {
choice Some(TaggedValue::RedGreenBlue(choice)) => choice,
} else { _ => {
warn!("Channel Mixer node properties panel could not be displayed."); warn!("Channel Mixer node properties panel could not be displayed.");
return vec![]; return vec![];
}
}; };
// Channel values // 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()]); 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() { let colors_choice_index = match &document_node.inputs[colors_index].as_value() {
choice Some(TaggedValue::SelectiveColorChoice(choice)) => choice,
} else { _ => {
warn!("Selective Color node properties panel could not be displayed."); warn!("Selective Color node properties panel could not be displayed.");
return vec![]; return vec![];
}
}; };
// CMYK // 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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![]; 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![ let entries = vec![
RadioEntryData::new("relative") RadioEntryData::new("relative")
.label("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."); log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![]; 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 // Values
let Some(input) = document_node.inputs.get(corner_radius_index) else { 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."); 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 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[fill_index].as_value(),
&document_node.inputs[backup_color_index].as_value(), &document_node.inputs[backup_color_index].as_value(),
&document_node.inputs[backup_gradient_index].as_value(), &document_node.inputs[backup_gradient_index].as_value(),

View file

@ -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 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)] #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum FrontendGraphDataType { pub enum FrontendGraphDataType {

View file

@ -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::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::misc::{GridSnapping, GridType}; use crate::messages::portfolio::document::utility_types::misc::{GridSnapping, GridType};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::DVec2;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use glam::DVec2;
use graphene_std::vector::style::FillChoice; use graphene_std::vector::style::FillChoice;
fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, spacing: DVec2) { 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> { pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
let mut widgets = Vec::new(); 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(); let grid = grid.clone();
move |input: &I| { move |input: &I| {
let mut grid = grid.clone(); 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>| { 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(val) = val.value {
if let Some(update) = update(grid) { if let Some(update) = update(grid) {
*update = val; *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>| { 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 FillChoice::Solid(color) = color.value {
if let Some(update_color) = update(grid) { if let Some(update_color) = update(grid) {
*update_color = color; *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>| { 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) { if let Some(update) = update(grid) {
*update = checkbox.checked; *update = checkbox.checked;
} }

View file

@ -1,4 +1,4 @@
use super::utility_types::{empty_provider, OverlayProvider}; use super::utility_types::{OverlayProvider, empty_provider};
use crate::messages::prelude::*; use crate::messages::prelude::*;
#[impl_message(Message, DocumentMessage, Overlays)] #[impl_message(Message, DocumentMessage, Overlays)]

View file

@ -2,12 +2,10 @@ use super::utility_types::{DrawHandles, OverlayContext};
use crate::consts::HIDE_HANDLE_DISTANCE; use crate::consts::HIDE_HANDLE_DISTANCE;
use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerState, ShapeState}; use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerState, ShapeState};
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler}; 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 bezier_rs::{Bezier, BezierHandles};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{PointId, SegmentId};
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> { pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> {

View file

@ -4,14 +4,12 @@ use crate::consts::{
COMPASS_ROSE_RING_INNER_DIAMETER, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
}; };
use crate::messages::prelude::Message; use crate::messages::prelude::Message;
use bezier_rs::{Bezier, Subpath}; use bezier_rs::{Bezier, Subpath};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use core::borrow::Borrow; use core::borrow::Borrow;
use core::f64::consts::{FRAC_PI_2, TAU}; use core::f64::consts::{FRAC_PI_2, TAU};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use std::collections::HashMap; use std::collections::HashMap;
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;

View file

@ -1,7 +1,6 @@
use graph_craft::document::NodeId;
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use graph_craft::document::NodeId;
pub struct PropertiesPanelMessageHandlerData<'a> { pub struct PropertiesPanelMessageHandlerData<'a> {
pub network_interface: &'a mut NodeNetworkInterface, pub network_interface: &'a mut NodeNetworkInterface,

View file

@ -1,5 +1,4 @@
use super::network_interface::NodeTemplate; use super::network_interface::NodeTemplate;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
#[repr(u8)] #[repr(u8)]

View file

@ -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::transform_utils;
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext; use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
use glam::{DAffine2, DVec2};
use super::network_interface::NodeNetworkInterface;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::renderer::ClickTarget; use graphene_core::renderer::ClickTarget;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::transform::Footprint; use graphene_core::transform::Footprint;
use graphene_std::vector::{PointId, VectorData}; use graphene_std::vector::{PointId, VectorData};
use glam::{DAffine2, DVec2};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64; use std::num::NonZeroU64;

View file

@ -1,5 +1,4 @@
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use thiserror::Error; use thiserror::Error;
/// The error type used by the Graphite editor. /// The error type used by the Graphite editor.

View file

@ -1,8 +1,6 @@
use crate::consts::COLOR_OVERLAY_GRAY; use crate::consts::COLOR_OVERLAY_GRAY;
use graphene_core::raster::Color;
use glam::DVec2; use glam::DVec2;
use graphene_core::raster::Color;
use std::fmt; use std::fmt;
#[repr(transparent)] #[repr(transparent)]

View file

@ -3,21 +3,21 @@ use super::misc::PTZ;
use super::nodes::SelectedNodes; 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::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::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::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::tool_messages::tool_prelude::NumberInputMode; use crate::messages::tool::tool_messages::tool_prelude::NumberInputMode;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork}; use glam::{DAffine2, DVec2, IVec2};
use graph_craft::{concrete, Type}; 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::renderer::{ClickTarget, Quad};
use graphene_std::transform::Footprint; use graphene_std::transform::Footprint;
use graphene_std::vector::{PointId, VectorData, VectorModificationType}; use graphene_std::vector::{PointId, VectorData, VectorModificationType};
use interpreted_executor::{dynamic_executor::ResolvedDocumentNodeTypes, node_registry::NODE_REGISTRY}; use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypes;
use interpreted_executor::node_registry::NODE_REGISTRY;
use glam::{DAffine2, DVec2, IVec2}; use serde_json::{Value, json};
use serde_json::{json, Value};
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::{DefaultHasher, Hash, Hasher}; 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 // 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 node_io.inputs[iterator_index].clone().nested_type() == input_type || node_io.inputs[iterator_index] == input_type
}); });
if valid_implementation { if valid_implementation { node_io.inputs.get(*input_index).cloned() } else { None }
node_io.inputs.get(*input_index).cloned()
} else {
None
}
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
@ -1339,7 +1335,7 @@ impl NodeNetworkInterface {
/// Layers excluding ones that are children of other layers in the list. /// Layers excluding ones that are children of other layers in the list.
// TODO: Cache this // 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) { let mut sorted_layers = if let Some(selected_nodes) = self.selected_nodes_in_nested_network(network_path) {
selected_nodes selected_nodes
.selected_layers(self.document_metadata()) .selected_layers(self.document_metadata())
@ -2528,10 +2524,9 @@ impl NodeNetworkInterface {
} }
} }
let number_of_outputs = if let DocumentNodeImplementation::Network(network) = &document_node.implementation { let number_of_outputs = match &document_node.implementation {
network.exports.len() DocumentNodeImplementation::Network(network) => network.exports.len(),
} else { _ => 1,
1
}; };
// If the node does not have a primary output, shift all ports down a row // 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 }; 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| { let Some(downstream_node_id) = downstream_node_connectors.iter().find_map(|input_connector| {
if let InputConnector::Node { node_id, input_index } = 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 }; let downstream_input_index = if self.is_layer(node_id, network_path) { 1 } else { 0 };
if *input_index == downstream_input_index { if *input_index == downstream_input_index { Some(node_id) } else { None }
Some(node_id)
} else {
None
}
} else { } else {
None None
} }
@ -2933,11 +2924,7 @@ impl NodeNetworkInterface {
log::error!("Could not get node_metadata for node {node_id}"); log::error!("Could not get node_metadata for node {node_id}");
return None; return None;
}; };
if !node_metadata.persistent_metadata.is_layer() { if !node_metadata.persistent_metadata.is_layer() { Some(*node_id) } else { None }
Some(*node_id)
} else {
None
}
}) })
.or_else(|| clicked_nodes.into_iter().next()) .or_else(|| clicked_nodes.into_iter().next())
} }
@ -3168,13 +3155,10 @@ impl NodeNetworkInterface {
// Only load structure if there is a root node // Only load structure if there is a root node
let Some(root_node) = self.root_node(&[]) else { return }; 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| { let Some(first_root_layer) = self
if self.is_layer(&node_id, &[]) { .upstream_flow_back_from_nodes(vec![root_node.node_id], &[], FlowType::PrimaryFlow)
Some(LayerNodeIdentifier::new(node_id, self, &[])) .find_map(|node_id| if self.is_layer(&node_id, &[]) { Some(LayerNodeIdentifier::new(node_id, self, &[])) } else { None })
} else { else {
None
}
}) else {
return; return;
}; };
// Should refer to output node // 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 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"); 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 { let previous_metadata = match &previous_input {
self.position(node_id, network_path).map(|position| (*node_id, position)) NodeInput::Node { node_id, .. } => self.position(node_id, network_path).map(|position| (*node_id, position)),
} else { _ => None,
None
}; };
let Some(network) = self.network_mut(network_path) else { 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}"); log::error!("Could not get node_metadata for node {node_id}");
return; return;
}; };
if let NodeTypePersistentMetadata::Layer(layer_metadata) = &mut node_metadata.persistent_metadata.node_type_metadata { match &mut node_metadata.persistent_metadata.node_type_metadata {
if layer_metadata.position == LayerPosition::Stack(y_offset) { NodeTypePersistentMetadata::Layer(layer_metadata) => {
return; 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| { stack_dependents_with_position.sort_unstable_by(|a, b| {
a.1.signum().cmp(&b.1.signum()).then_with(|| { 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 the node has a positive offset, then it is shifted up, so shift the top nodes first
if a.1.signum() == 1 { if a.1.signum() == 1 { a.2.cmp(&b.2) } else { b.2.cmp(&a.2) }
a.2.cmp(&b.2)
} else {
b.2.cmp(&a.2)
}
}) })
}); });
// Try shift every node that is offset from its original position // 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 { while offset != 0 {
if self.check_collision_with_stack_dependents(node_id, -offset.signum(), network_path).is_empty() { 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); self.vertical_shift_with_push(node_id, -offset.signum(), &mut HashSet::new(), network_path);
@ -5302,6 +5284,7 @@ impl NodeNetworkInterface {
self.transaction_modified(); self.transaction_modified();
} else if let LayerPosition::Stack(y_offset) = &mut layer_metadata.position { } else if let LayerPosition::Stack(y_offset) = &mut layer_metadata.position {
let shifted_y_offset = *y_offset as i32 + shift.y; let shifted_y_offset = *y_offset as i32 + shift.y;
// A layer can only be shifted to a positive y_offset // A layer can only be shifted to a positive y_offset
if shifted_y_offset < 0 { if shifted_y_offset < 0 {
log::error!( log::error!(
@ -5312,6 +5295,7 @@ impl NodeNetworkInterface {
if shift.x != 0 { if shift.x != 0 {
log::error!("Stack layer {node_id} cannot be shifted horizontally."); log::error!("Stack layer {node_id} cannot be shifted horizontally.");
} }
let new_y_offset = shifted_y_offset.max(0) as u32; let new_y_offset = shifted_y_offset.max(0) as u32;
if *y_offset == new_y_offset { if *y_offset == new_y_offset {
return; return;

View file

@ -1,8 +1,6 @@
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use super::network_interface::NodeNetworkInterface; use super::network_interface::NodeNetworkInterface;
use graph_craft::document::{NodeId, NodeNetwork}; use graph_craft::document::{NodeId, NodeNetwork};
use serde::ser::SerializeStruct; use serde::ser::SerializeStruct;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)]

View file

@ -7,13 +7,11 @@ use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::utility_types::ToolType; use crate::messages::tool::utility_types::ToolType;
use glam::{DAffine2, DMat2, DVec2};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::ManipulatorPointId; use graphene_core::vector::ManipulatorPointId;
use graphene_core::vector::VectorModificationType; use graphene_core::vector::VectorModificationType;
use graphene_std::vector::{HandleId, PointId}; use graphene_std::vector::{HandleId, PointId};
use glam::{DAffine2, DMat2, DVec2};
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::f64::consts::PI; use std::f64::consts::PI;
@ -136,11 +134,7 @@ impl Axis {
return (target, false); return (target, false);
} }
if local { if local { (Axis::Both, false) } else { (self, true) }
(Axis::Both, false)
} else {
(self, true)
}
} }
} }
@ -167,11 +161,7 @@ impl Translation {
} }
}; };
let displacement = transform.inverse().transform_vector2(displacement); let displacement = transform.inverse().transform_vector2(displacement);
if increment_mode { if increment_mode { displacement.round() } else { displacement }
displacement.round()
} else {
displacement
}
} }
#[must_use] #[must_use]
@ -259,11 +249,7 @@ impl Default for Scale {
impl Scale { impl Scale {
pub fn to_f64(self, increment: bool) -> f64 { pub fn to_f64(self, increment: bool) -> f64 {
let factor = if let Some(value) = self.typed_factor { value } else { self.dragged_factor }; let factor = if let Some(value) = self.typed_factor { value } else { self.dragged_factor };
if increment { if increment { (factor / SCALE_INCREMENT).round() * SCALE_INCREMENT } else { factor }
(factor / SCALE_INCREMENT).round() * SCALE_INCREMENT
} else {
factor
}
} }
pub fn to_dvec(self, increment_mode: bool) -> DVec2 { pub fn to_dvec(self, increment_mode: bool) -> DVec2 {

View file

@ -1,11 +1,10 @@
use graphene_std::vector::misc::BooleanOperation;
use crate::messages::debug::utility_types::MessageLoggingVerbosity; use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_std::vector::misc::BooleanOperation;
pub struct MenuBarMessageData { pub struct MenuBarMessageData {
pub has_active_document: bool, pub has_active_document: bool,

View file

@ -3,10 +3,9 @@ use super::utility_types::PanelType;
use crate::messages::frontend::utility_types::{ExportBounds, FileType}; use crate::messages::frontend::utility_types::{ExportBounds, FileType};
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_core::Color;
use graphene_core::raster::Image; use graphene_core::raster::Image;
use graphene_core::text::Font; use graphene_core::text::Font;
use graphene_core::Color;
#[impl_message(Message, Portfolio)] #[impl_message(Message, Portfolio)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]

View file

@ -7,15 +7,14 @@ use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::dialog::simple_dialogs; use crate::messages::dialog::simple_dialogs;
use crate::messages::frontend::utility_types::FrontendDocumentDetails; use crate::messages::frontend::utility_types::FrontendDocumentDetails;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::DocumentMessageData;
use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type;
use crate::messages::portfolio::document::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT}; use crate::messages::portfolio::document::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes; use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes;
use crate::messages::portfolio::document::DocumentMessageData;
use crate::messages::preferences::SelectionMode; use crate::messages::preferences::SelectionMode;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, ToolType}; use crate::messages::tool::utility_types::{HintData, HintGroup, ToolType};
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor}; use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::IVec2; use glam::IVec2;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
@ -24,7 +23,6 @@ use graphene_core::text::{Font, TypesettingConfig};
use graphene_std::vector::style::{Fill, FillType, Gradient}; use graphene_std::vector::style::{Fill, FillType, Gradient};
use graphene_std::vector::{VectorData, VectorDataTable}; use graphene_std::vector::{VectorData, VectorDataTable};
use interpreted_executor::dynamic_executor::IntrospectError; use interpreted_executor::dynamic_executor::IntrospectError;
use std::sync::Arc; use std::sync::Arc;
use std::vec; use std::vec;

View file

@ -2,7 +2,6 @@ use crate::messages::input_mapper::key_mapping::MappingVariant;
use crate::messages::portfolio::document::node_graph::utility_types::GraphWireStyle; use crate::messages::portfolio::document::node_graph::utility_types::GraphWireStyle;
use crate::messages::preferences::SelectionMode; use crate::messages::preferences::SelectionMode;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graph_craft::wasm_application_io::EditorPreferences; use graph_craft::wasm_application_io::EditorPreferences;
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, specta::Type)]

View file

@ -51,9 +51,7 @@ pub use crate::messages::tool::tool_messages::text_tool::{TextToolMessage, TextT
// Helper // Helper
pub use crate::messages::globals::global_variables::*; pub use crate::messages::globals::global_variables::*;
pub use crate::messages::portfolio::document::utility_types::misc::DocumentId; pub use crate::messages::portfolio::document::utility_types::misc::DocumentId;
pub use graphite_proc_macros::*; pub use graphite_proc_macros::*;
pub use std::collections::{HashMap, HashSet, VecDeque}; pub use std::collections::{HashMap, HashSet, VecDeque};
pub trait Responses { pub trait Responses {

View file

@ -1,7 +1,6 @@
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_core::Color; use graphene_core::Color;
use graphene_std::vector::style::FillChoice; use graphene_std::vector::style::FillChoice;

View file

@ -1,7 +1,6 @@
use crate::consts::{COMPASS_ROSE_ARROW_CLICK_TARGET_ANGLE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER}; use crate::consts::{COMPASS_ROSE_ARROW_CLICK_TARGET_ANGLE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::DocumentMessageHandler; use crate::messages::prelude::DocumentMessageHandler;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use std::f64::consts::FRAC_PI_2; use std::f64::consts::FRAC_PI_2;

View file

@ -3,18 +3,17 @@ 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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, NodeTemplate}; use crate::messages::portfolio::document::utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, NodeTemplate};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::DVec2;
use graph_craft::concrete; use graph_craft::concrete;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::value::TaggedValue;
use graphene_core::raster::image::ImageFrameTable; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig}; use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::style::Gradient; use graphene_core::vector::style::Gradient;
use graphene_core::Color;
use graphene_std::vector::{ManipulatorPointId, PointId, SegmentId, VectorModificationType}; use graphene_std::vector::{ManipulatorPointId, PointId, SegmentId, VectorModificationType};
use glam::DVec2;
use std::collections::VecDeque; use std::collections::VecDeque;
/// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists. /// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists.
@ -385,7 +384,7 @@ impl<'a> NodeGraphLayer<'a> {
} }
/// Return an iterator up the horizontal flow of the layer /// Return an iterator up the horizontal flow of the layer
pub fn horizontal_layer_flow(&self) -> impl Iterator<Item = NodeId> + 'a { pub fn horizontal_layer_flow(&self) -> impl Iterator<Item = NodeId> + use<'a> {
self.network_interface.upstream_flow_back_from_nodes(vec![self.layer_node], &[], FlowType::HorizontalFlow) self.network_interface.upstream_flow_back_from_nodes(vec![self.layer_node], &[], FlowType::HorizontalFlow)
} }

View file

@ -6,7 +6,6 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use std::collections::VecDeque; use std::collections::VecDeque;

View file

@ -1,7 +1,8 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration}; use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use crate::messages::{input_mapper::utility_types::input_keyboard::Key, portfolio::document::graph_operation::utility_types::TransformIn};
use glam::{DAffine2, DVec2, Vec2Swizzles}; use glam::{DAffine2, DVec2, Vec2Swizzles};
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]

View file

@ -6,12 +6,10 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration; use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration;
use crate::messages::tool::tool_messages::path_tool::PointSelectState; use crate::messages::tool::tool_messages::path_tool::PointSelectState;
use bezier_rs::{Bezier, BezierHandles, Subpath, TValue}; use bezier_rs::{Bezier, BezierHandles, Subpath, TValue};
use glam::{DAffine2, DVec2};
use graphene_core::transform::Transform; use graphene_core::transform::Transform;
use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType}; use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
use glam::{DAffine2, DVec2};
use graphene_std::vector::{HandleId, SegmentId}; use graphene_std::vector::{HandleId, SegmentId};
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -586,7 +584,7 @@ impl ShapeState {
.flat_map(|(data, selection_state)| { .flat_map(|(data, selection_state)| {
selection_state.selected_points.iter().filter_map(move |&point| { selection_state.selected_points.iter().filter_map(move |&point| {
let Some(data) = &data else { return None }; let Some(data) = &data else { return None };
let Some(_) = point.get_handle_pair(&data) else { return None }; // ignores the endpoints. let _ = point.get_handle_pair(data)?; // ignores the endpoints.
Some(data.colinear(point)) Some(data.colinear(point))
}) })
}); });
@ -1289,10 +1287,13 @@ impl ShapeState {
for point in self.selected_points().filter(|point| point.as_handle().is_some()) { for point in self.selected_points().filter(|point| point.as_handle().is_some()) {
let anchor = point.get_anchor(&vector_data); let anchor = point.get_anchor(&vector_data);
if let Some(handles) = point.get_handle_pair(&vector_data) { match point.get_handle_pair(&vector_data) {
points_to_select.push((layer, anchor, Some(handles[1].to_manipulator_point()))); Some(handles) => {
} else { points_to_select.push((layer, anchor, Some(handles[1].to_manipulator_point())));
points_to_select.push((layer, anchor, None)); }
_ => {
points_to_select.push((layer, anchor, None));
}
} }
} }
} }

View file

@ -3,21 +3,23 @@ mod distribution_snapper;
mod grid_snapper; mod grid_snapper;
mod layer_snapper; mod layer_snapper;
mod snap_results; mod snap_results;
pub use {alignment_snapper::*, distribution_snapper::*, grid_snapper::*, layer_snapper::*, snap_results::*};
use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_LABEL_BACKGROUND, COLOR_OVERLAY_WHITE}; use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_LABEL_BACKGROUND, COLOR_OVERLAY_WHITE};
use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, Pivot}; use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, Pivot};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, PathSnapTarget, SnapTarget}; use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, PathSnapTarget, SnapTarget};
use crate::messages::prelude::*; use crate::messages::prelude::*;
pub use alignment_snapper::*;
use bezier_rs::TValue; use bezier_rs::TValue;
pub use distribution_snapper::*;
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::PointId; use graphene_core::vector::PointId;
use graphene_std::renderer::Rect; use graphene_std::renderer::Rect;
use glam::{DAffine2, DVec2};
use graphene_std::vector::NoHashBuilder; use graphene_std::vector::NoHashBuilder;
pub use grid_snapper::*;
pub use layer_snapper::*;
pub use snap_results::*;
use std::cmp::Ordering; use std::cmp::Ordering;
/// Configuration for the relevant snap type /// Configuration for the relevant snap type

View file

@ -1,9 +1,7 @@
use super::*; use super::*;
use crate::messages::portfolio::document::utility_types::misc::*; use crate::messages::portfolio::document::utility_types::misc::*;
use graphene_core::renderer::Quad;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct AlignmentSnapper { pub struct AlignmentSnapper {

View file

@ -2,10 +2,8 @@ use super::*;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::*; use crate::messages::portfolio::document::utility_types::misc::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_core::renderer::Quad;
use glam::DVec2; use glam::DVec2;
use graphene_core::renderer::Quad;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct DistributionSnapper { pub struct DistributionSnapper {

View file

@ -1,7 +1,5 @@
use super::*; use super::*;
use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, GridSnapping, GridType, SnapTarget}; use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, GridSnapping, GridType, SnapTarget};
use glam::DVec2; use glam::DVec2;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;

View file

@ -3,13 +3,11 @@ use crate::consts::HIDE_HANDLE_DISTANCE;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::*; use crate::messages::portfolio::document::utility_types::misc::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::{Bezier, Identifier, Subpath, TValue}; use bezier_rs::{Bezier, Identifier, Subpath, TValue};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::PointId; use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2};
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct LayerSnapper { pub struct LayerSnapper {
points_to_snap: Vec<SnapCandidatePoint>, points_to_snap: Vec<SnapCandidatePoint>,

View file

@ -1,5 +1,4 @@
use std::collections::VecDeque; use super::DistributionMatch;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{DistributionSnapTarget, SnapSource, SnapTarget}; use crate::messages::portfolio::document::utility_types::misc::{DistributionSnapTarget, SnapSource, SnapTarget};
use crate::messages::tool::common_functionality::snapping::SnapCandidatePoint; use crate::messages::tool::common_functionality::snapping::SnapCandidatePoint;
@ -8,8 +7,7 @@ use glam::DVec2;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::PointId; use graphene_core::vector::PointId;
use graphene_std::renderer::Rect; use graphene_std::renderer::Rect;
use std::collections::VecDeque;
use super::DistributionMatch;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct SnapResults { pub struct SnapResults {

View file

@ -1,3 +1,4 @@
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
use crate::consts::{ use crate::consts::{
BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, COLOR_OVERLAY_WHITE, MAXIMUM_ALT_SCALE_FACTOR, MIN_LENGTH_FOR_CORNERS_VISIBILITY, MIN_LENGTH_FOR_EDGE_RESIZE_PRIORITY_OVER_CORNERS, BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, COLOR_OVERLAY_WHITE, MAXIMUM_ALT_SCALE_FACTOR, MIN_LENGTH_FOR_CORNERS_VISIBILITY, MIN_LENGTH_FOR_EDGE_RESIZE_PRIORITY_OVER_CORNERS,
MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR, MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY, RESIZE_HANDLE_SIZE, SELECTION_DRAG_ANGLE, SKEW_TRIANGLE_OFFSET, MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR, MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY, RESIZE_HANDLE_SIZE, SELECTION_DRAG_ANGLE, SKEW_TRIANGLE_OFFSET,
@ -8,14 +9,10 @@ use crate::messages::portfolio::document::overlays::utility_types::OverlayContex
use crate::messages::portfolio::document::utility_types::transformation::OriginalTransforms; use crate::messages::portfolio::document::utility_types::transformation::OriginalTransforms;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration; use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration;
use glam::{DAffine2, DMat2, DVec2};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_std::renderer::Rect; use graphene_std::renderer::Rect;
use glam::{DAffine2, DMat2, DVec2};
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
/// (top, bottom, left, right) /// (top, bottom, left, right)
pub type EdgeBool = (bool, bool, bool, bool); pub type EdgeBool = (bool, bool, bool, bool);

View file

@ -1,12 +1,10 @@
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils::get_text; use crate::messages::tool::common_functionality::graph_modification_utils::get_text;
use graphene_core::renderer::Quad;
use graphene_core::text::{load_face, FontCache};
use graphene_std::vector::PointId;
use glam::DVec2; use glam::DVec2;
use graphene_core::renderer::Quad;
use graphene_core::text::{FontCache, load_face};
use graphene_std::vector::PointId;
/// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable. /// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable.
pub fn should_extend( pub fn should_extend(

View file

@ -1,7 +1,6 @@
use super::utility_types::ToolType; use super::utility_types::ToolType;
use crate::messages::preferences::SelectionMode; use crate::messages::preferences::SelectionMode;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
#[impl_message(Message, Tool)] #[impl_message(Message, Tool)]

View file

@ -1,5 +1,5 @@
use super::common_functionality::shape_editor::ShapeState; use super::common_functionality::shape_editor::ShapeState;
use super::utility_types::{tool_message_to_tool_type, ToolActionHandlerData, ToolFsmState}; use super::utility_types::{ToolActionHandlerData, ToolFsmState, tool_message_to_tool_type};
use crate::application::generate_uuid; use crate::application::generate_uuid;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::overlays::utility_types::OverlayProvider; use crate::messages::portfolio::document::overlays::utility_types::OverlayProvider;
@ -7,7 +7,6 @@ use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::utility_types::ToolType; use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
const ARTBOARD_OVERLAY_PROVIDER: OverlayProvider = |context| DocumentMessage::DrawArtboardOverlays(context).into(); const ARTBOARD_OVERLAY_PROVIDER: OverlayProvider = |context| DocumentMessage::DrawArtboardOverlays(context).into();

View file

@ -9,7 +9,6 @@ use crate::messages::tool::common_functionality::snapping::SnapCandidatePoint;
use crate::messages::tool::common_functionality::snapping::SnapData; use crate::messages::tool::common_functionality::snapping::SnapData;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::common_functionality::transformation_cage::*; use crate::messages::tool::common_functionality::transformation_cage::*;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
@ -277,7 +276,7 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::ResizingBounds ArtboardToolFsmState::ResizingBounds
} }
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => { (ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
let axis_align = input.keyboard.get(constrain_axis_or_aspect as usize); let axis_align = input.keyboard.get(constrain_axis_or_aspect as usize);
let ignore = tool_data.selected_artboard.map_or(Vec::new(), |layer| vec![layer]); let ignore = tool_data.selected_artboard.map_or(Vec::new(), |layer| vec![layer]);

View file

@ -5,12 +5,11 @@ 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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::FlowType; use crate::messages::portfolio::document::utility_types::network_interface::FlowType;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graph_craft::document::value::TaggedValue;
use graphene_core::Color;
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle}; use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle};
use graphene_core::Color;
const BRUSH_MAX_SIZE: f64 = 5000.; const BRUSH_MAX_SIZE: f64 = 5000.;

View file

@ -9,8 +9,8 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData; use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color; use graphene_core::Color;
#[derive(Default)] #[derive(Default)]

View file

@ -7,13 +7,11 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::utility_functions::should_extend; use crate::messages::tool::common_functionality::utility_functions::should_extend;
use graph_craft::document::NodeId;
use graphene_core::vector::VectorModificationType;
use graphene_core::Color;
use graphene_std::vector::{PointId, SegmentId};
use glam::DVec2; use glam::DVec2;
use graph_craft::document::NodeId;
use graphene_core::Color;
use graphene_core::vector::VectorModificationType;
use graphene_std::vector::{PointId, SegmentId};
#[derive(Default)] #[derive(Default)]
pub struct FreehandTool { pub struct FreehandTool {

View file

@ -5,7 +5,6 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use crate::messages::tool::common_functionality::graph_modification_utils::get_gradient; use crate::messages::tool::common_functionality::graph_modification_utils::get_gradient;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use graphene_core::vector::style::{Fill, Gradient, GradientType}; use graphene_core::vector::style::{Fill, Gradient, GradientType};
#[derive(Default)] #[derive(Default)]

View file

@ -2,13 +2,14 @@ use super::tool_prelude::*;
use crate::consts::{BOUNDS_SELECT_THRESHOLD, DEFAULT_STROKE_WIDTH, LINE_ROTATE_SNAP_ANGLE}; use crate::consts::{BOUNDS_SELECT_THRESHOLD, DEFAULT_STROKE_WIDTH, LINE_ROTATE_SNAP_ANGLE};
use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::{document_metadata::LayerNodeIdentifier, network_interface::InputConnector}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer};
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration}; use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color; use graphene_core::Color;
#[derive(Default)] #[derive(Default)]

View file

@ -23,6 +23,5 @@ pub mod tool_prelude {
pub use crate::messages::prelude::*; pub use crate::messages::prelude::*;
pub use crate::messages::tool::utility_types::{EventToMessageMap, Fsm, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType}; pub use crate::messages::tool::utility_types::{EventToMessageMap, Fsm, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
pub use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; pub use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
pub use glam::{DAffine2, DVec2}; pub use glam::{DAffine2, DVec2};
} }

View file

@ -13,11 +13,9 @@ use crate::messages::tool::common_functionality::shape_editor::{
ClosestSegment, ManipulatorAngle, OpposingHandleLengths, SelectedPointsInfo, SelectionChange, SelectionShape, SelectionShapeType, ShapeState, ClosestSegment, ManipulatorAngle, OpposingHandleLengths, SelectedPointsInfo, SelectionChange, SelectionShape, SelectionShapeType, ShapeState,
}; };
use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager}; use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::{ManipulatorPointId, PointId}; use graphene_core::vector::{ManipulatorPointId, PointId};
use graphene_std::vector::{NoHashBuilder, SegmentId}; use graphene_std::vector::{NoHashBuilder, SegmentId};
use std::vec; use std::vec;
#[derive(Default)] #[derive(Default)]

View file

@ -9,11 +9,10 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils::{self, merge_layers}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, merge_layers};
use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration}; use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend}; use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend};
use bezier_rs::{Bezier, BezierHandles}; use bezier_rs::{Bezier, BezierHandles};
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::vector::{PointId, VectorModificationType};
use graphene_core::Color; use graphene_core::Color;
use graphene_core::vector::{PointId, VectorModificationType};
use graphene_std::vector::{HandleId, ManipulatorPointId, NoHashBuilder, SegmentId, VectorData}; use graphene_std::vector::{HandleId, ManipulatorPointId, NoHashBuilder, SegmentId, VectorData};
#[derive(Default)] #[derive(Default)]
@ -461,6 +460,7 @@ impl PenToolData {
Some(if close_subpath { PenToolFsmState::Ready } else { PenToolFsmState::PlacingAnchor }) Some(if close_subpath { PenToolFsmState::Ready } else { PenToolFsmState::PlacingAnchor })
} }
#[allow(clippy::too_many_arguments)]
/// Calculates snap position delta while moving anchor and its handles. /// Calculates snap position delta while moving anchor and its handles.
fn space_anchor_handle_snap( fn space_anchor_handle_snap(
&mut self, &mut self,
@ -493,7 +493,7 @@ impl PenToolData {
// Otherwise use either primary or end handle based on is_start flag // Otherwise use either primary or end handle based on is_start flag
if is_start { if is_start {
let primary_handle_id = ManipulatorPointId::PrimaryHandle(self.end_point_segment.unwrap()); let primary_handle_id = ManipulatorPointId::PrimaryHandle(self.end_point_segment.unwrap());
match primary_handle_id.get_position(&vector_data) { match primary_handle_id.get_position(vector_data) {
Some(primary_handle) => { Some(primary_handle) => {
let handle_offset = transform.transform_point2(primary_handle - self.next_handle_start); let handle_offset = transform.transform_point2(primary_handle - self.next_handle_start);
let handle_snap = SnapCandidatePoint::handle(document_pos + handle_offset); let handle_snap = SnapCandidatePoint::handle(document_pos + handle_offset);
@ -502,7 +502,7 @@ impl PenToolData {
None => None, None => None,
} }
} else { } else {
let end_handle = self.end_point_segment.map(|handle| ManipulatorPointId::EndHandle(handle).get_position(&vector_data)).flatten(); let end_handle = self.end_point_segment.and_then(|handle| ManipulatorPointId::EndHandle(handle).get_position(vector_data));
match end_handle { match end_handle {
Some(end_handle) => { Some(end_handle) => {
let handle_offset = transform.transform_point2(end_handle - self.next_handle_start); let handle_offset = transform.transform_point2(end_handle - self.next_handle_start);
@ -690,10 +690,10 @@ impl PenToolData {
return Some((handle - self.next_point).length()); return Some((handle - self.next_point).length());
} }
return self.handle_end.map(|handle| (handle - self.next_point).length()).or_else(|| { self.handle_end.map(|handle| (handle - self.next_point).length()).or_else(|| {
self.end_point_segment self.end_point_segment
.and_then(|segment| Some((ManipulatorPointId::EndHandle(segment).get_position(vector_data)? - self.next_point).length())) .and_then(|segment| Some((ManipulatorPointId::EndHandle(segment).get_position(vector_data)? - self.next_point).length()))
}); })
} }
fn adjust_equidistant_handle(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData, is_start: bool) { fn adjust_equidistant_handle(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData, is_start: bool) {
@ -755,12 +755,10 @@ impl PenToolData {
if let Some(handle) = self.handle_end.as_mut() { if let Some(handle) = self.handle_end.as_mut() {
*handle = new_position; *handle = new_position;
return;
} else { } else {
let Some(segment) = self.end_point_segment else { return }; let Some(segment) = self.end_point_segment else { return };
let modification_type = VectorModificationType::SetEndHandle { segment, relative_position }; let modification_type = VectorModificationType::SetEndHandle { segment, relative_position };
responses.add(GraphOperationMessage::Vector { layer, modification_type }); responses.add(GraphOperationMessage::Vector { layer, modification_type });
return;
} }
} }
@ -1455,7 +1453,7 @@ impl Fsm for PenToolFsmState {
} }
let state = tool_data let state = tool_data
.drag_handle(snap_data, transform, input.mouse.position, responses, layer, &input) .drag_handle(snap_data, transform, input.mouse.position, responses, layer, input)
.unwrap_or(PenToolFsmState::Ready); .unwrap_or(PenToolFsmState::Ready);
// Auto-panning // Auto-panning

View file

@ -10,8 +10,8 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer};
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData; use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color; use graphene_core::Color;
#[derive(Default)] #[derive(Default)]

View file

@ -1,14 +1,16 @@
use super::tool_prelude::*; use super::tool_prelude::*;
use crate::consts::DEFAULT_STROKE_WIDTH; use crate::consts::DEFAULT_STROKE_WIDTH;
use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn;
use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type;
use crate::messages::portfolio::document::{graph_operation::utility_types::TransformIn, overlays::utility_types::OverlayContext, utility_types::network_interface::InputConnector}; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData; use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color; use graphene_core::Color;
#[derive(Default)] #[derive(Default)]

View file

@ -14,22 +14,21 @@ use crate::messages::portfolio::document::utility_types::network_interface::{Flo
use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes; use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes;
use crate::messages::portfolio::document::utility_types::transformation::Selected; use crate::messages::portfolio::document::utility_types::transformation::Selected;
use crate::messages::preferences::SelectionMode; use crate::messages::preferences::SelectionMode;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use crate::messages::tool::common_functionality::compass_rose::{Axis, CompassRose}; use crate::messages::tool::common_functionality::compass_rose::{Axis, CompassRose};
use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name; use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name;
use crate::messages::tool::common_functionality::measure;
use crate::messages::tool::common_functionality::pivot::Pivot; use crate::messages::tool::common_functionality::pivot::Pivot;
use crate::messages::tool::common_functionality::shape_editor::SelectionShapeType; use crate::messages::tool::common_functionality::shape_editor::SelectionShapeType;
use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData, SnapManager}; use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData, SnapManager};
use crate::messages::tool::common_functionality::transformation_cage::*; use crate::messages::tool::common_functionality::transformation_cage::*;
use crate::messages::tool::common_functionality::utility_functions::text_bounding_box; use crate::messages::tool::common_functionality::utility_functions::text_bounding_box;
use crate::messages::tool::common_functionality::{auto_panning::AutoPanning, measure};
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::DMat2;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_std::renderer::Rect; use graphene_std::renderer::Rect;
use graphene_std::vector::misc::BooleanOperation; use graphene_std::vector::misc::BooleanOperation;
use glam::DMat2;
use std::fmt; use std::fmt;
#[derive(Default)] #[derive(Default)]
@ -137,7 +136,7 @@ impl SelectTool {
.widget_holder() .widget_holder()
} }
fn alignment_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> { fn alignment_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> + use<> {
[AlignAxis::X, AlignAxis::Y] [AlignAxis::X, AlignAxis::Y]
.into_iter() .into_iter()
.flat_map(|axis| [(axis, AlignAggregate::Min), (axis, AlignAggregate::Center), (axis, AlignAggregate::Max)]) .flat_map(|axis| [(axis, AlignAggregate::Min), (axis, AlignAggregate::Center), (axis, AlignAggregate::Max)])
@ -158,7 +157,7 @@ impl SelectTool {
}) })
} }
fn flip_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> { fn flip_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> + use<> {
[(FlipAxis::X, "Horizontal"), (FlipAxis::Y, "Vertical")].into_iter().map(move |(flip_axis, name)| { [(FlipAxis::X, "Horizontal"), (FlipAxis::Y, "Vertical")].into_iter().map(move |(flip_axis, name)| {
IconButton::new("Flip".to_string() + name, 24) IconButton::new("Flip".to_string() + name, 24)
.tooltip("Flip ".to_string() + name) .tooltip("Flip ".to_string() + name)
@ -168,7 +167,7 @@ impl SelectTool {
}) })
} }
fn turn_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> { fn turn_widgets(&self, disabled: bool) -> impl Iterator<Item = WidgetHolder> + use<> {
[(-90., "TurnNegative90", "Turn -90°"), (90., "TurnPositive90", "Turn 90°")] [(-90., "TurnNegative90", "Turn -90°"), (90., "TurnPositive90", "Turn 90°")]
.into_iter() .into_iter()
.map(move |(degrees, icon, name)| { .map(move |(degrees, icon, name)| {
@ -180,7 +179,7 @@ impl SelectTool {
}) })
} }
fn boolean_widgets(&self, selected_count: usize) -> impl Iterator<Item = WidgetHolder> { fn boolean_widgets(&self, selected_count: usize) -> impl Iterator<Item = WidgetHolder> + use<> {
let operations = BooleanOperation::list(); let operations = BooleanOperation::list();
let icons = BooleanOperation::icons(); let icons = BooleanOperation::icons();
operations.into_iter().zip(icons).map(move |(operation, icon)| { operations.into_iter().zip(icons).map(move |(operation, icon)| {
@ -1030,7 +1029,7 @@ impl Fsm for SelectToolFsmState {
} }
} }
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove(modifier_keys)) => { (SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove(modifier_keys)) => {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
if let Some(movement) = &mut bounds.selected_edges { if let Some(movement) = &mut bounds.selected_edges {
let (center, constrain) = (input.keyboard.key(modifier_keys.center), input.keyboard.key(modifier_keys.axis_align)); let (center, constrain) = (input.keyboard.key(modifier_keys.center), input.keyboard.key(modifier_keys.axis_align));
@ -1079,7 +1078,7 @@ impl Fsm for SelectToolFsmState {
SelectToolFsmState::ResizingBounds SelectToolFsmState::ResizingBounds
} }
(SelectToolFsmState::SkewingBounds { skew }, SelectToolMessage::PointerMove(_)) => { (SelectToolFsmState::SkewingBounds { skew }, SelectToolMessage::PointerMove(_)) => {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
if let Some(movement) = &mut bounds.selected_edges { if let Some(movement) = &mut bounds.selected_edges {
let free_movement = input.keyboard.key(skew); let free_movement = input.keyboard.key(skew);
let transformation = movement.skew_transform(input.mouse.position, bounds.original_bound_transform, free_movement); let transformation = movement.skew_transform(input.mouse.position, bounds.original_bound_transform, free_movement);
@ -1227,7 +1226,7 @@ impl Fsm for SelectToolFsmState {
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport(_)) => { (SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport(_)) => {
// AutoPanning // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += shift; bounds.center_of_transformation += shift;
bounds.original_bound_transform.translation += shift; bounds.original_bound_transform.translation += shift;
} }
@ -1631,12 +1630,14 @@ fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec
} }
fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) { fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
tool_data.layers_dragging.append(&mut vec![document.find_deepest(&selected).unwrap_or( tool_data.layers_dragging.append(&mut vec![
LayerNodeIdentifier::ROOT_PARENT document.find_deepest(&selected).unwrap_or(
.children(document.metadata()) LayerNodeIdentifier::ROOT_PARENT
.next() .children(document.metadata())
.expect("ROOT_PARENT should have a layer child when clicking"), .next()
)]); .expect("ROOT_PARENT should have a layer child when clicking"),
),
]);
responses.add(NodeGraphMessage::SelectedNodesSet { responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: tool_data nodes: tool_data
.layers_dragging .layers_dragging

View file

@ -9,7 +9,6 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils::{self, find_spline, merge_layers, merge_points}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, find_spline, merge_layers, merge_points};
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapData, SnapManager, SnapTypeConfiguration, SnappedPoint}; use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapData, SnapManager, SnapTypeConfiguration, SnappedPoint};
use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend}; use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend};
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color; use graphene_core::Color;
use graphene_std::vector::{PointId, SegmentId, VectorModificationType}; use graphene_std::vector::{PointId, SegmentId, VectorModificationType};

View file

@ -6,18 +6,20 @@ use crate::messages::portfolio::document::graph_operation::utility_types::Transf
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector; use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name};
use crate::messages::tool::common_functionality::pivot::Pivot;
use crate::messages::tool::common_functionality::resize::Resize;
use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData}; use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData};
use crate::messages::tool::common_functionality::transformation_cage::*; use crate::messages::tool::common_functionality::transformation_cage::*;
use crate::messages::tool::common_functionality::{auto_panning::AutoPanning, pivot::Pivot, resize::Resize, utility_functions::text_bounding_box}; use crate::messages::tool::common_functionality::utility_functions::text_bounding_box;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_core::renderer::Quad;
use graphene_core::text::{lines_clipping, load_face, Font, FontCache, TypesettingConfig};
use graphene_core::vector::style::Fill;
use graphene_core::Color; use graphene_core::Color;
use graphene_core::renderer::Quad;
use graphene_core::text::{Font, FontCache, TypesettingConfig, lines_clipping, load_face};
use graphene_core::vector::style::Fill;
#[derive(Default)] #[derive(Default)]
pub struct TextTool { pub struct TextTool {
@ -514,7 +516,7 @@ impl Fsm for TextToolFsmState {
// The angle is choosen to be parallel to the X axis in the bounds transform. // The angle is choosen to be parallel to the X axis in the bounds transform.
let angle = bounding_box_manager.transform.transform_vector2(DVec2::X).to_angle(); let angle = bounding_box_manager.transform.transform_vector2(DVec2::X).to_angle();
// Update pivot // Update pivot
tool_data.pivot.update_pivot(&document, &mut overlay_context, angle); tool_data.pivot.update_pivot(document, &mut overlay_context, angle);
} else { } else {
tool_data.bounding_box_manager.take(); tool_data.bounding_box_manager.take();
} }
@ -607,7 +609,7 @@ impl Fsm for TextToolFsmState {
TextToolFsmState::Dragging TextToolFsmState::Dragging
} }
(TextToolFsmState::ResizingBounds, TextToolMessage::PointerMove { center, lock_ratio }) => { (TextToolFsmState::ResizingBounds, TextToolMessage::PointerMove { center, lock_ratio }) => {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
if let Some(movement) = &mut bounds.selected_edges { if let Some(movement) = &mut bounds.selected_edges {
let (center_bool, lock_ratio_bool) = (input.keyboard.key(center), input.keyboard.key(lock_ratio)); let (center_bool, lock_ratio_bool) = (input.keyboard.key(center), input.keyboard.key(lock_ratio));
let center_position = center_bool.then_some(bounds.center_of_transformation); let center_position = center_bool.then_some(bounds.center_of_transformation);
@ -682,7 +684,7 @@ impl Fsm for TextToolFsmState {
(TextToolFsmState::ResizingBounds, TextToolMessage::PointerOutsideViewport { .. }) => { (TextToolFsmState::ResizingBounds, TextToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += shift; bounds.center_of_transformation += shift;
bounds.original_bound_transform.translation += shift; bounds.original_bound_transform.translation += shift;
} }

View file

@ -1,7 +1,6 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::DVec2; use glam::DVec2;
#[impl_message(Message, ToolMessage, TransformLayer)] #[impl_message(Message, ToolMessage, TransformLayer)]

View file

@ -8,12 +8,10 @@ use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::tool_messages::tool_prelude::Key; use crate::messages::tool::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::{ToolData, ToolType}; use crate::messages::tool::utility_types::{ToolData, ToolType};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::vector::ManipulatorPointId; use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{VectorData, VectorModificationType}; use graphene_std::vector::{VectorData, VectorModificationType};
use glam::{DAffine2, DVec2};
use std::f64::consts::TAU; use std::f64::consts::TAU;
const TRANSFORM_GRS_OVERLAY_PROVIDER: OverlayProvider = |context| TransformLayerMessage::Overlays(context).into(); const TRANSFORM_GRS_OVERLAY_PROVIDER: OverlayProvider = |context| TransformLayerMessage::Overlays(context).into();

View file

@ -2,8 +2,8 @@
use super::common_functionality::shape_editor::ShapeState; use super::common_functionality::shape_editor::ShapeState;
use super::tool_messages::*; use super::tool_messages::*;
use crate::messages::broadcast::broadcast_event::BroadcastEvent;
use crate::messages::broadcast::BroadcastMessage; use crate::messages::broadcast::BroadcastMessage;
use crate::messages::broadcast::broadcast_event::BroadcastEvent;
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, LayoutKeysGroup, MouseMotion}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, LayoutKeysGroup, MouseMotion};
use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::input_mapper::utility_types::misc::ActionKeys; use crate::messages::input_mapper::utility_types::misc::ActionKeys;
@ -12,10 +12,8 @@ use crate::messages::portfolio::document::overlays::utility_types::OverlayProvid
use crate::messages::preferences::PreferencesMessageHandler; use crate::messages::preferences::PreferencesMessageHandler;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use graphene_core::text::FontCache; use graphene_core::text::FontCache;
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};

View file

@ -1,13 +1,14 @@
use crate::consts::FILE_SAVE_SUFFIX; use crate::consts::FILE_SAVE_SUFFIX;
use crate::messages::frontend::utility_types::{ExportBounds, FileType}; use crate::messages::frontend::utility_types::{ExportBounds, FileType};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use glam::{DAffine2, DVec2, UVec2};
use graph_craft::concrete; use graph_craft::concrete;
use graph_craft::document::value::{RenderOutput, TaggedValue}; use graph_craft::document::value::{RenderOutput, TaggedValue};
use graph_craft::document::{generate_uuid, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork}; use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, generate_uuid};
use graph_craft::graphene_compiler::Compiler; use graph_craft::graphene_compiler::Compiler;
use graph_craft::proto::GraphErrors; use graph_craft::proto::GraphErrors;
use graph_craft::wasm_application_io::EditorPreferences; use graph_craft::wasm_application_io::EditorPreferences;
use graphene_core::Context;
use graphene_core::application_io::{NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig}; use graphene_core::application_io::{NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
use graphene_core::memo::IORecord; use graphene_core::memo::IORecord;
use graphene_core::renderer::{GraphicElementRendered, RenderParams, SvgRender}; use graphene_core::renderer::{GraphicElementRendered, RenderParams, SvgRender};
@ -15,18 +16,15 @@ use graphene_core::renderer::{RenderSvgSegmentList, SvgSegment};
use graphene_core::text::FontCache; use graphene_core::text::FontCache;
use graphene_core::transform::Footprint; use graphene_core::transform::Footprint;
use graphene_core::vector::style::ViewMode; use graphene_core::vector::style::ViewMode;
use graphene_core::Context; use graphene_std::renderer::{RenderMetadata, format_transform_matrix};
use graphene_std::renderer::{format_transform_matrix, RenderMetadata};
use graphene_std::vector::{VectorData, VectorDataTable}; use graphene_std::vector::{VectorData, VectorDataTable};
use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi}; use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta}; use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
use interpreted_executor::util::wrap_network_in_scope; use interpreted_executor::util::wrap_network_in_scope;
use glam::{DAffine2, DVec2, UVec2};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use spin::Mutex; use spin::Mutex;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};
/// Persistent data between graph executions. It's updated via message passing from the editor thread with [`NodeRuntimeMessage`]`. /// Persistent data between graph executions. It's updated via message passing from the editor thread with [`NodeRuntimeMessage`]`.
/// Some of these fields are put into a [`WasmEditorApi`] which is passed to the final compiled graph network upon each execution. /// Some of these fields are put into a [`WasmEditorApi`] which is passed to the final compiled graph network upon each execution.

View file

@ -1,5 +1,5 @@
use crate::application::set_uuid_seed;
use crate::application::Editor; use crate::application::Editor;
use crate::application::set_uuid_seed;
use crate::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use crate::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta, ViewportPosition}; use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta, ViewportPosition};
use crate::messages::portfolio::utility_types::Platform; use crate::messages::portfolio::utility_types::Platform;
@ -8,12 +8,10 @@ use crate::messages::tool::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::ToolType; use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::Instrumented; use crate::node_graph_executor::Instrumented;
use crate::node_graph_executor::NodeRuntime; use crate::node_graph_executor::NodeRuntime;
use graph_craft::document::DocumentNode;
use graphene_core::raster::color::Color;
use graphene_core::InputAccessor;
use glam::DVec2; use glam::DVec2;
use graph_craft::document::DocumentNode;
use graphene_core::InputAccessor;
use graphene_core::raster::color::Color;
/// A set of utility functions to make the writing of editor test more declarative /// A set of utility functions to make the writing of editor test more declarative
pub struct EditorTestUtils { pub struct EditorTestUtils {
@ -256,7 +254,7 @@ pub mod test_prelude {
pub use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; pub use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
pub use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; pub use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
pub use crate::messages::prelude::*; pub use crate::messages::prelude::*;
pub use crate::messages::tool::common_functionality::graph_modification_utils::{is_layer_fed_by_node_of_name, NodeGraphLayer}; pub use crate::messages::tool::common_functionality::graph_modification_utils::{NodeGraphLayer, is_layer_fed_by_node_of_name};
pub use crate::messages::tool::utility_types::ToolType; pub use crate::messages::tool::utility_types::ToolType;
pub use crate::node_graph_executor::NodeRuntime; pub use crate::node_graph_executor::NodeRuntime;
pub use crate::test_utils::EditorTestUtils; pub use crate::test_utils::EditorTestUtils;

View file

@ -1,4 +1,5 @@
use std::{fs, path::PathBuf}; use std::fs;
use std::path::PathBuf;
fn main() { fn main() {
// Directory required for compilation, but not tracked by git if empty. // Directory required for compilation, but not tracked by git if empty.

View file

@ -2,9 +2,9 @@
name = "graphite-wasm" name = "graphite-wasm"
publish = false publish = false
version = "0.0.0" version = "0.0.0"
rust-version = "1.79" rust-version = "1.85"
authors = ["Graphite Authors <contact@graphite.rs>"] authors = ["Graphite Authors <contact@graphite.rs>"]
edition = "2021" edition = "2024"
readme = "../../README.md" readme = "../../README.md"
homepage = "https://graphite.rs" homepage = "https://graphite.rs"
repository = "https://github.com/GraphiteEditor/Graphite" repository = "https://github.com/GraphiteEditor/Graphite"

View file

@ -5,8 +5,7 @@
// on the dispatcher messaging system and more complex Rust data types. // on the dispatcher messaging system and more complex Rust data types.
// //
use crate::helpers::translate_key; use crate::helpers::translate_key;
use crate::{Error, EDITOR, EDITOR_HANDLE, EDITOR_HAS_CRASHED}; use crate::{EDITOR, EDITOR_HANDLE, EDITOR_HAS_CRASHED, Error};
use editor::application::Editor; use editor::application::Editor;
use editor::consts::FILE_SAVE_SUFFIX; use editor::consts::FILE_SAVE_SUFFIX;
use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
@ -18,7 +17,6 @@ use editor::messages::prelude::*;
use editor::messages::tool::tool_messages::tool_prelude::WidgetId; use editor::messages::tool::tool_messages::tool_prelude::WidgetId;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
use serde::Serialize; use serde::Serialize;
use serde_wasm_bindgen::{self, from_value}; use serde_wasm_bindgen::{self, from_value};
use std::cell::RefCell; use std::cell::RefCell;
@ -757,10 +755,11 @@ impl EditorHandle {
use editor::messages::portfolio::document::graph_operation::transform_utils::*; use editor::messages::portfolio::document::graph_operation::transform_utils::*;
use editor::messages::portfolio::document::graph_operation::utility_types::*; use editor::messages::portfolio::document::graph_operation::utility_types::*;
use editor::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use editor::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type;
use editor::node_graph_executor::replace_node_runtime;
use editor::node_graph_executor::NodeRuntime; use editor::node_graph_executor::NodeRuntime;
use editor::node_graph_executor::replace_node_runtime;
use graph_craft::document::DocumentNodeImplementation;
use graph_craft::document::NodeInput; use graph_craft::document::NodeInput;
use graph_craft::document::{value::TaggedValue, DocumentNodeImplementation}; use graph_craft::document::value::TaggedValue;
use graphene_core::vector::*; use graphene_core::vector::*;
let (_, request_receiver) = std::sync::mpsc::channel(); let (_, request_receiver) = std::sync::mpsc::channel();
@ -989,7 +988,7 @@ fn set_timeout(f: &Closure<dyn FnMut()>, delay: Duration) {
fn editor<T: Default>(callback: impl FnOnce(&mut editor::application::Editor) -> T) -> T { fn editor<T: Default>(callback: impl FnOnce(&mut editor::application::Editor) -> T) -> T {
EDITOR.with(|editor| { EDITOR.with(|editor| {
let mut guard = editor.try_lock(); let mut guard = editor.try_lock();
let Ok(Some(ref mut editor)) = guard.as_deref_mut() else { return T::default() }; let Ok(Some(editor)) = guard.as_deref_mut() else { return T::default() };
callback(editor) callback(editor)
}) })
@ -1000,7 +999,7 @@ pub(crate) fn editor_and_handle(mut callback: impl FnMut(&mut Editor, &mut Edito
EDITOR_HANDLE.with(|editor_handle| { EDITOR_HANDLE.with(|editor_handle| {
editor(|editor| { editor(|editor| {
let mut guard = editor_handle.try_lock(); let mut guard = editor_handle.try_lock();
let Ok(Some(ref mut editor_handle)) = guard.as_deref_mut() else { let Ok(Some(editor_handle)) = guard.as_deref_mut() else {
log::error!("Failed to borrow editor handle"); log::error!("Failed to borrow editor handle");
return; return;
}; };

View file

@ -8,10 +8,9 @@ pub mod editor_api;
pub mod helpers; pub mod helpers;
use editor::messages::prelude::*; use editor::messages::prelude::*;
use std::panic; use std::panic;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
// Set up the persistent editor backend state // Set up the persistent editor backend state
@ -72,7 +71,7 @@ pub fn panic_hook(info: &panic::PanicHookInfo) {
EDITOR_HANDLE.with(|editor_handle| { EDITOR_HANDLE.with(|editor_handle| {
let mut guard = editor_handle.lock(); let mut guard = editor_handle.lock();
if let Ok(Some(ref mut handle)) = guard.as_deref_mut() { if let Ok(Some(handle)) = guard.as_deref_mut() {
handle.send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic { panic_info: info.to_string() }); handle.send_frontend_message_to_js_rust_proxy(FrontendMessage::DisplayDialogPanic { panic_info: info.to_string() });
} }
}); });

View file

@ -1,8 +1,8 @@
[package] [package]
name = "bezier-rs" name = "bezier-rs"
version = "0.4.0" version = "0.4.0"
rust-version = "1.79" rust-version = "1.85"
edition = "2021" edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"] authors = ["Graphite Authors <contact@graphite.rs>"]
description = "Computational geometry algorithms for Bézier segments and shapes useful in the context of 2D graphics" description = "Computational geometry algorithms for Bézier segments and shapes useful in the context of 2D graphics"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View file

@ -1,7 +1,6 @@
use super::*; use super::*;
use utils::format_point;
use std::fmt::Write; use std::fmt::Write;
use utils::format_point;
/// Functionality relating to core `Bezier` operations, such as constructors and `abs_diff_eq`. /// Functionality relating to core `Bezier` operations, such as constructors and `abs_diff_eq`.
impl Bezier { impl Bezier {

View file

@ -1,6 +1,5 @@
use crate::utils::{TValue, TValueType};
use super::*; use super::*;
use crate::utils::{TValue, TValueType};
/// Functionality relating to looking up properties of the `Bezier` or points along the `Bezier`. /// Functionality relating to looking up properties of the `Bezier` or points along the `Bezier`.
impl Bezier { impl Bezier {

View file

@ -69,7 +69,7 @@ impl Bezier {
/// - For a linear segment, the order of the points will be: `start`, `end`. /// - For a linear segment, the order of the points will be: `start`, `end`.
/// - For a quadratic segment, the order of the points will be: `start`, `handle`, `end`. /// - For a quadratic segment, the order of the points will be: `start`, `handle`, `end`.
/// - For a cubic segment, the order of the points will be: `start`, `handle_start`, `handle_end`, `end`. /// - For a cubic segment, the order of the points will be: `start`, `handle_start`, `handle_end`, `end`.
pub fn get_points(&self) -> impl Iterator<Item = DVec2> { pub fn get_points(&self) -> impl Iterator<Item = DVec2> + use<> {
match self.handles { match self.handles {
BezierHandles::Linear => [self.start, self.end, DVec2::ZERO, DVec2::ZERO].into_iter().take(2), BezierHandles::Linear => [self.start, self.end, DVec2::ZERO, DVec2::ZERO].into_iter().take(2),
BezierHandles::Quadratic { handle } => [self.start, handle, self.end, DVec2::ZERO].into_iter().take(3), BezierHandles::Quadratic { handle } => [self.start, handle, self.end, DVec2::ZERO].into_iter().take(3),

View file

@ -7,11 +7,9 @@ mod transform;
use crate::consts::*; use crate::consts::*;
use crate::utils; use crate::utils;
pub use structs::*;
use glam::DVec2; use glam::DVec2;
use std::fmt::{Debug, Formatter, Result}; use std::fmt::{Debug, Formatter, Result};
pub use structs::*;
/// Representation of the handle point(s) in a bezier segment. /// Representation of the handle point(s) in a bezier segment.
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]

View file

@ -1,8 +1,7 @@
use super::*; use super::*;
use crate::polynomial::Polynomial; use crate::polynomial::Polynomial;
use crate::utils::{solve_cubic, solve_quadratic, TValue}; use crate::utils::{TValue, solve_cubic, solve_quadratic};
use crate::{to_symmetrical_basis_pair, SymmetricalBasis}; use crate::{SymmetricalBasis, to_symmetrical_basis_pair};
use glam::DMat2; use glam::DMat2;
use std::ops::Range; use std::ops::Range;
@ -99,11 +98,7 @@ impl Bezier {
pub fn tangent(&self, t: TValue) -> DVec2 { pub fn tangent(&self, t: TValue) -> DVec2 {
let t = self.t_value_to_parametric(t); let t = self.t_value_to_parametric(t);
let tangent = self.non_normalized_tangent(t); let tangent = self.non_normalized_tangent(t);
if tangent.length() > 0. { if tangent.length() > 0. { tangent.normalize() } else { tangent }
tangent.normalize()
} else {
tangent
}
} }
/// Find the `t`-value(s) such that the tangent(s) at `t` pass through the specified point. /// Find the `t`-value(s) such that the tangent(s) at `t` pass through the specified point.
@ -147,11 +142,7 @@ impl Bezier {
let numerator = d.x * dd.y - d.y * dd.x; let numerator = d.x * dd.y - d.y * dd.x;
let denominator = (d.x.powf(2.) + d.y.powf(2.)).powf(1.5); let denominator = (d.x.powf(2.) + d.y.powf(2.)).powf(1.5);
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE { if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE { 0. } else { numerator / denominator }
0.
} else {
numerator / denominator
}
} }
/// Returns two lists of `t`-values representing the local extrema of the `x` and `y` parametric curves respectively. /// Returns two lists of `t`-values representing the local extrema of the `x` and `y` parametric curves respectively.
@ -228,7 +219,7 @@ impl Bezier {
} }
/// Returns an `Iterator` containing all possible parametric `t`-values at the given `x`-coordinate. /// Returns an `Iterator` containing all possible parametric `t`-values at the given `x`-coordinate.
pub fn find_tvalues_for_x(&self, x: f64) -> impl Iterator<Item = f64> { pub fn find_tvalues_for_x(&self, x: f64) -> impl Iterator<Item = f64> + use<> {
// Compute the roots of the resulting bezier curve // Compute the roots of the resulting bezier curve
match self.handles { match self.handles {
BezierHandles::Linear => { BezierHandles::Linear => {

View file

@ -1,9 +1,7 @@
use super::*; use super::*;
use crate::compare::compare_points; use crate::compare::compare_points;
use crate::utils::{f64_compare, Cap, TValue}; use crate::utils::{Cap, TValue, f64_compare};
use crate::{AppendType, ManipulatorGroup, Subpath}; use crate::{AppendType, ManipulatorGroup, Subpath};
use glam::DMat2; use glam::DMat2;
use std::f64::consts::PI; use std::f64::consts::PI;
@ -476,11 +474,7 @@ impl Bezier {
error, error,
max_iterations, max_iterations,
}); });
if final_low_t != 1. { if final_low_t != 1. { [auto_arcs, arc_approximations].concat() } else { auto_arcs }
[auto_arcs, arc_approximations].concat()
} else {
auto_arcs
}
} }
ArcStrategy::FavorLargerArcs => self.approximate_curve_with_arcs(0., 1., error, max_iterations, false).0, ArcStrategy::FavorLargerArcs => self.approximate_curve_with_arcs(0., 1., error, max_iterations, false).0,
ArcStrategy::FavorCorrectness => self ArcStrategy::FavorCorrectness => self
@ -620,9 +614,9 @@ impl Bezier {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::EmptyId;
use crate::compare::{compare_arcs, compare_points}; use crate::compare::{compare_arcs, compare_points};
use crate::utils::{Cap, TValue}; use crate::utils::{Cap, TValue};
use crate::EmptyId;
#[test] #[test]
fn test_split() { fn test_split() {
@ -777,14 +771,18 @@ mod tests {
// Check that the reduce helper is correct // Check that the reduce helper is correct
let (helper_curves, helper_t_values) = bezier.reduced_curves_and_t_values(None); let (helper_curves, helper_t_values) = bezier.reduced_curves_and_t_values(None);
assert!(reduced_curves assert!(
.iter() reduced_curves
.zip(helper_curves.iter()) .iter()
.all(|(bezier1, bezier2)| bezier1.abs_diff_eq(bezier2, MAX_ABSOLUTE_DIFFERENCE))); .zip(helper_curves.iter())
assert!(reduced_curves .all(|(bezier1, bezier2)| bezier1.abs_diff_eq(bezier2, MAX_ABSOLUTE_DIFFERENCE))
.iter() );
.zip(helper_t_values.iter()) assert!(
.all(|(curve, t_pair)| curve.abs_diff_eq(&bezier.trim(TValue::Parametric(t_pair[0]), TValue::Parametric(t_pair[1])), MAX_ABSOLUTE_DIFFERENCE))) reduced_curves
.iter()
.zip(helper_t_values.iter())
.all(|(curve, t_pair)| curve.abs_diff_eq(&bezier.trim(TValue::Parametric(t_pair[0]), TValue::Parametric(t_pair[1])), MAX_ABSOLUTE_DIFFERENCE))
)
} }
fn assert_valid_offset<PointId: crate::Identifier>(bezier: &Bezier, offset: &Subpath<PointId>, expected_distance: f64) { fn assert_valid_offset<PointId: crate::Identifier>(bezier: &Bezier, offset: &Subpath<PointId>, expected_distance: f64) {

Some files were not shown because too many files have changed in this diff Show more