Skip to content

Commit

Permalink
Merge pull request #51 from BrendanParmer/shader_node_group_fix
Browse files Browse the repository at this point in the history
fix: added group io logic to shader nodes
  • Loading branch information
BrendanParmer authored May 23, 2023
2 parents 8cf57f2 + 9894c54 commit 700ae47
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 138 deletions.
150 changes: 12 additions & 138 deletions geo_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down Expand Up @@ -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"))
Expand All @@ -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 = []

Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand All @@ -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'}:
Expand Down
69 changes: 69 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 700ae47

Please sign in to comment.