mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 05:18:19 +00:00
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:
parent
5ee79031ab
commit
b2ca643e6e
26 changed files with 308 additions and 238 deletions
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue