mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
* Add graph-storage crate * Split graph-storage lib.rs into smaller modules * Make graph_craft/core_types dependency optional * Fix CRDT correctness issues flagged in graph-storage PR review * Treat trailing empty export slots as value-equal in Network::value_equal * Address graph-storage review: parameterize CrdtError, reject hot-log corruption, drop LamportClock Default * Address graph-storage review: fix root-delta history walk, validate cross-network refs, make compute_deltas deterministic, harden Priority, index nodes by network * Address graph-storage review: sort sources on deserialize, treat inputs_attributes length as structural, dedupe demo-artwork loader * Add opt-in Delta rev validation, dedup resource sources on deserialize, fix doc grammar * Persist scope injections through storage; harden gesture-end and embedded-source checks * Review * Review * Review * Use new types for NodeId and NetworkId * Adress minor review comments --------- Co-authored-by: Timon <me@timon.zip>
131 lines
4.9 KiB
Rust
131 lines
4.9 KiB
Rust
//! Lets `from_runtime` read editor-side per-node metadata without depending on the editor crate.
|
|
//! The editor implements this on `NodeNetworkInterface`; tests pass [`NoMetadata`].
|
|
//!
|
|
//! `network_path` is the chain of runtime local `NodeId`s from the root down to (but not including)
|
|
//! the queried node, matching `NodeNetworkInterface::node_metadata(node_id, network_path)`.
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use core_types::uuid::NodeId as RuntimeNodeId;
|
|
|
|
/// One node's editor-side metadata, produced by `Registry::to_runtime_with_metadata`.
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct NodeMetadataEntry {
|
|
pub network_path: Vec<RuntimeNodeId>,
|
|
pub local_id: RuntimeNodeId,
|
|
pub position: Option<Position>,
|
|
pub is_layer: bool,
|
|
pub display_name: Option<String>,
|
|
pub locked: bool,
|
|
pub pinned: bool,
|
|
/// Always sized to match the runtime node's `inputs.len()`; absent slots use `Default`. The rebuild
|
|
/// returns an error if this length does not match the node's input count.
|
|
pub input_metadata: Vec<InputMetadataEntry>,
|
|
pub output_names: Vec<String>,
|
|
}
|
|
|
|
impl NodeMetadataEntry {
|
|
pub fn is_empty(&self) -> bool {
|
|
self.position.is_none()
|
|
&& !self.is_layer
|
|
&& self.display_name.is_none()
|
|
&& !self.locked
|
|
&& !self.pinned
|
|
&& self.output_names.is_empty()
|
|
&& self.input_metadata.iter().all(InputMetadataEntry::is_empty)
|
|
}
|
|
}
|
|
|
|
/// Per-network metadata (navigation, previewing). Separate from `NodeMetadataEntry` since these are
|
|
/// properties of a network, not of any node.
|
|
#[derive(Clone, Debug, Default, PartialEq)]
|
|
pub struct NetworkMetadataEntry {
|
|
/// Owning-node chain from the root to (and including) the node containing this network.
|
|
/// Empty = root network.
|
|
pub network_path: Vec<RuntimeNodeId>,
|
|
/// Stable storage id of this network. Lets the editor associate per-network, per-peer view state
|
|
/// (node-graph nav + previewing, in `session.json`) with a network across reparenting.
|
|
pub network_id: crate::NetworkId,
|
|
/// Matches the runtime's `NodeNetworkPersistentMetadata::reference` — definition lineage tag.
|
|
pub reference: Option<String>,
|
|
}
|
|
|
|
impl NetworkMetadataEntry {
|
|
pub fn is_empty(&self) -> bool {
|
|
self.reference.is_none()
|
|
}
|
|
}
|
|
|
|
/// Per-input editor metadata. Mirrors `InputPersistentMetadata` but wraps strings in `Option` so
|
|
/// unset (`""` on the runtime side) is distinguishable from an explicit empty string.
|
|
#[derive(Clone, Debug, Default, PartialEq)]
|
|
pub struct InputMetadataEntry {
|
|
pub input_name: Option<String>,
|
|
pub input_description: Option<String>,
|
|
pub widget_override: Option<String>,
|
|
/// Reassembled from `ui::input_data::<sub_key>` attributes.
|
|
pub input_data: HashMap<String, serde_json::Value>,
|
|
}
|
|
|
|
impl InputMetadataEntry {
|
|
pub fn is_empty(&self) -> bool {
|
|
self.input_name.is_none() && self.input_description.is_none() && self.widget_override.is_none() && self.input_data.is_empty()
|
|
}
|
|
}
|
|
|
|
/// Editor-side metadata source. Methods default to "no data" so implementors only override what
|
|
/// they carry. Returns are JSON-shaped where the underlying types live editor-side (PTZ, etc.).
|
|
pub trait NodeMetadataSource {
|
|
fn position(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> Option<Position> {
|
|
None
|
|
}
|
|
fn is_layer(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> bool {
|
|
false
|
|
}
|
|
fn display_name(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> Option<&str> {
|
|
None
|
|
}
|
|
fn locked(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> bool {
|
|
false
|
|
}
|
|
fn pinned(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> bool {
|
|
false
|
|
}
|
|
/// Empty vec = no overrides. Stored as a single `ui::output_names` attribute (whole-vec LWW).
|
|
fn output_names(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId) -> Vec<String> {
|
|
Vec::new()
|
|
}
|
|
|
|
fn input_name(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId, _input_index: usize) -> Option<&str> {
|
|
None
|
|
}
|
|
fn input_description(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId, _input_index: usize) -> Option<&str> {
|
|
None
|
|
}
|
|
fn widget_override(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId, _input_index: usize) -> Option<&str> {
|
|
None
|
|
}
|
|
/// Returns owned to stay object-safe. Each entry is stored as `ui::input_data::<key>` for per-key LWW.
|
|
fn input_data(&self, _network_path: &[RuntimeNodeId], _local_id: RuntimeNodeId, _input_index: usize) -> HashMap<String, serde_json::Value> {
|
|
HashMap::new()
|
|
}
|
|
|
|
fn reference(&self, _network_path: &[RuntimeNodeId]) -> Option<&str> {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// No-op metadata source. Use when there's nothing to attach (synthetic networks, CLI tools).
|
|
pub struct NoMetadata;
|
|
|
|
impl NodeMetadataSource for NoMetadata {}
|
|
|
|
/// Unified storage-side position. The valid variants depend on `attr::node::ui::IS_LAYER`:
|
|
/// layers use `Absolute` or `Stack`; non-layer nodes use `Absolute` or `Chain`.
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
pub enum Position {
|
|
Absolute([i32; 2]),
|
|
Chain,
|
|
Stack(u32),
|
|
}
|