Skip to content

Commit a2c0693

Browse files
authored
Fix most known issues with migrations failing to open documents from the past year (#3148)
1 parent 89c9cf1 commit a2c0693

18 files changed

Lines changed: 313 additions & 62 deletions

File tree

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,7 @@ impl DocumentMessageHandler {
17861786
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
17871787
let document_message_handler = serde_json::from_str::<DocumentMessageHandler>(serialized_content)
17881788
.or_else(|e| {
1789-
log::warn!("failed to directly load document with the following error: {e}. Trying old DocumentMessageHandler");
1789+
log::warn!("Failed to directly load document with the following error: {e}. Trying old DocumentMessageHandler.");
17901790
// TODO: Eventually remove this document upgrade code
17911791
#[derive(Debug, serde::Serialize, serde::Deserialize)]
17921792
pub struct OldDocumentMessageHandler {

editor/src/messages/portfolio/document/utility_types/error.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ pub enum EditorError {
1616
#[error("The operation caused a document error:\n{0:?}")]
1717
Document(String),
1818

19-
#[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:?}")]
19+
#[error(
20+
"This document was created in an older version of the editor.\n\
21+
\n\
22+
Full backwards compatibility is not guaranteed in the current alpha release.\n\
23+
\n\
24+
If this document is critical, ask for support in Graphite's Discord community."
25+
)]
2026
DocumentDeserialization(String),
2127

2228
#[error("{0}")]

editor/src/messages/portfolio/document/utility_types/network_interface.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ impl NodeNetworkInterface {
568568
let skip_footprint = 1;
569569

570570
let Some(input_type) = std::iter::once(node_types.call_argument.clone()).chain(node_types.inputs.clone()).nth(input_index + skip_footprint) else {
571-
log::error!("Could not get type for {node_id_path:?}, input: {input_index}");
571+
// log::warn!("Could not get type for {node_id_path:?}, input: {input_index}");
572572
return (concrete!(()), TypeSource::Error("could not get the protonode's input"));
573573
};
574574

@@ -2629,7 +2629,7 @@ impl NodeNetworkInterface {
26292629
InputConnector::Node { node_id, input_index } => {
26302630
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else { return };
26312631
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
2632-
log::error!("Node metadata must exist on node: {input:?}");
2632+
// log::warn!("Node metadata must exist on node: {input:?}");
26332633
return;
26342634
};
26352635
let wire_update = WirePathUpdate {
@@ -2721,7 +2721,7 @@ impl NodeNetworkInterface {
27212721
return;
27222722
};
27232723
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
2724-
log::error!("Node metadata must exist on node: {input:?}");
2724+
// log::warn!("Node metadata must exist on node: {input:?}");
27252725
return;
27262726
};
27272727
input_metadata.transient_metadata.wire = TransientMetadata::Unloaded;

editor/src/messages/portfolio/document_migration.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
113113
node: graphene_std::math_nodes::root::IDENTIFIER,
114114
aliases: &["graphene_core::ops::RootNode"],
115115
},
116+
NodeReplacement {
117+
node: graphene_std::math_nodes::absolute_value::IDENTIFIER,
118+
aliases: &["graphene_core::ops::AbsoluteValueNode"],
119+
},
116120
NodeReplacement {
117121
node: graphene_std::math_nodes::logarithm::IDENTIFIER,
118122
aliases: &["graphene_core::ops::LogarithmNode"],

editor/src/messages/portfolio/portfolio_message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub enum PortfolioMessage {
7979
document_is_saved: bool,
8080
document_serialized_content: String,
8181
to_front: bool,
82+
select_after_open: bool,
8283
},
8384
ToggleResetNodesToDefinitionsOnOpen,
8485
PasteIntoFolder {

editor/src/messages/portfolio/portfolio_message_handler.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -422,17 +422,16 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
422422
document_path,
423423
document_serialized_content,
424424
} => {
425-
let document_id = DocumentId(generate_uuid());
426425
responses.add(PortfolioMessage::OpenDocumentFileWithId {
427-
document_id,
426+
document_id: DocumentId(generate_uuid()),
428427
document_name,
429428
document_path,
430429
document_is_auto_saved: false,
431430
document_is_saved: true,
432431
document_serialized_content,
433432
to_front: false,
433+
select_after_open: true,
434434
});
435-
responses.add(PortfolioMessage::SelectDocument { document_id });
436435
}
437436
PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen => {
438437
self.reset_node_definitions_on_open = !self.reset_node_definitions_on_open;
@@ -446,6 +445,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
446445
document_is_saved,
447446
document_serialized_content,
448447
to_front,
448+
select_after_open,
449449
} => {
450450
// Upgrade the document being opened to use fresh copies of all nodes
451451
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
540540

541541
// Load the document into the portfolio so it opens in the editor
542542
self.load_document(document, document_id, self.layers_panel_open, responses, to_front);
543+
544+
if select_after_open {
545+
responses.add(PortfolioMessage::SelectDocument { document_id });
546+
}
543547
}
544548
PortfolioMessage::PasteIntoFolder { clipboard, parent, insert_index } => {
545549
let mut all_new_ids = Vec::new();
@@ -954,14 +958,15 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
954958
}
955959
PortfolioMessage::SubmitGraphRender { document_id, ignore_hash } => {
956960
let node_to_inspect = self.node_to_inspect();
957-
let result = self.executor.submit_node_graph_evaluation(
958-
self.documents.get_mut(&document_id).expect("Tried to render non-existent document"),
959-
document_id,
960-
ipp.viewport_bounds.size().as_uvec2(),
961-
timing_information,
962-
node_to_inspect,
963-
ignore_hash,
964-
);
961+
let Some(document) = self.documents.get_mut(&document_id) else {
962+
log::error!("Tried to render non-existent document");
963+
return;
964+
};
965+
let viewport_resolution = ipp.viewport_bounds.size().as_uvec2();
966+
967+
let result = self
968+
.executor
969+
.submit_node_graph_evaluation(document, document_id, viewport_resolution, timing_information, node_to_inspect, ignore_hash);
965970

966971
match result {
967972
Err(description) => {
@@ -1173,7 +1178,7 @@ impl PortfolioMessageHandler {
11731178

11741179
/// Returns an iterator over the open documents in order.
11751180
pub fn ordered_document_iterator(&self) -> impl Iterator<Item = &DocumentMessageHandler> {
1176-
self.document_ids.iter().map(|id| self.documents.get(id).expect("document id was not found in the document hashmap"))
1181+
self.document_ids.iter().map(|id| self.documents.get(id).expect("Document id was not found in the document hashmap"))
11771182
}
11781183

11791184
fn document_index(&self, document_id: DocumentId) -> usize {

frontend/wasm/src/editor_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ impl EditorHandle {
466466
document_is_saved,
467467
document_serialized_content,
468468
to_front,
469+
select_after_open: false,
469470
};
470471
self.dispatch(message);
471472
}

node-graph/gbrush/src/brush_cache.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,23 @@ use std::hash::Hasher;
1010
use std::sync::atomic::{AtomicU64, Ordering};
1111
use std::sync::{Arc, Mutex};
1212

13-
// TODO: This is a temporary hack, be sure to not reuse this when the brush is being rewritten.
13+
// TODO: This is a temporary hack, be sure to not reuse this when the brush system is replaced/rewritten.
1414
static NEXT_BRUSH_CACHE_IMPL_ID: AtomicU64 = AtomicU64::new(0);
1515

1616
#[derive(Clone, Debug, DynAny, serde::Serialize, serde::Deserialize)]
1717
struct BrushCacheImpl {
18+
#[serde(default = "new_unique_id")]
1819
unique_id: u64,
1920
// The full previous input that was cached.
21+
#[serde(default)]
2022
prev_input: Vec<BrushStroke>,
2123

2224
// The strokes that have been fully processed and blended into the background.
23-
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
25+
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
2426
background: TableRow<Raster<CPU>>,
25-
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
27+
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
2628
blended_image: TableRow<Raster<CPU>>,
27-
#[serde(deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
29+
#[serde(default, deserialize_with = "graphene_core::raster::image::migrate_image_frame_row")]
2830
last_stroke_texture: TableRow<Raster<CPU>>,
2931

3032
// A cache for brush textures.
@@ -98,7 +100,7 @@ impl BrushCacheImpl {
98100
impl Default for BrushCacheImpl {
99101
fn default() -> Self {
100102
Self {
101-
unique_id: NEXT_BRUSH_CACHE_IMPL_ID.fetch_add(1, Ordering::SeqCst),
103+
unique_id: new_unique_id(),
102104
prev_input: Vec::new(),
103105
background: Default::default(),
104106
blended_image: Default::default(),
@@ -120,6 +122,10 @@ impl Hash for BrushCacheImpl {
120122
}
121123
}
122124

125+
fn new_unique_id() -> u64 {
126+
NEXT_BRUSH_CACHE_IMPL_ID.fetch_add(1, Ordering::SeqCst)
127+
}
128+
123129
#[derive(Clone, Debug, Default)]
124130
pub struct BrushPlan {
125131
pub strokes: Vec<BrushStroke>,

node-graph/gcore/src/artboard.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,22 @@ pub fn migrate_artboard<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
6868

6969
#[derive(serde::Serialize, serde::Deserialize)]
7070
#[serde(untagged)]
71-
enum EitherFormat {
71+
enum ArtboardFormat {
7272
ArtboardGroup(ArtboardGroup),
73+
OldArtboardTable(OldTable<Artboard>),
7374
ArtboardTable(Table<Artboard>),
7475
}
7576

76-
Ok(match EitherFormat::deserialize(deserializer)? {
77-
EitherFormat::ArtboardGroup(artboard_group) => {
77+
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
78+
pub struct OldTable<T> {
79+
#[serde(alias = "instances", alias = "instance")]
80+
element: Vec<T>,
81+
transform: Vec<DAffine2>,
82+
alpha_blending: Vec<AlphaBlending>,
83+
}
84+
85+
Ok(match ArtboardFormat::deserialize(deserializer)? {
86+
ArtboardFormat::ArtboardGroup(artboard_group) => {
7887
let mut table = Table::new();
7988
for (artboard, source_node_id) in artboard_group.artboards {
8089
table.push(TableRow {
@@ -86,7 +95,18 @@ pub fn migrate_artboard<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
8695
}
8796
table
8897
}
89-
EitherFormat::ArtboardTable(artboard_table) => artboard_table,
98+
ArtboardFormat::OldArtboardTable(old_table) => old_table
99+
.element
100+
.into_iter()
101+
.zip(old_table.transform.into_iter().zip(old_table.alpha_blending))
102+
.map(|(element, (transform, alpha_blending))| TableRow {
103+
element,
104+
transform,
105+
alpha_blending,
106+
source_node_id: None,
107+
})
108+
.collect(),
109+
ArtboardFormat::ArtboardTable(artboard_table) => artboard_table,
90110
})
91111
}
92112

node-graph/gcore/src/context_modification.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::context::{CloneVarArgs, Context, ContextFeatures, Ctx, ExtractAll};
33
use crate::gradient::GradientStops;
44
use crate::raster_types::{CPU, GPU, Raster};
55
use crate::table::Table;
6+
use crate::transform::Footprint;
67
use crate::uuid::NodeId;
78
use crate::vector::Vector;
89
use crate::{Graphic, OwnedContextImpl};
@@ -24,6 +25,7 @@ async fn context_modification<T>(
2425
Context -> f64,
2526
Context -> String,
2627
Context -> DAffine2,
28+
Context -> Footprint,
2729
Context -> DVec2,
2830
Context -> Vec<DVec2>,
2931
Context -> Vec<NodeId>,

0 commit comments

Comments
 (0)