Add default argument value support
This commit is contained in:
parent
7dc083e361
commit
c28d6ced93
9 changed files with 107 additions and 43 deletions
|
|
@ -1,7 +1,8 @@
|
|||
import bpy
|
||||
from bpy.types import GeometryNodeCurveToMesh
|
||||
import bl_ui
|
||||
from .state import State
|
||||
from .types import *
|
||||
from ..absolute_path import absolute_path
|
||||
|
||||
class OutputsList(dict):
|
||||
__getattr__ = dict.get
|
||||
|
|
@ -14,7 +15,7 @@ def build_node(node_type):
|
|||
if _primary_arg is not None:
|
||||
State.current_node_tree.links.new(_primary_arg._socket, node.inputs[0])
|
||||
for prop in node.bl_rna.properties:
|
||||
argname = prop.name.lower().replace(' ', '_')
|
||||
argname = prop.identifier.lower().replace(' ', '_')
|
||||
if argname in kwargs:
|
||||
setattr(node, prop.identifier, kwargs[argname])
|
||||
for node_input in (node.inputs[1:] if _primary_arg is not None else node.inputs):
|
||||
|
|
@ -58,10 +59,29 @@ def register_node(node_type, category_path=None):
|
|||
registered_nodes.add(node_type)
|
||||
for category_name in list(filter(lambda x: x.startswith('NODE_MT_category_GEO_'), dir(bpy.types))):
|
||||
category = getattr(bpy.types, category_name)
|
||||
category_path = category.category.name.lower().replace(' ', '_')
|
||||
for node in category.category.items(None):
|
||||
node_type = getattr(bpy.types, node.nodetype)
|
||||
register_node(node_type, category_path)
|
||||
if not hasattr(category, 'category'):
|
||||
category_path = category.bl_label.lower().replace(' ', '_')
|
||||
add_node_type = bl_ui.node_add_menu.add_node_type
|
||||
draw_node_group_add_menu = bl_ui.node_add_menu.draw_node_group_add_menu
|
||||
draw_assets_for_catalog = bl_ui.node_add_menu.draw_assets_for_catalog
|
||||
bl_ui.node_add_menu.add_node_type = lambda _layout, node_type_name: register_node(getattr(bpy.types, node_type_name), category_path)
|
||||
bl_ui.node_add_menu.draw_node_group_add_menu = lambda _context, _layout: None
|
||||
bl_ui.node_add_menu.draw_assets_for_catalog = lambda _context, _layout: None
|
||||
class CategoryStub:
|
||||
bl_label = ""
|
||||
def __init__(self):
|
||||
self.layout = Layout()
|
||||
class Layout:
|
||||
def separator(self): pass
|
||||
category.draw(CategoryStub(), None)
|
||||
bl_ui.node_add_menu.add_node_type = add_node_type
|
||||
bl_ui.node_add_menu.draw_node_group_add_menu = draw_node_group_add_menu
|
||||
bl_ui.node_add_menu.draw_assets_for_catalog = draw_assets_for_catalog
|
||||
else:
|
||||
category_path = category.category.name.lower().replace(' ', '_')
|
||||
for node in category.category.items(None):
|
||||
node_type = getattr(bpy.types, node.nodetype)
|
||||
register_node(node_type, category_path)
|
||||
for node_type_name in list(filter(lambda x: 'GeometryNode' in x, dir(bpy.types))):
|
||||
node_type = getattr(bpy.types, node_type_name)
|
||||
if issubclass(node_type, bpy.types.GeometryNode):
|
||||
|
|
@ -200,9 +220,9 @@ def create_documentation():
|
|||
</body>
|
||||
</html>
|
||||
"""
|
||||
with open('docs/documentation.html', 'w') as f:
|
||||
with open(absolute_path('docs/documentation.html'), 'w') as f:
|
||||
f.write(html)
|
||||
with open('typeshed/geometry_script.pyi', 'w') as fpyi, open('typeshed/geometry_script.py', 'w') as fpy:
|
||||
with open(absolute_path('typeshed/geometry_script.pyi'), 'w') as fpyi, open(absolute_path('typeshed/geometry_script.py'), 'w') as fpy:
|
||||
newline = '\n'
|
||||
def type_symbol(t):
|
||||
return f"class {t.__name__}(Type): pass"
|
||||
|
|
|
|||
39
api/tree.py
39
api/tree.py
|
|
@ -1,6 +1,5 @@
|
|||
import bpy
|
||||
import re
|
||||
from inspect import getfullargspec
|
||||
import inspect
|
||||
try:
|
||||
import node_arrange as node_arrange
|
||||
except:
|
||||
|
|
@ -18,6 +17,8 @@ def _as_iterable(x):
|
|||
def tree(name):
|
||||
tree_name = name
|
||||
def build_tree(builder):
|
||||
signature = inspect.signature(builder)
|
||||
|
||||
# Locate or create the node group
|
||||
node_group = None
|
||||
if tree_name in bpy.data.node_groups:
|
||||
|
|
@ -27,8 +28,8 @@ def tree(name):
|
|||
# Clear the node group before building
|
||||
for node in node_group.nodes:
|
||||
node_group.nodes.remove(node)
|
||||
for group_input in node_group.inputs:
|
||||
node_group.inputs.remove(group_input)
|
||||
while len(node_group.inputs) > len(signature.parameters):
|
||||
node_group.inputs.remove(node_group.inputs[-1])
|
||||
for group_output in node_group.outputs:
|
||||
node_group.outputs.remove(group_output)
|
||||
|
||||
|
|
@ -37,21 +38,31 @@ def tree(name):
|
|||
group_output_node = node_group.nodes.new('NodeGroupOutput')
|
||||
|
||||
# Collect the inputs
|
||||
argspec = getfullargspec(builder)
|
||||
inputs = {}
|
||||
for arg in argspec.args:
|
||||
if not arg in argspec.annotations:
|
||||
raise Exception(f"Tree input '{arg}' has no type specified. Please specify a valid NodeInput subclass.")
|
||||
type_annotation = argspec.annotations[arg]
|
||||
if not issubclass(type_annotation, Type):
|
||||
raise Exception(f"Type of tree input '{arg}' is not a valid 'Type' subclass.")
|
||||
inputs[arg] = type_annotation
|
||||
for param in signature.parameters.values():
|
||||
if param.annotation == inspect.Parameter.empty:
|
||||
raise Exception(f"Tree input '{param.name}' has no type specified. Please annotate with a valid node input type.")
|
||||
if not issubclass(param.annotation, Type):
|
||||
raise Exception(f"Type of tree input '{param.name}' is not a valid 'Type' subclass.")
|
||||
inputs[param.name] = (param.annotation, param.default)
|
||||
|
||||
# Create the input sockets and collect input values.
|
||||
for i, node_input in enumerate(node_group.inputs):
|
||||
if node_input.bl_socket_idname != list(inputs.values())[i][0].socket_type:
|
||||
for ni in node_group.inputs:
|
||||
node_group.inputs.remove(ni)
|
||||
break
|
||||
builder_inputs = []
|
||||
for i, arg in enumerate(inputs.items()):
|
||||
node_group.inputs.new(arg[1].socket_type, re.sub('([A-Z])', r' \1', arg[0]).title())
|
||||
builder_inputs.append(arg[1](group_input_node.outputs[i]))
|
||||
input_name = arg[0].replace('_', ' ').title()
|
||||
if len(node_group.inputs) > i:
|
||||
node_group.inputs[i].name = input_name
|
||||
node_input = node_group.inputs[i]
|
||||
else:
|
||||
node_input = node_group.inputs.new(arg[1][0].socket_type, input_name)
|
||||
if arg[1][1] != inspect.Parameter.empty:
|
||||
node_input.default_value = arg[1][1]
|
||||
builder_inputs.append(arg[1][0](group_input_node.outputs[i]))
|
||||
|
||||
# Run the builder function
|
||||
State.current_node_tree = node_group
|
||||
|
|
|
|||
Reference in a new issue