Skip to content
Merged
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
4 changes: 2 additions & 2 deletions editor/src/messages/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ mod test {

fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool, file: &mut std::fs::File) {
// Print the current node
let (branch, child_prefix) = if tree.has_message_handler_data_fields() || tree.has_message_handler_fields() {
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() || tree.message_handler_fields().is_some() {
("├── ", format!("{}│ ", prefix))
} else {
if is_last {
Expand Down Expand Up @@ -97,7 +97,7 @@ mod test {
// Print handler field if any
if let Some(data) = tree.message_handler_fields() {
let len = data.fields().len();
let (branch, child_prefix) = if tree.has_message_handler_data_fields() {
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() {
("├── ", format!("{}│ ", prefix))
} else {
("└── ", format!("{} ", prefix))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::messages::tool::tool_messages::tool_prelude::*;
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;
Expand Down Expand Up @@ -153,7 +154,6 @@ macro_rules! generate_layout_downcast {
else { None }
}
}

// TODO: We simply try all these types sequentially. Find a better strategy.
fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'static>, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
generate_layout_downcast!(introspected_data, data, [
Expand All @@ -163,6 +163,7 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
Table<Raster<CPU>>,
Table<Raster<GPU>>,
Table<Color>,
Table<GradientStops>,
f64,
u32,
u64,
Expand Down Expand Up @@ -263,6 +264,7 @@ impl TableRowLayout for Graphic {
Self::RasterCPU(table) => table.identifier(),
Self::RasterGPU(table) => table.identifier(),
Self::Color(table) => table.identifier(),
Self::Gradient(table) => table.identifier(),
}
}
// Don't put a breadcrumb for Graphic
Expand All @@ -276,6 +278,7 @@ impl TableRowLayout for Graphic {
Self::RasterCPU(table) => table.layout_with_breadcrumb(data),
Self::RasterGPU(table) => table.layout_with_breadcrumb(data),
Self::Color(table) => table.layout_with_breadcrumb(data),
Self::Gradient(table) => table.layout_with_breadcrumb(data),
}
}
}
Expand Down Expand Up @@ -335,10 +338,6 @@ impl TableRowLayout for Vector {
TextLabel::new(format_dvec2(gradient.start)).widget_holder(),
]);
table_rows.push(vec![TextLabel::new("Fill Gradient End").widget_holder(), TextLabel::new(format_dvec2(gradient.end)).widget_holder()]);
table_rows.push(vec![
TextLabel::new("Fill Gradient Transform").widget_holder(),
TextLabel::new(format_transform_matrix(&gradient.transform)).widget_holder(),
]);
}
}

Expand Down Expand Up @@ -485,6 +484,25 @@ impl TableRowLayout for Color {
}
}

impl TableRowLayout for GradientStops {
fn type_name() -> &'static str {
"Gradient"
}
fn identifier(&self) -> String {
format!("Gradient ({} stops)", self.0.len())
}
fn element_widget(&self, _index: usize) -> WidgetHolder {
ColorInput::new(FillChoice::Gradient(self.clone()))
.disabled(true)
.menu_direction(Some(MenuDirection::Top))
.widget_holder()
}
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
let widgets = vec![self.element_widget(0)];
vec![LayoutGroup::Row { widgets }]
}
}

