Remove artboard from graphic element (#1824)

* Remove artboard from graphic element

* Fix transform bug
This commit is contained in:
James Lindsay 2024-07-14 05:10:29 +01:00 committed by GitHub
parent 027d3f4e60
commit 0c2e3361ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 51 additions and 72 deletions

View file

@ -301,57 +301,10 @@ impl NodeRuntime {
continue;
};
enum IntrospectedData<'a> {
GraphicElement(&'a graphene_core::GraphicElement),
Artboard(&'a graphene_core::Artboard),
}
let introspected_data_output = introspected_data
.downcast_ref::<IORecord<Footprint, graphene_core::GraphicElement>>()
.map(|io_data| IntrospectedData::GraphicElement(&io_data.output))
.or_else(|| {
introspected_data
.downcast_ref::<IORecord<Footprint, graphene_core::Artboard>>()
.map(|io_data| IntrospectedData::Artboard(&io_data.output))
});
let graphic_element = match introspected_data_output {
Some(IntrospectedData::GraphicElement(graphic_element)) => Some(graphic_element.clone()),
Some(IntrospectedData::Artboard(artboard)) => Some(artboard.clone().into()),
_ => None,
};
// If this is `GraphicElement` data:
// Regenerate click targets and thumbnails for the layers in the graph, modifying the state and updating the UI.
if let Some(graphic_element) = graphic_element {
let click_targets = self.click_targets.entry(parent_network_node_id).or_default();
click_targets.clear();
graphic_element.add_click_targets(click_targets);
// RENDER THUMBNAIL
let bounds = graphic_element.bounding_box(DAffine2::IDENTITY);
// Render the thumbnail from a `GraphicElement` into an SVG string
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::Base64, bounds, true, false, false);
let mut render = SvgRender::new();
graphic_element.render_svg(&mut render, &render_params);
// And give the SVG a viewbox and outer <svg>...</svg> wrapper tag
let [min, max] = bounds.unwrap_or_default();
render.format_svg(min, max);
// UPDATE FRONTEND THUMBNAIL
let new_thumbnail_svg = render.svg;
let old_thumbnail_svg = self.thumbnail_renders.entry(parent_network_node_id).or_default();
if old_thumbnail_svg != &new_thumbnail_svg {
responses.push_back(FrontendMessage::UpdateNodeThumbnail {
id: parent_network_node_id,
value: new_thumbnail_svg.to_svg_string(),
});
*old_thumbnail_svg = new_thumbnail_svg;
}
if let Some(io) = introspected_data.downcast_ref::<IORecord<Footprint, graphene_core::GraphicElement>>() {
Self::process_graphic_element(&mut self.thumbnail_renders, &mut self.click_targets, parent_network_node_id, &io.output, responses)
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Footprint, graphene_core::Artboard>>() {
Self::process_graphic_element(&mut self.thumbnail_renders, &mut self.click_targets, parent_network_node_id, &io.output, responses)
} else if let Some(record) = introspected_data.downcast_ref::<IORecord<Footprint, VectorData>>() {
// Insert the vector modify if we are dealing with vector data
self.vector_modify.insert(parent_network_node_id, record.output.clone());
@ -374,6 +327,46 @@ impl NodeRuntime {
}
}
}
// If this is `GraphicElement` data:
// Regenerate click targets and thumbnails for the layers in the graph, modifying the state and updating the UI.
fn process_graphic_element(
thumbnail_renders: &mut HashMap<NodeId, Vec<SvgSegment>>,
click_targets: &mut HashMap<NodeId, Vec<ClickTarget>>,
parent_network_node_id: NodeId,
graphic_element: &impl GraphicElementRendered,
responses: &mut VecDeque<FrontendMessage>,
) {
let click_targets = click_targets.entry(parent_network_node_id).or_default();
click_targets.clear();
graphic_element.add_click_targets(click_targets);
// RENDER THUMBNAIL
let bounds = graphic_element.bounding_box(DAffine2::IDENTITY);
// Render the thumbnail from a `GraphicElement` into an SVG string
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::Base64, bounds, true, false, false);
let mut render = SvgRender::new();
graphic_element.render_svg(&mut render, &render_params);
// And give the SVG a viewbox and outer <svg>...</svg> wrapper tag
let [min, max] = bounds.unwrap_or_default();
render.format_svg(min, max);
// UPDATE FRONTEND THUMBNAIL
let new_thumbnail_svg = render.svg;
let old_thumbnail_svg = thumbnail_renders.entry(parent_network_node_id).or_default();
if old_thumbnail_svg != &new_thumbnail_svg {
responses.push_back(FrontendMessage::UpdateNodeThumbnail {
id: parent_network_node_id,
value: new_thumbnail_svg.to_svg_string(),
});
*old_thumbnail_svg = new_thumbnail_svg;
}
}
}
pub fn introspect_node(path: &[NodeId]) -> Option<Arc<dyn std::any::Any>> {

View file

@ -121,15 +121,6 @@ impl ArtboardGroup {
fn add_artboard(&mut self, artboard: Artboard) {
self.artboards.push(artboard);
}
pub fn get_graphic_group(&self) -> GraphicGroup {
let mut graphic_group = GraphicGroup::EMPTY;
for artboard in self.artboards.clone() {
let graphic_element: GraphicElement = artboard.into();
graphic_group.push(graphic_element);
}
graphic_group
}
}
pub struct ConstructLayerNode<Stack, GraphicElement> {
@ -240,11 +231,6 @@ impl From<GraphicGroup> for GraphicElement {
GraphicElement::GraphicGroup(graphic_group)
}
}
impl From<Artboard> for GraphicElement {
fn from(artboard: Artboard) -> Self {
GraphicElement::Artboard(artboard)
}
}
impl Deref for GraphicGroup {
type Target = Vec<GraphicElement>;
@ -265,7 +251,6 @@ trait ToGraphicElement: Into<GraphicElement> {}
impl ToGraphicElement for VectorData {}
impl ToGraphicElement for ImageFrame<Color> {}
impl ToGraphicElement for Artboard {}
impl<T> From<T> for GraphicGroup
where

View file

@ -469,15 +469,19 @@ impl GraphicElementRendered for Artboard {
impl GraphicElementRendered for crate::ArtboardGroup {
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
self.get_graphic_group().render_svg(render, render_params);
for artboard in &self.artboards {
artboard.render_svg(render, render_params);
}
}
fn bounding_box(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
self.get_graphic_group().bounding_box(transform)
self.artboards.iter().filter_map(|element| element.bounding_box(transform)).reduce(Quad::combine_bounds)
}
fn add_click_targets(&self, click_targets: &mut Vec<ClickTarget>) {
self.get_graphic_group().add_click_targets(click_targets);
for artboard in &self.artboards {
artboard.add_click_targets(click_targets);
}
}
fn contains_artboard(&self) -> bool {

View file

@ -289,7 +289,6 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
async_node!(graphene_core::ops::IntoNode<_, GraphicGroup>, input: ImageFrame<Color>, output: GraphicGroup, params: []),
async_node!(graphene_core::ops::IntoNode<_, GraphicGroup>, input: VectorData, output: GraphicGroup, params: []),
async_node!(graphene_core::ops::IntoNode<_, GraphicGroup>, input: GraphicGroup, output: GraphicGroup, params: []),
async_node!(graphene_core::ops::IntoNode<_, GraphicGroup>, input: Artboard, output: GraphicGroup, params: []),
#[cfg(feature = "gpu")]
async_node!(graphene_core::ops::IntoNode<_, &WgpuExecutor>, input: &WasmEditorApi, output: &WgpuExecutor, params: []),
register_node!(graphene_std::raster::MaskImageNode<_, _, _>, input: ImageFrame<Color>, params: [ImageFrame<Color>]),
@ -753,11 +752,9 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
register_node!(graphene_core::ToGraphicElementNode, input: graphene_core::vector::VectorData, params: []),
register_node!(graphene_core::ToGraphicElementNode, input: ImageFrame<Color>, params: []),
register_node!(graphene_core::ToGraphicElementNode, input: GraphicGroup, params: []),
register_node!(graphene_core::ToGraphicElementNode, input: Artboard, params: []),
register_node!(graphene_core::ToGraphicGroupNode, input: graphene_core::vector::VectorData, params: []),
register_node!(graphene_core::ToGraphicGroupNode, input: ImageFrame<Color>, params: []),
register_node!(graphene_core::ToGraphicGroupNode, input: GraphicGroup, params: []),
register_node!(graphene_core::ToGraphicGroupNode, input: Artboard, params: []),
async_node!(graphene_core::ConstructArtboardNode<_, _, _, _, _, _>, input: Footprint, output: Artboard, fn_params: [Footprint => GraphicGroup, () => String, () => glam::IVec2, () => glam::IVec2, () => Color, () => bool]),
async_node!(graphene_core::AddArtboardNode<_, _>, input: Footprint, output: ArtboardGroup, fn_params: [Footprint => ArtboardGroup, Footprint => Artboard]),
];