Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ use crate::messages::portfolio::document::data_panel::DataPanelMessage;
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::prelude::*;
use crate::messages::tool::tool_messages::tool_prelude::*;
use glam::{Affine2, Vec2};
use glam::{Affine2, DAffine2, Vec2};
use graph_craft::document::NodeId;
use graphene_std::Color;
use graphene_std::Context;
use graphene_std::gradient::GradientStops;
use graphene_std::memo::IORecord;
use graphene_std::raster_types::{CPU, GPU, Raster};
use graphene_std::table::Table;
use graphene_std::vector::Vector;
use graphene_std::vector::style::{Fill, FillChoice};
use graphene_std::{AlphaBlending, Color};
use graphene_std::{Artboard, Graphic};
use std::any::Any;
use std::sync::Arc;
Expand Down Expand Up @@ -249,7 +249,7 @@ impl<T: TableRowLayout> TableRowLayout for Table<T> {
if let Some(index) = data.desired_path.get(data.current_depth).copied() {
if let Some(row) = self.get(index) {
data.current_depth += 1;
let result = row.element.layout_with_breadcrumb(data);
let result = row.element().layout_with_breadcrumb(data);
data.current_depth -= 1;
return result;
} else {
Expand All @@ -258,23 +258,42 @@ impl<T: TableRowLayout> TableRowLayout for Table<T> {
}
}

// Collect all unique attribute keys across all rows, preserving first-seen order
let mut attribute_keys: Vec<String> = Vec::new();
for row in self.iter() {
for key in row.attribute_keys() {
if !attribute_keys.iter().any(|existing| existing == key) {
attribute_keys.push(key.to_string());
}
}
}

let mut rows = self
.iter()
.enumerate()
.map(|(index, row)| {
vec![
TextLabel::new(format!("{index}")).narrow(true).widget_instance(),
row.element.element_widget(index),
TextLabel::new(format_transform_matrix(row.transform)).narrow(true).widget_instance(),
TextLabel::new(format!("{}", row.alpha_blending)).narrow(true).widget_instance(),
TextLabel::new(row.source_node_id.map_or_else(|| "-".to_string(), |id| format!("{}", id.0)))
.narrow(true)
.widget_instance(),
]
let mut cells = vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance(), row.element().element_widget(index)];
for key in &attribute_keys {
let value = row
.attribute_display_value(key, |ty| {
Some(match () {
() if let Some(&value) = ty.downcast_ref::<DAffine2>() => format_transform_matrix(value),
() if let Some(&value) = ty.downcast_ref::<DVec2>() => format_dvec2(value),
() if let Some(&value) = ty.downcast_ref::<AlphaBlending>() => format_alpha_blending(value),
() if let Some(&value) = ty.downcast_ref::<Option<NodeId>>() => value.map_or_else(|| "-".to_string(), |id| id.to_string()),
_ => return None,
})
})
.unwrap_or_else(|| "-".to_string());
cells.push(TextLabel::new(value).narrow(true).widget_instance());
}
cells
})
.collect::<Vec<_>>();

rows.insert(0, column_headings(&["", "element", "transform", "alpha_blending", "source_node_id"]));
let mut column_names = vec!["", "element"];
column_names.extend(attribute_keys.iter().map(|s| s.as_str()));
rows.insert(0, column_headings(&column_names));

vec![LayoutGroup::table(rows, false)]
}
Expand Down Expand Up @@ -430,7 +449,7 @@ impl TableRowLayout for Vector {
]);
table_rows.push(vec![
TextLabel::new("Stroke Transform").narrow(true).widget_instance(),
TextLabel::new(format_transform_matrix(&stroke.transform)).narrow(true).widget_instance(),
TextLabel::new(format_transform_matrix(stroke.transform)).narrow(true).widget_instance(),
]);
table_rows.push(vec![
TextLabel::new("Stroke Paint Order").narrow(true).widget_instance(),
Expand Down Expand Up @@ -695,7 +714,7 @@ impl TableRowLayout for DAffine2 {
"Transform".to_string()
}
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
let widgets = vec![TextLabel::new(format_transform_matrix(self)).widget_instance()];
let widgets = vec![TextLabel::new(format_transform_matrix(*self)).widget_instance()];
vec![LayoutGroup::row(widgets)]
}
}
Expand All @@ -709,12 +728,12 @@ impl TableRowLayout for Affine2 {
}
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
let matrix = DAffine2::from_cols_array(&self.to_cols_array().map(|x| x as f64));
let widgets = vec![TextLabel::new(format_transform_matrix(&matrix)).widget_instance()];
let widgets = vec![TextLabel::new(format_transform_matrix(matrix)).widget_instance()];
vec![LayoutGroup::row(widgets)]
}
}

