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"
publish = false
version = "0.0.0"
rust-version = "1.82"
rust-version = "1.85"
authors = ["Graphite Authors <contact@graphite.rs>"]
edition = "2021"
edition = "2024"
readme = "../README.md"
homepage = "https://graphite.rs"
repository = "https://github.com/GraphiteEditor/Graphite"

View file

@ -1,6 +1,5 @@
use crate::dispatcher::Dispatcher;
use crate::messages::prelude::*;
pub use graphene_core::uuid::*;
// 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 {
String::from_iter(queues.iter().enumerate().skip(1).map(|(index, queue)| {
if index == queues.len() - 1 {
if queue.is_empty() {
"└── "
} else {
"├── "
}
if queue.is_empty() { "└── " } else { "├── " }
} else if queue.is_empty() {
" "
} else {

View file

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

View file

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

View file

@ -26,7 +26,8 @@ impl LayoutHolder for ComingSoonDialog {
if let Some(issue) = self.issue {
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![
TextButton::new(format!("GitHub Issue #{issue}"))
.icon(Some("Website".into()))
.flush(true)
.on_update(move |_| {
@ -35,7 +36,8 @@ impl LayoutHolder for ComingSoonDialog {
}
.into()
})
.widget_holder()];
.widget_holder(),
];
rows.push(LayoutGroup::Row { widgets: row2 });
rows.push(LayoutGroup::Row { widgets: row3 });

View file

@ -32,11 +32,13 @@ impl LayoutHolder for DemoArtworkDialog {
.flat_map(|chunk| {
fn make_dialog(name: &str, filename: &str) -> Message {
DialogMessage::CloseDialogAndThen {
followups: vec![FrontendMessage::TriggerFetchAndOpenDocument {
followups: vec![
FrontendMessage::TriggerFetchAndOpenDocument {
name: name.to_string(),
filename: filename.to_string(),
}
.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_document_dialog::CloseDocumentDialog;
pub use coming_soon_dialog::ComingSoonDialog;
pub use demo_artwork_dialog::ARTWORK;
pub use demo_artwork_dialog::DemoArtworkDialog;
pub use error_dialog::ErrorDialog;
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::prelude::*;
use crate::messages::tool::utility_types::HintData;
use graph_craft::document::NodeId;
use graphene_core::raster::color::Color;
use graphene_core::text::Font;

View file

@ -1,5 +1,4 @@
use crate::messages::portfolio::utility_types::Platform;
use std::sync::OnceLock;
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::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*;
use std::fmt::Write;
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::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate;
use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
use glam::DVec2;
impl From<MappingVariant> for Mapping {

View file

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

View file

@ -1,6 +1,5 @@
use crate::consts::DRAG_THRESHOLD;
use crate::messages::prelude::*;
use bitflags::bitflags;
use glam::DVec2;
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.
/// 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 {
($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.
MappingEntry {
@ -72,7 +72,7 @@ macro_rules! entry {
/// (key_up, key_down, double_click, wheel_scroll, pointer_move)
/// ```
macro_rules! mapping {
[$($entry:expr),* $(,)?] => {{
[$($entry:expr_2021),* $(,)?] => {{
let mut key_up = KeyMappingEntries::key_array();
let mut key_down = 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()`.
macro_rules! action_keys {
($action:expr) => {
($action:expr_2021) => {
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::utility_types::input_keyboard::{KeyStates, NUMBER_OF_KEYS};
use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS;
use crate::messages::prelude::*;
use core::time::Duration;
#[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_mouse::{EditorMouseState, ViewportBounds};
use crate::messages::prelude::*;
use core::time::Duration;
#[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::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*;
use glam::DVec2;
pub struct InputPreprocessorMessageData {

View file

@ -1,11 +1,9 @@
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
use graphene_core::raster::color::Color;
use graphene_core::text::Font;
use graphene_std::vector::style::{FillChoice, GradientStops};
use serde_json::Value;
#[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::misc::ActionKeys;
use crate::messages::prelude::*;
use std::sync::Arc;
#[repr(transparent)]
@ -348,11 +347,7 @@ impl LayoutGroup {
val.clone_from(&tooltip);
}
}
if is_col {
Self::Column { widgets }
} else {
Self::Row { widgets }
}
if is_col { 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.

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::portfolio::document::node_graph::utility_types::FrontendGraphDataType;
use crate::messages::tool::tool_messages::tool_prelude::WidgetCallback;
use derivative::*;
use graphene_std::vector::style::FillChoice;
use graphite_proc_macros::WidgetBuilder;
use derivative::*;
#[derive(Clone, Default, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
#[derivative(Debug, PartialEq)]
pub struct IconButton {

View file

@ -1,11 +1,10 @@
use crate::messages::input_mapper::utility_types::misc::ActionKeys;
use crate::messages::layout::utility_types::widget_prelude::*;
use graphene_core::{raster::curve::Curve, Color};
use graphite_proc_macros::WidgetBuilder;
use derivative::*;
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)]
#[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::misc::ActionKeys;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
use super::input_widgets::InvisibleStandinInput;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Default, specta::Type)]
pub struct MenuBarEntryChildren(pub Vec<Vec<MenuBarEntry>>);

View file

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

View file

@ -2,10 +2,10 @@ use super::node_graph::document_node_definitions;
use super::node_graph::utility_types::Transform;
use super::overlays::utility_types::Pivot;
use super::utility_types::error::EditorError;
use super::utility_types::misc::{GroupFolderType, SnappingOptions, SnappingState, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS};
use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS, SnappingOptions, SnappingState};
use super::utility_types::network_interface::{self, NodeNetworkInterface, TransactionStatus};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes};
use crate::application::{generate_uuid, GRAPHITE_GIT_COMMIT_HASH};
use crate::application::{GRAPHITE_GIT_COMMIT_HASH, generate_uuid};
use crate::consts::{ASYMPTOTIC_EFFECT, COLOR_OVERLAY_GRAY, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL};
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
@ -24,17 +24,15 @@ use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
use crate::messages::tool::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor;
use bezier_rs::Subpath;
use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::vector::style::ViewMode;
use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{path_bool_lib, PointId};
use glam::{DAffine2, DVec2, IVec2};
use graphene_std::vector::{PointId, path_bool_lib};
pub struct DocumentMessageData<'a> {
pub document_id: DocumentId,
@ -1497,7 +1495,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
impl DocumentMessageHandler {
/// Runs an intersection test with all layers and a viewport space quad
pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
let document_quad = document_to_viewport.inverse() * viewport_quad;
@ -1505,12 +1503,12 @@ impl DocumentMessageHandler {
}
/// Runs an intersection test with all layers and a viewport space quad; ignoring artboards
pub fn intersect_quad_no_artboards<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_quad_no_artboards<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.intersect_quad(viewport_quad, ipp).filter(|layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
}
/// Runs an intersection test with all layers and a viewport space subpath
pub fn intersect_polygon<'a>(&'a self, mut viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_polygon<'a>(&'a self, mut viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
viewport_polygon.apply_transform(document_to_viewport.inverse());
@ -1518,7 +1516,7 @@ impl DocumentMessageHandler {
}
/// Runs an intersection test with all layers and a viewport space subpath; ignoring artboards
pub fn intersect_polygon_no_artboards<'a>(&'a self, viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn intersect_polygon_no_artboards<'a>(&'a self, viewport_polygon: Subpath<PointId>, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.intersect_polygon(viewport_polygon, ipp).filter(|layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
}
@ -1562,7 +1560,7 @@ impl DocumentMessageHandler {
}
/// Find all of the layers that were clicked on from a viewport space location
pub fn click_xray(&self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
pub fn click_xray(&self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'_> {
let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
let point = document_to_viewport.inverse().transform_point2(ipp.mouse.position);
ClickXRayIter::new(&self.network_interface, XRayTarget::Point(point))
@ -1584,7 +1582,7 @@ impl DocumentMessageHandler {
}
/// Find layers under the location in viewport space that was clicked, listed by their depth in the layer tree hierarchy.
pub fn click_list<'a>(&'a self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + 'a {
pub fn click_list<'a>(&'a self, ipp: &InputPreprocessorMessageHandler) -> impl Iterator<Item = LayerNodeIdentifier> + use<'a> {
self.click_xray(ipp)
.filter(move |&layer| !self.network_interface.is_artboard(&layer.to_node(), &[]))
.skip_while(|&layer| layer == LayerNodeIdentifier::ROOT_PARENT)

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

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

View file

@ -1,10 +1,9 @@
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface};
use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::vector::PointId;
/// Convert an affine transform into the tuple `(scale, angle, translation, shear)` assuming `shear.y = 0`.
pub fn compute_scale_angle_translation_shear(transform: DAffine2) -> (DVec2, f64, DVec2, DVec2) {
@ -89,11 +88,7 @@ pub fn get_current_transform(inputs: &[NodeInput]) -> DAffine2 {
/// Extract the current normalized pivot from the layer
pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 {
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() {
pivot
} else {
DVec2::splat(0.5)
}
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) }
}
/// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png)

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

View file

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

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

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

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

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

View file

@ -1,16 +1,16 @@
#![allow(clippy::too_many_arguments)]
use super::document_node_definitions::{NodePropertiesContext, NODE_OVERRIDES};
use super::document_node_definitions::{NODE_OVERRIDES, NodePropertiesContext};
use super::utility_types::FrontendGraphDataType;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::prelude::*;
use dyn_any::DynAny;
use glam::{DAffine2, DVec2, IVec2, UVec2};
use graph_craft::Type;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod};
use graph_craft::Type;
use graphene_core::raster::curve::Curve;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::raster::{
@ -22,25 +22,20 @@ use graphene_core::vector::misc::CentroidType;
use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
use graphene_std::application_io::TextureFrameTable;
use graphene_std::transform::Footprint;
use graphene_std::vector::VectorDataTable;
use graphene_std::vector::misc::BooleanOperation;
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
use graphene_std::vector::VectorDataTable;
use graphene_std::{GraphicGroupTable, RasterFrame};
use glam::{DAffine2, DVec2, IVec2, UVec2};
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
let widget = TextLabel::new(text).widget_holder();
vec![LayoutGroup::Row { widgets: vec![widget] }]
}
fn optionally_update_value<T>(value: impl Fn(&T) -> Option<TaggedValue> + 'static + Send + Sync, node_id: NodeId, input_index: usize) -> impl Fn(&T) -> Message + 'static + Send + Sync {
move |input_value: &T| {
if let Some(value) = value(input_value) {
NodeGraphMessage::SetInputValue { node_id, input_index, value }.into()
} else {
Message::NoOp
}
move |input_value: &T| match value(input_value) {
Some(value) => NodeGraphMessage::SetInputValue { node_id, input_index, value }.into(),
_ => Message::NoOp,
}
}
@ -177,7 +172,8 @@ pub(crate) fn property_from_type(
Some(x) if x == TypeId::of::<CellularDistanceFunction>() => cellular_distance_function(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<CellularReturnType>() => cellular_return_type(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<DomainWarpType>() => domain_warp_type(document_node, node_id, index, name, true, false),
Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![DropdownInput::new(vec![vec![
Some(x) if x == TypeId::of::<RelativeAbsolute>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Relative")
.label("Relative")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)),
@ -185,11 +181,13 @@ pub(crate) fn property_from_type(
.label("Absolute")
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)),
]])
.widget_holder()]
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<LineCap>() => line_cap_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<LineJoin>() => line_join_widget(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<FillType>() => vec![DropdownInput::new(vec![vec![
Some(x) if x == TypeId::of::<FillType>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Solid")
.label("Solid")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)),
@ -197,9 +195,11 @@ pub(crate) fn property_from_type(
.label("Gradient")
.on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)),
]])
.widget_holder()]
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<GradientType>() => vec![DropdownInput::new(vec![vec![
Some(x) if x == TypeId::of::<GradientType>() => vec![
DropdownInput::new(vec![vec![
MenuListEntry::new("Linear")
.label("Linear")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)),
@ -207,12 +207,14 @@ pub(crate) fn property_from_type(
.label("Radial")
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
]])
.widget_holder()]
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<BooleanOperation>() => boolean_operation_radio_buttons(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<CentroidType>() => centroid_widget(document_node, node_id, index),
Some(x) if x == TypeId::of::<LuminanceCalculation>() => luminance_calculation(document_node, node_id, index, name, true),
Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![DropdownInput::new(
Some(x) if x == TypeId::of::<ImaginateSamplingMethod>() => vec![
DropdownInput::new(
ImaginateSamplingMethod::list()
.into_iter()
.map(|method| {
@ -224,9 +226,11 @@ pub(crate) fn property_from_type(
})
.collect(),
)
.widget_holder()]
.widget_holder(),
]
.into(),
Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![DropdownInput::new(
Some(x) if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![
DropdownInput::new(
ImaginateMaskStartingFill::list()
.into_iter()
.map(|fill| {
@ -238,7 +242,8 @@ pub(crate) fn property_from_type(
})
.collect(),
)
.widget_holder()]
.widget_holder(),
]
.into(),
_ => {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, true);
@ -313,7 +318,7 @@ pub fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Bool(x)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Bool(x)) = input.as_non_exposed_value() {
widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
checkbox_input
@ -342,7 +347,7 @@ pub fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Footprint(footprint)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Footprint(footprint)) = input.as_non_exposed_value() {
let top_left = footprint.transform.transform_point2(DVec2::ZERO);
let bounds = footprint.scale();
let oversample = footprint.resolution.as_dvec2() / bounds;
@ -752,7 +757,7 @@ pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::RedGreenBlue(mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RedGreenBlue(mode)) = input.as_non_exposed_value() {
let calculation_modes = [RedGreenBlue::Red, RedGreenBlue::Green, RedGreenBlue::Blue];
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@ -779,7 +784,7 @@ pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::RedGreenBlueAlpha(mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RedGreenBlueAlpha(mode)) = input.as_non_exposed_value() {
let calculation_modes = [RedGreenBlueAlpha::Red, RedGreenBlueAlpha::Green, RedGreenBlueAlpha::Blue, RedGreenBlueAlpha::Alpha];
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@ -807,7 +812,7 @@ pub fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, n
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::NoiseType(noise_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::NoiseType(noise_type)) = input.as_non_exposed_value() {
let entries = NoiseType::list()
.iter()
.map(|noise_type| {
@ -833,7 +838,7 @@ pub fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::FractalType(fractal_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::FractalType(fractal_type)) = input.as_non_exposed_value() {
let entries = FractalType::list()
.iter()
.map(|fractal_type| {
@ -859,7 +864,7 @@ pub fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId,
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CellularDistanceFunction(cellular_distance_function)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CellularDistanceFunction(cellular_distance_function)) = input.as_non_exposed_value() {
let entries = CellularDistanceFunction::list()
.iter()
.map(|cellular_distance_function| {
@ -888,7 +893,7 @@ pub fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CellularReturnType(cellular_return_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CellularReturnType(cellular_return_type)) = input.as_non_exposed_value() {
let entries = CellularReturnType::list()
.iter()
.map(|cellular_return_type| {
@ -914,7 +919,7 @@ pub fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::DomainWarpType(domain_warp_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::DomainWarpType(domain_warp_type)) = input.as_non_exposed_value() {
let entries = DomainWarpType::list()
.iter()
.map(|domain_warp_type| {
@ -940,7 +945,7 @@ pub fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, n
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::BlendMode(blend_mode)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::BlendMode(blend_mode)) = input.as_non_exposed_value() {
let entries = BlendMode::list_svg_subset()
.iter()
.map(|category| {
@ -973,7 +978,7 @@ pub fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, inde
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LuminanceCalculation(calculation)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LuminanceCalculation(calculation)) = input.as_non_exposed_value() {
let calculation_modes = LuminanceCalculation::list();
let mut entries = Vec::with_capacity(calculation_modes.len());
for method in calculation_modes {
@ -1001,7 +1006,7 @@ pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: No
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::BooleanOperation(calculation)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::BooleanOperation(calculation)) = input.as_non_exposed_value() {
let operations = BooleanOperation::list();
let icons = BooleanOperation::icons();
let mut entries = Vec::with_capacity(operations.len());
@ -1030,7 +1035,7 @@ pub fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usi
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LineCap(line_cap)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LineCap(line_cap)) = input.as_non_exposed_value() {
let entries = [("Butt", LineCap::Butt), ("Round", LineCap::Round), ("Square", LineCap::Square)]
.into_iter()
.map(|(name, val)| {
@ -1055,7 +1060,7 @@ pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: us
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::LineJoin(line_join)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::LineJoin(line_join)) = input.as_non_exposed_value() {
let entries = [("Miter", LineJoin::Miter), ("Bevel", LineJoin::Bevel), ("Round", LineJoin::Round)]
.into_iter()
.map(|(name, val)| {
@ -1101,7 +1106,7 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
.on_commit(commit_value)
.widget_holder(),
),
TaggedValue::GradientStops(ref x) => widgets.push(
TaggedValue::GradientStops(x) => widgets.push(
color_button
.value(FillChoice::Gradient(x.clone()))
.on_update(update_value(
@ -1143,7 +1148,7 @@ pub fn centroid_widget(document_node: &DocumentNode, node_id: NodeId, index: usi
log::warn!("A widget failed to be built because its node's input index is invalid.");
return LayoutGroup::Row { widgets: vec![] };
};
if let Some(&TaggedValue::CentroidType(centroid_type)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::CentroidType(centroid_type)) = input.as_non_exposed_value() {
let entries = vec![
RadioEntryData::new("area")
.label("Area")
@ -1223,13 +1228,10 @@ pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesCo
let document_node = get_document_node(node_id, context)?;
// This is safe since the node is a proto node and the implementation cannot be changed.
let randomize_index = 5;
Ok(
if let Some(&TaggedValue::Bool(randomize_enabled)) = &document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
randomize_enabled
} else {
false
},
)
Ok(match document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
Some(TaggedValue::Bool(randomize_enabled)) => *randomize_enabled,
_ => false,
})
}
pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
@ -1244,10 +1246,9 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
// Monochrome
let monochrome_index = 1;
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true);
let is_monochrome = if let Some(&TaggedValue::Bool(monochrome_choice)) = &document_node.inputs[monochrome_index].as_value() {
monochrome_choice
} else {
false
let is_monochrome = match document_node.inputs[monochrome_index].as_value() {
Some(TaggedValue::Bool(monochrome_choice)) => *monochrome_choice,
_ => false,
};
// Output channel choice
@ -1277,11 +1278,12 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
output_channel.extend([RadioInput::new(entries).selected_index(Some(choice as u32)).widget_holder()]);
};
let is_output_channel = if let Some(&TaggedValue::RedGreenBlue(choice)) = &document_node.inputs[output_channel_index].as_value() {
choice
} else {
let is_output_channel = match &document_node.inputs[output_channel_index].as_value() {
Some(TaggedValue::RedGreenBlue(choice)) => choice,
_ => {
warn!("Channel Mixer node properties panel could not be displayed.");
return vec![];
}
};
// Channel values
@ -1376,11 +1378,12 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
colors.extend([DropdownInput::new(entries).selected_index(Some(choice as u32)).widget_holder()]);
}
let colors_choice_index = if let Some(&TaggedValue::SelectiveColorChoice(choice)) = &document_node.inputs[colors_index].as_value() {
choice
} else {
let colors_choice_index = match &document_node.inputs[colors_index].as_value() {
Some(TaggedValue::SelectiveColorChoice(choice)) => choice,
_ => {
warn!("Selective Color node properties panel could not be displayed.");
return vec![];
}
};
// CMYK
@ -1409,7 +1412,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::RelativeAbsolute(relative_or_absolute)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::RelativeAbsolute(relative_or_absolute)) = input.as_non_exposed_value() {
let entries = vec![
RadioEntryData::new("relative")
.label("Relative")
@ -1495,7 +1498,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Bool(is_individual)) = &input.as_non_exposed_value() {
if let Some(&TaggedValue::Bool(is_individual)) = input.as_non_exposed_value() {
// Values
let Some(input) = document_node.inputs.get(corner_radius_index) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
@ -2216,7 +2219,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
let mut widgets_first_row = start_widgets(document_node, node_id, fill_index, "Fill", FrontendGraphDataType::General, true);
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), Some(&TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), &Some(&TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
&document_node.inputs[fill_index].as_value(),
&document_node.inputs[backup_color_index].as_value(),
&document_node.inputs[backup_gradient_index].as_value(),

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 graph_craft::document::NodeId;
use graph_craft::document::value::TaggedValue;
use graphene_core::Type;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum FrontendGraphDataType {

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::utility_types::misc::{GridSnapping, GridType};
use crate::messages::prelude::*;
use glam::DVec2;
use graphene_core::raster::color::Color;
use graphene_core::renderer::Quad;
use glam::DVec2;
use graphene_std::vector::style::FillChoice;
fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, spacing: DVec2) {
@ -211,7 +209,7 @@ pub fn grid_overlay(document: &DocumentMessageHandler, overlay_context: &mut Ove
pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
let mut widgets = Vec::new();
fn update_val<I>(grid: &GridSnapping, update: impl Fn(&mut GridSnapping, &I)) -> impl Fn(&I) -> Message {
fn update_val<I, F: Fn(&mut GridSnapping, &I)>(grid: &GridSnapping, update: F) -> impl Fn(&I) -> Message + use<I, F> {
let grid = grid.clone();
move |input: &I| {
let mut grid = grid.clone();
@ -220,7 +218,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
}
}
let update_origin = |grid, update: fn(&mut GridSnapping) -> Option<&mut f64>| {
update_val::<NumberInput>(grid, move |grid, val| {
update_val::<NumberInput, _>(grid, move |grid, val| {
if let Some(val) = val.value {
if let Some(update) = update(grid) {
*update = val;
@ -229,7 +227,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
})
};
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
update_val::<ColorInput>(grid, move |grid, color| {
update_val::<ColorInput, _>(grid, move |grid, color| {
if let FillChoice::Solid(color) = color.value {
if let Some(update_color) = update(grid) {
*update_color = color;
@ -238,7 +236,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
})
};
let update_display = |grid, update: fn(&mut GridSnapping) -> Option<&mut bool>| {
update_val::<CheckboxInput>(grid, move |grid, checkbox| {
update_val::<CheckboxInput, _>(grid, move |grid, checkbox| {
if let Some(update) = update(grid) {
*update = checkbox.checked;
}

View file

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

View file

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

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,
};
use crate::messages::prelude::Message;
use bezier_rs::{Bezier, Subpath};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use core::borrow::Borrow;
use core::f64::consts::{FRAC_PI_2, TAU};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use std::collections::HashMap;
use wasm_bindgen::JsValue;

View file

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

View file

@ -1,5 +1,4 @@
use super::network_interface::NodeTemplate;
use graph_craft::document::NodeId;
#[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::utility_types::ModifyInputsContext;
use super::network_interface::NodeNetworkInterface;
use glam::{DAffine2, DVec2};
use graph_craft::document::NodeId;
use graphene_core::renderer::ClickTarget;
use graphene_core::renderer::Quad;
use graphene_core::transform::Footprint;
use graphene_std::vector::{PointId, VectorData};
use glam::{DAffine2, DVec2};
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;

View file

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

View file

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

View file

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

View file

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

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

View file

@ -1,11 +1,10 @@
use graphene_std::vector::misc::BooleanOperation;
use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType};
use crate::messages::prelude::*;
use graphene_std::vector::misc::BooleanOperation;
pub struct MenuBarMessageData {
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::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::prelude::*;
use graphene_core::Color;
use graphene_core::raster::Image;
use graphene_core::text::Font;
use graphene_core::Color;
#[impl_message(Message, Portfolio)]
#[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::frontend::utility_types::FrontendDocumentDetails;
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::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes;
use crate::messages::portfolio::document::DocumentMessageData;
use crate::messages::preferences::SelectionMode;
use crate::messages::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, ToolType};
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
use bezier_rs::Subpath;
use glam::IVec2;
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::{VectorData, VectorDataTable};
use interpreted_executor::dynamic_executor::IntrospectError;
use std::sync::Arc;
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::preferences::SelectionMode;
use crate::messages::prelude::*;
use graph_craft::wasm_application_io::EditorPreferences;
#[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
pub use crate::messages::globals::global_variables::*;
pub use crate::messages::portfolio::document::utility_types::misc::DocumentId;
pub use graphite_proc_macros::*;
pub use std::collections::{HashMap, HashSet, VecDeque};
pub trait Responses {

View file

@ -1,7 +1,6 @@
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use graphene_core::Color;
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::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::DocumentMessageHandler;
use glam::{DAffine2, DVec2};
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::network_interface::{FlowType, InputConnector, NodeNetworkInterface, NodeTemplate};
use crate::messages::prelude::*;
use bezier_rs::Subpath;
use glam::DVec2;
use graph_craft::concrete;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graphene_core::raster::image::ImageFrameTable;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
use graphene_core::raster::BlendMode;
use graphene_core::raster::image::ImageFrameTable;
use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::style::Gradient;
use graphene_core::Color;
use graphene_std::vector::{ManipulatorPointId, PointId, SegmentId, VectorModificationType};
use glam::DVec2;
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.
@ -385,7 +384,7 @@ impl<'a> NodeGraphLayer<'a> {
}
/// 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)
}

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::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use glam::{DAffine2, DVec2};
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::prelude::*;
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};
#[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::tool::common_functionality::snapping::SnapTypeConfiguration;
use crate::messages::tool::tool_messages::path_tool::PointSelectState;
use bezier_rs::{Bezier, BezierHandles, Subpath, TValue};
use glam::{DAffine2, DVec2};
use graphene_core::transform::Transform;
use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
use glam::{DAffine2, DVec2};
use graphene_std::vector::{HandleId, SegmentId};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -586,7 +584,7 @@ impl ShapeState {
.flat_map(|(data, selection_state)| {
selection_state.selected_points.iter().filter_map(move |&point| {
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))
})
});
@ -1289,13 +1287,16 @@ impl ShapeState {
for point in self.selected_points().filter(|point| point.as_handle().is_some()) {
let anchor = point.get_anchor(&vector_data);
if let Some(handles) = point.get_handle_pair(&vector_data) {
match point.get_handle_pair(&vector_data) {
Some(handles) => {
points_to_select.push((layer, anchor, Some(handles[1].to_manipulator_point())));
} else {
}
_ => {
points_to_select.push((layer, anchor, None));
}
}
}
}
for (layer, anchor, handle) in points_to_select {
if let Some(state) = self.selected_shape_state.get_mut(&layer) {

View file

@ -3,21 +3,23 @@ mod distribution_snapper;
mod grid_snapper;
mod layer_snapper;
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::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::misc::{GridSnapTarget, PathSnapTarget, SnapTarget};
use crate::messages::prelude::*;
pub use alignment_snapper::*;
use bezier_rs::TValue;
pub use distribution_snapper::*;
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_core::vector::PointId;
use graphene_std::renderer::Rect;
use glam::{DAffine2, DVec2};
use graphene_std::vector::NoHashBuilder;
pub use grid_snapper::*;
pub use layer_snapper::*;
pub use snap_results::*;
use std::cmp::Ordering;
/// Configuration for the relevant snap type

View file

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

View file

@ -1,7 +1,5 @@
use super::*;
use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, GridSnapping, GridType, SnapTarget};
use glam::DVec2;
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::misc::*;
use crate::messages::prelude::*;
use bezier_rs::{Bezier, Identifier, Subpath, TValue};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2};
#[derive(Clone, Debug, Default)]
pub struct LayerSnapper {
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::misc::{DistributionSnapTarget, SnapSource, SnapTarget};
use crate::messages::tool::common_functionality::snapping::SnapCandidatePoint;
@ -8,8 +7,7 @@ use glam::DVec2;
use graphene_core::renderer::Quad;
use graphene_core::vector::PointId;
use graphene_std::renderer::Rect;
use super::DistributionMatch;
use std::collections::VecDeque;
#[derive(Clone, Debug, Default)]
pub struct SnapResults {

View file

@ -1,3 +1,4 @@
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
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,
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::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration;
use glam::{DAffine2, DMat2, DVec2};
use graphene_core::renderer::Quad;
use graphene_std::renderer::Rect;
use glam::{DAffine2, DMat2, DVec2};
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
/// (top, bottom, left, right)
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::prelude::*;
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 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.
pub fn should_extend(

View file

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

View file

@ -1,5 +1,5 @@
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::messages::layout::utility_types::widget_prelude::*;
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::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor;
use graphene_core::raster::color::Color;
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::SnapManager;
use crate::messages::tool::common_functionality::transformation_cage::*;
use graph_craft::document::NodeId;
use graphene_core::renderer::Quad;
@ -277,7 +276,7 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::ResizingBounds
}
(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 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::network_interface::FlowType;
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::value::TaggedValue;
use graphene_core::Color;
use graphene_core::raster::BlendMode;
use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle};
use graphene_core::Color;
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::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
#[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::graph_modification_utils;
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 graph_craft::document::NodeId;
use graphene_core::Color;
use graphene_core::vector::VectorModificationType;
use graphene_std::vector::{PointId, SegmentId};
#[derive(Default)]
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::graph_modification_utils::get_gradient;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use graphene_core::vector::style::{Fill, Gradient, GradientType};
#[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::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::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::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer};
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
#[derive(Default)]

View file

@ -23,6 +23,5 @@ pub mod tool_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::{HintData, HintGroup, HintInfo};
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,
};
use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager};
use graphene_core::renderer::Quad;
use graphene_core::vector::{ManipulatorPointId, PointId};
use graphene_std::vector::{NoHashBuilder, SegmentId};
use std::vec;
#[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::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend};
use bezier_rs::{Bezier, BezierHandles};
use graph_craft::document::NodeId;
use graphene_core::vector::{PointId, VectorModificationType};
use graphene_core::Color;
use graphene_core::vector::{PointId, VectorModificationType};
use graphene_std::vector::{HandleId, ManipulatorPointId, NoHashBuilder, SegmentId, VectorData};
#[derive(Default)]
@ -461,6 +460,7 @@ impl PenToolData {
Some(if close_subpath { PenToolFsmState::Ready } else { PenToolFsmState::PlacingAnchor })
}
#[allow(clippy::too_many_arguments)]
/// Calculates snap position delta while moving anchor and its handles.
fn space_anchor_handle_snap(
&mut self,
@ -493,7 +493,7 @@ impl PenToolData {
// Otherwise use either primary or end handle based on is_start flag
if is_start {
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) => {
let handle_offset = transform.transform_point2(primary_handle - self.next_handle_start);
let handle_snap = SnapCandidatePoint::handle(document_pos + handle_offset);
@ -502,7 +502,7 @@ impl PenToolData {
None => None,
}
} 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 {
Some(end_handle) => {
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 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
.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) {
@ -755,12 +755,10 @@ impl PenToolData {
if let Some(handle) = self.handle_end.as_mut() {
*handle = new_position;
return;
} else {
let Some(segment) = self.end_point_segment else { return };
let modification_type = VectorModificationType::SetEndHandle { segment, relative_position };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
return;
}
}
@ -1455,7 +1453,7 @@ impl Fsm for PenToolFsmState {
}
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);
// 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::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
#[derive(Default)]

View file

@ -1,14 +1,16 @@
use super::tool_prelude::*;
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::{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::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize;
use crate::messages::tool::common_functionality::snapping::SnapData;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
#[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::transformation::Selected;
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::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::shape_editor::SelectionShapeType;
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::utility_functions::text_bounding_box;
use crate::messages::tool::common_functionality::{auto_panning::AutoPanning, measure};
use bezier_rs::Subpath;
use glam::DMat2;
use graph_craft::document::NodeId;
use graphene_core::renderer::Quad;
use graphene_std::renderer::Rect;
use graphene_std::vector::misc::BooleanOperation;
use glam::DMat2;
use std::fmt;
#[derive(Default)]
@ -137,7 +136,7 @@ impl SelectTool {
.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]
.into_iter()
.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)| {
IconButton::new("Flip".to_string() + name, 24)
.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°")]
.into_iter()
.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 icons = BooleanOperation::icons();
operations.into_iter().zip(icons).map(move |(operation, icon)| {
@ -1030,7 +1029,7 @@ impl Fsm for SelectToolFsmState {
}
}
(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 {
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::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 {
let free_movement = input.keyboard.key(skew);
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(_)) => {
// AutoPanning
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.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) {
tool_data.layers_dragging.append(&mut vec![document.find_deepest(&selected).unwrap_or(
tool_data.layers_dragging.append(&mut vec![
document.find_deepest(&selected).unwrap_or(
LayerNodeIdentifier::ROOT_PARENT
.children(document.metadata())
.next()
.expect("ROOT_PARENT should have a layer child when clicking"),
)]);
),
]);
responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: tool_data
.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::snapping::{SnapCandidatePoint, SnapData, SnapManager, SnapTypeConfiguration, SnappedPoint};
use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend};
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
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::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::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::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::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::{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::renderer::Quad;
use graphene_core::text::{Font, FontCache, TypesettingConfig, lines_clipping, load_face};
use graphene_core::vector::style::Fill;
#[derive(Default)]
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.
let angle = bounding_box_manager.transform.transform_vector2(DVec2::X).to_angle();
// Update pivot
tool_data.pivot.update_pivot(&document, &mut overlay_context, angle);
tool_data.pivot.update_pivot(document, &mut overlay_context, angle);
} else {
tool_data.bounding_box_manager.take();
}
@ -607,7 +609,7 @@ impl Fsm for TextToolFsmState {
TextToolFsmState::Dragging
}
(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 {
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);
@ -682,7 +684,7 @@ impl Fsm for TextToolFsmState {
(TextToolFsmState::ResizingBounds, TextToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning
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.original_bound_transform.translation += shift;
}

View file

@ -1,7 +1,6 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::prelude::*;
use glam::DVec2;
#[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::tool_messages::tool_prelude::Key;
use crate::messages::tool::utility_types::{ToolData, ToolType};
use glam::{DAffine2, DVec2};
use graphene_core::renderer::Quad;
use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{VectorData, VectorModificationType};
use glam::{DAffine2, DVec2};
use std::f64::consts::TAU;
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::tool_messages::*;
use crate::messages::broadcast::broadcast_event::BroadcastEvent;
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::macros::action_keys;
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::prelude::*;
use crate::node_graph_executor::NodeGraphExecutor;
use graphene_core::raster::color::Color;
use graphene_core::text::FontCache;
use std::borrow::Cow;
use std::fmt::{self, Debug};

View file

@ -1,13 +1,14 @@
use crate::consts::FILE_SAVE_SUFFIX;
use crate::messages::frontend::utility_types::{ExportBounds, FileType};
use crate::messages::prelude::*;
use glam::{DAffine2, DVec2, UVec2};
use graph_craft::concrete;
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::proto::GraphErrors;
use graph_craft::wasm_application_io::EditorPreferences;
use graphene_core::Context;
use graphene_core::application_io::{NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
use graphene_core::memo::IORecord;
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::transform::Footprint;
use graphene_core::vector::style::ViewMode;
use graphene_core::Context;
use graphene_std::renderer::{format_transform_matrix, RenderMetadata};
use graphene_std::renderer::{RenderMetadata, format_transform_matrix};
use graphene_std::vector::{VectorData, VectorDataTable};
use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
use interpreted_executor::util::wrap_network_in_scope;
use glam::{DAffine2, DVec2, UVec2};
use once_cell::sync::Lazy;
use spin::Mutex;
use std::sync::mpsc::{Receiver, Sender};
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`]`.
/// 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::set_uuid_seed;
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::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::node_graph_executor::Instrumented;
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 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
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::document_metadata::LayerNodeIdentifier;
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::node_graph_executor::NodeRuntime;
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() {
// Directory required for compilation, but not tracked by git if empty.

View file

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

View file

@ -5,8 +5,7 @@
// on the dispatcher messaging system and more complex Rust data types.
//
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::consts::FILE_SAVE_SUFFIX;
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 graph_craft::document::NodeId;
use graphene_core::raster::color::Color;
use serde::Serialize;
use serde_wasm_bindgen::{self, from_value};
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::utility_types::*;
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::replace_node_runtime;
use graph_craft::document::DocumentNodeImplementation;
use graph_craft::document::NodeInput;
use graph_craft::document::{value::TaggedValue, DocumentNodeImplementation};
use graph_craft::document::value::TaggedValue;
use graphene_core::vector::*;
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 {
EDITOR.with(|editor| {
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)
})
@ -1000,7 +999,7 @@ pub(crate) fn editor_and_handle(mut callback: impl FnMut(&mut Editor, &mut Edito
EDITOR_HANDLE.with(|editor_handle| {
editor(|editor| {
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");
return;
};

View file

@ -8,10 +8,9 @@ pub mod editor_api;
pub mod helpers;
use editor::messages::prelude::*;
use std::panic;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use wasm_bindgen::prelude::*;
// Set up the persistent editor backend state
@ -72,7 +71,7 @@ pub fn panic_hook(info: &panic::PanicHookInfo) {
EDITOR_HANDLE.with(|editor_handle| {
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() });
}
});

View file

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

View file

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

View file

@ -1,6 +1,5 @@
use crate::utils::{TValue, TValueType};
use super::*;
use crate::utils::{TValue, TValueType};
/// Functionality relating to looking up properties of the `Bezier` or points along the `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 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`.
pub fn get_points(&self) -> impl Iterator<Item = DVec2> {
pub fn get_points(&self) -> impl Iterator<Item = DVec2> + use<> {
match self.handles {
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),

View file

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

View file

@ -1,8 +1,7 @@
use super::*;
use crate::polynomial::Polynomial;
use crate::utils::{solve_cubic, solve_quadratic, TValue};
use crate::{to_symmetrical_basis_pair, SymmetricalBasis};
use crate::utils::{TValue, solve_cubic, solve_quadratic};
use crate::{SymmetricalBasis, to_symmetrical_basis_pair};
use glam::DMat2;
use std::ops::Range;
@ -99,11 +98,7 @@ impl Bezier {
pub fn tangent(&self, t: TValue) -> DVec2 {
let t = self.t_value_to_parametric(t);
let tangent = self.non_normalized_tangent(t);
if tangent.length() > 0. {
tangent.normalize()
} else {
tangent
}
if tangent.length() > 0. { tangent.normalize() } else { tangent }
}
/// 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 denominator = (d.x.powf(2.) + d.y.powf(2.)).powf(1.5);
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE {
0.
} else {
numerator / denominator
}
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE { 0. } else { numerator / denominator }
}
/// 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.
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
match self.handles {
BezierHandles::Linear => {

View file

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

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