Rename graphic subtypes to remove their "data" and "group" suffixes (#2990)

* Rename VectorData to Vector

* Rename other VectorData* types to Vector*

* Move assorted data types out of vector_data.rs into misc.rs

* Rename vector_data.rs to vector_types.rs and remove the vector_types module folder

* Rename other references to "vector data"

* Remove label widgets for raster/vector/group to use "-" instead

* Rename RasterData to Raster

* Rename GraphicGroup to Group

* Fix migrations and rename graphic_element.rs -> graphic.rs

* Rename TaggedValue::ArtboardGroup -> TaggedValue::Artboard
This commit is contained in:
Keavon Chambers
2025-08-04 04:53:25 -07:00
committed by GitHub
parent 853c26cbc1
commit c98477d8ed
72 changed files with 1820 additions and 1901 deletions
@@ -692,7 +692,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
});
if layer_to_move.parent(self.metadata()) != Some(parent) {
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty VectorData table row.
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty vector table row.
// TODO: See #2688 for this issue.
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
@@ -2907,7 +2907,7 @@ impl DocumentMessageHandler {
/// Create a network interface with a single export
fn default_document_network_interface() -> NodeNetworkInterface {
let mut network_interface = NodeNetworkInterface::default();
network_interface.add_export(TaggedValue::ArtboardGroup(Default::default()), -1, "", &[]);
network_interface.add_export(TaggedValue::Artboard(Default::default()), -1, "", &[]);
network_interface
}
@@ -174,7 +174,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index } => {
let mut modify_inputs = ModifyInputsContext::new(network_interface, responses);
let layer = modify_inputs.create_layer(id);
modify_inputs.insert_vector_data(subpaths, layer, true, true, true);
modify_inputs.insert_vector(subpaths, layer, true, true, true);
network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
responses.add(NodeGraphMessage::RunDocumentGraph);
}
@@ -349,7 +349,7 @@ fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node,
let subpaths = convert_usvg_path(path);
let bounds = subpaths.iter().filter_map(|subpath| subpath.bounding_box()).reduce(Quad::combine_bounds).unwrap_or_default();
modify_inputs.insert_vector_data(subpaths, layer, true, path.fill().is_some(), path.stroke().is_some());
modify_inputs.insert_vector(subpaths, layer, true, path.fill().is_some(), path.stroke().is_some());
if let Some(transform_node_id) = modify_inputs.existing_node_id("Transform", true) {
transform_utils::update_transform(modify_inputs.network_interface, &transform_node_id, transform * usvg_transform(node.abs_transform()));
@@ -14,7 +14,7 @@ use graphene_std::raster::BlendMode;
use graphene_std::raster_types::{CPU, Raster};
use graphene_std::table::Table;
use graphene_std::text::{Font, TypesettingConfig};
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
use graphene_std::vector::style::{Fill, Stroke};
use graphene_std::vector::{PointId, VectorModificationType};
use graphene_std::{Graphic, NodeInputDecleration};
@@ -131,8 +131,8 @@ impl<'a> ModifyInputsContext<'a> {
/// Creates an artboard as the primary export for the document network
pub fn create_artboard(&mut self, new_id: NodeId, artboard: Artboard) -> LayerNodeIdentifier {
let artboard_node_template = resolve_document_node_type("Artboard").expect("Node").node_template_input_override([
Some(NodeInput::value(TaggedValue::ArtboardGroup(Default::default()), true)),
Some(NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true)),
Some(NodeInput::value(TaggedValue::Artboard(Default::default()), true)),
Some(NodeInput::value(TaggedValue::Group(Default::default()), true)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.location.into()), false)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.dimensions.into()), false)),
Some(NodeInput::value(TaggedValue::Color(artboard.background), false)),
@@ -144,7 +144,7 @@ impl<'a> ModifyInputsContext<'a> {
pub fn insert_boolean_data(&mut self, operation: graphene_std::path_bool::BooleanOperation, layer: LayerNodeIdentifier) {
let boolean = resolve_document_node_type("Boolean Operation").expect("Boolean node does not exist").node_template_input_override([
Some(NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true)),
Some(NodeInput::value(TaggedValue::Group(Default::default()), true)),
Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),
]);
@@ -153,12 +153,12 @@ impl<'a> ModifyInputsContext<'a> {
self.network_interface.move_node_to_chain_start(&boolean_id, layer, &[]);
}
pub fn insert_vector_data(&mut self, subpaths: Vec<Subpath<PointId>>, layer: LayerNodeIdentifier, include_transform: bool, include_fill: bool, include_stroke: bool) {
let vector_data = Table::new_from_element(VectorData::from_subpaths(subpaths, true));
pub fn insert_vector(&mut self, subpaths: Vec<Subpath<PointId>>, layer: LayerNodeIdentifier, include_transform: bool, include_fill: bool, include_stroke: bool) {
let vector = Table::new_from_element(Vector::from_subpaths(subpaths, true));
let shape = resolve_document_node_type("Path")
.expect("Path node does not exist")
.node_template_input_override([Some(NodeInput::value(TaggedValue::VectorData(vector_data), false))]);
.node_template_input_override([Some(NodeInput::value(TaggedValue::Vector(vector), false))]);
let shape_id = NodeId::new();
self.network_interface.insert_node(shape_id, shape, &[]);
self.network_interface.move_node_to_chain_start(&shape_id, layer, &[]);
@@ -223,7 +223,7 @@ impl<'a> ModifyInputsContext<'a> {
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_node_template();
let image = resolve_document_node_type("Image Value")
.expect("ImageValue node does not exist")
.node_template_input_override([Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::RasterData(image_frame), false))]);
.node_template_input_override([Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::Raster(image_frame), false))]);
let image_id = NodeId::new();
self.network_interface.insert_node(image_id, image, &[]);
@@ -296,11 +296,12 @@ impl<'a> ModifyInputsContext<'a> {
pub fn create_node(&mut self, reference: &str) -> Option<NodeId> {
let output_layer = self.get_output_layer()?;
let Some(node_definition) = resolve_document_node_type(reference) else {
log::error!("Node type {} does not exist in ModifyInputsContext::existing_node_id", reference);
log::error!("Node type {reference} does not exist in ModifyInputsContext::existing_node_id");
return None;
};
// If inserting a path node, insert a Flatten Path if the type is a graphic group.
// TODO: Allow the path node to operate on Graphic Group data by utilizing the reference for each vector data in a group.
// If inserting a path node, insert a Flatten Path if the type is Group.
// TODO: Allow the path node to operate on Group data by utilizing the reference for each Vector in a group.
if node_definition.identifier == "Path" {
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type().clone();
if layer_input_type == concrete!(Table<Graphic>) {
@@ -24,7 +24,7 @@ use graphene_std::table::Table;
use graphene_std::text::{Font, TypesettingConfig};
#[allow(unused_imports)]
use graphene_std::transform::Footprint;
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
use graphene_std::*;
use std::collections::{HashMap, HashSet, VecDeque};
@@ -232,14 +232,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
// Secondary (left) input type coercion
DocumentNode {
inputs: vec![NodeInput::network(generic!(T), 1)],
implementation: DocumentNodeImplementation::ProtoNode(graphic_element::to_element::IDENTIFIER),
implementation: DocumentNodeImplementation::ProtoNode(graphic::to_element::IDENTIFIER),
manual_composition: Some(concrete!(Context)),
..Default::default()
},
// Primary (bottom) input type coercion
DocumentNode {
inputs: vec![NodeInput::network(generic!(T), 0)],
implementation: DocumentNodeImplementation::ProtoNode(graphic_element::to_group::IDENTIFIER),
implementation: DocumentNodeImplementation::ProtoNode(graphic::to_group::IDENTIFIER),
manual_composition: Some(concrete!(Context)),
..Default::default()
},
@@ -258,7 +258,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
NodeInput::node(NodeId(2), 0),
NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath),
],
implementation: DocumentNodeImplementation::ProtoNode(graphic_element::layer::IDENTIFIER),
implementation: DocumentNodeImplementation::ProtoNode(graphic::layer::IDENTIFIER),
..Default::default()
},
]
@@ -269,8 +269,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true),
NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true),
NodeInput::value(TaggedValue::Group(Default::default()), true),
NodeInput::value(TaggedValue::Group(Default::default()), true),
],
..Default::default()
},
@@ -377,8 +377,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::ArtboardGroup(Default::default()), true),
NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true),
NodeInput::value(TaggedValue::Artboard(Default::default()), true),
NodeInput::value(TaggedValue::Group(Default::default()), true),
NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false),
NodeInput::value(TaggedValue::DVec2(DVec2::new(1920., 1080.)), false),
NodeInput::value(TaggedValue::Color(Color::WHITE), false),
@@ -628,7 +628,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::VectorData(Default::default()), true),
NodeInput::value(TaggedValue::Vector(Default::default()), true),
NodeInput::value(
TaggedValue::Footprint(Footprint {
transform: DAffine2::from_scale_angle_translation(DVec2::new(1000., 1000.), 0., DVec2::new(0., 0.)),
@@ -682,7 +682,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
},
},
description: Cow::Borrowed("Rasterizes the given vector data"),
description: Cow::Borrowed("TODO"),
properties: None,
},
DocumentNodeDefinition {
@@ -794,7 +794,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
.collect(),
..Default::default()
}),
inputs: vec![NodeInput::value(TaggedValue::RasterData(Default::default()), true)],
inputs: vec![NodeInput::value(TaggedValue::Raster(Default::default()), true)],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
@@ -879,7 +879,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![NodeInput::value(TaggedValue::RasterData(Default::default()), true)],
inputs: vec![NodeInput::value(TaggedValue::Raster(Default::default()), true)],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
@@ -947,7 +947,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::RasterData(Default::default()), true),
NodeInput::value(TaggedValue::Raster(Default::default()), true),
NodeInput::value(TaggedValue::BrushStrokes(Vec::new()), false),
NodeInput::value(TaggedValue::BrushCache(BrushCache::default()), false),
],
@@ -986,7 +986,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
node_template: NodeTemplate {
document_node: DocumentNode {
implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER),
inputs: vec![NodeInput::value(TaggedValue::RasterData(Default::default()), true)],
inputs: vec![NodeInput::value(TaggedValue::Raster(Default::default()), true)],
manual_composition: Some(concrete!(Context)),
..Default::default()
},
@@ -1005,7 +1005,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
node_template: NodeTemplate {
document_node: DocumentNode {
implementation: DocumentNodeImplementation::ProtoNode(memo::impure_memo::IDENTIFIER),
inputs: vec![NodeInput::value(TaggedValue::RasterData(Default::default()), true)],
inputs: vec![NodeInput::value(TaggedValue::Raster(Default::default()), true)],
manual_composition: Some(concrete!(Context)),
..Default::default()
},
@@ -1117,7 +1117,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
.collect(),
..Default::default()
}),
inputs: vec![NodeInput::value(TaggedValue::RasterData(Default::default()), true)],
inputs: vec![NodeInput::value(TaggedValue::Raster(Default::default()), true)],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
@@ -1196,7 +1196,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
// document_node: DocumentNode {
// implementation: DocumentNodeImplementation::proto("graphene_core::raster::CurvesNode"),
// inputs: vec![
// NodeInput::value(TaggedValue::RasterData(Default::default()), true),
// NodeInput::value(TaggedValue::Raster(Default::default()), true),
// NodeInput::value(TaggedValue::Curve(Default::default()), false),
// ],
// ..Default::default()
@@ -1219,7 +1219,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
exports: vec![NodeInput::node(NodeId(1), 0)],
nodes: vec![
DocumentNode {
inputs: vec![NodeInput::network(concrete!(Table<VectorData>), 0)],
inputs: vec![NodeInput::network(concrete!(Table<Vector>), 0)],
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
manual_composition: Some(generic!(T)),
skip_deduplication: true,
@@ -1243,14 +1243,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::VectorData(Default::default()), true),
NodeInput::value(TaggedValue::Vector(Default::default()), true),
NodeInput::value(TaggedValue::VectorModification(Default::default()), false),
],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
input_metadata: vec![("Vector Data", "TODO").into(), ("Modification", "TODO").into()],
output_names: vec!["Vector Data".to_string()],
input_metadata: vec![("Content", "TODO").into(), ("Modification", "TODO").into()],
output_names: vec!["Modified".to_string()],
network_metadata: Some(NodeNetworkMetadata {
persistent_metadata: NodeNetworkPersistentMetadata {
node_metadata: [
@@ -1374,7 +1374,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}),
),
InputMetadata::with_name_description_override("Align", "TODO", WidgetOverride::Custom("text_align".to_string())),
("Per-Glyph Instances", "Splits each text glyph into its own row in the table of vector data.").into(),
("Per-Glyph Instances", "Splits each text glyph into its own row in the table of vector geometry.").into(),
],
output_names: vec!["Vector".to_string()],
..Default::default()
@@ -1496,7 +1496,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
exports: vec![NodeInput::node(NodeId(3), 0)],
nodes: vec![
DocumentNode {
inputs: vec![NodeInput::network(concrete!(Table<VectorData>), 0), NodeInput::network(concrete!(vector::style::Fill), 1)],
inputs: vec![NodeInput::network(concrete!(Table<Vector>), 0), NodeInput::network(concrete!(vector::style::Fill), 1)],
implementation: DocumentNodeImplementation::ProtoNode(path_bool::boolean_operation::IDENTIFIER),
manual_composition: Some(generic!(T)),
..Default::default()
@@ -1527,7 +1527,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true),
NodeInput::value(TaggedValue::Group(Default::default()), true),
NodeInput::value(TaggedValue::BooleanOperation(path_bool::BooleanOperation::Union), false),
],
..Default::default()
@@ -1594,14 +1594,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
exports: vec![NodeInput::node(NodeId(4), 0)],
nodes: [
DocumentNode {
inputs: vec![NodeInput::network(concrete!(Table<VectorData>), 0)],
inputs: vec![NodeInput::network(concrete!(Table<Vector>), 0)],
implementation: DocumentNodeImplementation::ProtoNode(vector::subpath_segment_lengths::IDENTIFIER),
manual_composition: Some(generic!(T)),
..Default::default()
},
DocumentNode {
inputs: vec![
NodeInput::network(concrete!(Table<VectorData>), 0),
NodeInput::network(concrete!(Table<Vector>), 0),
NodeInput::network(concrete!(vector::misc::PointSpacingType), 1),
NodeInput::network(concrete!(f64), 2),
NodeInput::network(concrete!(u32), 3),
@@ -1640,7 +1640,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::VectorData(Default::default()), true),
NodeInput::value(TaggedValue::Vector(Default::default()), true),
NodeInput::value(TaggedValue::PointSpacingType(Default::default()), false),
NodeInput::value(TaggedValue::F64(100.), false),
NodeInput::value(TaggedValue::U32(100), false),
@@ -1704,7 +1704,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
input_metadata: vec![
("Vector Data", "The shape to be resampled and converted into a polyline.").into(),
("Content", "The shape to be resampled and converted into a polyline.").into(),
("Spacing", node_properties::SAMPLE_POLYLINE_TOOLTIP_SPACING).into(),
InputMetadata::with_name_description_override(
"Separation",
@@ -1761,7 +1761,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
nodes: [
DocumentNode {
inputs: vec![
NodeInput::network(concrete!(Table<VectorData>), 0),
NodeInput::network(concrete!(Table<Vector>), 0),
NodeInput::network(concrete!(f64), 1),
NodeInput::network(concrete!(u32), 2),
],
@@ -1795,7 +1795,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::VectorData(Default::default()), true),
NodeInput::value(TaggedValue::Vector(Default::default()), true),
NodeInput::value(TaggedValue::F64(10.), false),
NodeInput::value(TaggedValue::U32(0), false),
],
@@ -1847,7 +1847,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
}),
input_metadata: vec![
("Vector Data", "TODO").into(),
("Content", "TODO").into(),
InputMetadata::with_name_description_override(
"Separation Disk Diameter",
"TODO",
@@ -11,6 +11,7 @@ use glam::{DAffine2, DVec2};
use graph_craft::Type;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graphene_std::NodeInputDecleration;
use graphene_std::animation::RealTimeMode;
use graphene_std::extract_xy::XY;
use graphene_std::path_bool::BooleanOperation;
@@ -19,14 +20,10 @@ use graphene_std::raster::{
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
SelectiveColorChoice,
};
use graphene_std::raster_types::{CPU, GPU, Raster};
use graphene_std::table::Table;
use graphene_std::text::{Font, TextAlign};
use graphene_std::transform::{Footprint, ReferencePoint, Transform};
use graphene_std::vector::VectorData;
use graphene_std::vector::misc::{ArcType, CentroidType, GridType, MergeByDistanceAlgorithm, PointSpacingType};
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
use graphene_std::{Graphic, NodeInputDecleration};
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
let widget = TextLabel::new(text).widget_holder();
@@ -180,12 +177,6 @@ pub(crate) fn property_from_type(
// ==========================
Some(x) if x == TypeId::of::<Vec<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
Some(x) if x == TypeId::of::<Vec<DVec2>>() => array_of_vec2_widget(default_info, TextInput::default()).into(),
// ====================
// GRAPHICAL DATA TYPES
// ====================
Some(x) if x == TypeId::of::<Table<VectorData>>() => vector_data_widget(default_info).into(),
Some(x) if x == TypeId::of::<Table<Raster<CPU>>>() || x == TypeId::of::<Table<Raster<GPU>>>() => raster_widget(default_info).into(),
Some(x) if x == TypeId::of::<Table<Graphic>>() => group_widget(default_info).into(),
// ============
// STRUCT TYPES
// ============
@@ -794,33 +785,6 @@ pub fn font_inputs(parameter_widgets_info: ParameterWidgetsInfo) -> (Vec<WidgetH
(first_widgets, second_widgets)
}
pub fn vector_data_widget(parameter_widgets_info: ParameterWidgetsInfo) -> Vec<WidgetHolder> {
let mut widgets = start_widgets(parameter_widgets_info);
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(TextLabel::new("Vector data is supplied through the node graph").widget_holder());
widgets
}
pub fn raster_widget(parameter_widgets_info: ParameterWidgetsInfo) -> Vec<WidgetHolder> {
let mut widgets = start_widgets(parameter_widgets_info);
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(TextLabel::new("Raster data is supplied through the node graph").widget_holder());
widgets
}
pub fn group_widget(parameter_widgets_info: ParameterWidgetsInfo) -> Vec<WidgetHolder> {
let mut widgets = start_widgets(parameter_widgets_info);
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(TextLabel::new("Group data is supplied through the node graph").widget_holder());
widgets
}
pub fn number_widget(parameter_widgets_info: ParameterWidgetsInfo, number_props: NumberInput) -> Vec<WidgetHolder> {
let ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info;
@@ -1880,7 +1844,7 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
let mut expression = x.value.trim().to_string();
if ["+", "-", "*", "/", "^", "%"].iter().any(|&infix| infix == expression) {
expression = format!("A {} B", expression);
expression = format!("A {expression} B");
} else if expression == "^" {
expression = String::from("A^B");
}
@@ -2078,7 +2042,7 @@ pub mod choice {
pub fn property_row(self) -> LayoutGroup {
let ParameterWidgetsInfo { document_node, node_id, index, .. } = self.parameter_info;
let Some(document_node) = document_node else {
log::error!("Could not get document node when building property row for node {:?}", node_id);
log::error!("Could not get document node when building property row for node {node_id:?}");
return LayoutGroup::Row { widgets: Vec::new() };
};
@@ -9,7 +9,7 @@ pub enum FrontendGraphDataType {
#[default]
General,
Raster,
VectorData,
Vector,
Number,
Group,
Artboard,
@@ -18,8 +18,8 @@ pub enum FrontendGraphDataType {
impl FrontendGraphDataType {
pub fn from_type(input: &Type) -> Self {
match TaggedValue::from_type_or_none(input) {
TaggedValue::RasterData(_) => Self::Raster,
TaggedValue::VectorData(_) => Self::VectorData,
TaggedValue::Raster(_) => Self::Raster,
TaggedValue::Vector(_) => Self::Vector,
TaggedValue::U32(_)
| TaggedValue::U64(_)
| TaggedValue::F64(_)
@@ -28,8 +28,8 @@ impl FrontendGraphDataType {
| TaggedValue::VecF64(_)
| TaggedValue::VecDVec2(_)
| TaggedValue::DAffine2(_) => Self::Number,
TaggedValue::GraphicGroup(_) => Self::Group,
TaggedValue::ArtboardGroup(_) => Self::Artboard,
TaggedValue::Group(_) => Self::Group,
TaggedValue::Artboard(_) => Self::Artboard,
_ => Self::General,
}
}
@@ -5,7 +5,7 @@ use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerSta
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler};
use bezier_rs::{Bezier, BezierHandles};
use glam::{DAffine2, DVec2};
use graphene_std::vector::ManipulatorPointId;
use graphene_std::vector::misc::ManipulatorPointId;
use graphene_std::vector::{PointId, SegmentId};
use wasm_bindgen::JsCast;
@@ -42,9 +42,9 @@ pub fn selected_segments(network_interface: &NodeNetworkInterface, shape_editor:
// TODO: Currently if there are two duplicate layers, both of their segments get overlays
// Adding segments which are are connected to selected anchors
for layer in network_interface.selected_nodes().selected_layers(network_interface.document_metadata()) {
let Some(vector_data) = network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = network_interface.compute_modified_vector(layer) else { continue };
for (segment_id, _bezier, start, end) in vector_data.segment_bezier_iter() {
for (segment_id, _bezier, start, end) in vector.segment_bezier_iter() {
if selected_anchors.contains(&start) || selected_anchors.contains(&end) {
selected_segments.push(segment_id);
}
@@ -118,14 +118,14 @@ pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandle
let display_anchors = overlay_context.visibility_settings.anchors();
for layer in document.network_interface.selected_nodes().selected_layers(document.metadata()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
let transform = document.metadata().transform_to_viewport_if_feeds(layer, &document.network_interface);
if display_path {
overlay_context.outline_vector(&vector_data, transform);
overlay_context.outline_vector(&vector, transform);
}
// Get the selected segments and then add a bold line overlay on them
for (segment_id, bezier, _, _) in vector_data.segment_bezier_iter() {
for (segment_id, bezier, _, _) in vector.segment_bezier_iter() {
let Some(selected_shape_state) = shape_editor.selected_shape_state.get_mut(&layer) else {
continue;
};
@@ -139,30 +139,30 @@ pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandle
let is_selected = |point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_point_selected(point));
if display_handles {
let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector_data.adjacent_segment(point_id)).collect();
let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector.adjacent_segment(point_id)).collect();
match draw_handles {
DrawHandles::All => {
vector_data.segment_bezier_iter().for_each(|(segment_id, bezier, _start, _end)| {
vector.segment_bezier_iter().for_each(|(segment_id, bezier, _start, _end)| {
overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context);
});
}
DrawHandles::SelectedAnchors(ref selected_segments) => {
vector_data
vector
.segment_bezier_iter()
.filter(|(segment_id, ..)| selected_segments.contains(segment_id))
.for_each(|(segment_id, bezier, _start, _end)| {
overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context);
});
for (segment_id, bezier, start, end) in vector_data.segment_bezier_iter() {
for (segment_id, bezier, start, end) in vector.segment_bezier_iter() {
if let Some((corresponding_anchor, _)) = opposite_handles_data.iter().find(|(_, adj_segment_id)| adj_segment_id == &segment_id) {
overlay_bezier_handle_specific_point(bezier, segment_id, (start, end), *corresponding_anchor, transform, is_selected, overlay_context);
}
}
}
DrawHandles::FrontierHandles(ref segment_endpoints) => {
vector_data
vector
.segment_bezier_iter()
.filter(|(segment_id, ..)| segment_endpoints.contains_key(segment_id))
.for_each(|(segment_id, bezier, start, end)| {
@@ -179,7 +179,7 @@ pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandle
}
if display_anchors {
for (&id, &position) in vector_data.point_domain.ids().iter().zip(vector_data.point_domain.positions()) {
for (&id, &position) in vector.point_domain.ids().iter().zip(vector.point_domain.positions()) {
overlay_context.manipulator_anchor(transform.transform_point2(position), is_selected(ManipulatorPointId::Anchor(id)), None);
}
}
@@ -192,7 +192,7 @@ pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &
}
for layer in document.network_interface.selected_nodes().selected_layers(document.metadata()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
let Some(vector) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
//let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
@@ -200,8 +200,8 @@ pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &
let selected = shape_editor.selected_shape_state.get(&layer);
let is_selected = |selected: Option<&SelectedLayerState>, point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_point_selected(point));
for point in vector_data.extendable_points(preferences.vector_meshes) {
let Some(position) = vector_data.point_domain.position_from_id(point) else { continue };
for point in vector.extendable_points(preferences.vector_meshes) {
let Some(position) = vector.point_domain.position_from_id(point) else { continue };
let position = transform.transform_point2(position);
overlay_context.manipulator_anchor(position, is_selected(selected, ManipulatorPointId::Anchor(point)), None);
}
@@ -12,7 +12,7 @@ use glam::{DAffine2, DVec2};
use graphene_std::Color;
use graphene_std::math::quad::Quad;
use graphene_std::vector::click_target::ClickTargetType;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use graphene_std::vector::{PointId, SegmentId, Vector};
use std::collections::HashMap;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{OffscreenCanvas, OffscreenCanvasRenderingContext2d};
@@ -757,12 +757,12 @@ impl OverlayContext {
}
/// Used by the Pen and Path tools to outline the path of the shape.
pub fn outline_vector(&mut self, vector_data: &VectorData, transform: DAffine2) {
pub fn outline_vector(&mut self, vector: &Vector, transform: DAffine2) {
self.start_dpi_aware_transform();
self.render_context.begin_path();
let mut last_point = None;
for (_, bezier, start_id, end_id) in vector_data.segment_bezier_iter() {
for (_, bezier, start_id, end_id) in vector.segment_bezier_iter() {
let move_to = last_point != Some(start_id);
last_point = Some(end_id);
@@ -11,7 +11,7 @@ use glam::{DAffine2, DVec2};
use graphene_std::Color;
use graphene_std::math::quad::Quad;
use graphene_std::vector::click_target::ClickTargetType;
use graphene_std::vector::{PointId, SegmentId, VectorData};
use graphene_std::vector::{PointId, SegmentId, Vector};
use std::collections::HashMap;
use std::sync::{Arc, Mutex, MutexGuard};
use vello::Scene;
@@ -338,8 +338,8 @@ impl OverlayContext {
}
/// Used by the Pen and Path tools to outline the path of the shape.
pub fn outline_vector(&mut self, vector_data: &VectorData, transform: DAffine2) {
self.internal().outline_vector(vector_data, transform);
pub fn outline_vector(&mut self, vector: &Vector, transform: DAffine2) {
self.internal().outline_vector(vector, transform);
}
/// Used by the Pen tool in order to show how the bezier curve would look like.
@@ -834,12 +834,12 @@ impl OverlayContextInternal {
}
/// Used by the Pen and Path tools to outline the path of the shape.
fn outline_vector(&mut self, vector_data: &VectorData, transform: DAffine2) {
fn outline_vector(&mut self, vector: &Vector, transform: DAffine2) {
let vello_transform = self.get_transform();
let mut path = BezPath::new();
let mut last_point = None;
for (_, bezier, start_id, end_id) in vector_data.segment_bezier_iter() {
for (_, bezier, start_id, end_id) in vector.segment_bezier_iter() {
let move_to = last_point != Some(start_id);
last_point = Some(end_id);
@@ -8,7 +8,7 @@ use graph_craft::document::NodeId;
use graphene_std::math::quad::Quad;
use graphene_std::transform::Footprint;
use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
use graphene_std::vector::{PointId, VectorData};
use graphene_std::vector::{PointId, Vector};
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;
@@ -26,7 +26,7 @@ pub struct DocumentMetadata {
pub structure: HashMap<LayerNodeIdentifier, NodeRelations>,
pub click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
pub clip_targets: HashSet<NodeId>,
pub vector_modify: HashMap<NodeId, VectorData>,
pub vector_modify: HashMap<NodeId, Vector>,
/// Transform from document space to viewport space.
pub document_to_viewport: DAffine2,
}
@@ -18,7 +18,7 @@ use graphene_std::math::quad::Quad;
use graphene_std::table::Table;
use graphene_std::transform::Footprint;
use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
use graphene_std::vector::{PointId, VectorData, VectorModificationType};
use graphene_std::vector::{PointId, Vector, VectorModificationType};
use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypes;
use interpreted_executor::node_registry::NODE_REGISTRY;
use serde_json::{Value, json};
@@ -675,7 +675,7 @@ impl NodeNetworkInterface {
let valid_implementation = (0..number_of_inputs).filter(|iterator_index| iterator_index != input_index).all(|iterator_index| {
let input_type = self.input_type(&InputConnector::node(*node_id, iterator_index), network_path).0;
// Value inputs are stored as concrete, so they are compared to the nested type. Node inputs are stored as fn, so they are compared to the entire type.
// For example a node input of (Footprint) -> VectorData would not be compatible with () -> VectorData
// For example a node input of (Footprint) -> Vector would not be compatible with () -> Vector
node_io.inputs.get(iterator_index).map(|ty| ty.nested_type().clone()).as_ref() == Some(&input_type) || node_io.inputs.get(iterator_index) == Some(&input_type)
});
if valid_implementation { node_io.inputs.get(*input_index).cloned() } else { None }
@@ -3444,12 +3444,12 @@ impl NodeNetworkInterface {
(layer_widths, chain_widths, has_left_input_wire)
}
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<VectorData> {
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
if let Some(path_node) = graph_layer.upstream_visible_node_id_from_name_in_layer("Path") {
if let Some(vector_data) = self.document_metadata.vector_modify.get(&path_node) {
let mut modified = vector_data.clone();
if let Some(vector) = self.document_metadata.vector_modify.get(&path_node) {
let mut modified = vector.clone();
let path_node = self.document_network().nodes.get(&path_node);
let modification_input = path_node.and_then(|node: &DocumentNode| node.inputs.get(1)).and_then(|input| input.as_value());
@@ -3464,7 +3464,7 @@ impl NodeNetworkInterface {
.click_targets
.get(&layer)
.map(|click| click.iter().map(ClickTarget::target_type))
.map(|target_types| VectorData::from_target_types(target_types, true))
.map(|target_types| Vector::from_target_types(target_types, true))
}
/// Loads the structure of layer nodes from a node graph.
@@ -3575,7 +3575,7 @@ impl NodeNetworkInterface {
}
/// Update the vector modify of the layers
pub fn update_vector_modify(&mut self, new_vector_modify: HashMap<NodeId, VectorData>) {
pub fn update_vector_modify(&mut self, new_vector_modify: HashMap<NodeId, Vector>) {
self.document_metadata.vector_modify = new_vector_modify;
}
}
@@ -6613,22 +6613,26 @@ fn migrate_output_names<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
const REPLACEMENTS: &[(&str, &str)] = &[
// Single to table data
("VectorData", "Table<VectorData>"),
("GraphicGroup", "Table<GraphicGroup>"),
("VectorData", "Table<Vector>"),
("GraphicGroup", "Table<Group>"),
("ImageFrame", "Table<Image>"),
// `ImageFrame` to `Image` rename
("Instances<ImageFrame>", "Table<Image>"),
// `Instances` to `Table` rename
("Instances<VectorData>", "Table<VectorData>"),
("Instances<GraphicGroup>", "Table<GraphicGroup>"),
("Instances<VectorData>", "Table<Vector>"),
("Instances<GraphicGroup>", "Table<Group>"),
("Instances<Image>", "Table<Image>"),
("Instances<GraphicElement>", "Table<Graphic>"),
("Table<GraphicElement>", "Table<Graphic>"),
("Future<Instances<VectorData>>", "Future<Table<VectorData>>"),
("Future<Instances<GraphicGroup>>", "Future<Table<GraphicGroup>>"),
("Future<Instances<Vector>>", "Future<Table<Vector>>"),
("Future<Instances<GraphicGroup>>", "Future<Table<Group>>"),
("Future<Instances<Image>>", "Future<Table<Image>>"),
("Future<Instances<GraphicElement>>", "Future<Table<Graphic>>"),
("Future<Table<GraphicElement>>", "Future<Table<Graphic>>"),
("Future<Table<VectorData>>", "Future<Table<Vector>>"),
("Table<VectorData>", "Table<Vector>"),
("Table<GraphicGroup>", "Table<Group>"),
("Future<Table<GraphicGroup>>", "Future<Table<Group>>"),
];
let mut names = Vec::<String>::deserialize(deserializer)?;
@@ -8,7 +8,8 @@ use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::utility_types::ToolType;
use glam::{DAffine2, DMat2, DVec2};
use graphene_std::renderer::Quad;
use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, VectorModificationType};
use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
use graphene_std::vector::{HandleExt, PointId, VectorModificationType};
use std::collections::{HashMap, VecDeque};
use std::f64::consts::PI;
@@ -79,7 +80,7 @@ impl OriginalTransforms {
if path_map.contains_key(&layer) {
continue;
}
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
let Some(vector) = network_interface.compute_modified_vector(layer) else {
continue;
};
let Some(selected_points) = shape_editor.selected_points_in_layer(layer) else {
@@ -91,7 +92,7 @@ impl OriginalTransforms {
let mut selected_points = selected_points.clone();
for (segment_id, _, start, end) in vector_data.segment_bezier_iter() {
for (segment_id, _, start, end) in vector.segment_bezier_iter() {
if selected_segments.contains(&segment_id) {
selected_points.insert(ManipulatorPointId::Anchor(start));
selected_points.insert(ManipulatorPointId::Anchor(end));
@@ -100,23 +101,23 @@ impl OriginalTransforms {
// Anchors also move their handles
let anchor_ids = selected_points.iter().filter_map(|point| point.as_anchor());
let anchors = anchor_ids.filter_map(|id| vector_data.point_domain.position_from_id(id).map(|pos| (id, AnchorPoint { initial: pos, current: pos })));
let anchors = anchor_ids.filter_map(|id| vector.point_domain.position_from_id(id).map(|pos| (id, AnchorPoint { initial: pos, current: pos })));
let anchors = anchors.collect();
let selected_handles = selected_points.iter().filter_map(|point| point.as_handle());
let anchor_ids = selected_points.iter().filter_map(|point| point.as_anchor());
let connected_handles = anchor_ids.flat_map(|point| vector_data.all_connected(point));
let connected_handles = anchor_ids.flat_map(|point| vector.all_connected(point));
let all_handles = selected_handles.chain(connected_handles);
let handles = all_handles
.filter_map(|id| {
let anchor = id.to_manipulator_point().get_anchor(&vector_data)?;
let initial = id.to_manipulator_point().get_position(&vector_data)?;
let relative = vector_data.point_domain.position_from_id(anchor)?;
let other_handle = vector_data
let anchor = id.to_manipulator_point().get_anchor(&vector)?;
let initial = id.to_manipulator_point().get_position(&vector)?;
let relative = vector.point_domain.position_from_id(anchor)?;
let other_handle = vector
.other_colinear_handle(id)
.filter(|other| !selected_points.contains(&other.to_manipulator_point()) && !selected_points.contains(&ManipulatorPointId::Anchor(anchor)));
let mirror = other_handle.and_then(|id| Some((id, id.to_manipulator_point().get_position(&vector_data)?)));
let mirror = other_handle.and_then(|id| Some((id, id.to_manipulator_point().get_position(&vector)?)));
Some((id, HandlePoint { initial, relative, anchor, mirror }))
})
@@ -13,7 +13,7 @@ use graphene_std::ProtoNodeIdentifier;
use graphene_std::table::Table;
use graphene_std::text::{TextAlign, TypesettingConfig};
use graphene_std::uuid::NodeId;
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
use graphene_std::vector::style::{PaintOrder, StrokeAlign};
use std::collections::HashMap;
@@ -38,12 +38,28 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
aliases: &["graphene_core::ConstructArtboardNode", "graphene_core::graphic_element::ToArtboardNode"],
},
NodeReplacement {
node: graphene_std::graphic_element::to_element::IDENTIFIER,
node: graphene_std::graphic::to_element::IDENTIFIER,
aliases: &["graphene_core::ToGraphicElementNode", "graphene_core::graphic_element::ToElementNode"],
},
NodeReplacement {
node: graphene_std::graphic_element::to_group::IDENTIFIER,
aliases: &["graphene_core::ToGraphicGroupNode"],
node: graphene_std::graphic::to_group::IDENTIFIER,
aliases: &["graphene_core::ToGraphicGroupNode", "graphene_core::graphic_element::ToGroupNode"],
},
NodeReplacement {
node: graphene_std::graphic::layer::IDENTIFIER,
aliases: &["graphene_core::graphic_element::LayerNode"],
},
NodeReplacement {
node: graphene_std::graphic::flatten_group::IDENTIFIER,
aliases: &["graphene_core::graphic_element::FlattenGroupNode"],
},
NodeReplacement {
node: graphene_std::graphic::flatten_vector::IDENTIFIER,
aliases: &["graphene_core::graphic_element::FlattenVectorNode"],
},
NodeReplacement {
node: graphene_std::graphic::index::IDENTIFIER,
aliases: &["graphene_core::graphic_element::IndexNode"],
},
// math_nodes
NodeReplacement {
@@ -456,6 +472,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
node: graphene_std::path_bool::boolean_operation::IDENTIFIER,
aliases: &["graphene_std::vector::BooleanOperationNode"],
},
NodeReplacement {
node: graphene_std::vector::path_modify::IDENTIFIER,
aliases: &["graphene_core::vector::vector_data::modification::PathModifyNode"],
},
// brush
NodeReplacement {
node: graphene_std::brush::brush::brush_stamp_generator::IDENTIFIER,
@@ -591,13 +611,13 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
return None;
}
// Obtain the document node for the given node ID, extract the vector points, and create vector data from the list of points
// Obtain the document node for the given node ID, extract the vector points, and create a Vector path from the list of points
let node = document.network_interface.document_node(node_id, network_path)?;
let Some(TaggedValue::VecDVec2(points)) = node.inputs.get(1).and_then(|tagged_value| tagged_value.as_value()) else {
log::error!("The old Spline node's input at index 1 is not a TaggedValue::VecDVec2");
return None;
};
let vector_data = VectorData::from_subpath(Subpath::from_anchors_linear(points.to_vec(), false));
let vector = Vector::from_subpath(Subpath::from_anchors_linear(points.to_vec(), false));
// Retrieve the output connectors linked to the "Spline" node's output port
let Some(spline_outputs) = document.network_interface.outward_wires(network_path)?.get(&OutputConnector::node(*node_id, 0)).cloned() else {
@@ -611,13 +631,13 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
return None;
};
// Get the "Path" node definition and fill it in with the vector data and default vector modification
// Get the "Path" node definition and fill it in with the Vector path and default vector modification
let Some(path_node_type) = resolve_document_node_type("Path") else {
log::error!("Path node does not exist.");
return None;
};
let path_node = path_node_type.node_template_input_override([
Some(NodeInput::value(TaggedValue::VectorData(Table::new_from_element(vector_data)), true)),
Some(NodeInput::value(TaggedValue::Vector(Table::new_from_element(vector)), true)),
Some(NodeInput::value(TaggedValue::VectorModification(Default::default()), false)),
]);
@@ -29,7 +29,8 @@ use graph_craft::document::NodeId;
use graphene_std::Color;
use graphene_std::renderer::Quad;
use graphene_std::text::Font;
use graphene_std::vector::{HandleId, PointId, SegmentId, VectorData, VectorModificationType};
use graphene_std::vector::misc::HandleId;
use graphene_std::vector::{PointId, SegmentId, Vector, VectorModificationType};
use std::vec;
#[derive(ExtractField)]
@@ -567,7 +568,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
// If not using Path tool, create new layers and add paths into those
if let Some(document) = self.active_document() {
let Ok(data) = serde_json::from_str::<Vec<(LayerNodeIdentifier, VectorData, DAffine2)>>(&data) else {
let Ok(data) = serde_json::from_str::<Vec<(LayerNodeIdentifier, Vector, DAffine2)>>(&data) else {
return;
};
@@ -603,7 +604,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
let stroke = graphene_std::vector::style::Stroke::new(Some(stroke_color.to_gamma_srgb()), DEFAULT_STROKE_WIDTH);
responses.add(GraphOperationMessage::StrokeSet { layer, stroke });
// Create new point ids and add those into the existing vector data
// Create new point ids and add those into the existing Vector path
let mut points_map = HashMap::new();
for (point, position) in new_vector.point_domain.iter() {
let new_point_id = PointId::generate();
@@ -612,7 +613,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
// Create new segment ids and add the segments into the existing vector data
// Create new segment ids and add the segments into the existing Vector path
let mut segments_map = HashMap::new();
for (segment_id, bezier, start, end) in new_vector.segment_bezier_iter() {
let new_segment_id = SegmentId::generate();
@@ -19,13 +19,13 @@ pub enum SpreadsheetMessage {
len: usize,
},
ViewVectorDataDomain {
domain: VectorDataDomain,
ViewVectorDomain {
domain: VectorDomain,
},
}
#[derive(PartialEq, Eq, Clone, Copy, Default, Debug, serde::Serialize, serde::Deserialize)]
pub enum VectorDataDomain {
pub enum VectorDomain {
#[default]
Points,
Segments,
@@ -1,4 +1,4 @@
use super::VectorDataDomain;
use super::VectorDomain;
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, LayoutTarget, WidgetLayout};
use crate::messages::prelude::*;
use crate::messages::tool::tool_messages::tool_prelude::*;
@@ -8,7 +8,7 @@ use graphene_std::Context;
use graphene_std::memo::IORecord;
use graphene_std::raster::Image;
use graphene_std::table::Table;
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
use graphene_std::{Artboard, Graphic};
use std::any::Any;
use std::sync::Arc;
@@ -21,7 +21,7 @@ pub struct SpreadsheetMessageHandler {
inspect_node: Option<NodeId>,
introspected_data: Option<Arc<dyn Any + Send + Sync>>,
element_path: Vec<usize>,
viewing_vector_data_domain: VectorDataDomain,
viewing_vector_domain: VectorDomain,
}
#[message_handler_data]
@@ -54,8 +54,8 @@ impl MessageHandler<SpreadsheetMessage, ()> for SpreadsheetMessageHandler {
self.update_layout(responses);
}
SpreadsheetMessage::ViewVectorDataDomain { domain } => {
self.viewing_vector_data_domain = domain;
SpreadsheetMessage::ViewVectorDomain { domain } => {
self.viewing_vector_domain = domain;
self.update_layout(responses);
}
}
@@ -79,7 +79,7 @@ impl SpreadsheetMessageHandler {
current_depth: 0,
desired_path: &mut self.element_path,
breadcrumbs: Vec::new(),
vector_data_domain: self.viewing_vector_data_domain,
vector_domain: self.viewing_vector_domain,
};
let mut layout = self
.introspected_data
@@ -106,7 +106,7 @@ struct LayoutData<'a> {
current_depth: usize,
desired_path: &'a mut Vec<usize>,
breadcrumbs: Vec<String>,
vector_data_domain: VectorDataDomain,
vector_domain: VectorDomain,
}
fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'static>, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
@@ -116,9 +116,9 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<Artboard>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<VectorData>>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Vector>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<VectorData>>>() {
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<(), Table<Vector>>>() {
Some(io.output.layout_with_breadcrumb(data))
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Graphic>>>() {
Some(io.output.layout_with_breadcrumb(data))
@@ -154,10 +154,10 @@ impl TableRowLayout for Graphic {
}
fn identifier(&self) -> String {
match self {
Self::GraphicGroup(table) => table.identifier(),
Self::VectorData(table) => table.identifier(),
Self::RasterDataCPU(_) => "RasterDataCPU".to_string(),
Self::RasterDataGPU(_) => "RasterDataGPU".to_string(),
Self::Group(group) => group.identifier(),
Self::Vector(vector) => vector.identifier(),
Self::RasterCPU(_) => "Raster (on CPU)".to_string(),
Self::RasterGPU(_) => "Raster (on GPU)".to_string(),
}
}
// Don't put a breadcrumb for Graphic
@@ -166,48 +166,48 @@ impl TableRowLayout for Graphic {
}
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
match self {
Self::GraphicGroup(table) => table.layout_with_breadcrumb(data),
Self::VectorData(table) => table.layout_with_breadcrumb(data),
Self::RasterDataCPU(_) => label("Raster is not supported"),
Self::RasterDataGPU(_) => label("Raster is not supported"),
Self::Group(table) => table.layout_with_breadcrumb(data),
Self::Vector(table) => table.layout_with_breadcrumb(data),
Self::RasterCPU(_) => label("Raster is not supported"),
Self::RasterGPU(_) => label("Raster is not supported"),
}
}
}
impl TableRowLayout for VectorData {
impl TableRowLayout for Vector {
fn type_name() -> &'static str {
"VectorData"
"Vector"
}
fn identifier(&self) -> String {
format!("Vector Data (points={}, segments={})", self.point_domain.ids().len(), self.segment_domain.ids().len())
format!("Vector ({} points, {} segments)", self.point_domain.ids().len(), self.segment_domain.ids().len())
}
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
let colinear = self.colinear_manipulators.iter().map(|[a, b]| format!("[{a} / {b}]")).collect::<Vec<_>>().join(", ");
let colinear = if colinear.is_empty() { "None" } else { &colinear };
let style = vec![
TextLabel::new(format!(
"{}\n\nColinear Handle IDs: {}\n\nUpstream Graphic Group Table: {}",
"{}\n\nColinear Handle IDs: {}\n\nUpstream Group Table: {}",
self.style,
colinear,
if self.upstream_graphic_group.is_some() { "Yes" } else { "No" }
if self.upstream_group.is_some() { "Yes" } else { "No" }
))
.multiline(true)
.widget_holder(),
];
let domain_entries = [VectorDataDomain::Points, VectorDataDomain::Segments, VectorDataDomain::Regions]
let domain_entries = [VectorDomain::Points, VectorDomain::Segments, VectorDomain::Regions]
.into_iter()
.map(|domain| {
RadioEntryData::new(format!("{domain:?}"))
.label(format!("{domain:?}"))
.on_update(move |_| SpreadsheetMessage::ViewVectorDataDomain { domain }.into())
.on_update(move |_| SpreadsheetMessage::ViewVectorDomain { domain }.into())
})
.collect();
let domain = vec![RadioInput::new(domain_entries).selected_index(Some(data.vector_data_domain as u32)).widget_holder()];
let domain = vec![RadioInput::new(domain_entries).selected_index(Some(data.vector_domain as u32)).widget_holder()];
let mut table_rows = Vec::new();
match data.vector_data_domain {
VectorDataDomain::Points => {
match data.vector_domain {
VectorDomain::Points => {
table_rows.push(column_headings(&["", "position"]));
table_rows.extend(
self.point_domain
@@ -215,7 +215,7 @@ impl TableRowLayout for VectorData {
.map(|(id, position)| vec![TextLabel::new(format!("{}", id.inner())).widget_holder(), TextLabel::new(format!("{}", position)).widget_holder()]),
);
}
VectorDataDomain::Segments => {
VectorDomain::Segments => {
table_rows.push(column_headings(&["", "start_index", "end_index", "handles"]));
table_rows.extend(self.segment_domain.iter().map(|(id, start, end, handles)| {
vec![
@@ -226,7 +226,7 @@ impl TableRowLayout for VectorData {
]
}));
}
VectorDataDomain::Regions => {
VectorDomain::Regions => {
table_rows.push(column_headings(&["", "segment_range", "fill"]));
table_rows.extend(self.region_domain.iter().map(|(id, segment_range, fill)| {
vec![
@@ -263,7 +263,7 @@ impl TableRowLayout for Artboard {
self.label.clone()
}
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
self.graphic_group.compute_layout(data)
self.group.compute_layout(data)
}
}