Fix transforms, Brush tool, and G/R/S (#1473)

* Transform fixes

* Fix the desert artwork

* Change artboard icon

* Better handling when transforming brush strokes

* Code review pass

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube 2023-11-27 04:54:06 +00:00 committed by GitHub
parent 5ee79031ab
commit b2ca643e6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 308 additions and 238 deletions

View file

@ -1,6 +1,7 @@
use crate::raster::ImageFrame;
use crate::text::FontCache;
use crate::transform::{Footprint, Transform, TransformMut};
use crate::vector::style::ViewMode;
use crate::{Color, Node};
use dyn_any::{StaticType, StaticTypeSized};
@ -151,6 +152,7 @@ pub enum ExportFormat {
pub struct RenderConfig {
pub viewport: Footprint,
pub export_format: ExportFormat,
pub view_mode: ViewMode,
}
pub struct EditorApi<'a, Io> {

View file

@ -284,6 +284,7 @@ impl GraphicElementRendered for Artboard {
"g",
|attributes| {
attributes.push("class", "artboard");
attributes.push("transform", format_transform_matrix(self.graphic_group.transform));
if self.clip {
let id = format!("artboard-{}", generate_uuid());
let selector = format!("url(#{id})");
@ -298,8 +299,15 @@ impl GraphicElementRendered for Artboard {
}
},
|render| {
let old_opacity = render.opacity;
render.opacity *= self.graphic_group.opacity;
// Contents
self.graphic_group.render_svg(render, render_params);
for element in self.graphic_group.iter() {
render.blend_mode = element.blend_mode;
element.graphic_element_data.render_svg(render, render_params);
}
render.opacity = old_opacity;
},
);
}

View file

@ -349,6 +349,13 @@ impl<P: Hash + Pixel> Hash for ImageFrame<P> {
}
}
impl<P: Pixel> ImageFrame<P> {
/// Compute the pivot in local space with the current transform applied
pub fn local_pivot(&self, normalized_pivot: DVec2) -> DVec2 {
self.transform.transform_point2(normalized_pivot)
}
}
/* This does not work because of missing specialization
* so we have to manually implement this for now
impl<S: Into<P> + Pixel, P: Pixel> From<Image<S>> for Image<P> {

View file

@ -37,11 +37,17 @@ impl<P: Pixel> Transform for ImageFrame<P> {
fn transform(&self) -> DAffine2 {
self.transform
}
fn local_pivot(&self, pivot: DVec2) -> DVec2 {
self.local_pivot(pivot)
}
}
impl<P: Pixel> Transform for &ImageFrame<P> {
fn transform(&self) -> DAffine2 {
self.transform
}
fn local_pivot(&self, pivot: DVec2) -> DVec2 {
(*self).local_pivot(pivot)
}
}
impl<P: Pixel> TransformMut for ImageFrame<P> {
fn transform_mut(&mut self) -> &mut DAffine2 {
@ -69,8 +75,8 @@ impl Transform for GraphicElementData {
GraphicElementData::VectorShape(vector_shape) => vector_shape.transform(),
GraphicElementData::ImageFrame(image_frame) => image_frame.transform(),
GraphicElementData::Text(_) => todo!("Transform of text"),
GraphicElementData::GraphicGroup(_graphic_group) => DAffine2::IDENTITY,
GraphicElementData::Artboard(_artboard) => DAffine2::IDENTITY,
GraphicElementData::GraphicGroup(graphic_group) => graphic_group.transform(),
GraphicElementData::Artboard(artboard) => artboard.graphic_group.transform(),
}
}
fn local_pivot(&self, pivot: DVec2) -> DVec2 {
@ -78,23 +84,17 @@ impl Transform for GraphicElementData {
GraphicElementData::VectorShape(vector_shape) => vector_shape.local_pivot(pivot),
GraphicElementData::ImageFrame(image_frame) => image_frame.local_pivot(pivot),
GraphicElementData::Text(_) => todo!("Transform of text"),
GraphicElementData::GraphicGroup(_graphic_group) => pivot,
GraphicElementData::Artboard(_artboard) => pivot,
GraphicElementData::GraphicGroup(graphic_group) => graphic_group.local_pivot(pivot),
GraphicElementData::Artboard(artboard) => artboard.graphic_group.local_pivot(pivot),
}
}
fn decompose_scale(&self) -> DVec2 {
let standard = || {
DVec2::new(
self.transform().transform_vector2((1., 0.).into()).length(),
self.transform().transform_vector2((0., 1.).into()).length(),
)
};
match self {
GraphicElementData::VectorShape(vector_shape) => vector_shape.decompose_scale(),
GraphicElementData::ImageFrame(image_frame) => image_frame.decompose_scale(),
GraphicElementData::Text(_) => todo!("Transform of text"),
GraphicElementData::GraphicGroup(_graphic_group) => standard(),
GraphicElementData::Artboard(_artboard) => standard(),
GraphicElementData::GraphicGroup(graphic_group) => graphic_group.decompose_scale(),
GraphicElementData::Artboard(artboard) => artboard.graphic_group.decompose_scale(),
}
}
}
@ -104,8 +104,8 @@ impl TransformMut for GraphicElementData {
GraphicElementData::VectorShape(vector_shape) => vector_shape.transform_mut(),
GraphicElementData::ImageFrame(image_frame) => image_frame.transform_mut(),
GraphicElementData::Text(_) => todo!("Transform of text"),
GraphicElementData::GraphicGroup(_graphic_group) => todo!("Mutable transform of graphic group"),
GraphicElementData::Artboard(_artboard) => todo!("Mutable transform of artboard"),
GraphicElementData::GraphicGroup(graphic_group) => graphic_group.transform_mut(),
GraphicElementData::Artboard(artboard) => artboard.graphic_group.transform_mut(),
}
}
}

View file

@ -6,7 +6,6 @@ use graphene_core::application_io::{ApplicationError, ApplicationIo, ExportForma
use graphene_core::raster::Image;
use graphene_core::renderer::{GraphicElementRendered, RenderParams, SvgRender};
use graphene_core::transform::Footprint;
use graphene_core::vector::style::ViewMode;
use graphene_core::Color;
use graphene_core::{
raster::{color::SRGBA8, ImageFrame},
@ -285,7 +284,6 @@ fn decode_image_node<'a: 'input>(data: Arc<[u8]>) -> ImageFrame<Color> {
image
}
pub use graph_craft::document::value::RenderOutput;
pub struct RenderNode<Data, Surface, Parameter> {
data: Data,
surface_handle: Surface,
@ -365,7 +363,7 @@ where
fn eval(&'input self, editor: WasmEditorApi<'a>) -> Self::Output {
Box::pin(async move {
let footprint = editor.render_config.viewport;
let render_params = RenderParams::new(ViewMode::Normal, graphene_core::renderer::ImageRenderMode::Base64, None, false);
let render_params = RenderParams::new(editor.render_config.view_mode, graphene_core::renderer::ImageRenderMode::Base64, None, false);
let output_format = editor.render_config.export_format;
match output_format {
@ -393,7 +391,7 @@ where
use graphene_core::renderer::ImageRenderMode;
let footprint = editor.render_config.viewport;
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::Base64, None, false);
let render_params = RenderParams::new(editor.render_config.view_mode, ImageRenderMode::Base64, None, false);
let output_format = editor.render_config.export_format;
match output_format {

View file

@ -800,6 +800,7 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
},
)],
register_node!(graphene_core::transform::CullNode<_>, input: Footprint, params: [Artboard]),
register_node!(graphene_core::transform::CullNode<_>, input: Footprint, params: [ImageFrame<Color>]),
vec![(
NodeIdentifier::new("graphene_core::transform::CullNode<_>"),
|args| {