From 9894c542edd89494975bbd213c8cfe1d881498d3 Mon Sep 17 00:00:00 2001 From: BrendanParmer <51296046+BrendanParmer@users.noreply.github.com> Date: Tue, 23 May 2023 13:56:25 -0500 Subject: [PATCH] fix: added group io logic to shader nodes --- geo_nodes.py | 150 +++++---------------------------------------------- materials.py | 10 ++++ utils.py | 69 ++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 138 deletions(-) diff --git a/geo_nodes.py b/geo_nodes.py index 6f9082a..9257fba 100644 --- a/geo_nodes.py +++ b/geo_nodes.py @@ -3,9 +3,6 @@ from .utils import * -#node tree input sockets that have default properties -default_sockets = {'VALUE', 'INT', 'BOOLEAN', 'VECTOR', 'RGBA'} - geo_node_settings = { # Attribute nodes "GeometryNodeAttributeStatistic" : ["data_type", "domain"], @@ -212,14 +209,14 @@ def execute(self, context): used_vars = set() def process_geo_nodes_group(node_tree, level, node_vars, used_vars): - node_tree_var = create_var(node_tree.name, used_vars) + nt_var = create_var(node_tree.name, used_vars) outer, inner = make_indents(level) #initialize node group - file.write(f"{outer}#initialize {node_tree_var} node group\n") - file.write(f"{outer}def {node_tree_var}_node_group():\n") - file.write((f"{inner}{node_tree_var}" + file.write(f"{outer}#initialize {nt_var} node group\n") + file.write(f"{outer}def {nt_var}_node_group():\n") + file.write((f"{inner}{nt_var}" f"= bpy.data.node_groups.new(" f"type = \"GeometryNodeTree\", " f"name = \"{node_tree.name}\")\n")) @@ -229,7 +226,7 @@ def process_geo_nodes_group(node_tree, level, node_vars, used_vars): outputs_set = False #initialize nodes - file.write(f"{inner}#initialize {node_tree_var} nodes\n") + file.write(f"{inner}#initialize {nt_var} nodes\n") sim_inputs = [] @@ -241,138 +238,15 @@ def process_geo_nodes_group(node_tree, level, node_vars, used_vars): used_vars) node_trees.add(node_nt) elif node.bl_idname == 'NodeGroupInput' and not inputs_set: - file.write(f"{inner}#{node_tree_var} inputs\n") - for i, input in enumerate(node.outputs): - if input.bl_idname != "NodeSocketVirtual": - file.write(f"{inner}#input {input.name}\n") - file.write((f"{inner}{node_tree_var}.inputs.new" - f"(\"{input.bl_idname}\", " - f"\"{input.name}\")\n")) - socket = node_tree.inputs[i] - if input.type in default_sockets: - if input.type == 'RGBA': - dv = vec4_to_py_str(socket.default_value) - elif input.type == 'VECTOR': - dv = vec3_to_py_str(socket.default_value) - else: - dv = socket.default_value - - #default value - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".default_value = {dv}\n")) - - #min value - if hasattr(socket, "min_value"): - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".min_value = " - f"{socket.min_value}\n")) - #max value - if hasattr(socket, "max_value"): - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".max_value = " - f"{socket.max_value}\n")) - #default attribute name - if hasattr(socket, "default_attribute_name"): - if socket.default_attribute_name != "": - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".default_attribute_name = \"" - f"{socket.default_attribute_name}" - f"\"\n")) - #description - if socket.description != "": - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".description = " - f"\"{socket.description}\"\n")) - #hide value - if socket.hide_value is True: - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".hide_value = " - f"{socket.hide_value}\n")) - - #hide in modifier - if hasattr(socket, "hide_in_modifier"): - if socket.hide_in_modifier is True: - file.write((f"{inner}{node_tree_var}" - f".inputs[{i}]" - f".hide_in_modifier = " - f"{socket.hide_in_modifier}\n")) - file.write("\n") - file.write("\n") + group_io_settings(node, file, inner, "input", nt_var, node_tree) inputs_set = True elif node.bl_idname == 'NodeGroupOutput' and not outputs_set: - file.write(f"{inner}#{node_tree_var} outputs\n") - for i, output in enumerate(node.inputs): - if output.bl_idname != 'NodeSocketVirtual': - file.write((f"{inner}{node_tree_var}.outputs" - f".new(\"{output.bl_idname}\", " - f"\"{output.name}\")\n")) - - socket = node_tree.outputs[i] - if output.type in default_sockets: - if output.type == 'RGBA': - dv = vec4_to_py_str(socket.default_value) - elif output.type == 'VECTOR': - dv = vec3_to_py_str(socket.default_value) - else: - dv = socket.default_value - - #default value - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".default_value = {dv}\n")) - - #min value - if hasattr(socket, "min_value"): - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".min_value = " - f"{socket.min_value}\n")) - #max value - if hasattr(socket, "max_value"): - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".max_value = " - f"{socket.max_value}\n")) - #description - if socket.description != "": - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".description = " - f"\"{socket.description}\"\n")) - #hide value - if socket.hide_value is True: - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".hide_value = " - f"{socket.hide_value}\n")) - - #default attribute name - if hasattr(socket, "default_attribute_name"): - if socket.default_attribute_name != "": - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".default_attribute_name = \"" - f"{socket.default_attribute_name}" - f"\"\n")) - #attribute domain - if hasattr(socket, "attribute_domain"): - file.write((f"{inner}{node_tree_var}" - f".outputs[{i}]" - f".attribute_domain = " - f"\'{socket.attribute_domain}\'\n")) - - file.write("\n") + group_io_settings(node, file, inner, "output", nt_var, node_tree) outputs_set = True #create node - node_var = create_node(node, file, inner, node_tree_var, + node_var = create_node(node, file, inner, nt_var, node_vars, used_vars) set_settings_defaults(node, geo_node_settings, file, inner, node_var) @@ -428,13 +302,13 @@ def process_geo_nodes_group(node_tree, level, node_vars, used_vars): set_locations(node_tree, file, inner, node_vars) set_dimensions(node_tree, file, inner, node_vars) - init_links(node_tree, file, inner, node_tree_var, node_vars) + init_links(node_tree, file, inner, nt_var, node_vars) - file.write(f"{inner}return {node_tree_var}\n") + file.write(f"{inner}return {nt_var}\n") #create node group - file.write((f"\n{outer}{node_tree_var} = " - f"{node_tree_var}_node_group()\n\n")) + file.write((f"\n{outer}{nt_var} = " + f"{nt_var}_node_group()\n\n")) return used_vars process_geo_nodes_group(nt, 2, node_vars, used_vars) diff --git a/materials.py b/materials.py index b03fa4d..3946ed4 100644 --- a/materials.py +++ b/materials.py @@ -155,6 +155,9 @@ def process_mat_node_group(node_tree, level, node_vars, used_vars): f"name = \"{nt_name}\")\n")) file.write("\n") + inputs_set = False + outputs_set = False + #initialize nodes file.write(f"{inner}#initialize {nt_var} nodes\n") @@ -177,6 +180,13 @@ def process_mat_node_group(node_tree, level, node_vars, used_vars): file.write((f"{inner}{node_var}.node_tree = " f"bpy.data.node_groups" f"[\"{node.node_tree.name}\"]\n")) + elif node.bl_idname == 'NodeGroupInput' and not inputs_set: + group_io_settings(node, file, inner, "input", nt_var, node_tree) + inputs_set = True + elif node.bl_idname == 'NodeGroupOutput' and not outputs_set: + group_io_settings(node, file, inner, "output", nt_var, node_tree) + outputs_set = True + elif node.bl_idname in image_nodes: img = node.image if img.source in {'FILE', 'GENERATED', 'TILED'}: diff --git a/utils.py b/utils.py index 5392324..738c948 100644 --- a/utils.py +++ b/utils.py @@ -13,6 +13,9 @@ 'NodeSocketShader', 'NodeSocketVirtual'} +#node tree input sockets that have default properties +default_sockets = {'VALUE', 'INT', 'BOOLEAN', 'VECTOR', 'RGBA'} + def clean_string(string: str, lower: bool = True) -> str: """ Cleans up a string for use as a variable or file name @@ -265,6 +268,72 @@ def hide_sockets(node, file: TextIO, inner: str, node_var: str): if socket.hide is True: file.write(f"{inner}{node_var}.outputs[{i}].hide = True\n") +def group_io_settings(node, file: TextIO, inner: str, io: str, node_tree_var: str, node_tree): + if io == "input": + ios = node.outputs + ntio = node_tree.inputs + else: + ios = node.inputs + ntio = node_tree.outputs + file.write(f"{inner}#{node_tree_var} {io}s\n") + for i, inout in enumerate(ios): + if inout.bl_idname == 'NodeSocketVirtual': + continue + file.write(f"{inner}#{io} {inout.name}\n") + idname = enum_to_py_str(inout.bl_idname) + name = str_to_py_str(inout.name) + file.write(f"{inner}{node_tree_var}.{io}s.new({idname}, {name})\n") + socket = ntio[i] + socket_var = f"{node_tree_var}.{io}s[{i}]" + + print(f"{io} {i}: {name}") + if inout.type in default_sockets: + print(socket.default_value) + #default value + if inout.type == 'RGBA': + dv = vec4_to_py_str(socket.default_value) + elif inout.type == 'VECTOR': + dv = vec3_to_py_str(socket.default_value) + else: + dv = socket.default_value + file.write(f"{inner}{socket_var}.default_value = {dv}\n") + + #min value + if hasattr(socket, "min_value"): + file.write(f"{inner}{socket_var}.min_value = {socket.min_value}\n") + #max value + if hasattr(socket, "min_value"): + file.write((f"{inner}{socket_var}.max_value = {socket.max_value}\n")) + + #default attribute name + if hasattr(socket, "default_attribute_name"): + if socket.default_attribute_name != "": + dan = str_to_py_str(socket.default_attribute_name) + file.write((f"{inner}{socket_var}" + f".default_attribute_name = {dan}\n")) + + #attribute domain + if hasattr(socket, "attribute_domain"): + ad = enum_to_py_str(socket.attribute_domain) + file.write(f"{inner}{socket_var}.attribute_domain = {ad}\n") + + #tooltip + if socket.description != "": + description = str_to_py_str(socket.description) + file.write((f"{inner}{socket_var}.description = {description}\n")) + + #hide_value + if socket.hide_value is True: + file.write(f"{inner}{socket_var}.hide_value = True\n") + + #hide in modifier + if hasattr(socket, "hide_in_modifier"): + if socket.hide_in_modifier is True: + file.write(f"{inner}{socket_var}.hide_in_modifier = True\n") + + file.write("\n") + file.write("\n") + def color_ramp_settings(node, file: TextIO, inner: str, node_var: str): """ Replicate a color ramp node