WIP: Closures and deferred evaluation for geometry nodes #107842
|
@ -9,6 +9,7 @@ from bpy.types import (
|
|||
from bpy.props import (
|
||||
BoolProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
StringProperty,
|
||||
)
|
||||
|
||||
|
@ -198,10 +199,109 @@ class NODE_OT_tree_path_parent(Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NodeFunctionSignatureOperator():
|
||||
# Dictionary of node types with methods to get the signature
|
||||
signature_nodes = {
|
||||
'FunctionNodeEvaluate' : lambda node: node.signature,
|
||||
}
|
||||
|
||||
param_type: EnumProperty(
|
||||
name = "Parameter Type",
|
||||
items = [
|
||||
('INPUT', "Input", ""),
|
||||
('OUTPUT', "Output", ""),
|
||||
]
|
||||
)
|
||||
|
||||
def params_get(self, signature):
|
||||
return signature.inputs if self.param_type == 'INPUT' else signature.outputs
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
snode = context.space_data
|
||||
if snode is None:
|
||||
return False
|
||||
node = context.active_node
|
||||
if node is None or node.bl_idname not in cls.signature_nodes:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class NODE_OT_function_parameter_add(NodeFunctionSignatureOperator, Operator):
|
||||
'''Add a parameter to the function signature'''
|
||||
bl_idname = "node.function_parameter_add"
|
||||
bl_label = "Add Parameter"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
default_socket_type = 'FLOAT'
|
||||
|
||||
def execute(self, context):
|
||||
node = context.active_node
|
||||
signature = self.signature_nodes[node.bl_idname](node)
|
||||
params = self.params_get(signature)
|
||||
|
||||
# Remember index to move the item
|
||||
dst_index = min(params.active_index + 1, len(params))
|
||||
# Empty name so it is based on the type only
|
||||
params.new(self.default_socket_type, "")
|
||||
params.move(len(params) - 1, dst_index)
|
||||
params.active_index = dst_index
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NODE_OT_function_parameter_remove(NodeFunctionSignatureOperator, Operator):
|
||||
'''Remove a parameter from the function signature'''
|
||||
bl_idname = "node.function_parameter_remove"
|
||||
bl_label = "Remove Parameter"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
node = context.active_node
|
||||
signature = self.signature_nodes[node.bl_idname](node)
|
||||
params = self.params_get(signature)
|
||||
|
||||
if params.active:
|
||||
params.remove(params.active)
|
||||
params.active_index = min(params.active_index, len(params) - 1)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NODE_OT_function_parameter_move(NodeFunctionSignatureOperator, Operator):
|
||||
'''Move a parameter item up or down in the signature'''
|
||||
bl_idname = "node.function_parameter_move"
|
||||
bl_label = "Move Parameter"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
direction: EnumProperty(
|
||||
name="Direction",
|
||||
items=[('UP', "Up", ""), ('DOWN', "Down", "")],
|
||||
default = 'UP',
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
node = context.active_node
|
||||
signature = self.signature_nodes[node.bl_idname](node)
|
||||
params = self.params_get(signature)
|
||||
|
||||
if self.direction == 'UP' and params.active_index > 0:
|
||||
params.move(params.active_index, params.active_index - 1)
|
||||
params.active_index -= 1
|
||||
elif self.direction == 'DOWN' and params.active_index < len(params) - 1:
|
||||
params.move(params.active_index, params.active_index + 1)
|
||||
params.active_index += 1
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
classes = (
|
||||
NodeSetting,
|
||||
|
||||
NODE_OT_add_node,
|
||||
NODE_OT_collapse_hide_unused_toggle,
|
||||
NODE_OT_tree_path_parent,
|
||||
NODE_OT_function_parameter_add,
|
||||
NODE_OT_function_parameter_remove,
|
||||
NODE_OT_function_parameter_move,
|
||||
)
|
||||
|
|
|
@ -955,6 +955,98 @@ class NODE_PT_node_tree_interface_outputs(NodeTreeInterfacePanel):
|
|||
self.draw_socket_list(context, "OUT", "outputs", "active_output")
|
||||
|
||||
|
||||
class NODE_UL_function_parameters(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
row = layout.row(align=True)
|
||||
|
||||
row.template_node_socket(color=item.color)
|
||||
row.prop(item, "name", text="", emboss=False, icon_value=icon)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.template_node_socket(color=item.color)
|
||||
|
||||
|
||||
class FunctionSignaturePanel():
|
||||
# Must be defined by subclasses
|
||||
param_type = None
|
||||
params_prop = None
|
||||
|
||||
# Dictionary of node types with methods to get the signature
|
||||
signature_nodes = {
|
||||
'FunctionNodeEvaluate' : lambda node: node.signature,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
snode = context.space_data
|
||||
if snode is None:
|
||||
return False
|
||||
node = context.active_node
|
||||
if node is None or node.bl_idname not in cls.signature_nodes:
|
||||
return False
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node = context.active_node
|
||||
signature = self.signature_nodes[node.bl_idname](node)
|
||||
params = getattr(signature, self.params_prop)
|
||||
|
||||
split = layout.row()
|
||||
|
||||
split.template_list(
|
||||
"NODE_UL_function_parameters",
|
||||
self.params_prop,
|
||||
signature,
|
||||
self.params_prop,
|
||||
params,
|
||||
"active_index")
|
||||
|
||||
ops_col = split.column()
|
||||
|
||||
add_remove_col = ops_col.column(align=True)
|
||||
props = add_remove_col.operator("node.function_parameter_add", icon='ADD', text="")
|
||||
props.param_type = self.param_type
|
||||
props = add_remove_col.operator("node.function_parameter_remove", icon='REMOVE', text="")
|
||||
props.param_type = self.param_type
|
||||
|
||||
ops_col.separator()
|
||||
|
||||
up_down_col = ops_col.column(align=True)
|
||||
props = up_down_col.operator("node.function_parameter_move", icon='TRIA_UP', text="")
|
||||
props.param_type = self.param_type
|
||||
props.direction = 'UP'
|
||||
props = up_down_col.operator("node.function_parameter_move", icon='TRIA_DOWN', text="")
|
||||
props.param_type = self.param_type
|
||||
props.direction = 'DOWN'
|
||||
|
||||
active_param = params.active
|
||||
if active_param is not None:
|
||||
layout.prop(active_param, "socket_type")
|
||||
layout.prop(active_param, "name")
|
||||
|
||||
|
||||
class NODE_PT_function_signature_inputs(FunctionSignaturePanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_label = "Function Signature Inputs"
|
||||
|
||||
param_type = 'INPUT'
|
||||
params_prop = "inputs"
|
||||
|
||||
|
||||
class NODE_PT_function_signature_outputs(FunctionSignaturePanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_label = "Function Signature Outputs"
|
||||
|
||||
param_type = 'OUTPUT'
|
||||
params_prop = "outputs"
|
||||
|
||||
|
||||
# Grease Pencil properties
|
||||
class NODE_PT_annotation(AnnotationDataPanel, Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
|
@ -1019,6 +1111,9 @@ classes = (
|
|||
NODE_UL_interface_sockets,
|
||||
NODE_PT_node_tree_interface_inputs,
|
||||
NODE_PT_node_tree_interface_outputs,
|
||||
NODE_UL_function_parameters,
|
||||
NODE_PT_function_signature_inputs,
|
||||
NODE_PT_function_signature_outputs,
|
||||
|
||||
node_panel(EEVEE_MATERIAL_PT_settings),
|
||||
node_panel(MATERIAL_PT_viewport),
|
||||
|
|
|
@ -258,6 +258,10 @@ bool nodeFunctionParameterSetUniqueName(bNodeFunctionSignature *sig,
|
|||
unique_name,
|
||||
ARRAY_SIZE(unique_name));
|
||||
}
|
||||
else if (unique_name[0] == '\0') {
|
||||
/* Should use default if name is empty, same as BLI_uniquename_cb behavior. */
|
||||
BLI_strncpy(unique_name, defname, sizeof(unique_name));
|
||||
}
|
||||
param->name = BLI_strdup(unique_name);
|
||||
return name_changed;
|
||||
}
|
||||
|
|
|
@ -5490,30 +5490,57 @@ static void rna_def_node_function_parameter(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Color", "Socket color");
|
||||
}
|
||||
|
||||
static void rna_def_node_function_signature_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
|
||||
static void rna_def_node_function_signature_api(BlenderRNA *brna, PropertyRNA *cprop, eNodeFunctionParameterType param_type)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
const char *structtype = (in_out == SOCK_IN ? "NodeFunctionSignatureInputs" : "NodeFunctionSignatureOutputs");
|
||||
const char *uiname = (in_out == SOCK_IN ? "Node Function Signature Inputs" : "Node Function Signature Outputs");
|
||||
const char *newfunc = (in_out == SOCK_IN ? "rna_NodeFunctionSignature_inputs_new" :
|
||||
"rna_NodeFunctionSignature_outputs_new");
|
||||
const char *structtype = (param_type == NODE_FUNC_PARAM_IN ? "NodeFunctionSignatureInputs" :
|
||||
"NodeFunctionSignatureOutputs");
|
||||
const char *uiname = (param_type == NODE_FUNC_PARAM_IN ? "Node Function Signature Inputs" :
|
||||
"Node Function Signature Outputs");
|
||||
const char *active_index_sdna = (param_type == NODE_FUNC_PARAM_IN ? "active_input" :
|
||||
"active_output");
|
||||
const char *active_param_get = (param_type == NODE_FUNC_PARAM_IN ?
|
||||
"rna_NodeFunctionSignature_active_input_get" :
|
||||
"rna_NodeFunctionSignature_active_output_get");
|
||||
const char *active_param_set = (param_type == NODE_FUNC_PARAM_IN ?
|
||||
"rna_NodeFunctionSignature_active_input_set" :
|
||||
"rna_NodeFunctionSignature_active_output_set");
|
||||
const char *newfunc = (param_type == NODE_FUNC_PARAM_IN ?
|
||||
"rna_NodeFunctionSignature_inputs_new" :
|
||||
"rna_NodeFunctionSignature_outputs_new");
|
||||
const char *removefunc = "rna_NodeFunctionSignature_params_remove";
|
||||
const char *clearfunc = (in_out == SOCK_IN ? "rna_NodeFunctionSignature_inputs_clear" :
|
||||
"rna_NodeFunctionSignature_outputs_clear");
|
||||
const char *movefunc = (in_out == SOCK_IN ? "rna_NodeFunctionSignature_inputs_move" :
|
||||
"rna_NodeFunctionSignature_outputs_move");
|
||||
const char *clearfunc = (param_type == NODE_FUNC_PARAM_IN ?
|
||||
"rna_NodeFunctionSignature_inputs_clear" :
|
||||
"rna_NodeFunctionSignature_outputs_clear");
|
||||
const char *movefunc = (param_type == NODE_FUNC_PARAM_IN ?
|
||||
"rna_NodeFunctionSignature_inputs_move" :
|
||||
"rna_NodeFunctionSignature_outputs_move");
|
||||
|
||||
RNA_def_property_srna(cprop, structtype);
|
||||
srna = RNA_def_struct(brna, structtype, NULL);
|
||||
RNA_def_struct_sdna(srna, "bNodeFunctionSignature");
|
||||
RNA_def_struct_ui_text(srna, uiname, "Collection of node function parameters");
|
||||
|
||||
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, active_index_sdna);
|
||||
RNA_def_property_ui_text(prop, "Active Index", "Index of the active parameter");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NodeFunctionParameter");
|
||||
RNA_def_property_pointer_funcs(prop, active_param_get, active_param_set, NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Active", "Active parameter");
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
|
||||
func = RNA_def_function(srna, "new", newfunc);
|
||||
RNA_def_function_ui_description(func, "Add a parameter to this signature");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
|
||||
parm = RNA_def_string(func, "type", NULL, MAX_NAME, "Type", "Data type");
|
||||
parm = RNA_def_enum(
|
||||
func, "socket_type", node_socket_data_type_items, SOCK_FLOAT, "Type", "Data type");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", "");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
@ -5529,11 +5556,11 @@ static void rna_def_node_function_signature_api(BlenderRNA *brna, PropertyRNA *c
|
|||
|
||||
func = RNA_def_function(srna, "clear", clearfunc);
|
||||
RNA_def_function_ui_description(func, "Remove all parameters from this collection");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
|
||||
|
||||
func = RNA_def_function(srna, "move", movefunc);
|
||||
RNA_def_function_ui_description(func, "Move a parameter to another position");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
|
||||
parm = RNA_def_int(
|
||||
func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the parameter to move", 0, 10000);
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
@ -5556,46 +5583,14 @@ static void rna_def_node_function_signature(BlenderRNA *brna)
|
|||
RNA_def_property_struct_type(prop, "NodeFunctionParameter");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Inputs", "Function inputs");
|
||||
rna_def_node_function_signature_api(brna, prop, SOCK_IN);
|
||||
rna_def_node_function_signature_api(brna, prop, NODE_FUNC_PARAM_IN);
|
||||
|
||||
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "outputs", "outputs_num");
|
||||
RNA_def_property_struct_type(prop, "NodeFunctionParameter");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Outputs", "Function outputs");
|
||||
rna_def_node_function_signature_api(brna, prop, SOCK_OUT);
|
||||
|
||||
prop = RNA_def_property(srna, "active_input_index", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "active_input");
|
||||
RNA_def_property_ui_text(prop, "Active Input Index", "Index of the active input");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active_output_index", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "active_output");
|
||||
RNA_def_property_ui_text(prop, "Active Output Index", "Index of the active output");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active_input", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NodeFunctionParameter");
|
||||
RNA_def_property_pointer_funcs(prop,
|
||||
"rna_NodeFunctionSignature_active_input_get",
|
||||
"rna_NodeFunctionSignature_active_input_set",
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(prop, "Active Input Index", "Index of the active input");
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active_output", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NodeFunctionParameter");
|
||||
RNA_def_property_pointer_funcs(prop,
|
||||
"rna_NodeFunctionSignature_active_output_get",
|
||||
"rna_NodeFunctionSignature_active_output_set",
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(prop, "Active Output Index", "Index of the active output");
|
||||
RNA_def_property_update(prop, NC_NODE, NULL);
|
||||
rna_def_node_function_signature_api(brna, prop, NODE_FUNC_PARAM_OUT);
|
||||
}
|
||||
|
||||
static void def_fn_evaluate(StructRNA *srna)
|
||||
|
|
|
@ -342,7 +342,9 @@ SocketDeclarationPtr declaration_for_signature_parameter(const bNodeFunctionPara
|
|||
dst = std::make_unique<decl::Custom>();
|
||||
break;
|
||||
}
|
||||
dst->name = param.name;
|
||||
dst->name = param.name ? param.name : "";
|
||||
char buf[MAX_NAME];
|
||||
dst->identifier = BLI_snprintf(buf, sizeof(buf), "Item_%d", param.identifier);
|
||||
dst->in_out = in_out;
|
||||
dst->hide_value = true;
|
||||
dst->compact = false;
|
||||
|
|
Loading…
Reference in New Issue