mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 15:28:04 +08:00
Incremental compilation and stable node IDs (#977)
* Generate stable node ids * checkpoint * Implement borrow tree * Add eval function on borrow tree * Refactor Node trait to fix lifetime issues * Compiler infinite loop * Impl compose pair * Transition to double lifetime on trait * Change node trait to use a generic arg for the input * Start adapting node_macro * Migrate more nodes to new macro * Fix raster tests * Port vector nodes * Make Node trait object safe * Fix FlatMapResultNode * Translate most of gstd * Fix DowncastBothNode * Refactor node trait once again to allow for HRTB for type erased nodes * Start working on type erased nodes * Try getting DowncastBothNode to work * Introduce Upcasting node + work on BorrowTree * Make enough 'static to get the code to compile * Transition DynamicExecutor to use borrow tree * Make Compose Node use HRTB's * Fix MapResultNode * Disable blur test * Add workaround for Composing type erased nodes * Convert more nodes in the node_registry * Convert more of the node_registry * Add update tree fn and hook up to frontend * Fix blur node * Implement CacheNode * Make frontend use graph compiler * Fix document_node_types type declaration for most nodes * Remove unused imports * Move comment down * Reuse nodes via borrow tree * Deprecate trait based value in favor of TaggedValue * Remove unsafe code in buffer creation * Fix blur node * Fix stable node id generation * Fix types for Image adjustment document nodes * Fix Imaginate Node * Remove unused imports * Remove log * Fix off by one error * Remove macro generated imaginate node entry * Create parameterized add node * Fix test case * Remove link from layer_panel.rs * Fix formatting
This commit is contained in:
committed by
Keavon Chambers
parent
12d6818d73
commit
004e87ca3e
@@ -68,7 +68,7 @@ pub const ASYMPTOTIC_EFFECT: f64 = 0.5;
|
||||
pub const SCALE_EFFECT: f64 = 0.5;
|
||||
|
||||
// Colors
|
||||
pub const COLOR_ACCENT: Color = Color::from_unsafe(0x00 as f32 / 255., 0xA8 as f32 / 255., 0xFF as f32 / 255.);
|
||||
pub const COLOR_ACCENT: Color = Color::from_uchecked(0x00 as f32 / 255., 0xA8 as f32 / 255., 0xFF as f32 / 255.);
|
||||
|
||||
// Fonts
|
||||
pub const DEFAULT_FONT_FAMILY: &str = "Merriweather";
|
||||
|
||||
@@ -284,7 +284,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
}
|
||||
ClearLayerTree => {
|
||||
// Send an empty layer tree
|
||||
let data_buffer: RawBuffer = Self::default().serialize_root().into();
|
||||
let data_buffer: RawBuffer = Self::default().serialize_root().as_slice().into();
|
||||
responses.push_back(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer }.into());
|
||||
|
||||
// Clear the options bar
|
||||
@@ -360,7 +360,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
DocumentHistoryBackward => self.undo(responses).unwrap_or_else(|e| warn!("{}", e)),
|
||||
DocumentHistoryForward => self.redo(responses).unwrap_or_else(|e| warn!("{}", e)),
|
||||
DocumentStructureChanged => {
|
||||
let data_buffer: RawBuffer = self.serialize_root().into();
|
||||
let data_buffer: RawBuffer = self.serialize_root().as_slice().into();
|
||||
responses.push_back(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer }.into())
|
||||
}
|
||||
DuplicateSelectedLayers => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use super::{node_properties, FrontendGraphDataType, FrontendNodeType};
|
||||
use crate::messages::layout::utility_types::layout_widget::LayoutGroup;
|
||||
|
||||
use graph_craft::concrete;
|
||||
use graph_craft::document::value::*;
|
||||
use graph_craft::document::*;
|
||||
use graph_craft::document::{value::*, DocumentNodeImplementation};
|
||||
use graph_craft::imaginate_input::ImaginateSamplingMethod;
|
||||
use graph_craft::proto::{NodeIdentifier, Type};
|
||||
use graph_craft::{concrete, generic};
|
||||
use graphene_core::raster::Image;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
@@ -91,8 +91,8 @@ fn document_node_types() -> Vec<DocumentNodeType> {
|
||||
1,
|
||||
DocumentNode {
|
||||
name: "BlurNode".to_string(),
|
||||
inputs: vec![NodeInput::Node(0), NodeInput::Network, NodeInput::Network],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlurNode", &[])),
|
||||
inputs: vec![NodeInput::Node(0), NodeInput::Network, NodeInput::Network, NodeInput::Node(0)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlurNode", &[concrete!("Image")])),
|
||||
metadata: Default::default(),
|
||||
},
|
||||
),
|
||||
@@ -118,7 +118,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Identity",
|
||||
category: "General",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[concrete!("Any<'_>")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[generic!("T")]),
|
||||
inputs: &[DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -130,7 +130,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Image",
|
||||
category: "Ignore",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[concrete!("Any<'_>")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[generic!("T")]),
|
||||
inputs: &[DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), false)],
|
||||
outputs: &[FrontendGraphDataType::Raster],
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"),
|
||||
@@ -138,7 +138,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Input",
|
||||
category: "Ignore",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[concrete!("Any<'_>")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[generic!("T")]),
|
||||
inputs: &[DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
@@ -150,7 +150,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Output",
|
||||
category: "Ignore",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[concrete!("Any<'_>")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[generic!("T")]),
|
||||
inputs: &[DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
@@ -162,7 +162,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Grayscale",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::GrayscaleNode", &[]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::GrayscaleNode", &[concrete!("Image")]),
|
||||
inputs: &[DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true)],
|
||||
outputs: &[FrontendGraphDataType::Raster],
|
||||
properties: node_properties::no_properties,
|
||||
@@ -171,7 +171,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "GpuImage",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::executor::MapGpuSingleImageNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::executor::MapGpuSingleImageNode", &[concrete!("Image")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType {
|
||||
@@ -187,7 +187,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "QuantizeImage",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::quantization::GenerateQuantizationNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::quantization::GenerateQuantizationNode", &[concrete!("Image")]),
|
||||
inputs: &[
|
||||
DocumentInputType {
|
||||
name: "Image",
|
||||
@@ -219,7 +219,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Invert RGB",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::InvertRGBNode", &[]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::InvertRGBNode", &[concrete!("Image")]),
|
||||
inputs: &[DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true)],
|
||||
outputs: &[FrontendGraphDataType::Raster],
|
||||
properties: node_properties::no_properties,
|
||||
@@ -227,7 +227,10 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Hue/Saturation",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::HueSaturationNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto(
|
||||
"graphene_std::raster::HueSaturationNode<_, _, _>",
|
||||
&[concrete!("Image"), concrete!("f64"), concrete!("f64"), concrete!("f64")],
|
||||
),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Hue Shift", TaggedValue::F64(0.), false),
|
||||
@@ -240,7 +243,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Brightness/Contrast",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::BrightnessContrastNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::BrightnessContrastNode<_, _>", &[concrete!("Image"), concrete!("f64"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Brightness", TaggedValue::F64(0.), false),
|
||||
@@ -252,7 +255,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Gamma",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::GammaNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::GammaNode<_>", &[concrete!("Image"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Gamma", TaggedValue::F64(1.), false),
|
||||
@@ -263,7 +266,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Opacity",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::OpacityNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::OpacityNode<_>", &[concrete!("Image"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Factor", TaggedValue::F64(1.), false),
|
||||
@@ -274,7 +277,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Posterize",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::PosterizeNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::PosterizeNode<_>", &[concrete!("Image"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Value", TaggedValue::F64(5.), false),
|
||||
@@ -285,7 +288,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Exposure",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::ExposureNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::ExposureNode<_>", &[concrete!("Image"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Value", TaggedValue::F64(0.), false),
|
||||
@@ -297,7 +300,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Add",
|
||||
category: "Math",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::AddNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::AddParameterNode<_>", &[concrete!("f64"), concrete!("f64")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Input", TaggedValue::F64(0.), true),
|
||||
DocumentInputType::new("Addend", TaggedValue::F64(0.), true),
|
||||
@@ -324,7 +327,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
DocumentNodeType {
|
||||
name: "Path Generator",
|
||||
category: "Vector",
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[concrete!("Any<'_>")]),
|
||||
identifier: NodeImplementation::proto("graphene_core::ops::IdNode", &[generic!("T")]),
|
||||
inputs: &[DocumentInputType {
|
||||
name: "Path Data",
|
||||
data_type: FrontendGraphDataType::Subpath,
|
||||
@@ -363,7 +366,7 @@ static STATIC_NODES: &[DocumentNodeType] = &[
|
||||
pub const IMAGINATE_NODE: DocumentNodeType = DocumentNodeType {
|
||||
name: "Imaginate",
|
||||
category: "Image Synthesis",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::ImaginateNode", &[concrete!("&TypeErasedNode")]),
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::ImaginateNode<_>", &[concrete!("Image"), concrete!("Option<std::sync::Arc<Image>>")]),
|
||||
inputs: &[
|
||||
DocumentInputType::new("Input Image", TaggedValue::Image(Image::empty()), true),
|
||||
DocumentInputType::new("Seed", TaggedValue::F64(0.), false),
|
||||
|
||||
@@ -373,7 +373,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
||||
panic!("Invalid status input")
|
||||
};
|
||||
let NodeInput::Value {tagged_value: TaggedValue::RcImage( cached_data),..} = cached_value else {
|
||||
panic!("Invalid cached image input")
|
||||
panic!("Invalid cached image input, recieved {:?}, index: {}", cached_value, cached_index)
|
||||
};
|
||||
let &NodeInput::Value {tagged_value: TaggedValue::F64( percent_complete),..} = complete_value else {
|
||||
panic!("Invalid percent complete input")
|
||||
|
||||
@@ -9,15 +9,9 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)]
|
||||
pub struct RawBuffer(Vec<u8>);
|
||||
|
||||
impl From<Vec<u64>> for RawBuffer {
|
||||
fn from(iter: Vec<u64>) -> Self {
|
||||
// https://github.com/rust-lang/rust-clippy/issues/4484
|
||||
let v_from_raw: Vec<u8> = unsafe {
|
||||
// prepare for an auto-forget of the initial vec:
|
||||
let v_orig: &mut Vec<_> = &mut *std::mem::ManuallyDrop::new(iter);
|
||||
Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut u8, v_orig.len() * 8, v_orig.capacity() * 8)
|
||||
// v_orig is never used again, so no aliasing issue
|
||||
};
|
||||
impl From<&[u64]> for RawBuffer {
|
||||
fn from(iter: &[u64]) -> Self {
|
||||
let v_from_raw: Vec<u8> = iter.iter().flat_map(|x| x.to_ne_bytes()).collect();
|
||||
Self(v_from_raw)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ use document_legacy::{LayerId, Operation as DocumentOperation};
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::NodeId;
|
||||
use graph_craft::document::{NodeInput, NodeNetwork};
|
||||
use graph_craft::executor::Compiler;
|
||||
use graphene_core::raster::Image;
|
||||
|
||||
use glam::DVec2;
|
||||
use interpreted_executor::executor::DynamicExecutor;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
@@ -30,6 +32,7 @@ pub struct PortfolioMessageHandler {
|
||||
menu_bar_message_handler: MenuBarMessageHandler,
|
||||
documents: HashMap<u64, DocumentMessageHandler>,
|
||||
document_ids: Vec<u64>,
|
||||
executor: interpreted_executor::executor::DynamicExecutor,
|
||||
active_document_id: Option<u64>,
|
||||
copy_buffer: [Vec<CopyBufferEntry>; INTERNAL_CLIPBOARD_COUNT as usize],
|
||||
pub persistent_data: PersistentData,
|
||||
@@ -680,39 +683,31 @@ impl PortfolioMessageHandler {
|
||||
}
|
||||
|
||||
/// Execute the network by flattening it and creating a borrow stack. Casts the output to the generic `T`.
|
||||
fn execute_network<T: dyn_any::StaticType>(mut network: NodeNetwork, image: Image) -> Result<T, String> {
|
||||
for node_id in network.nodes.keys().copied().collect::<Vec<_>>() {
|
||||
network.flatten(node_id);
|
||||
}
|
||||
|
||||
let mut proto_network = network.into_proto_network();
|
||||
proto_network.reorder_ids();
|
||||
fn execute_network<T: dyn_any::StaticType>(executor: &mut DynamicExecutor, network: NodeNetwork, image: Image) -> Result<T, String> {
|
||||
let c = Compiler {};
|
||||
let proto_network = c.compile(network, true);
|
||||
|
||||
assert_ne!(proto_network.nodes.len(), 0, "No protonodes exist?");
|
||||
let stack = borrow_stack::FixedSizeStack::new(proto_network.nodes.len());
|
||||
for (_id, node) in proto_network.nodes {
|
||||
interpreted_executor::node_registry::push_node(node, &stack);
|
||||
}
|
||||
executor.update(proto_network);
|
||||
|
||||
use borrow_stack::BorrowStack;
|
||||
use dyn_any::IntoDynAny;
|
||||
use graphene_core::Node;
|
||||
use graph_craft::executor::Executor;
|
||||
|
||||
let boxed = unsafe { stack.get().last().unwrap().eval(image.into_dyn()) };
|
||||
let boxed = executor.execute(image.into_dyn()).map_err(|e| e.to_string())?;
|
||||
|
||||
dyn_any::downcast::<T>(boxed).map(|v| *v)
|
||||
}
|
||||
|
||||
/// Computes an input for a node in the graph
|
||||
fn compute_input<T: dyn_any::StaticType>(old_network: &NodeNetwork, node_path: &[NodeId], mut input_index: usize, image: Cow<Image>) -> Result<T, String> {
|
||||
fn compute_input<T: dyn_any::StaticType>(executor: &mut DynamicExecutor, old_network: &NodeNetwork, node_path: &[NodeId], mut input_index: usize, image: Cow<Image>) -> Result<T, String> {
|
||||
let mut network = old_network.clone();
|
||||
// Adjust the output of the graph so we find the relevant output
|
||||
'outer: for end in (0..node_path.len()).rev() {
|
||||
let mut inner_network = &mut network;
|
||||
for node_id in node_path.iter().take(end) {
|
||||
inner_network.output = *node_id;
|
||||
for &node_id in &node_path[..end] {
|
||||
inner_network.output = node_id;
|
||||
|
||||
let Some(new_inner) = inner_network.nodes.get_mut(node_id).and_then(|node| node.implementation.get_network_mut()) else {
|
||||
let Some(new_inner) = inner_network.nodes.get_mut(&node_id).and_then(|node| node.implementation.get_network_mut()) else {
|
||||
return Err("Failed to find network".to_string());
|
||||
};
|
||||
inner_network = new_inner;
|
||||
@@ -730,7 +725,7 @@ impl PortfolioMessageHandler {
|
||||
.0;
|
||||
}
|
||||
// If the input is just a value, return that value
|
||||
NodeInput::Value { tagged_value, .. } => return dyn_any::downcast::<T>(tagged_value.clone().to_value().up_box()).map(|v| *v),
|
||||
NodeInput::Value { tagged_value, .. } => return dyn_any::downcast::<T>(tagged_value.clone().to_any()).map(|v| *v),
|
||||
// If the input is from a node, set the node to be the output (so that is what is evaluated)
|
||||
NodeInput::Node(n) => {
|
||||
inner_network.output = *n;
|
||||
@@ -739,7 +734,7 @@ impl PortfolioMessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
Self::execute_network(network, image.into_owned())
|
||||
Self::execute_network(executor, network, image.into_owned())
|
||||
}
|
||||
|
||||
/// Encodes an image into a format using the image crate
|
||||
@@ -793,7 +788,7 @@ impl PortfolioMessageHandler {
|
||||
|
||||
let get = |name: &str| IMAGINATE_NODE.inputs.iter().position(|input| input.name == name).unwrap_or_else(|| panic!("Input {name} not found"));
|
||||
|
||||
let resolution: Option<glam::DVec2> = Self::compute_input(&network, &imaginate_node, get("Resolution"), Cow::Borrowed(&image))?;
|
||||
let resolution: Option<glam::DVec2> = Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Resolution"), Cow::Borrowed(&image))?;
|
||||
let resolution = resolution.unwrap_or_else(|| {
|
||||
let transform = document.document_legacy.root.transform.inverse() * document.document_legacy.multiply_transforms(&layer_path).unwrap();
|
||||
let (x, y) = pick_safe_imaginate_resolution((transform.transform_vector2(DVec2::new(1., 0.)).length(), transform.transform_vector2(DVec2::new(0., 1.)).length()));
|
||||
@@ -802,23 +797,23 @@ impl PortfolioMessageHandler {
|
||||
|
||||
let transform = document.document_legacy.root.transform.inverse() * document.document_legacy.multiply_transforms(&layer_path).unwrap();
|
||||
let parameters = ImaginateGenerationParameters {
|
||||
seed: Self::compute_input::<f64>(&network, &imaginate_node, get("Seed"), Cow::Borrowed(&image))? as u64,
|
||||
seed: Self::compute_input::<f64>(&mut self.executor, &network, &imaginate_node, get("Seed"), Cow::Borrowed(&image))? as u64,
|
||||
resolution: resolution.as_uvec2().into(),
|
||||
samples: Self::compute_input::<f64>(&network, &imaginate_node, get("Samples"), Cow::Borrowed(&image))? as u32,
|
||||
sampling_method: Self::compute_input::<ImaginateSamplingMethod>(&network, &imaginate_node, get("Sampling Method"), Cow::Borrowed(&image))?
|
||||
samples: Self::compute_input::<f64>(&mut self.executor, &network, &imaginate_node, get("Samples"), Cow::Borrowed(&image))? as u32,
|
||||
sampling_method: Self::compute_input::<ImaginateSamplingMethod>(&mut self.executor, &network, &imaginate_node, get("Sampling Method"), Cow::Borrowed(&image))?
|
||||
.api_value()
|
||||
.to_string(),
|
||||
text_guidance: Self::compute_input(&network, &imaginate_node, get("Prompt Guidance"), Cow::Borrowed(&image))?,
|
||||
text_prompt: Self::compute_input(&network, &imaginate_node, get("Prompt"), Cow::Borrowed(&image))?,
|
||||
negative_prompt: Self::compute_input(&network, &imaginate_node, get("Negative Prompt"), Cow::Borrowed(&image))?,
|
||||
image_creativity: Some(Self::compute_input::<f64>(&network, &imaginate_node, get("Image Creativity"), Cow::Borrowed(&image))? / 100.),
|
||||
restore_faces: Self::compute_input(&network, &imaginate_node, get("Improve Faces"), Cow::Borrowed(&image))?,
|
||||
tiling: Self::compute_input(&network, &imaginate_node, get("Tiling"), Cow::Borrowed(&image))?,
|
||||
text_guidance: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Prompt Guidance"), Cow::Borrowed(&image))?,
|
||||
text_prompt: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Prompt"), Cow::Borrowed(&image))?,
|
||||
negative_prompt: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Negative Prompt"), Cow::Borrowed(&image))?,
|
||||
image_creativity: Some(Self::compute_input::<f64>(&mut self.executor, &network, &imaginate_node, get("Image Creativity"), Cow::Borrowed(&image))? / 100.),
|
||||
restore_faces: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Improve Faces"), Cow::Borrowed(&image))?,
|
||||
tiling: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Tiling"), Cow::Borrowed(&image))?,
|
||||
};
|
||||
let use_base_image = Self::compute_input::<bool>(&network, &imaginate_node, get("Adapt Input Image"), Cow::Borrowed(&image))?;
|
||||
let use_base_image = Self::compute_input::<bool>(&mut self.executor, &network, &imaginate_node, get("Adapt Input Image"), Cow::Borrowed(&image))?;
|
||||
|
||||
let base_image = if use_base_image {
|
||||
let image: Image = Self::compute_input(&network, &imaginate_node, get("Input Image"), Cow::Borrowed(&image))?;
|
||||
let image: Image = Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Input Image"), Cow::Borrowed(&image))?;
|
||||
// Only use if has size
|
||||
if image.width > 0 && image.height > 0 {
|
||||
let (image_data, size) = Self::encode_img(image, Some(resolution), image::ImageOutputFormat::Png)?;
|
||||
@@ -834,7 +829,7 @@ impl PortfolioMessageHandler {
|
||||
|
||||
let mask_image =
|
||||
if base_image.is_some() {
|
||||
let mask_path: Option<Vec<LayerId>> = Self::compute_input(&network, &imaginate_node, get("Masking Layer"), Cow::Borrowed(&image))?;
|
||||
let mask_path: Option<Vec<LayerId>> = Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Masking Layer"), Cow::Borrowed(&image))?;
|
||||
|
||||
// Calculate the size of the node graph frame
|
||||
let size = DVec2::new(transform.transform_vector2(DVec2::new(1., 0.)).length(), transform.transform_vector2(DVec2::new(0., 1.)).length());
|
||||
@@ -864,13 +859,13 @@ impl PortfolioMessageHandler {
|
||||
parameters: Box::new(parameters),
|
||||
base_image: base_image.map(Box::new),
|
||||
mask_image: mask_image.map(Box::new),
|
||||
mask_paint_mode: if Self::compute_input::<bool>(&network, &imaginate_node, get("Inpaint"), Cow::Borrowed(&image))? {
|
||||
mask_paint_mode: if Self::compute_input::<bool>(&mut self.executor, &network, &imaginate_node, get("Inpaint"), Cow::Borrowed(&image))? {
|
||||
ImaginateMaskPaintMode::Inpaint
|
||||
} else {
|
||||
ImaginateMaskPaintMode::Outpaint
|
||||
},
|
||||
mask_blur_px: Self::compute_input::<f64>(&network, &imaginate_node, get("Mask Blur"), Cow::Borrowed(&image))? as u32,
|
||||
imaginate_mask_starting_fill: Self::compute_input(&network, &imaginate_node, get("Mask Starting Fill"), Cow::Borrowed(&image))?,
|
||||
mask_blur_px: Self::compute_input::<f64>(&mut self.executor, &network, &imaginate_node, get("Mask Blur"), Cow::Borrowed(&image))? as u32,
|
||||
imaginate_mask_starting_fill: Self::compute_input(&mut self.executor, &network, &imaginate_node, get("Mask Starting Fill"), Cow::Borrowed(&image))?,
|
||||
hostname: preferences.imaginate_server_hostname.clone(),
|
||||
refresh_frequency: preferences.imaginate_refresh_frequency,
|
||||
document_id,
|
||||
@@ -880,7 +875,7 @@ impl PortfolioMessageHandler {
|
||||
.into(),
|
||||
);
|
||||
} else {
|
||||
let mut image: Image = Self::execute_network(network, image)?;
|
||||
let mut image: Image = Self::execute_network(&mut self.executor, network, image)?;
|
||||
|
||||
// If no image was generated, use the input image
|
||||
if image.width == 0 || image.height == 0 {
|
||||
|
||||
Reference in New Issue
Block a user