fn format_transform_matrix(transform: &DAffine2) -> String {
fn format_transform_matrix(transform: DAffine2) -> String {
let (scale, angle, translation) = if transform.matrix2.determinant().abs() <= f64::EPSILON {
let [col_0, col_1] = transform.matrix2.to_cols_array_2d().map(|[x, y]| DVec2::new(x, y));

Expand Down Expand Up @@ -748,3 +767,14 @@ fn format_dvec2(value: DVec2) -> String {
let round = |x: f64| (x * 1e3).round() / 1e3;
format!("({} px, {} px)", round(value.x), round(value.y))
}

fn format_alpha_blending(value: AlphaBlending) -> String {
let round = |x: f32| (x * 1e3).round() / 1e3;
format!(
"Blend Mode: {} — Opacity: {}% — Fill: {}% — Clip: {}",
value.blend_mode,
round(value.opacity * 100.),
round(value.fill * 100.),
if value.clip { "Yes" } else { "No" }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -713,10 +713,10 @@ fn set_import_child_positions(
let child_pos = IVec2::new(child_x, current_y);

if i == 0 {
// Top of stack set to `Absolute` position
// Top of stack: set to `Absolute` position
network_interface.set_layer_position_for_import(&child_layer.to_node(), LayerPosition::Absolute(child_pos), &[]);
} else {
// Below top set `Stack` with `y_offset` based on previous sibling's subtree extent
// Below top: set `Stack` with `y_offset` based on previous sibling's subtree extent
let prev_sibling_svg_index = n - i;
let y_offset = child_extents_svg_order[prev_sibling_svg_index] + STACK_VERTICAL_GAP as u32;
network_interface.set_layer_position_for_import(&child_layer.to_node(), LayerPosition::Stack(y_offset), &[]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
TaggedValue::Color(color_table) => widgets.push(
color_button
.value(match color_table.iter().next() {
Some(color) => FillChoice::Solid(*color.element),
Some(color) => FillChoice::Solid(*color.element()),
None => FillChoice::None,
})
.on_update(update_value(
Expand All @@ -1193,7 +1193,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
TaggedValue::GradientTable(gradient_table) => widgets.push(
color_button
.value(match gradient_table.iter().next() {
Some(row) => FillChoice::Gradient(row.element.clone()),
Some(row) => FillChoice::Gradient(row.element().clone()),
None => FillChoice::Gradient(GradientStops::default()),
})
.on_update(update_value(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1170,12 +1170,13 @@ impl OverlayContextInternal {
// Use the existing bezier_to_path infrastructure to convert Vector to BezPath
let mut path = BezPath::new();
let mut last_point = None;
let transform: DAffine2 = row.attribute_cloned_or_default("transform");

for (_, bezier, start_id, end_id) in row.element.segment_iter() {
for (_, bezier, start_id, end_id) in row.element().segment_iter() {
let move_to = last_point != Some(start_id);
last_point = Some(end_id);

self.bezier_to_path(bezier, *row.transform, move_to, &mut path);
self.bezier_to_path(bezier, transform, move_to, &mut path);
}

// Render the path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl DocumentMetadata {
.any(|upstream| Some(upstream) == source)
{
use_local = false;
info!("Local transform is invalid — using the identity for the local transform instead")
info!("Local transform is invalid. Using the identity for the local transform instead.");
}
let local_transform = use_local.then(|| self.local_transforms.get(&layer.to_node()).copied()).flatten().unwrap_or_default();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5521,11 +5521,11 @@ impl NodeNetworkInterface {

match post_node_input {
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) | NodeInput::Reflection(_) => {
// First child in the stack wire layer output to the post_node input
// First child in the stack: wire layer output to the post_node input
self.set_input_for_import(&post_node, layer_output, network_path);
}
NodeInput::Node { .. } => {
// Subsequent childinsert layer between post_node and its current upstream:
// Subsequent child: insert layer between post_node and its current upstream...
// 1. Disconnect old upstream from post_node, wire layer output to post_node
self.set_input_for_import(&post_node, layer_output, network_path);
// 2. Wire old upstream into layer's primary (stack) input
Expand Down
4 changes: 2 additions & 2 deletions editor/src/messages/portfolio/document_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
&& let TaggedValue::Vector(vector_table) = &**tagged_value
&& !vector_table.is_empty()
{
let vector = vector_table.iter().next()?.element;
let vector = vector_table.iter().next()?.element();
let modification = Box::new(graphene_std::vector::VectorModification::create_from_vector(vector));

// Reset input 0 to the default exposed state
Expand All @@ -1983,7 +1983,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
&& let TaggedValue::Raster(raster_table) = &**tagged_value
&& let Some(row) = raster_table.iter().next()
{
let image = row.element.data().clone();
let image = row.element().data().clone();

document
.network_interface
Expand Down
2 changes: 1 addition & 1 deletion editor/src/messages/tool/tool_messages/artboard_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ mod test_artboard {
let artboards = get_artboards(editor)
.await
.iter()
.map(|row| ArtboardLayoutDocument::new(row.element.location, row.element.dimensions))
.map(|row| ArtboardLayoutDocument::new(row.element().location, row.element().dimensions))
.collect::<Vec<_>>();
assert_eq!(artboards.len(), expected.len(), "incorrect len: actual {:?}, expected {:?}", artboards, expected);

Expand Down
5 changes: 2 additions & 3 deletions editor/src/node_graph_executor/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use graphene_std::ops::Convert;
use graphene_std::platform_application_io::canvas_utils::{Canvas, CanvasSurface, CanvasSurfaceHandle};
use graphene_std::raster_types::Raster;
use graphene_std::renderer::{Render, RenderParams, RenderSvgSegmentList, SvgRender, SvgSegment};
use graphene_std::table::{Table, TableRow};
use graphene_std::table::Table;
use graphene_std::text::FontCache;
use graphene_std::transform::RenderQuality;
use graphene_std::vector::Vector;
Expand Down Expand Up @@ -441,9 +441,8 @@ impl NodeRuntime {
// Vector table: vector modifications
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Vector>>>() {
// Insert the vector modify
let default = TableRow::default();
self.vector_modify
.insert(parent_network_node_id, io.output.iter().next().unwrap_or_else(|| default.as_ref()).element.clone());
.insert(parent_network_node_id, io.output.iter().next().map(|row| row.element().clone()).unwrap_or_default());
}
// Other
else {
Expand Down
18 changes: 9 additions & 9 deletions node-graph/graph-craft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ wasm = [
[dependencies]
Comment thread
Keavon marked this conversation as resolved.
# Local dependencies
dyn-any = { workspace = true }
core-types = { workspace = true }
brush-nodes = { workspace = true }
graphene-core = { workspace = true }
graphene-application-io = { workspace = true }
rendering = { workspace = true }
raster-nodes = { workspace = true }
vector-nodes = { workspace = true }
graphic-types = { workspace = true }
text-nodes = { workspace = true }
core-types = { workspace = true, features = ["serde"] }
brush-nodes = { workspace = true, features = ["serde"] }
graphene-core = { workspace = true, features = ["serde"] }
graphene-application-io = { workspace = true, features = ["serde"] }
rendering = { workspace = true, features = ["serde"] }
raster-nodes = { workspace = true, features = ["serde"] }
vector-nodes = { workspace = true, features = ["serde"] }
graphic-types = { workspace = true, features = ["serde"] }
text-nodes = { workspace = true, features = ["serde"] }

# Workspace dependencies
log = { workspace = true }
Expand Down
1 change: 0 additions & 1 deletion node-graph/graph-craft/src/document/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ tagged_value! {
// ===========
// TABLE TYPES
// ===========
GraphicUnused(Graphic), // TODO: This is unused but removing it causes `cargo test` to infinitely recurse its type solving; figure out why and then remove this
#[serde(deserialize_with = "graphic_types::migrations::migrate_vector")] // TODO: Eventually remove this migration document upgrade code
#[serde(alias = "VectorData")]
Vector(Table<Vector>),
Expand Down
6 changes: 5 additions & 1 deletion node-graph/libraries/application-io/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ authors = ["Graphite Authors <contact@graphite.art>"]
license = "MIT OR Apache-2.0"

[features]
default = ["serde"]
serde = ["dep:serde", "core-types/serde", "vector-types/serde", "text-nodes/serde"]
wasm = ["dep:web-sys"]
wgpu = ["dep:wgpu"]

Expand All @@ -19,9 +21,11 @@ text-nodes = { workspace = true }

# Workspace dependencies
glam = { workspace = true }
serde = { workspace = true }
log = { workspace = true }

# Optional workspace dependencies
serde = { workspace = true, optional = true }

# Optional workspace dependencies
web-sys = { workspace = true, optional = true }
wgpu = { workspace = true, optional = true }
14 changes: 9 additions & 5 deletions node-graph/libraries/application-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ pub enum ApplicationError {
InvalidUrl,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum NodeGraphUpdateMessage {}

pub trait NodeGraphUpdateSender {
Expand All @@ -90,26 +91,29 @@ pub trait GetEditorPreferences {
fn max_render_region_area(&self) -> u32;
}

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ExportFormat {
#[default]
Svg,
Raster,
}

#[derive(Debug, Default, Clone, Copy, PartialEq, DynAny, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Default, Clone, Copy, PartialEq, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TimingInformation {
pub time: f64,
pub animation_time: Duration,
}

#[derive(Debug, Default, Clone, Copy, PartialEq, DynAny, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Default, Clone, Copy, PartialEq, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RenderConfig {
pub viewport: Footprint,
pub scale: f64,
pub time: TimingInformation,
pub pointer: DVec2,
#[serde(alias = "view_mode")]
#[cfg_attr(feature = "serde", serde(alias = "view_mode"))]
pub render_mode: RenderMode,
pub export_format: ExportFormat,
pub for_export: bool,
Expand Down
1 change: 1 addition & 0 deletions node-graph/libraries/core-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0"

[features]
default = ["serde"]
serde = ["dep:serde"]
nightly = []
type_id_logging = []
dealloc_nodes = []
Expand Down
9 changes: 6 additions & 3 deletions node-graph/libraries/core-types/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ impl<T: Ctx + InjectVarArgs + ExtractVarArgs> ModifyVarArgs for T {}
// ================

// Public enum for flexible node macro codegen
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ContextFeature {
ExtractFootprint,
ExtractRealTime,
Expand All @@ -151,7 +152,8 @@ pub enum ContextFeature {
// Internal bitflags for fast compiler analysis
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, Default)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, dyn_any::DynAny, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ContextFeatures: u32 {
const FOOTPRINT = 1 << 0;
const REAL_TIME = 1 << 1;
Expand Down Expand Up @@ -182,7 +184,8 @@ impl ContextFeatures {
// CONTEXT DEPENDENCIES
// ====================

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, Default)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, dyn_any::DynAny, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ContextDependencies {
pub extract: ContextFeatures,
pub inject: ContextFeatures,
Expand Down
4 changes: 2 additions & 2 deletions node-graph/libraries/core-types/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ pub fn migrate_color<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Resul
use no_std_types::color::Color;
use serde::Deserialize;

#[derive(serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
enum ColorFormat {
Color(Color),
OptionalColor(Option<Color>),
Expand Down
Loading
Loading