Fix most known issues with migrations failing to open documents from the past year (#3148)
This commit is contained in:
parent
89c9cf1352
commit
a2c0693038
|
|
@ -1786,7 +1786,7 @@ impl DocumentMessageHandler {
|
||||||
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
|
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
|
||||||
let document_message_handler = serde_json::from_str::<DocumentMessageHandler>(serialized_content)
|
let document_message_handler = serde_json::from_str::<DocumentMessageHandler>(serialized_content)
|
||||||
.or_else(|e| {
|
.or_else(|e| {
|
||||||
log::warn!("failed to directly load document with the following error: {e}. Trying old DocumentMessageHandler");
|
log::warn!("Failed to directly load document with the following error: {e}. Trying old DocumentMessageHandler.");
|
||||||
// TODO: Eventually remove this document upgrade code
|
// TODO: Eventually remove this document upgrade code
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct OldDocumentMessageHandler {
|
pub struct OldDocumentMessageHandler {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,13 @@ pub enum EditorError {
|
||||||
#[error("The operation caused a document error:\n{0:?}")]
|
#[error("The operation caused a document error:\n{0:?}")]
|
||||||
Document(String),
|
Document(String),
|
||||||
|
|
||||||
#[error("This document was created in an older version of the editor.\n\nBackwards compatibility is, regrettably, not present in the current alpha release.\n\nTechnical details:\n{0:?}")]
|
#[error(
|
||||||
|
"This document was created in an older version of the editor.\n\
|
||||||
|
\n\
|
||||||
|
Full backwards compatibility is not guaranteed in the current alpha release.\n\
|
||||||
|
\n\
|
||||||
|
If this document is critical, ask for support in Graphite's Discord community."
|
||||||
|
)]
|
||||||
DocumentDeserialization(String),
|
DocumentDeserialization(String),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,7 @@ impl NodeNetworkInterface {
|
||||||
let skip_footprint = 1;
|
let skip_footprint = 1;
|
||||||
|
|
||||||
let Some(input_type) = std::iter::once(node_types.call_argument.clone()).chain(node_types.inputs.clone()).nth(input_index + skip_footprint) else {
|
let Some(input_type) = std::iter::once(node_types.call_argument.clone()).chain(node_types.inputs.clone()).nth(input_index + skip_footprint) else {
|
||||||
log::error!("Could not get type for {node_id_path:?}, input: {input_index}");
|
// log::warn!("Could not get type for {node_id_path:?}, input: {input_index}");
|
||||||
return (concrete!(()), TypeSource::Error("could not get the protonode's input"));
|
return (concrete!(()), TypeSource::Error("could not get the protonode's input"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2629,7 +2629,7 @@ impl NodeNetworkInterface {
|
||||||
InputConnector::Node { node_id, input_index } => {
|
InputConnector::Node { node_id, input_index } => {
|
||||||
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else { return };
|
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else { return };
|
||||||
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
||||||
log::error!("Node metadata must exist on node: {input:?}");
|
// log::warn!("Node metadata must exist on node: {input:?}");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let wire_update = WirePathUpdate {
|
let wire_update = WirePathUpdate {
|
||||||
|
|
@ -2721,7 +2721,7 @@ impl NodeNetworkInterface {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
||||||
log::error!("Node metadata must exist on node: {input:?}");
|
// log::warn!("Node metadata must exist on node: {input:?}");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
input_metadata.transient_metadata.wire = TransientMetadata::Unloaded;
|
input_metadata.transient_metadata.wire = TransientMetadata::Unloaded;
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||||
node: graphene_std::math_nodes::root::IDENTIFIER,
|
node: graphene_std::math_nodes::root::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ops::RootNode"],
|
aliases: &["graphene_core::ops::RootNode"],
|
||||||
},
|
},
|
||||||
|
NodeReplacement {
|
||||||
|
node: graphene_std::math_nodes::absolute_value::IDENTIFIER,
|
||||||
|
aliases: &["graphene_core::ops::AbsoluteValueNode"],
|
||||||
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::math_nodes::logarithm::IDENTIFIER,
|
node: graphene_std::math_nodes::logarithm::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ops::LogarithmNode"],
|
aliases: &["graphene_core::ops::LogarithmNode"],
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ pub enum PortfolioMessage {
|
||||||
document_is_saved: bool,
|
document_is_saved: bool,
|
||||||
document_serialized_content: String,
|
document_serialized_content: String,
|
||||||
to_front: bool,
|
to_front: bool,
|
||||||
|
select_after_open: bool,
|
||||||
},
|
},
|
||||||
ToggleResetNodesToDefinitionsOnOpen,
|
ToggleResetNodesToDefinitionsOnOpen,
|
||||||
PasteIntoFolder {
|
PasteIntoFolder {
|
||||||
|
|
|
||||||
|
|
@ -422,17 +422,16 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||||
document_path,
|
document_path,
|
||||||
document_serialized_content,
|
document_serialized_content,
|
||||||
} => {
|
} => {
|
||||||
let document_id = DocumentId(generate_uuid());
|
|
||||||
responses.add(PortfolioMessage::OpenDocumentFileWithId {
|
responses.add(PortfolioMessage::OpenDocumentFileWithId {
|
||||||
document_id,
|
document_id: DocumentId(generate_uuid()),
|
||||||
document_name,
|
document_name,
|
||||||
document_path,
|
document_path,
|
||||||
document_is_auto_saved: false,
|
document_is_auto_saved: false,
|
||||||
document_is_saved: true,
|
document_is_saved: true,
|
||||||
document_serialized_content,
|
document_serialized_content,
|
||||||
to_front: false,
|
to_front: false,
|
||||||
|
select_after_open: true,
|
||||||
});
|
});
|
||||||
responses.add(PortfolioMessage::SelectDocument { document_id });
|
|
||||||
}
|
}
|
||||||
PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen => {
|
PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen => {
|
||||||
self.reset_node_definitions_on_open = !self.reset_node_definitions_on_open;
|
self.reset_node_definitions_on_open = !self.reset_node_definitions_on_open;
|
||||||
|
|
@ -446,6 +445,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||||
document_is_saved,
|
document_is_saved,
|
||||||
document_serialized_content,
|
document_serialized_content,
|
||||||
to_front,
|
to_front,
|
||||||
|
select_after_open,
|
||||||
} => {
|
} => {
|
||||||
// Upgrade the document being opened to use fresh copies of all nodes
|
// Upgrade the document being opened to use fresh copies of all nodes
|
||||||
let reset_node_definitions_on_open = reset_node_definitions_on_open || document_migration_reset_node_definition(&document_serialized_content);
|
let reset_node_definitions_on_open = reset_node_definitions_on_open || document_migration_reset_node_definition(&document_serialized_content);
|
||||||
|
|
@ -540,6 +540,10 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||||
|
|
||||||
// Load the document into the portfolio so it opens in the editor
|
// Load the document into the portfolio so it opens in the editor
|
||||||
self.load_document(document, document_id, self.layers_panel_open, responses, to_front);
|
self.load_document(document, document_id, self.layers_panel_open, responses, to_front);
|
||||||
|
|
||||||
|
if select_after_open {
|
||||||
|
responses.add(PortfolioMessage::SelectDocument { document_id });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PortfolioMessage::PasteIntoFolder { clipboard, parent, insert_index } => {
|
PortfolioMessage::PasteIntoFolder { clipboard, parent, insert_index } => {
|
||||||
let mut all_new_ids = Vec::new();
|
let mut all_new_ids = Vec::new();
|
||||||
|
|
@ -954,14 +958,15 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||||
}
|
}
|
||||||
PortfolioMessage::SubmitGraphRender { document_id, ignore_hash } => {
|
PortfolioMessage::SubmitGraphRender { document_id, ignore_hash } => {
|
||||||
let node_to_inspect = self.node_to_inspect();
|
let node_to_inspect = self.node_to_inspect();
|
||||||
let result = self.executor.submit_node_graph_evaluation(
|
let Some(document) = self.documents.get_mut(&document_id) else {
|
||||||
self.documents.get_mut(&document_id).expect("Tried to render non-existent document"),
|
log::error!("Tried to render non-existent document");
|
||||||
document_id,
|
return;
|
||||||
ipp.viewport_bounds.size().as_uvec2(),
|
};
|
||||||
timing_information,
|
let viewport_resolution = ipp.viewport_bounds.size().as_uvec2();
|
||||||
node_to_inspect,
|
|
||||||
ignore_hash,
|
let result = self
|
||||||
);
|
.executor
|
||||||
|
.submit_node_graph_evaluation(document, document_id, viewport_resolution, timing_information, node_to_inspect, ignore_hash);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(description) => {
|
Err(description) => {
|
||||||
|
|
@ -1173,7 +1178,7 @@ impl PortfolioMessageHandler {
|
||||||
|
|
||||||
/// Returns an iterator over the open documents in order.
|
/// Returns an iterator over the open documents in order.
|
||||||
pub fn ordered_document_iterator(&self) -> impl Iterator<Item = &DocumentMessageHandler> {
|
pub fn ordered_document_iterator(&self) -> impl Iterator<Item = &DocumentMessageHandler> {
|
||||||
self.document_ids.iter().map(|id| self.documents.get(id).expect("document id was not found in the document hashmap"))
|
self.document_ids.iter().map(|id| self.documents.get(id).expect("Document id was not found in the document hashmap"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn document_index(&self, document_id: DocumentId) -> usize {
|
fn document_index(&self, document_id: DocumentId) -> usize {
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,7 @@ impl EditorHandle {
|
||||||
document_is_saved,
|
document_is_saved,
|
||||||
document_serialized_content,
|
document_serialized_content,
|
||||||
to_front,
|
to_front,
|
||||||
|
select_after_open: false,
|
||||||
};
|
};
|
||||||
self.dispatch(message);
|
self.dispatch(message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,23 @@ use std::hash::Hasher;
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
// TODO: This is a temporary hack, be sure to not reuse this when the brush is being rewritten.
|
// TODO: This is a temporary hack, be sure to not reuse this when the brush system is replaced/rewritten.
|
||||||
static NEXT_BRUSH_CACHE_IMPL_ID: AtomicU64 = AtomicU64::new(0);
|
static NEXT_BRUSH_CACHE_IMPL_ID: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
#[derive(Clone, Debug, DynAny, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, DynAny, serde::Serialize, serde::Deserialize)]
|
||||||
struct BrushCacheImpl {
|
struct BrushCacheImpl {
|
||||||
|
#[serde(default = "new_unique_id")]
|
||||||
unique_id: u64,
|
unique_id: u64,
|
||||||
// The full previous input that was cached.
|
// The full previous input that was cached.
|
||||||
|
#[serde(default)]
|
||||||
prev_input: Vec<BrushStroke>,
|
prev_input: Vec<BrushStroke>,
|
||||||
|
|
||||||
// The strokes that have been fully processed and blended into the background.
|
// The strokes that have been fully processed and blended into the background.
|
||||||
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
||||||
background: TableRow<Raster<CPU>>,
|
background: TableRow<Raster<CPU>>,
|
||||||
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
||||||
blended_image: TableRow<Raster<CPU>>,
|
blended_image: TableRow<Raster<CPU>>,
|
||||||
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
|
||||||
last_stroke_texture: TableRow<Raster<CPU>>,
|
last_stroke_texture: TableRow<Raster<CPU>>,
|
||||||
|
|
||||||
// A cache for brush textures.
|
// A cache for brush textures.
|
||||||
|
|
@ -98,7 +100,7 @@ impl BrushCacheImpl {
|
||||||
impl Default for BrushCacheImpl {
|
impl Default for BrushCacheImpl {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
unique_id: NEXT_BRUSH_CACHE_IMPL_ID.fetch_add(1, Ordering::SeqCst),
|
unique_id: new_unique_id(),
|
||||||
prev_input: Vec::new(),
|
prev_input: Vec::new(),
|
||||||
background: Default::default(),
|
background: Default::default(),
|
||||||
blended_image: Default::default(),
|
blended_image: Default::default(),
|
||||||
|
|
@ -120,6 +122,10 @@ impl Hash for BrushCacheImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_unique_id() -> u64 {
|
||||||
|
NEXT_BRUSH_CACHE_IMPL_ID.fetch_add(1, Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct BrushPlan {
|
pub struct BrushPlan {
|
||||||
pub strokes: Vec<BrushStroke>,
|
pub strokes: Vec<BrushStroke>,
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,22 @@ pub fn migrate_artboard<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum EitherFormat {
|
enum ArtboardFormat {
|
||||||
ArtboardGroup(ArtboardGroup),
|
ArtboardGroup(ArtboardGroup),
|
||||||
|
OldArtboardTable(OldTable<Artboard>),
|
||||||
ArtboardTable(Table<Artboard>),
|
ArtboardTable(Table<Artboard>),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
EitherFormat::ArtboardGroup(artboard_group) => {
|
pub struct OldTable<T> {
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
transform: Vec<DAffine2>,
|
||||||
|
alpha_blending: Vec<AlphaBlending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match ArtboardFormat::deserialize(deserializer)? {
|
||||||
|
ArtboardFormat::ArtboardGroup(artboard_group) => {
|
||||||
let mut table = Table::new();
|
let mut table = Table::new();
|
||||||
for (artboard, source_node_id) in artboard_group.artboards {
|
for (artboard, source_node_id) in artboard_group.artboards {
|
||||||
table.push(TableRow {
|
table.push(TableRow {
|
||||||
|
|
@ -86,7 +95,18 @@ pub fn migrate_artboard<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
|
||||||
}
|
}
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
EitherFormat::ArtboardTable(artboard_table) => artboard_table,
|
ArtboardFormat::OldArtboardTable(old_table) => old_table
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.zip(old_table.transform.into_iter().zip(old_table.alpha_blending))
|
||||||
|
.map(|(element, (transform, alpha_blending))| TableRow {
|
||||||
|
element,
|
||||||
|
transform,
|
||||||
|
alpha_blending,
|
||||||
|
source_node_id: None,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
ArtboardFormat::ArtboardTable(artboard_table) => artboard_table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use crate::context::{CloneVarArgs, Context, ContextFeatures, Ctx, ExtractAll};
|
||||||
use crate::gradient::GradientStops;
|
use crate::gradient::GradientStops;
|
||||||
use crate::raster_types::{CPU, GPU, Raster};
|
use crate::raster_types::{CPU, GPU, Raster};
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
|
use crate::transform::Footprint;
|
||||||
use crate::uuid::NodeId;
|
use crate::uuid::NodeId;
|
||||||
use crate::vector::Vector;
|
use crate::vector::Vector;
|
||||||
use crate::{Graphic, OwnedContextImpl};
|
use crate::{Graphic, OwnedContextImpl};
|
||||||
|
|
@ -24,6 +25,7 @@ async fn context_modification<T>(
|
||||||
Context -> f64,
|
Context -> f64,
|
||||||
Context -> String,
|
Context -> String,
|
||||||
Context -> DAffine2,
|
Context -> DAffine2,
|
||||||
|
Context -> Footprint,
|
||||||
Context -> DVec2,
|
Context -> DVec2,
|
||||||
Context -> Vec<DVec2>,
|
Context -> Vec<DVec2>,
|
||||||
Context -> Vec<NodeId>,
|
Context -> Vec<NodeId>,
|
||||||
|
|
|
||||||
|
|
@ -507,15 +507,34 @@ pub fn migrate_graphic<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Res
|
||||||
elements: Vec<(Graphic, Option<NodeId>)>,
|
elements: Vec<(Graphic, Option<NodeId>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OlderTable<T> {
|
||||||
|
id: Vec<u64>,
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OldTable<T> {
|
||||||
|
id: Vec<u64>,
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
transform: Vec<DAffine2>,
|
||||||
|
alpha_blending: Vec<AlphaBlending>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum EitherFormat {
|
enum GraphicFormat {
|
||||||
OldGraphicGroup(OldGraphicGroup),
|
OldGraphicGroup(OldGraphicGroup),
|
||||||
|
OlderTableOldGraphicGroup(OlderTable<OldGraphicGroup>),
|
||||||
|
OldTableOldGraphicGroup(OldTable<OldGraphicGroup>),
|
||||||
|
OldTableGraphicGroup(OldTable<GraphicGroup>),
|
||||||
Table(serde_json::Value),
|
Table(serde_json::Value),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
Ok(match GraphicFormat::deserialize(deserializer)? {
|
||||||
EitherFormat::OldGraphicGroup(old) => {
|
GraphicFormat::OldGraphicGroup(old) => {
|
||||||
let mut graphic_table = Table::new();
|
let mut graphic_table = Table::new();
|
||||||
for (graphic, source_node_id) in old.elements {
|
for (graphic, source_node_id) in old.elements {
|
||||||
graphic_table.push(TableRow {
|
graphic_table.push(TableRow {
|
||||||
|
|
@ -527,7 +546,43 @@ pub fn migrate_graphic<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Res
|
||||||
}
|
}
|
||||||
graphic_table
|
graphic_table
|
||||||
}
|
}
|
||||||
EitherFormat::Table(value) => {
|
GraphicFormat::OlderTableOldGraphicGroup(old) => old
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|element| {
|
||||||
|
element.elements.into_iter().map(move |(graphic, source_node_id)| TableRow {
|
||||||
|
element: graphic,
|
||||||
|
transform: element.transform,
|
||||||
|
alpha_blending: element.alpha_blending,
|
||||||
|
source_node_id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
GraphicFormat::OldTableOldGraphicGroup(old) => old
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|element| {
|
||||||
|
element.elements.into_iter().map(move |(graphic, source_node_id)| TableRow {
|
||||||
|
element: graphic,
|
||||||
|
transform: element.transform,
|
||||||
|
alpha_blending: element.alpha_blending,
|
||||||
|
source_node_id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
GraphicFormat::OldTableGraphicGroup(old) => old
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|element| {
|
||||||
|
element.elements.into_iter().map(move |(graphic, source_node_id)| TableRow {
|
||||||
|
element: graphic,
|
||||||
|
transform: Default::default(),
|
||||||
|
alpha_blending: Default::default(),
|
||||||
|
source_node_id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
GraphicFormat::Table(value) => {
|
||||||
// Try to deserialize as either table format
|
// Try to deserialize as either table format
|
||||||
if let Ok(old_table) = serde_json::from_value::<Table<GraphicGroup>>(value.clone()) {
|
if let Ok(old_table) = serde_json::from_value::<Table<GraphicGroup>>(value.clone()) {
|
||||||
let mut graphic_table = Table::new();
|
let mut graphic_table = Table::new();
|
||||||
|
|
|
||||||
|
|
@ -69,21 +69,21 @@ pub fn migrate_color<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Resul
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum EitherFormat {
|
enum ColorFormat {
|
||||||
Color(Color),
|
Color(Color),
|
||||||
OptionalColor(Option<Color>),
|
OptionalColor(Option<Color>),
|
||||||
ColorTable(Table<Color>),
|
ColorTable(Table<Color>),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
Ok(match ColorFormat::deserialize(deserializer)? {
|
||||||
EitherFormat::Color(color) => Table::new_from_element(color),
|
ColorFormat::Color(color) => Table::new_from_element(color),
|
||||||
EitherFormat::OptionalColor(color) => {
|
ColorFormat::OptionalColor(color) => {
|
||||||
if let Some(color) = color {
|
if let Some(color) = color {
|
||||||
Table::new_from_element(color)
|
Table::new_from_element(color)
|
||||||
} else {
|
} else {
|
||||||
Table::new()
|
Table::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EitherFormat::ColorTable(color_table) => color_table,
|
ColorFormat::ColorTable(color_table) => color_table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,6 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, DynAny)]
|
#[derive(Clone, Debug, Hash, PartialEq, DynAny)]
|
||||||
enum RasterFrame {
|
enum RasterFrame {
|
||||||
/// A CPU-based bitmap image with a finite position and extent, equivalent to the SVG <image> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image
|
|
||||||
ImageFrame(Table<Image<Color>>),
|
ImageFrame(Table<Image<Color>>),
|
||||||
}
|
}
|
||||||
impl<'de> serde::Deserialize<'de> for RasterFrame {
|
impl<'de> serde::Deserialize<'de> for RasterFrame {
|
||||||
|
|
@ -236,9 +235,7 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, DynAny, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Hash, PartialEq, DynAny, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum GraphicElement {
|
pub enum GraphicElement {
|
||||||
/// Equivalent to the SVG <g> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g
|
|
||||||
GraphicGroup(Table<GraphicElement>),
|
GraphicGroup(Table<GraphicElement>),
|
||||||
/// A vector shape, equivalent to the SVG <path> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path
|
|
||||||
VectorData(Table<Vector>),
|
VectorData(Table<Vector>),
|
||||||
RasterFrame(RasterFrame),
|
RasterFrame(RasterFrame),
|
||||||
}
|
}
|
||||||
|
|
@ -283,11 +280,73 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||||
enum FormatVersions {
|
enum FormatVersions {
|
||||||
Image(Image<Color>),
|
Image(Image<Color>),
|
||||||
OldImageFrame(OldImageFrame<Color>),
|
OldImageFrame(OldImageFrame<Color>),
|
||||||
|
OlderImageFrameTable(OlderTable<ImageFrame<Color>>),
|
||||||
|
OldImageFrameTable(OldTable<ImageFrame<Color>>),
|
||||||
|
OldImageTable(OldTable<Image<Color>>),
|
||||||
|
OldRasterTable(OldTable<Raster<CPU>>),
|
||||||
ImageFrameTable(Table<ImageFrame<Color>>),
|
ImageFrameTable(Table<ImageFrame<Color>>),
|
||||||
ImageTable(Table<Image<Color>>),
|
ImageTable(Table<Image<Color>>),
|
||||||
RasterTable(Table<Raster<CPU>>),
|
RasterTable(Table<Raster<CPU>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OldTable<T> {
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
transform: Vec<DAffine2>,
|
||||||
|
alpha_blending: Vec<AlphaBlending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OlderTable<T> {
|
||||||
|
id: Vec<u64>,
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_image_table(table: Table<Image<Color>>) -> Table<Raster<CPU>> {
|
||||||
|
Table::new_from_element(Raster::new_cpu(table.iter().next().unwrap().element.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn old_table_to_new_table<T>(old_table: OldTable<T>) -> Table<T> {
|
||||||
|
old_table
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.zip(old_table.transform.into_iter().zip(old_table.alpha_blending))
|
||||||
|
.map(|(element, (transform, alpha_blending))| TableRow {
|
||||||
|
element,
|
||||||
|
transform,
|
||||||
|
alpha_blending,
|
||||||
|
source_node_id: None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn older_table_to_new_table<T>(old_table: OlderTable<T>) -> Table<T> {
|
||||||
|
old_table
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.map(|element| TableRow {
|
||||||
|
element,
|
||||||
|
transform: DAffine2::IDENTITY,
|
||||||
|
alpha_blending: AlphaBlending::default(),
|
||||||
|
source_node_id: None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_image_frame_table(image_frame: Table<ImageFrame<Color>>) -> Table<Raster<CPU>> {
|
||||||
|
Table::new_from_element(Raster::new_cpu(
|
||||||
|
image_frame
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.unwrap_or(Table::new_from_element(ImageFrame::default()).iter().next().unwrap())
|
||||||
|
.element
|
||||||
|
.image
|
||||||
|
.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
Ok(match FormatVersions::deserialize(deserializer)? {
|
Ok(match FormatVersions::deserialize(deserializer)? {
|
||||||
FormatVersions::Image(image) => Table::new_from_element(Raster::new_cpu(image)),
|
FormatVersions::Image(image) => Table::new_from_element(Raster::new_cpu(image)),
|
||||||
FormatVersions::OldImageFrame(OldImageFrame { image, transform, alpha_blending }) => {
|
FormatVersions::OldImageFrame(OldImageFrame { image, transform, alpha_blending }) => {
|
||||||
|
|
@ -296,16 +355,12 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||||
*image_frame_table.iter_mut().next().unwrap().alpha_blending = alpha_blending;
|
*image_frame_table.iter_mut().next().unwrap().alpha_blending = alpha_blending;
|
||||||
image_frame_table
|
image_frame_table
|
||||||
}
|
}
|
||||||
FormatVersions::ImageFrameTable(image_frame) => Table::new_from_element(Raster::new_cpu(
|
FormatVersions::OlderImageFrameTable(old_table) => from_image_frame_table(older_table_to_new_table(old_table)),
|
||||||
image_frame
|
FormatVersions::OldImageFrameTable(old_table) => from_image_frame_table(old_table_to_new_table(old_table)),
|
||||||
.iter()
|
FormatVersions::OldImageTable(old_table) => from_image_table(old_table_to_new_table(old_table)),
|
||||||
.next()
|
FormatVersions::OldRasterTable(old_table) => old_table_to_new_table(old_table),
|
||||||
.unwrap_or(Table::new_from_element(ImageFrame::default()).iter().next().unwrap())
|
FormatVersions::ImageFrameTable(image_frame) => from_image_frame_table(image_frame),
|
||||||
.element
|
FormatVersions::ImageTable(table) => from_image_table(table),
|
||||||
.image
|
|
||||||
.clone(),
|
|
||||||
)),
|
|
||||||
FormatVersions::ImageTable(table) => Table::new_from_element(Raster::new_cpu(table.iter().next().unwrap().element.clone())),
|
|
||||||
FormatVersions::RasterTable(table) => table,
|
FormatVersions::RasterTable(table) => table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,10 @@ impl SegmentDomain {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles, stroke: StrokeId) {
|
pub fn push(&mut self, id: SegmentId, start: usize, end: usize, handles: BezierHandles, stroke: StrokeId) {
|
||||||
debug_assert!(!self.id.contains(&id), "Tried to push an existing point to a point domain");
|
#[cfg(debug_assertions)]
|
||||||
|
if self.id.contains(&id) {
|
||||||
|
warn!("Tried to push an existing point to a point domain");
|
||||||
|
}
|
||||||
|
|
||||||
self.id.push(id);
|
self.id.push(id);
|
||||||
self.start_point.push(start);
|
self.start_point.push(start);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ pub use super::vector_modification::*;
|
||||||
use crate::bounds::{BoundingBox, RenderBoundingBox};
|
use crate::bounds::{BoundingBox, RenderBoundingBox};
|
||||||
use crate::math::quad::Quad;
|
use crate::math::quad::Quad;
|
||||||
use crate::subpath::{BezierHandles, ManipulatorGroup, Subpath};
|
use crate::subpath::{BezierHandles, ManipulatorGroup, Subpath};
|
||||||
use crate::table::Table;
|
use crate::table::{Table, TableRow};
|
||||||
use crate::transform::Transform;
|
use crate::transform::Transform;
|
||||||
use crate::vector::click_target::{ClickTargetType, FreePoint};
|
use crate::vector::click_target::{ClickTargetType, FreePoint};
|
||||||
use crate::vector::misc::{HandleId, ManipulatorPointId};
|
use crate::vector::misc::{HandleId, ManipulatorPointId};
|
||||||
|
|
@ -490,18 +490,35 @@ pub fn migrate_vector<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Resu
|
||||||
pub upstream_graphic_group: Option<Table<Graphic>>,
|
pub upstream_graphic_group: Option<Table<Graphic>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OldTable<T> {
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
transform: Vec<DAffine2>,
|
||||||
|
alpha_blending: Vec<AlphaBlending>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct OlderTable<T> {
|
||||||
|
id: Vec<u64>,
|
||||||
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
|
element: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum EitherFormat {
|
enum VectorFormat {
|
||||||
Vector(Vector),
|
Vector(Vector),
|
||||||
OldVectorData(OldVectorData),
|
OldVectorData(OldVectorData),
|
||||||
|
OldVectorTable(OldTable<Vector>),
|
||||||
|
OlderVectorTable(OlderTable<Vector>),
|
||||||
VectorTable(Table<Vector>),
|
VectorTable(Table<Vector>),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
Ok(match VectorFormat::deserialize(deserializer)? {
|
||||||
EitherFormat::Vector(vector) => Table::new_from_element(vector),
|
VectorFormat::Vector(vector) => Table::new_from_element(vector),
|
||||||
EitherFormat::OldVectorData(old) => {
|
VectorFormat::OldVectorData(old) => {
|
||||||
let mut vector_table = Table::new_from_element(Vector {
|
let mut vector_table = Table::new_from_element(Vector {
|
||||||
style: old.style,
|
style: old.style,
|
||||||
colinear_manipulators: old.colinear_manipulators,
|
colinear_manipulators: old.colinear_manipulators,
|
||||||
|
|
@ -514,7 +531,19 @@ pub fn migrate_vector<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Resu
|
||||||
*vector_table.iter_mut().next().unwrap().alpha_blending = old.alpha_blending;
|
*vector_table.iter_mut().next().unwrap().alpha_blending = old.alpha_blending;
|
||||||
vector_table
|
vector_table
|
||||||
}
|
}
|
||||||
EitherFormat::VectorTable(vector_table) => vector_table,
|
VectorFormat::OlderVectorTable(older_table) => older_table.element.into_iter().map(|element| TableRow { element, ..Default::default() }).collect(),
|
||||||
|
VectorFormat::OldVectorTable(old_table) => old_table
|
||||||
|
.element
|
||||||
|
.into_iter()
|
||||||
|
.zip(old_table.transform.into_iter().zip(old_table.alpha_blending))
|
||||||
|
.map(|(element, (transform, alpha_blending))| TableRow {
|
||||||
|
element,
|
||||||
|
transform,
|
||||||
|
alpha_blending,
|
||||||
|
source_node_id: None,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
VectorFormat::VectorTable(vector_table) => vector_table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ pub struct DocumentNode {
|
||||||
#[cfg_attr(target_family = "wasm", serde(alias = "outputs"))]
|
#[cfg_attr(target_family = "wasm", serde(alias = "outputs"))]
|
||||||
pub inputs: Vec<NodeInput>,
|
pub inputs: Vec<NodeInput>,
|
||||||
/// Type of the argument which this node can be evaluated with.
|
/// Type of the argument which this node can be evaluated with.
|
||||||
#[serde(alias = "manual_composition", default)]
|
#[serde(default, alias = "manual_composition", deserialize_with = "migrate_call_argument")]
|
||||||
pub call_argument: Type,
|
pub call_argument: Type,
|
||||||
// A nested document network or a proto-node identifier.
|
// A nested document network or a proto-node identifier.
|
||||||
pub implementation: DocumentNodeImplementation,
|
pub implementation: DocumentNodeImplementation,
|
||||||
|
|
@ -57,12 +57,12 @@ pub struct DocumentNode {
|
||||||
/// However sometimes this is not desirable, for example in the case of a [`graphene_core::memo::MonitorNode`] that needs to be accessed outside of the graph.
|
/// However sometimes this is not desirable, for example in the case of a [`graphene_core::memo::MonitorNode`] that needs to be accessed outside of the graph.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub skip_deduplication: bool,
|
pub skip_deduplication: bool,
|
||||||
/// The path to this node and its inputs and outputs as of when [`NodeNetwork::generate_node_paths`] was called.
|
|
||||||
#[serde(skip)]
|
|
||||||
pub original_location: OriginalLocation,
|
|
||||||
/// List of Extract and Inject annotations for the Context.
|
/// List of Extract and Inject annotations for the Context.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub context_features: ContextDependencies,
|
pub context_features: ContextDependencies,
|
||||||
|
/// The path to this node and its inputs and outputs as of when [`NodeNetwork::generate_node_paths`] was called.
|
||||||
|
#[serde(skip)]
|
||||||
|
pub original_location: OriginalLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the original location of a node input/output when [`NodeNetwork::generate_node_paths`] was called, allowing the types and errors to be derived.
|
/// Represents the original location of a node input/output when [`NodeNetwork::generate_node_paths`] was called, allowing the types and errors to be derived.
|
||||||
|
|
@ -1105,6 +1105,22 @@ impl<'a> Iterator for RecursiveNodeIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn migrate_call_argument<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Type, D::Error> {
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum CallArg {
|
||||||
|
New(Type),
|
||||||
|
Old(Option<Type>),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match CallArg::deserialize(deserializer)? {
|
||||||
|
CallArg::New(ty) => ty,
|
||||||
|
CallArg::Old(ty) => ty.unwrap_or_default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ tagged_value! {
|
||||||
#[serde(alias = "VectorData")]
|
#[serde(alias = "VectorData")]
|
||||||
Vector(Table<Vector>),
|
Vector(Table<Vector>),
|
||||||
#[cfg_attr(target_family = "wasm", serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame"))] // TODO: Eventually remove this migration document upgrade code
|
#[cfg_attr(target_family = "wasm", serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame"))] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "ImageFrame", alias = "RasterData")]
|
#[serde(alias = "ImageFrame", alias = "RasterData", alias = "Image")]
|
||||||
Raster(Table<Raster<CPU>>),
|
Raster(Table<Raster<CPU>>),
|
||||||
#[cfg_attr(target_family = "wasm", serde(deserialize_with = "graphene_core::graphic::migrate_graphic"))] // TODO: Eventually remove this migration document upgrade code
|
#[cfg_attr(target_family = "wasm", serde(deserialize_with = "graphene_core::graphic::migrate_graphic"))] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "GraphicGroup", alias = "Group")]
|
#[serde(alias = "GraphicGroup", alias = "Group")]
|
||||||
|
|
@ -361,7 +361,7 @@ impl TaggedValue {
|
||||||
x if x == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
|
x if x == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
|
||||||
x if x == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
|
x if x == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
|
||||||
x if x == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
|
x if x == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
|
||||||
x if x == TypeId::of::<Color>() => to_color(string).map(|color| TaggedValue::ColorNotInTable(color))?,
|
x if x == TypeId::of::<Color>() => to_color(string).map(TaggedValue::ColorNotInTable)?,
|
||||||
x if x == TypeId::of::<Option<Color>>() => TaggedValue::ColorNotInTable(to_color(string)?),
|
x if x == TypeId::of::<Option<Color>>() => TaggedValue::ColorNotInTable(to_color(string)?),
|
||||||
x if x == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
|
x if x == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
|
||||||
x if x == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
x if x == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use graphene_std::brush::brush_cache::BrushCache;
|
||||||
use graphene_std::brush::brush_stroke::BrushStroke;
|
use graphene_std::brush::brush_stroke::BrushStroke;
|
||||||
use graphene_std::gradient::GradientStops;
|
use graphene_std::gradient::GradientStops;
|
||||||
use graphene_std::table::Table;
|
use graphene_std::table::Table;
|
||||||
|
use graphene_std::transform::Footprint;
|
||||||
use graphene_std::uuid::NodeId;
|
use graphene_std::uuid::NodeId;
|
||||||
use graphene_std::vector::Vector;
|
use graphene_std::vector::Vector;
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
|
|
@ -153,13 +154,15 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Arc<WasmSurfaceHandle>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Arc<WasmSurfaceHandle>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),
|
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => SurfaceFrame]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => SurfaceFrame]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f32]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f32]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => u32]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => u32]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => u64]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => u64]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => DVec2]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => String]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => String]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => DAffine2]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Footprint]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => RenderOutput]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => RenderOutput]),
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => &WasmEditorApi]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => &WasmEditorApi]),
|
||||||
|
|
@ -167,6 +170,51 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<f64>]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Color]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<Color>]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => [f64; 4]]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Graphic]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => glam::f32::Vec2]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => glam::f32::Affine2]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Stroke]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Gradient]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::text::Font]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<BrushStroke>]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => BrushCache]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => DocumentNode]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::ContextFeatures]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::curve::Curve]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::transform::Footprint]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Box<graphene_core::vector::VectorModification>]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Fill]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::blending::BlendMode]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::LuminanceCalculation]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::extract_xy::XY]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::RedGreenBlue]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::RedGreenBlueAlpha]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::animation::RealTimeMode]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::NoiseType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::FractalType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::CellularDistanceFunction]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::CellularReturnType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::DomainWarpType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::RelativeAbsolute]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_std::raster::SelectiveColorChoice]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::GridType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::ArcType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::MergeByDistanceAlgorithm]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::PointSpacingType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeCap]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeJoin]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeAlign]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::PaintOrder]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::FillType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::style::GradientType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::transform::ReferencePoint]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::CentroidType]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_path_bool::BooleanOperation]),
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => graphene_core::text::TextAlign]),
|
||||||
// =================
|
// =================
|
||||||
// IMPURE MEMO NODES
|
// IMPURE MEMO NODES
|
||||||
// =================
|
// =================
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue