mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 03:18:06 +08:00
Lay groundwork for adaptive resolution system (#1395)
* Make transform node accept footprint as input and pass it along to its input use f32 instead of f64 and add default to document node definition * Add cull node * Fix types for Transform and Cull Nodes * Add render config struct * Add Render Node skeleton * Add Render Node to node_registry * Make types macro use macro hygiene * Place Render Node as output * Start making DownresNode footprint aware * Correctly calculate footprint in Transform Node * Add cropping and resizing to downres node * Fix Output node declaration * Fix image transform * Fix Vector Data rendering * Add concept of ImageRenderMode * Take base image size into account when calculating the final image size * Supply viewport transform to the node graph * Start adapting document graph to resolution agnosticism * Make document node short circuting not shift the input index * Apply clippy lints
This commit is contained in:
committed by
Keavon Chambers
parent
239ca698e5
commit
d82f133514
@@ -13,12 +13,12 @@ use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{generate_uuid, DocumentNodeImplementation, NodeId, NodeNetwork};
|
||||
use graph_craft::graphene_compiler::Compiler;
|
||||
use graph_craft::imaginate_input::ImaginatePreferences;
|
||||
use graph_craft::{concrete, Type, TypeDescriptor};
|
||||
use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender};
|
||||
use graph_craft::{concrete, Type};
|
||||
use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
|
||||
use graphene_core::raster::{Image, ImageFrame};
|
||||
use graphene_core::renderer::{ClickTarget, SvgSegment, SvgSegmentList};
|
||||
use graphene_core::text::FontCache;
|
||||
use graphene_core::transform::Transform;
|
||||
use graphene_core::transform::{Footprint, Transform};
|
||||
use graphene_core::vector::style::ViewMode;
|
||||
|
||||
use graphene_core::{Color, SurfaceFrame, SurfaceId};
|
||||
@@ -26,7 +26,6 @@ use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
|
||||
use interpreted_executor::dynamic_executor::DynamicExecutor;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
@@ -72,6 +71,7 @@ pub(crate) struct GenerationRequest {
|
||||
graph: NodeNetwork,
|
||||
path: Vec<LayerId>,
|
||||
image_frame: Option<ImageFrame<Color>>,
|
||||
transform: DAffine2,
|
||||
}
|
||||
|
||||
pub(crate) struct GenerationResponse {
|
||||
@@ -140,6 +140,7 @@ impl NodeRuntime {
|
||||
generation_id,
|
||||
graph,
|
||||
image_frame,
|
||||
transform,
|
||||
path,
|
||||
..
|
||||
}) => {
|
||||
@@ -151,7 +152,7 @@ impl NodeRuntime {
|
||||
.map(|node| node.path.clone().unwrap_or_default())
|
||||
.collect();
|
||||
|
||||
let result = self.execute_network(&path, network, image_frame).await;
|
||||
let result = self.execute_network(&path, network, image_frame, transform).await;
|
||||
let mut responses = VecDeque::new();
|
||||
self.update_thumbnails(&path, monitor_nodes, &mut responses);
|
||||
let response = GenerationResponse {
|
||||
@@ -168,7 +169,7 @@ impl NodeRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute_network<'a>(&'a mut self, path: &[LayerId], scoped_network: NodeNetwork, image_frame: Option<ImageFrame<Color>>) -> Result<TaggedValue, String> {
|
||||
async fn execute_network<'a>(&'a mut self, path: &[LayerId], scoped_network: NodeNetwork, image_frame: Option<ImageFrame<Color>>, transform: DAffine2) -> Result<TaggedValue, String> {
|
||||
if self.wasm_io.is_none() {
|
||||
self.wasm_io = Some(WasmApplicationIo::new().await);
|
||||
}
|
||||
@@ -179,6 +180,10 @@ impl NodeRuntime {
|
||||
application_io: self.wasm_io.as_ref().unwrap(),
|
||||
node_graph_message_sender: &self.sender,
|
||||
imaginate_preferences: &self.imaginate_preferences,
|
||||
render_config: RenderConfig {
|
||||
viewport: Footprint { transform, ..Default::default() },
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
|
||||
// We assume only one output
|
||||
@@ -197,7 +202,8 @@ impl NodeRuntime {
|
||||
let result = match self.executor.input_type() {
|
||||
Some(t) if t == concrete!(WasmEditorApi) => (&self.executor).execute(editor_api).await.map_err(|e| e.to_string()),
|
||||
Some(t) if t == concrete!(()) => (&self.executor).execute(()).await.map_err(|e| e.to_string()),
|
||||
_ => Err("Invalid input type".to_string()),
|
||||
Some(t) => Err(format!("Invalid input type {:?}", t)),
|
||||
_ => Err("No input type".to_string()),
|
||||
}?;
|
||||
|
||||
if let TaggedValue::SurfaceFrame(SurfaceFrame { surface_id, transform: _ }) = result {
|
||||
@@ -231,7 +237,7 @@ impl NodeRuntime {
|
||||
};
|
||||
use graphene_core::renderer::*;
|
||||
let bounds = graphic_element_data.bounding_box(DAffine2::IDENTITY);
|
||||
let render_params = RenderParams::new(ViewMode::Normal, bounds, true);
|
||||
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::BlobUrl, bounds, true);
|
||||
let mut render = SvgRender::new();
|
||||
graphic_element_data.render_svg(&mut render, &render_params);
|
||||
let [min, max] = bounds.unwrap_or_default();
|
||||
@@ -339,13 +345,14 @@ impl Default for NodeGraphExecutor {
|
||||
|
||||
impl NodeGraphExecutor {
|
||||
/// Execute the network by flattening it and creating a borrow stack.
|
||||
fn queue_execution(&self, network: NodeNetwork, image_frame: Option<ImageFrame<Color>>, layer_path: Vec<LayerId>) -> u64 {
|
||||
fn queue_execution(&self, network: NodeNetwork, image_frame: Option<ImageFrame<Color>>, layer_path: Vec<LayerId>, transform: DAffine2) -> u64 {
|
||||
let generation_id = generate_uuid();
|
||||
let request = GenerationRequest {
|
||||
path: layer_path,
|
||||
graph: network,
|
||||
image_frame,
|
||||
generation_id,
|
||||
transform,
|
||||
};
|
||||
self.sender.send(NodeRuntimeMessage::GenerationRequest(request)).expect("Failed to send generation request");
|
||||
|
||||
@@ -452,9 +459,10 @@ impl NodeGraphExecutor {
|
||||
// Construct the input image frame
|
||||
let transform = DAffine2::IDENTITY;
|
||||
let image_frame = ImageFrame { image, transform };
|
||||
let document_transform = document.document_legacy.metadata.document_to_viewport;
|
||||
|
||||
// Execute the node graph
|
||||
let generation_id = self.queue_execution(network, Some(image_frame), layer_path.clone());
|
||||
let generation_id = self.queue_execution(network, Some(image_frame), layer_path.clone(), document_transform);
|
||||
|
||||
self.futures.insert(generation_id, ExecutionContext { layer_path, document_id });
|
||||
|
||||
@@ -533,12 +541,21 @@ impl NodeGraphExecutor {
|
||||
warn!("Rendered graph produced artboard (which is not currently rendered): {artboard:#?}");
|
||||
return Err("Artboard (see console)".to_string());
|
||||
}
|
||||
TaggedValue::RenderOutput(graphene_std::wasm_application_io::RenderOutput::Svg(svg)) => {
|
||||
// Send to frontend
|
||||
log::debug!("svg: {svg}");
|
||||
responses.add(FrontendMessage::UpdateDocumentNodeRender { svg });
|
||||
responses.add(DocumentMessage::RenderScrollbars);
|
||||
//responses.add(FrontendMessage::UpdateDocumentNodeRender { svg });
|
||||
|
||||
//return Err("Graphic group (see console)".to_string());
|
||||
}
|
||||
TaggedValue::GraphicGroup(graphic_group) => {
|
||||
use graphene_core::renderer::{GraphicElementRendered, RenderParams, SvgRender};
|
||||
|
||||
// Setup rendering
|
||||
let mut render = SvgRender::new();
|
||||
let render_params = RenderParams::new(ViewMode::Normal, None, false);
|
||||
let render_params = RenderParams::new(ViewMode::Normal, graphene_core::renderer::ImageRenderMode::BlobUrl, None, false);
|
||||
|
||||
// Render svg
|
||||
graphic_group.render_svg(&mut render, &render_params);
|
||||
|
||||
Reference in New Issue
Block a user