mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08:00
Replace raw node input indices with compile-time parameter symbols (#4387)
* Remove the dead InputAccessor traits and the uncallable test helper built on them * Replace raw node input indices with macro-generated parameter symbols across the editor * Audit dynamic input index usage, converting to parameter symbols and named input position constants * Abstract the remaining input index plumbing behind ParameterRef APIs and accessors * Build SetInputValue messages as struct literals to keep message enums impl-free * Delete the typed parameter markers in favor of explicit-output test introspection * Wire the interpolation control path input per chain node type * Return no input when a parameter symbol is read against the wrong node's parameter view
This commit is contained in:
committed by
Dennis Kobert
parent
7d25f84210
commit
81cb0515f5
@@ -5,7 +5,7 @@ use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode};
|
||||
use core_types::memo::MemoHashGuard;
|
||||
pub use core_types::uuid::NodeId;
|
||||
pub use core_types::uuid::generate_uuid;
|
||||
use core_types::{Context, ContextDependencies, Cow, MemoHash, ProtoNodeIdentifier, Type};
|
||||
use core_types::{Context, ContextDependencies, Cow, MemoHash, NodeParameter, ProtoNodeIdentifier, Type};
|
||||
use dyn_any::DynAny;
|
||||
use glam::IVec2;
|
||||
use rustc_hash::FxHashMap;
|
||||
@@ -121,6 +121,21 @@ impl OriginalLocation {
|
||||
}
|
||||
}
|
||||
impl DocumentNode {
|
||||
/// The input slot named by the given parameter symbol, e.g. `node.input(stroke::WeightInput)`.
|
||||
pub fn input<P: NodeParameter>(&self, _parameter: P) -> Option<&NodeInput> {
|
||||
self.inputs.get(P::INDEX)
|
||||
}
|
||||
|
||||
/// Mutable access to the input slot named by the given parameter symbol.
|
||||
pub fn input_mut<P: NodeParameter>(&mut self, _parameter: P) -> Option<&mut NodeInput> {
|
||||
self.inputs.get_mut(P::INDEX)
|
||||
}
|
||||
|
||||
/// The stored value of the given parameter, if that input currently holds a value rather than a wire.
|
||||
pub fn input_value<P: NodeParameter>(&self, parameter: P) -> Option<&TaggedValue> {
|
||||
self.input(parameter)?.as_value()
|
||||
}
|
||||
|
||||
/// Locate the input that is a [`NodeInput::Import`] at index `offset` and replace it with a [`NodeInput::Node`].
|
||||
pub fn populate_first_network_input(&mut self, node_id: NodeId, output_index: usize, offset: usize, source: impl Iterator<Item = Source>, skip: usize) {
|
||||
let (index, _) = self
|
||||
|
||||
@@ -70,3 +70,23 @@ pub trait NodeInputDecleration {
|
||||
fn identifier() -> ProtoNodeIdentifier;
|
||||
type Result;
|
||||
}
|
||||
|
||||
/// Master spells this trait `NodeParameter`; our node macro emits `NodeInputDecleration`.
|
||||
pub use NodeInputDecleration as NodeParameter;
|
||||
|
||||
/// A runtime reference to one parameter of one proto node, for heterogeneous tables and runtime-chosen parameters.
|
||||
/// Convert a symbol with `.into()`; unlike a raw index, the node identifier and index always stay paired.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ParameterRef {
|
||||
pub node_identifier: ProtoNodeIdentifier,
|
||||
pub input_index: usize,
|
||||
}
|
||||
|
||||
impl<P: NodeParameter> From<P> for ParameterRef {
|
||||
fn from(_: P) -> Self {
|
||||
ParameterRef {
|
||||
node_identifier: P::identifier(),
|
||||
input_index: P::INDEX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,25 +29,21 @@ pub(crate) fn generate_node_input_references(
|
||||
let struct_name = format_ident!("{}Input", input_ident.ident.to_string().to_case(Case::Pascal));
|
||||
let (fn_generic_params, phantom_data_declerations) = generate_phantom_data(used.iter());
|
||||
|
||||
// Only create structs with phantom data where necessary.
|
||||
generated_input_accessor.push(if phantom_data_declerations.is_empty() {
|
||||
quote! {
|
||||
pub struct #struct_name;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
pub struct #struct_name <#(#used),*>{
|
||||
#(#phantom_data_declerations,)*
|
||||
}
|
||||
}
|
||||
});
|
||||
// The marker is always a unit struct so it can be passed as a value; its generics would only have described
|
||||
// `Result`, which nothing reads through the marker.
|
||||
let _ = &phantom_data_declerations;
|
||||
generated_input_accessor.push(quote! {
|
||||
impl <#(#used),*> #core_types::NodeInputDecleration for #struct_name <#(#fn_generic_params),*> {
|
||||
pub struct #struct_name;
|
||||
});
|
||||
let result_ty = if used.is_empty() { quote!(#ty) } else { quote!(()) };
|
||||
let _ = &fn_generic_params;
|
||||
generated_input_accessor.push(quote! {
|
||||
impl #core_types::NodeInputDecleration for #struct_name {
|
||||
const INDEX: usize = #input_index;
|
||||
fn identifier() -> #core_types::ProtoNodeIdentifier {
|
||||
#inputs_module_name::IDENTIFIER.clone()
|
||||
}
|
||||
type Result = #ty;
|
||||
type Result = #result_ty;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user