impl TableRowLayout for f64 {
fn type_name() -> &'static str {
"Number (f64)"
Expand Down Expand Up @@ -545,7 +563,7 @@ impl TableRowLayout for String {
"String".to_string()
}
fn element_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
let widgets = vec![TextLabel::new(self.to_string()).widget_holder()];
let widgets = vec![TextAreaInput::new(self.to_string()).disabled(true).widget_holder()];
vec![LayoutGroup::Row { widgets }]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, t
Fill::Gradient(Gradient {
start,
end,
transform: DAffine2::IDENTITY,
gradient_type: GradientType::Linear,
stops,
})
Expand All @@ -453,7 +452,6 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, t
Fill::Gradient(Gradient {
start,
end,
transform: DAffine2::IDENTITY,
gradient_type: GradientType::Radial,
stops,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pub(crate) fn property_from_type(
// STRUCT TYPES
// ============
Some(x) if x == TypeId::of::<Table<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
Some(x) if x == TypeId::of::<Table<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<Font>() => font_widget(default_info),
Some(x) if x == TypeId::of::<Curve>() => curve_widget(default_info),
Expand Down Expand Up @@ -922,6 +923,20 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
.on_commit(commit_value)
.widget_holder(),
),
TaggedValue::GradientTable(gradient_table) => widgets.push(
color_button
.value(match gradient_table.iter().next() {
Some(row) => FillChoice::Gradient(row.element.clone()),
None => FillChoice::None,
})
.on_update(update_value(
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
node_id,
index,
))
.on_commit(commit_value)
.widget_holder(),
),
TaggedValue::GradientStops(gradient_stops) => widgets.push(
color_button
.value(FillChoice::Gradient(gradient_stops.clone()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub enum FrontendGraphDataType {
Raster,
Vector,
Color,
Gradient,
Typography,
}

impl FrontendGraphDataType {
Expand All @@ -32,6 +34,8 @@ impl FrontendGraphDataType {
TaggedValue::Raster(_) => Self::Raster,
TaggedValue::Vector(_) => Self::Vector,
TaggedValue::Color(_) => Self::Color,
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) | TaggedValue::GradientTable(_) => Self::Gradient,
TaggedValue::String(_) => Self::Typography,
_ => Self::General,
}
}
Expand Down
10 changes: 1 addition & 9 deletions editor/src/messages/tool/tool_messages/gradient_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ impl SelectedGradient {

/// Update the layer fill to the current gradient
pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) {
self.gradient.transform = self.transform;
if let Some(layer) = self.layer {
responses.add(GraphOperationMessage::FillSet {
layer,
Expand Down Expand Up @@ -436,14 +435,7 @@ impl Fsm for GradientToolFsmState {
gradient.clone()
} else {
// Generate a new gradient
Gradient::new(
DVec2::ZERO,
global_tool_data.secondary_color,
DVec2::ONE,
global_tool_data.primary_color,
DAffine2::IDENTITY,
tool_options.gradient_type,
)
Gradient::new(DVec2::ZERO, global_tool_data.secondary_color, DVec2::ONE, global_tool_data.primary_color, tool_options.gradient_type)
};
let selected_gradient = SelectedGradient::new(gradient, layer, document).with_gradient_start(input.mouse.position);

Expand Down
88 changes: 27 additions & 61 deletions editor/src/node_graph_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ use graph_craft::proto::GraphErrors;
use graph_craft::wasm_application_io::EditorPreferences;
use graphene_std::application_io::TimingInformation;
use graphene_std::application_io::{NodeGraphUpdateMessage, RenderConfig};
use graphene_std::renderer::RenderSvgSegmentList;
use graphene_std::renderer::{Render, RenderParams, SvgRender};
use graphene_std::renderer::{RenderMetadata, format_transform_matrix};
use graphene_std::text::FontCache;
use graphene_std::transform::Footprint;
use graphene_std::vector::Vector;
use graphene_std::vector::style::ViewMode;
use graphene_std::wasm_application_io::RenderOutputType;
use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta;

Expand All @@ -34,7 +31,6 @@ pub struct ExecutionResponse {
execution_id: u64,
result: Result<TaggedValue, String>,
responses: VecDeque<FrontendMessage>,
footprint: Footprint,
vector_modify: HashMap<NodeId, Vector>,
/// The resulting value from the temporary inspected during execution
inspect_result: Option<InspectResult>,
Expand Down Expand Up @@ -131,6 +127,7 @@ impl NodeGraphExecutor {
.send(GraphRuntimeRequest::GraphUpdate(GraphUpdate { network, node_to_inspect }))
.map_err(|e| e.to_string())?;
}

Ok(())
}

Expand Down Expand Up @@ -252,6 +249,7 @@ impl NodeGraphExecutor {
let size = (size * scale_factor).into();
responses.add(FrontendMessage::TriggerExportImage { svg, name, mime, size });
}

Ok(())
}

Expand All @@ -264,7 +262,6 @@ impl NodeGraphExecutor {
execution_id,
result,
responses: existing_responses,
footprint,
vector_modify,
inspect_result,
} = execution_response;
Expand All @@ -289,7 +286,7 @@ impl NodeGraphExecutor {
// Special handling for exporting the artwork
self.export(node_graph_output, export_config, responses)?;
} else {
self.process_node_graph_output(node_graph_output, footprint, responses)?;
self.process_node_graph_output(node_graph_output, responses)?;
}
responses.add_front(DeferMessage::TriggerGraphRun(execution_id, execution_context.document_id));

Expand Down Expand Up @@ -330,73 +327,41 @@ impl NodeGraphExecutor {
}
}
}

Ok(())
}

fn debug_render(render_object: impl Render, footprint: Footprint, responses: &mut VecDeque<Message>) {
// Setup rendering
let mut render = SvgRender::new();
let render_params = RenderParams {
view_mode: ViewMode::Normal,
footprint,
thumbnail: false,
hide_artboards: false,
for_export: false,
for_mask: false,
alignment_parent_transform: None,
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, responses: &mut VecDeque<Message>) -> Result<(), String> {
let TaggedValue::RenderOutput(render_output) = node_graph_output else {
return Err(format!("Invalid node graph output type: {node_graph_output:#?}"));
};

// Render SVG
render_object.render_svg(&mut render, &render_params);

// Concatenate the defs and the SVG into one string
render.wrap_with_transform(footprint.transform, None);
let svg = render.svg.to_svg_string();

// Send to frontend
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}

fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, footprint: Footprint, responses: &mut VecDeque<Message>) -> Result<(), String> {
let mut render_output_metadata = RenderMetadata::default();

match node_graph_output {
TaggedValue::RenderOutput(render_output) => {
match render_output.data {
RenderOutputType::Svg { svg, image_data } => {
// Send to frontend
responses.add(FrontendMessage::UpdateImageData { image_data });
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
RenderOutputType::CanvasFrame(frame) => {
let matrix = format_transform_matrix(frame.transform);
let transform = if matrix.is_empty() { String::new() } else { format!(" transform=\"{matrix}\"") };
let svg = format!(
r#"<svg><foreignObject width="{}" height="{}"{transform}><div data-canvas-placeholder="{}"></div></foreignObject></svg>"#,
frame.resolution.x, frame.resolution.y, frame.surface_id.0
);
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
RenderOutputType::Texture { .. } => {}
_ => return Err(format!("Invalid node graph output type: {:#?}", render_output.data)),
}

render_output_metadata = render_output.metadata;
match render_output.data {
RenderOutputType::Svg { svg, image_data } => {
// Send to frontend
responses.add(FrontendMessage::UpdateImageData { image_data });
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
TaggedValue::Bool(render_object) => Self::debug_render(render_object, footprint, responses),
TaggedValue::F64(render_object) => Self::debug_render(render_object, footprint, responses),
TaggedValue::DVec2(render_object) => Self::debug_render(render_object, footprint, responses),
TaggedValue::String(render_object) => Self::debug_render(render_object, footprint, responses),
_ => return Err(format!("Invalid node graph output type: {node_graph_output:#?}")),
};
RenderOutputType::CanvasFrame(frame) => {
let matrix = format_transform_matrix(frame.transform);
let transform = if matrix.is_empty() { String::new() } else { format!(" transform=\"{matrix}\"") };
let svg = format!(
r#"<svg><foreignObject width="{}" height="{}"{transform}><div data-canvas-placeholder="{}"></div></foreignObject></svg>"#,
frame.resolution.x, frame.resolution.y, frame.surface_id.0
);
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
RenderOutputType::Texture { .. } => {}
_ => return Err(format!("Invalid node graph output type: {:#?}", render_output.data)),
}

let graphene_std::renderer::RenderMetadata {
let RenderMetadata {
upstream_footprints,
local_transforms,
first_element_source_id,
click_targets,
clip_targets,
} = render_output_metadata;
} = render_output.metadata;

// Run these update state messages immediately
responses.add(DocumentMessage::UpdateUpstreamTransforms {
Expand All @@ -409,6 +374,7 @@ impl NodeGraphExecutor {
responses.add(DocumentMessage::RenderScrollbars);
responses.add(DocumentMessage::RenderRulers);
responses.add(OverlaysMessage::Draw);

Ok(())
}
}
Expand Down
8 changes: 1 addition & 7 deletions editor/src/node_graph_executor/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use graphene_std::table::{Table, TableRow};
use graphene_std::text::FontCache;
use graphene_std::transform::RenderQuality;
use graphene_std::vector::Vector;
use graphene_std::vector::style::ViewMode;
use graphene_std::wasm_application_io::{RenderOutputType, WasmApplicationIo, WasmEditorApi};
use graphene_std::{Artboard, Context, Graphic};
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
Expand Down Expand Up @@ -228,7 +227,6 @@ impl NodeRuntime {
execution_id,
result,
responses,
footprint: render_config.viewport,
vector_modify: self.vector_modify.clone(),
inspect_result,
});
Expand Down Expand Up @@ -361,13 +359,9 @@ impl NodeRuntime {

// Render the thumbnail from a `Graphic` into an SVG string
let render_params = RenderParams {
view_mode: ViewMode::Normal,
footprint,
thumbnail: true,
hide_artboards: false,
for_export: false,
for_mask: false,
alignment_parent_transform: None,
..Default::default()
};
let mut render = SvgRender::new();
graphic.render_svg(&mut render, &render_params);
Expand Down
Loading
Loading