mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 18:38:05 +08:00
Move node visibility flag from NodeNetwork to DocumentNode (#1708)
* protonode -> proto node * Move node visibility flag from NodeNetwork to DocumentNode * Add serde default for new field * Logic improvements
This commit is contained in:
@@ -152,18 +152,24 @@ pub struct DocumentNode {
|
||||
/// Now, the call from `F` directly reaches the `CacheNode` and the `CacheNode` can decide whether to call `G.eval(input_from_f)`
|
||||
/// in the event of a cache miss or just return the cached data in the event of a cache hit.
|
||||
pub manual_composition: Option<Type>,
|
||||
// TODO: Remove once this references its definition instead (see above TODO).
|
||||
/// Indicates to the UI if a primary output should be drawn for this node.
|
||||
/// True for most nodes, but the Split Channels node is an example of a node that has multiple secondary outputs but no primary output.
|
||||
#[serde(default = "return_true")]
|
||||
pub has_primary_output: bool,
|
||||
// A nested document network or a proto-node identifier.
|
||||
pub implementation: DocumentNodeImplementation,
|
||||
/// Represents the eye icon for hiding/showing the node in the graph UI. When hidden, a node gets replaced with an identity node during the graph flattening step.
|
||||
#[serde(default = "return_true")]
|
||||
pub visible: bool,
|
||||
/// Metadata about the node including its position in the graph UI.
|
||||
pub metadata: DocumentNodeMetadata,
|
||||
/// When two different protonodes hash to the same value (e.g. two value nodes each containing `2_u32` or two multiply nodes that have the same node IDs as input), the duplicates are removed.
|
||||
/// When two different proto nodes hash to the same value (e.g. two value nodes each containing `2_u32` or two multiply nodes that have the same node IDs as input), the duplicates are removed.
|
||||
/// See [`crate::proto::ProtoNetwork::generate_stable_node_ids`] for details.
|
||||
/// 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)]
|
||||
pub skip_deduplication: bool,
|
||||
/// Used as a hash of the graph input where applicable. This ensures that protonodes that depend on the graph's input are always regenerated.
|
||||
/// Used as a hash of the graph input where applicable. This ensures that proto nodes that depend on the graph's input are always regenerated.
|
||||
#[serde(default)]
|
||||
pub world_state_hash: u64,
|
||||
/// The path to this node and its inputs and outputs as of when [`NodeNetwork::generate_node_paths`] was called.
|
||||
@@ -185,7 +191,7 @@ pub struct Source {
|
||||
pub struct OriginalLocation {
|
||||
/// The original location to the document node - e.g. [grandparent_id, parent_id, node_id].
|
||||
pub path: Option<Vec<NodeId>>,
|
||||
/// Each document input source maps to one protonode input (however one protonode input may come from several sources)
|
||||
/// Each document input source maps to one proto node input (however one proto node input may come from several sources)
|
||||
pub inputs_source: HashMap<Source, usize>,
|
||||
/// A list of document sources for the node's output
|
||||
pub outputs_source: HashMap<Source, usize>,
|
||||
@@ -203,6 +209,7 @@ impl Default for DocumentNode {
|
||||
manual_composition: Default::default(),
|
||||
has_primary_output: true,
|
||||
implementation: Default::default(),
|
||||
visible: true,
|
||||
metadata: Default::default(),
|
||||
skip_deduplication: Default::default(),
|
||||
world_state_hash: Default::default(),
|
||||
@@ -272,7 +279,7 @@ impl DocumentNode {
|
||||
(ProtoNodeInput::None, ConstructionArgs::Value(tagged_value))
|
||||
}
|
||||
NodeInput::Node { node_id, output_index, lambda } => {
|
||||
assert_eq!(output_index, 0, "Outputs should be flattened before converting to protonode. {:#?}", self.name);
|
||||
assert_eq!(output_index, 0, "Outputs should be flattened before converting to proto node. {:#?}", self.name);
|
||||
let node = if lambda { ProtoNodeInput::NodeLambda(node_id) } else { ProtoNodeInput::Node(node_id) };
|
||||
(node, ConstructionArgs::Nodes(vec![]))
|
||||
}
|
||||
@@ -445,9 +452,9 @@ pub enum DocumentNodeImplementation {
|
||||
///
|
||||
/// A nested [`NodeNetwork`] that is flattened by the [`NodeNetwork::flatten`] function.
|
||||
Network(NodeNetwork),
|
||||
/// This describes a (document) node implemented as a protonode.
|
||||
/// This describes a (document) node implemented as a proto node.
|
||||
///
|
||||
/// A protonode identifier which can be found in `node_registry.rs`.
|
||||
/// A proto node identifier which can be found in `node_registry.rs`.
|
||||
ProtoNode(ProtoNodeIdentifier),
|
||||
/// The Extract variant is a tag which tells the compilation process to do something special. It invokes language-level functionality built for use by the ExtractNode to enable metaprogramming.
|
||||
/// When the ExtractNode is compiled, it gets replaced by a value node containing a representation of the source code for the function/lambda of the document node that's fed into the ExtractNode
|
||||
@@ -523,9 +530,6 @@ pub struct NodeNetwork {
|
||||
pub exports: Vec<NodeOutput>,
|
||||
/// The list of all nodes in this network.
|
||||
pub nodes: HashMap<NodeId, DocumentNode>,
|
||||
/// Nodes that the user has disabled/hidden with the visibility eye icon.
|
||||
/// These nodes get replaced with Identity nodes during the graph flattening step.
|
||||
pub disabled: Vec<NodeId>,
|
||||
/// In the case when another node is previewed (chosen by the user as a temporary output), this stores what it previously was so it can be restored later.
|
||||
pub previous_outputs: Option<Vec<NodeOutput>>,
|
||||
}
|
||||
@@ -540,7 +544,6 @@ impl std::hash::Hash for NodeNetwork {
|
||||
id.hash(state);
|
||||
node.hash(state);
|
||||
}
|
||||
self.disabled.hash(state);
|
||||
self.previous_outputs.hash(state);
|
||||
}
|
||||
}
|
||||
@@ -567,7 +570,6 @@ impl NodeNetwork {
|
||||
imports: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(),
|
||||
exports: vec![NodeOutput::new(NodeId(0), 0)],
|
||||
nodes: [(NodeId(0), node)].into_iter().collect(),
|
||||
disabled: vec![],
|
||||
previous_outputs: None,
|
||||
}
|
||||
}
|
||||
@@ -815,7 +817,6 @@ impl NodeNetwork {
|
||||
pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId + Copy) {
|
||||
self.imports.iter_mut().for_each(|id| *id = f(*id));
|
||||
self.exports.iter_mut().for_each(|output| output.node_id = f(output.node_id));
|
||||
self.disabled.iter_mut().for_each(|id| *id = f(*id));
|
||||
self.previous_outputs
|
||||
.iter_mut()
|
||||
.for_each(|nodes| nodes.iter_mut().for_each(|output| output.node_id = f(output.node_id)));
|
||||
@@ -843,7 +844,7 @@ impl NodeNetwork {
|
||||
outwards_links
|
||||
}
|
||||
|
||||
/// Populate the [`DocumentNode::path`], which stores the location of the document node to allow for matching the resulting protonodes to the document node for the purposes of typing and finding monitor nodes.
|
||||
/// Populate the [`DocumentNode::path`], which stores the location of the document node to allow for matching the resulting proto nodes to the document node for the purposes of typing and finding monitor nodes.
|
||||
pub fn generate_node_paths(&mut self, prefix: &[NodeId]) {
|
||||
for (node_id, node) in &mut self.nodes {
|
||||
let mut new_path = prefix.to_vec();
|
||||
@@ -930,8 +931,11 @@ impl NodeNetwork {
|
||||
return;
|
||||
};
|
||||
|
||||
if node.implementation != DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()) && self.disabled.contains(&id) {
|
||||
node.implementation = DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into());
|
||||
// If the node is hidden, replace it with an identity node
|
||||
let identity_node = DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into());
|
||||
if !node.visible && node.implementation != identity_node {
|
||||
node.implementation = identity_node;
|
||||
|
||||
if node.is_layer() {
|
||||
// Connect layer node to the graphic group below
|
||||
node.inputs.drain(..1);
|
||||
@@ -939,6 +943,7 @@ impl NodeNetwork {
|
||||
node.inputs.drain(1..);
|
||||
}
|
||||
self.nodes.insert(id, node);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -983,7 +988,6 @@ impl NodeNetwork {
|
||||
let new_nodes = inner_network.nodes.keys().cloned().collect::<Vec<_>>();
|
||||
// Copy nodes from the inner network into the parent network
|
||||
self.nodes.extend(inner_network.nodes);
|
||||
self.disabled.extend(inner_network.disabled);
|
||||
|
||||
let mut network_offsets = HashMap::new();
|
||||
assert_eq!(
|
||||
|
||||
@@ -200,7 +200,7 @@ impl ConstructionArgs {
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
|
||||
/// A protonode is an intermediate step between the `DocumentNode` and the boxed struct that actually runs the node (found in the [`BorrowTree`]). It has one primary input and several secondary inputs in [`ConstructionArgs`].
|
||||
/// A proto node is an intermediate step between the `DocumentNode` and the boxed struct that actually runs the node (found in the [`BorrowTree`]). It has one primary input and several secondary inputs in [`ConstructionArgs`].
|
||||
pub struct ProtoNode {
|
||||
pub construction_args: ConstructionArgs,
|
||||
pub input: ProtoNodeInput,
|
||||
@@ -718,7 +718,7 @@ impl TypingContext {
|
||||
ConstructionArgs::Inline(ref inline) => vec![inline.ty.clone()],
|
||||
};
|
||||
|
||||
// Get the node input type from the protonode declaration
|
||||
// Get the node input type from the proto node declaration
|
||||
let input = match node.input {
|
||||
ProtoNodeInput::None => concrete!(()),
|
||||
ProtoNodeInput::ManualComposition(ref ty) => ty.clone(),
|
||||
|
||||
Reference in New Issue
Block a user