Clean up code for optional node inputs/outputs

This removes the unused Split Channels node's primary output
This commit is contained in:
Keavon Chambers 2023-09-03 05:15:02 -07:00
parent bafde43145
commit c4bea2b400
5 changed files with 60 additions and 50 deletions

View File

@ -58,14 +58,14 @@ impl FrontendGraphDataType {
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct NodeGraphInput {
pub struct FrontendGraphInput {
#[serde(rename = "dataType")]
data_type: FrontendGraphDataType,
name: String,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct NodeGraphOutput {
pub struct FrontendGraphOutput {
#[serde(rename = "dataType")]
data_type: FrontendGraphDataType,
name: String,
@ -77,13 +77,13 @@ pub struct FrontendNode {
#[serde(rename = "displayName")]
pub display_name: String,
#[serde(rename = "primaryInput")]
pub primary_input: Option<FrontendGraphDataType>,
pub primary_input: Option<FrontendGraphInput>,
#[serde(rename = "exposedInputs")]
pub exposed_inputs: Vec<NodeGraphInput>,
pub exposed_inputs: Vec<FrontendGraphInput>,
#[serde(rename = "primaryOutput")]
pub primary_output: Option<NodeGraphOutput>,
pub primary_output: Option<FrontendGraphOutput>,
#[serde(rename = "exposedOutputs")]
pub exposed_outputs: Vec<NodeGraphOutput>,
pub exposed_outputs: Vec<FrontendGraphOutput>,
pub position: (i32, i32),
pub disabled: bool,
pub previewed: bool,
@ -291,34 +291,26 @@ impl NodeGraphMessageHandler {
let mut nodes = Vec::new();
for (id, node) in &network.nodes {
// TODO: This should be based on the graph runtime type inference system in order to change the colors of node connectors to match the data type in use
let Some(node_type) = document_node_types::resolve_document_node_type(&node.name) else {
warn!("Node '{}' does not exist in library", node.name);
continue;
};
let primary_input = node
.inputs
.first()
.filter(|input| input.is_exposed())
.and_then(|_| node_type.inputs.get(0))
.map(|input_type| input_type.data_type);
let exposed_inputs = node
.inputs
.iter()
.zip(node_type.inputs.iter())
.skip(1)
.filter(|(input, _)| input.is_exposed())
.map(|(_, input_type)| NodeGraphInput {
// Inputs
let mut inputs = node.inputs.iter().zip(node_type.inputs.iter().map(|input_type| FrontendGraphInput {
data_type: input_type.data_type,
name: input_type.name.to_string(),
})
.collect();
}));
let primary_input = inputs.next().filter(|(input, _)| input.is_exposed()).map(|(_, input_type)| input_type);
let exposed_inputs = inputs.filter(|(input, _)| input.is_exposed()).map(|(_, input_type)| input_type).collect();
let mut outputs = node_type.outputs.iter().map(|output_type| NodeGraphOutput {
// Outputs
let mut outputs = node_type.outputs.iter().map(|output_type| FrontendGraphOutput {
data_type: output_type.data_type,
name: output_type.name.to_string(),
});
let primary_output = outputs.next();
let primary_output = if node.has_primary_output { outputs.next() } else { None };
let _graph_identifier = GraphIdentifier::new(layer_id);

View File

@ -101,7 +101,7 @@ pub struct DocumentNodeType {
pub identifier: NodeImplementation,
pub inputs: Vec<DocumentInputType>,
pub outputs: Vec<DocumentOutputType>,
pub primary_output: bool,
pub has_primary_output: bool,
pub properties: fn(&DocumentNode, NodeId, &mut NodePropertiesContext) -> Vec<LayoutGroup>,
pub manual_composition: Option<graphene_core::Type>,
}
@ -114,7 +114,7 @@ impl Default for DocumentNodeType {
identifier: Default::default(),
inputs: Default::default(),
outputs: Default::default(),
primary_output: Default::default(),
has_primary_output: true,
properties: node_properties::no_properties,
manual_composition: Default::default(),
}
@ -836,12 +836,6 @@ fn static_nodes() -> Vec<DocumentNodeType> {
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::ExtractAlphaNode<>")),
..Default::default()
},
DocumentNode {
name: "EmptyOutput".to_string(),
inputs: vec![NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), false)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
..Default::default()
},
]
.into_iter()
.enumerate()
@ -852,13 +846,12 @@ fn static_nodes() -> Vec<DocumentNodeType> {
}),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
outputs: vec![
DocumentOutputType::new("Empty", FrontendGraphDataType::Raster),
DocumentOutputType::new("Red", FrontendGraphDataType::Raster),
DocumentOutputType::new("Green", FrontendGraphDataType::Raster),
DocumentOutputType::new("Blue", FrontendGraphDataType::Raster),
DocumentOutputType::new("Alpha", FrontendGraphDataType::Raster),
],
primary_output: false,
has_primary_output: false,
..Default::default()
},
DocumentNodeType {
@ -2468,6 +2461,7 @@ impl DocumentNodeType {
DocumentNode {
name: self.name.to_string(),
inputs,
has_primary_output: self.has_primary_output,
implementation: self.generate_implementation(),
metadata,
manual_composition: self.manual_composition.clone(),

View File

@ -681,9 +681,9 @@
viewBox="0 0 8 8"
class="port"
data-port="input"
data-datatype={node.primaryInput}
style:--data-color={`var(--color-data-${node.primaryInput})`}
style:--data-color-dim={`var(--color-data-${node.primaryInput}-dim)`}
data-datatype={node.primaryInput?.dataType}
style:--data-color={`var(--color-data-${node.primaryInput?.dataType})`}
style:--data-color-dim={`var(--color-data-${node.primaryInput?.dataType}-dim)`}
>
<title>{node.primaryInput} data</title>
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" />
@ -768,15 +768,15 @@
{/if}
<!-- Input ports -->
<div class="input ports">
{#if node.primaryInput}
{#if node.primaryInput?.dataType}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="port primary-port"
data-port="input"
data-datatype={node.primaryInput}
style:--data-color={`var(--color-data-${node.primaryInput})`}
style:--data-color-dim={`var(--color-data-${node.primaryInput}-dim)`}
data-datatype={node.primaryInput?.dataType}
style:--data-color={`var(--color-data-${node.primaryInput?.dataType})`}
style:--data-color-dim={`var(--color-data-${node.primaryInput?.dataType}-dim)`}
>
<title>{node.primaryInput} data</title>
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" />
@ -835,7 +835,7 @@
<clipPath id={clipPathId}>
<path
clip-rule="evenodd"
d={nodeBorderMask(120, node.primaryInput !== undefined, node.exposedInputs.length, node.primaryOutput !== undefined, node.exposedOutputs.length)}
d={nodeBorderMask(120, node.primaryInput?.dataType !== undefined, node.exposedInputs.length, node.primaryOutput !== undefined, node.exposedOutputs.length)}
/>
</clipPath>
</defs>

View File

@ -81,13 +81,13 @@ export class FrontendDocumentDetails extends DocumentDetails {
export type FrontendGraphDataType = "general" | "raster" | "color" | "vector" | "vec2" | "graphic" | "artboard";
export class NodeGraphInput {
export class FrontendGraphInput {
readonly dataType!: FrontendGraphDataType;
readonly name!: string;
}
export class NodeGraphOutput {
export class FrontendGraphOutput {
readonly dataType!: FrontendGraphDataType;
readonly name!: string;
@ -98,13 +98,13 @@ export class FrontendNode {
readonly displayName!: string;
readonly primaryInput!: FrontendGraphDataType | undefined;
readonly primaryInput!: FrontendGraphInput | undefined;
readonly exposedInputs!: NodeGraphInput[];
readonly exposedInputs!: FrontendGraphInput[];
readonly primaryOutput!: NodeGraphOutput | undefined;
readonly primaryOutput!: FrontendGraphOutput | undefined;
readonly exposedOutputs!: NodeGraphOutput[];
readonly exposedOutputs!: FrontendGraphOutput[];
@TupleToVec2
readonly position!: XY | undefined;

View File

@ -31,12 +31,20 @@ impl DocumentNodeMetadata {
}
}
#[derive(Clone, Debug, PartialEq, Hash, DynAny, Default)]
/// Utility function for providing a default boolean value to serde.
#[inline(always)]
fn return_true() -> bool {
true
}
#[derive(Clone, Debug, PartialEq, Hash, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DocumentNode {
pub name: String,
pub inputs: Vec<NodeInput>,
pub manual_composition: Option<Type>,
#[serde(default = "return_true")]
pub has_primary_output: bool,
pub implementation: DocumentNodeImplementation,
pub metadata: DocumentNodeMetadata,
#[serde(default)]
@ -47,6 +55,22 @@ pub struct DocumentNode {
pub path: Option<Vec<NodeId>>,
}
impl Default for DocumentNode {
fn default() -> Self {
Self {
name: Default::default(),
inputs: Default::default(),
manual_composition: Default::default(),
has_primary_output: true,
implementation: Default::default(),
metadata: Default::default(),
skip_deduplication: Default::default(),
hash: Default::default(),
path: Default::default(),
}
}
}
impl DocumentNode {
pub fn populate_first_network_input(&mut self, node_id: NodeId, output_index: usize, offset: usize, lambda: bool) {
let (index, _) = self