mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 18:48:12 +08:00
Restore backwards compatibility broken with #1750 to prepare next release
This commit is contained in:
@@ -27,7 +27,6 @@ use graphene_core::raster::BlendMode;
|
|||||||
use graphene_core::raster::ImageFrame;
|
use graphene_core::raster::ImageFrame;
|
||||||
use graphene_core::renderer::ClickTarget;
|
use graphene_core::renderer::ClickTarget;
|
||||||
use graphene_core::vector::style::ViewMode;
|
use graphene_core::vector::style::ViewMode;
|
||||||
use graphene_std::vector::style::{Fill, FillType, Gradient};
|
|
||||||
|
|
||||||
use glam::{DAffine2, DVec2, IVec2};
|
use glam::{DAffine2, DVec2, IVec2};
|
||||||
|
|
||||||
@@ -1312,81 +1311,7 @@ impl DocumentMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
|
pub fn deserialize_document(serialized_content: &str) -> Result<Self, EditorError> {
|
||||||
// serde_json::from_str(serialized_content).map_err(|e| EditorError::DocumentDeserialization(e.to_string()))
|
serde_json::from_str(serialized_content).map_err(|e| EditorError::DocumentDeserialization(e.to_string()))
|
||||||
|
|
||||||
match serde_json::from_str::<Self>(serialized_content).map_err(|e| EditorError::DocumentDeserialization(e.to_string())) {
|
|
||||||
Ok(mut document) => {
|
|
||||||
for (_, node) in &mut document.network.nodes {
|
|
||||||
// Upgrade Fill nodes to the format change in #1778
|
|
||||||
// TODO: Eventually remove this (probably starting late 2024)
|
|
||||||
if node.name == "Fill" && node.inputs.len() == 8 {
|
|
||||||
let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
|
|
||||||
let default_definition_node = node_definition.default_document_node();
|
|
||||||
|
|
||||||
node.implementation = default_definition_node.implementation.clone();
|
|
||||||
let old_inputs = std::mem::replace(&mut node.inputs, default_definition_node.inputs.clone());
|
|
||||||
|
|
||||||
node.inputs[0] = old_inputs[0].clone();
|
|
||||||
|
|
||||||
let Some(fill_type) = old_inputs[1].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::FillType(fill_type) = fill_type else { continue };
|
|
||||||
let Some(solid_color) = old_inputs[2].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::OptionalColor(solid_color) = solid_color else { continue };
|
|
||||||
let Some(gradient_type) = old_inputs[3].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::GradientType(gradient_type) = gradient_type else { continue };
|
|
||||||
let Some(start) = old_inputs[4].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::DVec2(start) = start else { continue };
|
|
||||||
let Some(end) = old_inputs[5].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::DVec2(end) = end else { continue };
|
|
||||||
let Some(transform) = old_inputs[6].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::DAffine2(transform) = transform else { continue };
|
|
||||||
let Some(positions) = old_inputs[7].as_value().cloned() else { continue };
|
|
||||||
let TaggedValue::GradientStops(positions) = positions else { continue };
|
|
||||||
|
|
||||||
let fill = match (fill_type, solid_color) {
|
|
||||||
(FillType::Solid, None) => Fill::None,
|
|
||||||
(FillType::Solid, Some(color)) => Fill::Solid(color),
|
|
||||||
(FillType::Gradient, _) => Fill::Gradient(Gradient {
|
|
||||||
stops: positions,
|
|
||||||
gradient_type,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
transform,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
node.inputs[1] = NodeInput::value(TaggedValue::Fill(fill.clone()), false);
|
|
||||||
match fill {
|
|
||||||
Fill::None => {
|
|
||||||
node.inputs[2] = NodeInput::value(TaggedValue::OptionalColor(None), false);
|
|
||||||
}
|
|
||||||
Fill::Solid(color) => {
|
|
||||||
node.inputs[2] = NodeInput::value(TaggedValue::OptionalColor(Some(color)), false);
|
|
||||||
}
|
|
||||||
Fill::Gradient(gradient) => {
|
|
||||||
node.inputs[3] = NodeInput::value(TaggedValue::Gradient(gradient), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(document)
|
|
||||||
}
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This can be used, if uncommented, to upgrade demo artwork with outdated document node internals from their definitions. Delete when it's no longer needed.
|
|
||||||
// Used for upgrading old internal networks for demo artwork nodes. Will reset all node internals for any opened file
|
|
||||||
// match serde_json::from_str::<Self>(serialized_content).map_err(|e| EditorError::DocumentDeserialization(e.to_string())) {
|
|
||||||
// Ok(mut document) => {
|
|
||||||
// for (_, node) in &mut document.network.nodes {
|
|
||||||
// let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
|
|
||||||
// let default_definition_node = node_definition.default_document_node();
|
|
||||||
|
|
||||||
// node.implementation = default_definition_node.implementation.clone();
|
|
||||||
// }
|
|
||||||
// Ok(document)
|
|
||||||
// }
|
|
||||||
// Err(e) => Err(e),
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_name(name: String, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> Self {
|
pub fn with_name(name: String, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> Self {
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ pub enum GraphOperationMessage {
|
|||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
reconnect: bool,
|
reconnect: bool,
|
||||||
},
|
},
|
||||||
// TODO: Eventually remove this (probably starting late 2024)
|
|
||||||
DeleteLegacyOutputNode,
|
|
||||||
DisconnectInput {
|
DisconnectInput {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
|
|||||||
-6
@@ -141,12 +141,6 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
|
|||||||
load_network_structure(document_network, document_metadata, collapsed);
|
load_network_structure(document_network, document_metadata, collapsed);
|
||||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||||
}
|
}
|
||||||
// TODO: Eventually remove this (probably starting late 2024)
|
|
||||||
GraphOperationMessage::DeleteLegacyOutputNode => {
|
|
||||||
if document_network.nodes.iter().any(|(node_id, node)| node.name == "Output" && *node_id == NodeId(0)) {
|
|
||||||
ModifyInputsContext::delete_nodes(node_graph, document_network, selected_nodes, vec![NodeId(0)], true, responses, Vec::new());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Make sure to also update NodeGraphMessage::DisconnectInput when changing this
|
// Make sure to also update NodeGraphMessage::DisconnectInput when changing this
|
||||||
GraphOperationMessage::DisconnectInput { node_id, input_index } => {
|
GraphOperationMessage::DisconnectInput { node_id, input_index } => {
|
||||||
let Some(existing_input) = document_network
|
let Some(existing_input) = document_network
|
||||||
|
|||||||
@@ -4,14 +4,18 @@ use crate::consts::DEFAULT_DOCUMENT_NAME;
|
|||||||
use crate::messages::dialog::simple_dialogs;
|
use crate::messages::dialog::simple_dialogs;
|
||||||
use crate::messages::frontend::utility_types::FrontendDocumentDetails;
|
use crate::messages::frontend::utility_types::FrontendDocumentDetails;
|
||||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||||
|
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
|
||||||
use crate::messages::portfolio::document::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
|
use crate::messages::portfolio::document::utility_types::clipboards::{Clipboard, CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
|
||||||
|
use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes;
|
||||||
use crate::messages::portfolio::document::DocumentMessageData;
|
use crate::messages::portfolio::document::DocumentMessageData;
|
||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
use crate::messages::tool::utility_types::{HintData, HintGroup};
|
use crate::messages::tool::utility_types::{HintData, HintGroup};
|
||||||
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
|
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
|
||||||
|
|
||||||
use graph_craft::document::NodeId;
|
use graph_craft::document::value::TaggedValue;
|
||||||
|
use graph_craft::document::{NodeId, NodeInput};
|
||||||
use graphene_core::text::Font;
|
use graphene_core::text::Font;
|
||||||
|
use graphene_std::vector::style::{Fill, FillType, Gradient};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -375,10 +379,104 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
|||||||
document_is_saved,
|
document_is_saved,
|
||||||
document_serialized_content,
|
document_serialized_content,
|
||||||
} => {
|
} => {
|
||||||
// TODO: Eventually remove this (probably starting late 2024)
|
let upgrade_from_before_editable_subgraphs = document_serialized_content.contains("node_output_index");
|
||||||
let do_not_upgrade = document_name.contains("__DO_NOT_UPGRADE__");
|
let upgrade_vector_manipulation_format = document_serialized_content.contains("ManipulatorGroupIds") && !document_name.contains("__DO_NOT_UPGRADE__");
|
||||||
let document_name = document_name.replace("__DO_NOT_UPGRADE__", "");
|
let document_name = document_name.replace("__DO_NOT_UPGRADE__", "");
|
||||||
if document_serialized_content.contains("ManipulatorGroupIds") && !do_not_upgrade {
|
|
||||||
|
let document = DocumentMessageHandler::with_name_and_content(document_name.clone(), document_serialized_content);
|
||||||
|
let mut document = match document {
|
||||||
|
Ok(document) => document,
|
||||||
|
Err(e) => {
|
||||||
|
if !document_is_auto_saved {
|
||||||
|
responses.add(DialogMessage::DisplayDialogError {
|
||||||
|
title: "Failed to open document".to_string(),
|
||||||
|
description: e.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Eventually remove this (probably starting late 2024)
|
||||||
|
// Upgrade all old nodes to support editable subgraphs introduced in #1750
|
||||||
|
if upgrade_from_before_editable_subgraphs {
|
||||||
|
for (_, node) in &mut document.network.nodes {
|
||||||
|
let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
|
||||||
|
let default_definition_node = node_definition.default_document_node();
|
||||||
|
|
||||||
|
node.implementation = default_definition_node.implementation.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if document.network.nodes.iter().any(|(node_id, node)| node.name == "Output" && *node_id == NodeId(0)) {
|
||||||
|
ModifyInputsContext::delete_nodes(
|
||||||
|
&mut document.node_graph_handler,
|
||||||
|
&mut document.network,
|
||||||
|
&mut SelectedNodes(vec![]),
|
||||||
|
vec![NodeId(0)],
|
||||||
|
true,
|
||||||
|
responses,
|
||||||
|
Vec::new(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Eventually remove this (probably starting late 2024)
|
||||||
|
// Upgrade Fill nodes to the format change in #1778
|
||||||
|
for (_, node) in &mut document.network.nodes {
|
||||||
|
if node.name == "Fill" && node.inputs.len() == 8 {
|
||||||
|
let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
|
||||||
|
let default_definition_node = node_definition.default_document_node();
|
||||||
|
|
||||||
|
node.implementation = default_definition_node.implementation.clone();
|
||||||
|
let old_inputs = std::mem::replace(&mut node.inputs, default_definition_node.inputs.clone());
|
||||||
|
|
||||||
|
node.inputs[0] = old_inputs[0].clone();
|
||||||
|
|
||||||
|
let Some(fill_type) = old_inputs[1].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::FillType(fill_type) = fill_type else { continue };
|
||||||
|
let Some(solid_color) = old_inputs[2].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::OptionalColor(solid_color) = solid_color else { continue };
|
||||||
|
let Some(gradient_type) = old_inputs[3].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::GradientType(gradient_type) = gradient_type else { continue };
|
||||||
|
let Some(start) = old_inputs[4].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::DVec2(start) = start else { continue };
|
||||||
|
let Some(end) = old_inputs[5].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::DVec2(end) = end else { continue };
|
||||||
|
let Some(transform) = old_inputs[6].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::DAffine2(transform) = transform else { continue };
|
||||||
|
let Some(positions) = old_inputs[7].as_value().cloned() else { continue };
|
||||||
|
let TaggedValue::GradientStops(positions) = positions else { continue };
|
||||||
|
|
||||||
|
let fill = match (fill_type, solid_color) {
|
||||||
|
(FillType::Solid, None) => Fill::None,
|
||||||
|
(FillType::Solid, Some(color)) => Fill::Solid(color),
|
||||||
|
(FillType::Gradient, _) => Fill::Gradient(Gradient {
|
||||||
|
stops: positions,
|
||||||
|
gradient_type,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
transform,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
node.inputs[1] = NodeInput::value(TaggedValue::Fill(fill.clone()), false);
|
||||||
|
match fill {
|
||||||
|
Fill::None => {
|
||||||
|
node.inputs[2] = NodeInput::value(TaggedValue::OptionalColor(None), false);
|
||||||
|
}
|
||||||
|
Fill::Solid(color) => {
|
||||||
|
node.inputs[2] = NodeInput::value(TaggedValue::OptionalColor(Some(color)), false);
|
||||||
|
}
|
||||||
|
Fill::Gradient(gradient) => {
|
||||||
|
node.inputs[3] = NodeInput::value(TaggedValue::Gradient(gradient), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Eventually remove this (probably starting late 2024)
|
||||||
|
// Upgrade document to the new vector manipulation format introduced in #1676
|
||||||
|
let document_serialized_content = document.serialize_document();
|
||||||
|
if upgrade_vector_manipulation_format && document_serialized_content != "" {
|
||||||
responses.add(FrontendMessage::TriggerUpgradeDocumentToVectorManipulationFormat {
|
responses.add(FrontendMessage::TriggerUpgradeDocumentToVectorManipulationFormat {
|
||||||
document_id,
|
document_id,
|
||||||
document_name,
|
document_name,
|
||||||
@@ -389,25 +487,9 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let document = DocumentMessageHandler::with_name_and_content(document_name, document_serialized_content);
|
document.set_auto_save_state(document_is_auto_saved);
|
||||||
match document {
|
document.set_save_state(document_is_saved);
|
||||||
Ok(mut document) => {
|
self.load_document(document, document_id, responses);
|
||||||
document.set_auto_save_state(document_is_auto_saved);
|
|
||||||
document.set_save_state(document_is_saved);
|
|
||||||
self.load_document(document, document_id, responses);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
if !document_is_auto_saved {
|
|
||||||
responses.add(DialogMessage::DisplayDialogError {
|
|
||||||
title: "Failed to open document".to_string(),
|
|
||||||
description: e.to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Eventually remove this (probably starting late 2024)
|
|
||||||
responses.add(GraphOperationMessage::DeleteLegacyOutputNode);
|
|
||||||
}
|
}
|
||||||
PortfolioMessage::PasteIntoFolder { clipboard, parent, insert_index } => {
|
PortfolioMessage::PasteIntoFolder { clipboard, parent, insert_index } => {
|
||||||
let paste = |entry: &CopyBufferEntry, responses: &mut VecDeque<_>| {
|
let paste = |entry: &CopyBufferEntry, responses: &mut VecDeque<_>| {
|
||||||
|
|||||||
@@ -660,8 +660,6 @@ impl EditorHandle {
|
|||||||
let (response_sender, _) = std::sync::mpsc::channel();
|
let (response_sender, _) = std::sync::mpsc::channel();
|
||||||
let old_runtime = replace_node_runtime(NodeRuntime::new(request_receiver, response_sender));
|
let old_runtime = replace_node_runtime(NodeRuntime::new(request_receiver, response_sender));
|
||||||
|
|
||||||
let document_serialized_content = document_serialized_content.replace("\"ManipulatorGroupIds\"", "\"PointIds\"");
|
|
||||||
|
|
||||||
let mut editor = Editor::new();
|
let mut editor = Editor::new();
|
||||||
let document_id = DocumentId(document_id);
|
let document_id = DocumentId(document_id);
|
||||||
editor.handle_message(PortfolioMessage::OpenDocumentFileWithId {
|
editor.handle_message(PortfolioMessage::OpenDocumentFileWithId {
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ tagged_value! {
|
|||||||
GradientStops(graphene_core::vector::style::GradientStops),
|
GradientStops(graphene_core::vector::style::GradientStops),
|
||||||
Quantization(graphene_core::quantization::QuantizationChannels),
|
Quantization(graphene_core::quantization::QuantizationChannels),
|
||||||
OptionalColor(Option<graphene_core::raster::color::Color>),
|
OptionalColor(Option<graphene_core::raster::color::Color>),
|
||||||
|
#[serde(alias = "ManipulatorGroupIds")] // TODO: Eventually remove this alias (probably starting late 2024)
|
||||||
PointIds(Vec<graphene_core::vector::PointId>),
|
PointIds(Vec<graphene_core::vector::PointId>),
|
||||||
Font(graphene_core::text::Font),
|
Font(graphene_core::text::Font),
|
||||||
BrushStrokes(Vec<graphene_core::vector::brush_stroke::BrushStroke>),
|
BrushStrokes(Vec<graphene_core::vector::brush_stroke::BrushStroke>),
|
||||||
|
|||||||
Reference in New Issue
Block a user