mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 21:58:12 +08:00
Fix default value for the Output node (#1042)
* Fix default value for output node * Don't set frame transform to zero * Fix typo in hash function * Clear frame on empty image --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
bd89c12595
commit
5ad5ee61a3
+2
-2
@@ -8,7 +8,7 @@ use graph_craft::document::*;
|
|||||||
use graph_craft::imaginate_input::ImaginateSamplingMethod;
|
use graph_craft::imaginate_input::ImaginateSamplingMethod;
|
||||||
|
|
||||||
use graph_craft::NodeIdentifier;
|
use graph_craft::NodeIdentifier;
|
||||||
use graphene_core::raster::{Color, Image, LuminanceCalculation};
|
use graphene_core::raster::{Color, Image, ImageFrame, LuminanceCalculation};
|
||||||
use graphene_core::*;
|
use graphene_core::*;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@@ -176,7 +176,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
|||||||
inputs: vec![DocumentInputType {
|
inputs: vec![DocumentInputType {
|
||||||
name: "In",
|
name: "In",
|
||||||
data_type: FrontendGraphDataType::Raster,
|
data_type: FrontendGraphDataType::Raster,
|
||||||
default: NodeInput::value(TaggedValue::Image(Image::empty()), true),
|
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||||
}],
|
}],
|
||||||
outputs: vec![],
|
outputs: vec![],
|
||||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is rendered into the frame"),
|
properties: |_document_node, _node_id, _context| node_properties::string_properties("The graph's output is rendered into the frame"),
|
||||||
|
|||||||
@@ -245,34 +245,39 @@ impl NodeGraphExecutor {
|
|||||||
if let Some(imaginate_node) = imaginate_node {
|
if let Some(imaginate_node) = imaginate_node {
|
||||||
responses.push_back(self.generate_imaginate(network, imaginate_node, (document, document_id), layer_path, image_frame, persistent_data)?);
|
responses.push_back(self.generate_imaginate(network, imaginate_node, (document, document_id), layer_path, image_frame, persistent_data)?);
|
||||||
} else {
|
} else {
|
||||||
let ImageFrame { mut image, transform } = self.execute_network(network, image_frame)?;
|
let ImageFrame { image, transform } = self.execute_network(network, image_frame)?;
|
||||||
|
|
||||||
// If no image was generated, use the input image
|
// If no image was generated, clear the frame
|
||||||
if image.width == 0 || image.height == 0 {
|
if image.width == 0 || image.height == 0 {
|
||||||
image = graphene_core::raster::Image::from_image_data(&image_data, width, height);
|
responses.push_back(DocumentMessage::FrameClear.into());
|
||||||
|
} else {
|
||||||
|
// Update the image data
|
||||||
|
let (image_data, _size) = Self::encode_img(image, None, image::ImageOutputFormat::Bmp)?;
|
||||||
|
|
||||||
|
responses.push_back(
|
||||||
|
Operation::SetNodeGraphFrameImageData {
|
||||||
|
layer_path: layer_path.clone(),
|
||||||
|
image_data: image_data.clone(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
let mime = "image/bmp".to_string();
|
||||||
|
let image_data = std::sync::Arc::new(image_data);
|
||||||
|
let image_data = vec![FrontendImageData {
|
||||||
|
path: layer_path.clone(),
|
||||||
|
image_data,
|
||||||
|
mime,
|
||||||
|
}];
|
||||||
|
responses.push_back(FrontendMessage::UpdateImageData { document_id, image_data }.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (image_data, _size) = Self::encode_img(image, None, image::ImageOutputFormat::Bmp)?;
|
// Don't update the frame's transform if the new transform is DAffine2::ZERO.
|
||||||
|
if !transform.abs_diff_eq(DAffine2::ZERO, f64::EPSILON) {
|
||||||
responses.push_back(
|
// Update the transform based on the graph output
|
||||||
Operation::SetNodeGraphFrameImageData {
|
let transform = transform.to_cols_array();
|
||||||
layer_path: layer_path.clone(),
|
responses.push_back(Operation::SetLayerTransform { path: layer_path.clone(), transform }.into());
|
||||||
image_data: image_data.clone(),
|
responses.push_back(Operation::SetLayerVisibility { path: layer_path, visible: true }.into());
|
||||||
}
|
}
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
let mime = "image/bmp".to_string();
|
|
||||||
let image_data = std::sync::Arc::new(image_data);
|
|
||||||
let image_data = vec![FrontendImageData {
|
|
||||||
path: layer_path.clone(),
|
|
||||||
image_data,
|
|
||||||
mime,
|
|
||||||
}];
|
|
||||||
responses.push_back(FrontendMessage::UpdateImageData { document_id, image_data }.into());
|
|
||||||
|
|
||||||
// Update the transform based on the graph output
|
|
||||||
let transform = transform.to_cols_array();
|
|
||||||
responses.push_back(Operation::SetLayerTransform { path: layer_path, transform }.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -374,11 +374,21 @@ mod image {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DynAny, Default)]
|
#[derive(Clone, Debug, PartialEq, DynAny, Default, specta::Type)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct ImageFrame {
|
pub struct ImageFrame {
|
||||||
pub image: Image,
|
pub image: Image,
|
||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ImageFrame {
|
||||||
|
pub const fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
image: Image::empty(),
|
||||||
|
transform: DAffine2::ZERO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub enum TaggedValue {
|
|||||||
DAffine2(DAffine2),
|
DAffine2(DAffine2),
|
||||||
Image(graphene_core::raster::Image),
|
Image(graphene_core::raster::Image),
|
||||||
RcImage(Option<Arc<graphene_core::raster::Image>>),
|
RcImage(Option<Arc<graphene_core::raster::Image>>),
|
||||||
|
ImageFrame(graphene_core::raster::ImageFrame),
|
||||||
Color(graphene_core::raster::color::Color),
|
Color(graphene_core::raster::color::Color),
|
||||||
Subpath(graphene_core::vector::subpath::Subpath),
|
Subpath(graphene_core::vector::subpath::Subpath),
|
||||||
RcSubpath(Arc<graphene_core::vector::subpath::Subpath>),
|
RcSubpath(Arc<graphene_core::vector::subpath::Subpath>),
|
||||||
@@ -113,6 +114,11 @@ impl Hash for TaggedValue {
|
|||||||
19.hash(state);
|
19.hash(state);
|
||||||
p.hash(state)
|
p.hash(state)
|
||||||
}
|
}
|
||||||
|
Self::ImageFrame(i) => {
|
||||||
|
20.hash(state);
|
||||||
|
i.image.hash(state);
|
||||||
|
i.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,6 +138,7 @@ impl<'a> TaggedValue {
|
|||||||
TaggedValue::DAffine2(x) => Box::new(x),
|
TaggedValue::DAffine2(x) => Box::new(x),
|
||||||
TaggedValue::Image(x) => Box::new(x),
|
TaggedValue::Image(x) => Box::new(x),
|
||||||
TaggedValue::RcImage(x) => Box::new(x),
|
TaggedValue::RcImage(x) => Box::new(x),
|
||||||
|
TaggedValue::ImageFrame(x) => Box::new(x),
|
||||||
TaggedValue::Color(x) => Box::new(x),
|
TaggedValue::Color(x) => Box::new(x),
|
||||||
TaggedValue::Subpath(x) => Box::new(x),
|
TaggedValue::Subpath(x) => Box::new(x),
|
||||||
TaggedValue::RcSubpath(x) => Box::new(x),
|
TaggedValue::RcSubpath(x) => Box::new(x),
|
||||||
@@ -157,6 +164,7 @@ impl<'a> TaggedValue {
|
|||||||
TaggedValue::OptionalDVec2(_) => concrete!(Option<DVec2>),
|
TaggedValue::OptionalDVec2(_) => concrete!(Option<DVec2>),
|
||||||
TaggedValue::Image(_) => concrete!(graphene_core::raster::Image),
|
TaggedValue::Image(_) => concrete!(graphene_core::raster::Image),
|
||||||
TaggedValue::RcImage(_) => concrete!(Option<Arc<graphene_core::raster::Image>>),
|
TaggedValue::RcImage(_) => concrete!(Option<Arc<graphene_core::raster::Image>>),
|
||||||
|
TaggedValue::ImageFrame(_) => concrete!(graphene_core::raster::ImageFrame),
|
||||||
TaggedValue::Color(_) => concrete!(graphene_core::raster::Color),
|
TaggedValue::Color(_) => concrete!(graphene_core::raster::Color),
|
||||||
TaggedValue::Subpath(_) => concrete!(graphene_core::vector::subpath::Subpath),
|
TaggedValue::Subpath(_) => concrete!(graphene_core::vector::subpath::Subpath),
|
||||||
TaggedValue::RcSubpath(_) => concrete!(Arc<graphene_core::vector::subpath::Subpath>),
|
TaggedValue::RcSubpath(_) => concrete!(Arc<graphene_core::vector::subpath::Subpath>),
|
||||||
|
|||||||
Reference in New Issue
Block a user