diff --git a/api/static/input_options.py b/api/static/input_options.py index 894dba3..9f91f4d 100644 --- a/api/static/input_options.py +++ b/api/static/input_options.py @@ -1,32 +1,56 @@ import enum -class SubtypeInt(enum.Enum): - NONE = 'None' - PERCENTAGE = 'Percentage' - FACTOR = 'Factor' - -class SubtypeFloat(enum.Enum): - NONE = 'None' - PERCENTAGE = 'Percentage' - FACTOR = 'Factor' - ANGLE = 'Angle' - TIME = 'Time (Scene Relative)' - TIME_ABSOLUTE = 'Time (Absolute)' - DISTANCE = 'Distance' - -class InputOptions: - """Input options parent class""" - -class IntOptions(InputOptions): +class Subtype(enum.Enum): """ - Title. + If using subtype option, your geometry script must run in the active workspace containing the Geometry Node Editor + """ + +class SubtypeInt(Subtype): + NONE = 'NONE' + PERCENTAGE = 'PERCENTAGE' + FACTOR = 'FACTOR' + +class SubtypeFloat(Subtype): + NONE = 'NONE' + PERCENTAGE = 'PERCENTAGE' + FACTOR = 'FACTOR' + ANGLE = 'ANGLE' + TIME = 'TIME' + TIME_ABSOLUTE = 'TIME_ABSOLUTE' + DISTANCE = 'DISTANCE' + +class SubtypeVector(Subtype): + NONE = 'NONE' + TRANSLATION = 'TRANSLATION' + VELOCITY = 'VELOCITY' + ACCELERATION = 'ACCELERATION' + EULER = 'EULER' + XYZ = 'XYZ' + + +class _InputOptions: + """Input options parent class.""" + def __init__(self, default, min, max, subtype, name, tooltip, hide_in_modifier): + self.default_value = default + self.min_value = min + self.max_value = max + self.bl_subtype_label = subtype.value if subtype != None else None + self.name = name + self.description = tooltip + self.hide_in_modifier = hide_in_modifier + + +class IntOptions(_InputOptions): + """ + Integer input options. - Example descriptions: + Usage example: ```python my_int: Float = IntOptions( default=3, min=1, - max=5 + max=5, + subtype=SubtypeInt.DISTANCE ), ``` """ @@ -43,24 +67,20 @@ class IntOptions(InputOptions): tooltip: str = None, hide_in_modifier: bool = None, ): - self.default_value = default - self.min_value = min - self.max_value = max - self.bl_subtype_label = subtype.value if subtype != None else None - self.name = name - self.description = tooltip - self.hide_in_modifier = hide_in_modifier + super().__init__(default, min, max, subtype, name, tooltip, hide_in_modifier) -class FloatOptions(InputOptions): + +class FloatOptions(_InputOptions): """ - Title. + Float input options. - Example descriptions: + Usage example: ```python my_float: Float = FloatOptions( default=1.5, min=-0.5, - max=2.5 + max=2.5, + subtype=SubtypeFloat.DISTANCE ), ``` """ @@ -77,10 +97,36 @@ class FloatOptions(InputOptions): tooltip: str = None, hide_in_modifier: bool = None, ): - self.default_value = default - self.min_value = min - self.max_value = max - self.bl_subtype_label = subtype.value if subtype != None else None - self.name = name - self.description = tooltip - self.hide_in_modifier = hide_in_modifier \ No newline at end of file + super().__init__(default, min, max, subtype, name, tooltip, hide_in_modifier) + + +class VectorOptions(_InputOptions): + """ + Vector input options. + + Usage example: + ```python + my_float: Vector = VectorOptions( + default_x=0.5, + default_y=1.0, + default_z=1.5, + min=-0.5, + max=2.5, + subtype=SubtypeVecotr.TRANSLATION + ), + ``` + """ + + def __init__( + self, + default_x: float | None = None, + default_y: float | None = None, + default_z: float | None = None, + min: float | None = None, + max: float | None = None, + subtype: SubtypeVector | None = None, + name: str | None = None, + tooltip: str = None, + hide_in_modifier: bool = None, + ): + super().__init__((default_x, default_y, default_z), min, max, subtype, name, tooltip, hide_in_modifier) \ No newline at end of file diff --git a/api/tree.py b/api/tree.py index 3e79563..7f76735 100644 --- a/api/tree.py +++ b/api/tree.py @@ -108,7 +108,7 @@ def tree(name): node_inputs = get_node_inputs(node_group) for i, arg in enumerate(inputs.items()): if (arg[1][1] != inspect.Parameter.empty - and (isinstance(arg[1][1], IntOptions) or isinstance(arg[1][1], FloatOptions)) + and (isinstance(arg[1][1], IntOptions) or isinstance(arg[1][1], FloatOptions) or isinstance(arg[1][1], VectorOptions)) and arg[1][1].name != None): input_name = arg[1][1].name else: @@ -124,25 +124,33 @@ def tree(name): node_input = node_group.inputs.new(arg[1][0].socket_type, input_name) if arg[1][1] != inspect.Parameter.empty: - if (isinstance(arg[1][1], IntOptions) or isinstance(arg[1][1], FloatOptions)) : + if (isinstance(arg[1][1], IntOptions) or isinstance(arg[1][1], FloatOptions) or isinstance(arg[1][1], VectorOptions)) : if arg[1][1].default_value != None: node_input.default_value = arg[1][1].default_value if arg[1][1].min_value != None: node_input.min_value = arg[1][1].min_value elif isinstance(arg[1][1], IntOptions): node_input.min_value = IntOptions.MIN - elif isinstance(arg[1][1], FloatOptions): + elif (isinstance(arg[1][1], FloatOptions) or isinstance(arg[1][1], VectorOptions)): node_input.min_value = FloatOptions.MIN if arg[1][1].max_value != None: node_input.max_value = arg[1][1].max_value elif isinstance(arg[1][1], IntOptions): node_input.max_value = IntOptions.MAX - elif isinstance(arg[1][1], FloatOptions): + elif (isinstance(arg[1][1], FloatOptions) or isinstance(arg[1][1], VectorOptions)): node_input.max_value = FloatOptions.MAX if arg[1][1].bl_subtype_label != None: - # node_input.bl_subtype_label = arg[1][1].bl_subtype_label # broken - # TODO: run operator to change this - pass + subtype = arg[1][1].bl_subtype_label + try: + for area in bpy.context.screen.areas: + for space in area.spaces: + if space.type == 'NODE_EDITOR': + with bpy.context.temp_override(area=area, space=space, interface_socket=node_input): + bpy.ops.node.tree_socket_change_subtype('INVOKE_DEFAULT', socket_subtype=subtype) + break + except: + # TODO: log the exception as operation failure ? + pass if arg[1][1].description != None: node_input.description = arg[1][1].description if arg[1][1].hide_in_modifier != None: