Exemple #1
0
class SvVDMK4Properties(bpy.types.PropertyGroup):
    # this populates a property-group using VDExperimental.__annotations__ as the source -
    __annotations__ = {}
    for key, v in maximum_spec_vd_dict.items():
        prop_func, kw_args = get_func_and_args(SvViewerDrawMk4.__annotations__[key])
        copy_kw_args = copy.deepcopy(kw_args)
        copy_kw_args.pop('update', None)
        __annotations__[key] = prop_func(**copy_kw_args)
Exemple #2
0
    def add_properties(self, node_annotations: dict):
        """Assign properties to annotation dictionary of a node, update function will be assigned automatically"""
        def update_node(node, context):
            with self.wrap_node.read_data_mode(node):
                # without this manager sockets wont be able to read properties of a node instance
                self.wrap_node.inputs.hide_sockets(node)
                self.wrap_node.outputs.hide_sockets(node)
                updateNode(node, context)

        for name, prop in self.properties.items():
            bpy_prop, bpy_prop_arguments = get_func_and_args(prop.bpy_props)
            bpy_prop_arguments['update'] = update_node
            rebuild_bpy_prop = blender_properties[bpy_prop](**bpy_prop_arguments)

            node_annotations[name] = rebuild_bpy_prop
Exemple #3
0
    def add_prop_from(self, socket):
        """
        Add a property if possible
        """
        other = socket.other
        cls = get_node_class_reference(self.cls_bl_idname)
        cls_dict = cls.__dict__ if cls else {}

        local_debug = False
        # reference_obj_id = cls.instances[0]
        # print(reference_obj_id.__annotations__)

        try:
            monad_prop_names = self.get_stored_prop_names()
            has_monad_prop_names = True
            print(monad_prop_names)
        except:
            print('no prop names yet in : add_prop_from call')
            has_monad_prop_names = False


        if other.prop_name:

            prop_name = other.prop_name

            try:
                prop_func, prop_dict = get_func_and_args(other.node.__annotations__[prop_name])
            except:
                prop_func, prop_dict = ("", {})


            if 'attr' in prop_dict:
                prop_dict.pop('attr')  # this we store in prop_name anyway
            
            if 'update' in prop_dict:
                """
                the node may be doing a tonne of stuff in a wrapped update,
                but because this property will be on a shell node (the monad outside) we can
                replace it with a reference to updateNode. i think this is a sane thing to ensure.
                """
                prop_dict['update'] = updateNode
            
            if not 'name' in prop_dict:
                """ 
                name is used exclusively for displaying name on the slider or label 
                most properties will have this defined anyway, but just in case.
                """ 
                regex = re.compile('[^a-z A-Z0-9]')
                prop_dict['name'] = regex.sub('', prop_name)
                print(f"monad: generated name for property function: {prop_name} -> {prop_dict['name']}")

            if local_debug:
                print("prop_func:", prop_func)   # tells us the kind of property to make
                print("prop_dict:", prop_dict)   # tells us the attributes of the property
                print("prop_name:", prop_name)   # tells the socket / slider ui which prop to display
                #                                # and its associated 'name' attribute from the prop_dict
            
            if prop_func.__name__ == "FloatProperty":
                self.get_current_as_default(prop_dict, other.node, prop_name)
                prop_settings = self.float_props.add()
                prop_name_prefix = f"floats_{len(self.float_props)}_"
            elif prop_func.__name__ == "IntProperty":
                self.get_current_as_default(prop_dict, other.node, prop_name)
                prop_settings = self.int_props.add()
                prop_name_prefix = f"ints_{len(self.int_props)}_"
            elif prop_func.__name__ == "FloatVectorProperty":
                info("FloatVectorProperty ignored (normal behaviour since day one). prop_func: %s, prop_dict: %s.", prop_func, prop_dict)
                return None
            else: # no way to handle it
                return None

            if other.node.bl_idname == "SvNumberNode":
                if "float" in prop_name:
                    prop_dict['min'] = other.node.float_min
                    prop_dict['max'] = other.node.float_max
                elif "int" in prop_name:
                    prop_dict['min'] = other.node.int_min
                    prop_dict['max'] = other.node.int_max

            new_name = prop_name_prefix + prop_name
            if has_monad_prop_names:
                new_name = ensure_unique(monad_prop_names, new_name)
            
            prop_settings.prop_name = new_name
            prop_settings.set_settings(prop_dict)
            socket.prop_name = new_name
            return new_name

        elif hasattr(other, "prop_type"):
            
            # if you are seeing errors with this and the other.node.bl_idname is not scriptnodelite
            # the fix will be here somewhere.
            print(f'{other.node} = other.node')
            print(f'{other.prop_type} = other.prop_type')
            
            if not any(substring in other.prop_type for substring in ["float", "int"]): 
                return None    
        
            if "float" in other.prop_type:
                prop_settings = self.float_props.add()
                prop_name_prefix = f"floats_{len(self.float_props)}_"
            elif "int" in other.prop_type:
                prop_settings = self.int_props.add()
                prop_name_prefix = f"ints_{len(self.int_props)}_"

            new_name = prop_name_prefix + other.name
            if has_monad_prop_names:
                new_name = ensure_unique(monad_prop_names, new_name)
            
            # this name will be used as the attr name of the newly generated property for the shellnode
            # essentially this is 
            #       __annotations__[prop_name] = new property function
            prop_settings.prop_name = new_name
      
            custom_prop_dict = {
                "name": nice_ui_name(other.name),
                "update": updateNode
            }

            # there are other nodes that use this technique, 
            if other.node.bl_idname == "SvScriptNodeLite":
                prop_list = other.node.float_list if "float" in other.prop_type else other.node.int_list
                default = prop_list[other.prop_index]
                custom_prop_dict["default"] = default

            prop_settings.set_settings(custom_prop_dict)
            socket.prop_name = new_name
            return new_name

        return None
Exemple #4
0
        """Assign properties to annotation dictionary of a node, update function will be assigned automatically"""
        def update_node(node, context):
            with self.wrap_node.read_data_mode(node):
                # without this manager sockets wont be able to read properties of a node instance
                self.wrap_node.inputs.hide_sockets(node)
                self.wrap_node.outputs.hide_sockets(node)
                updateNode(node, context)

        for name, prop in self.properties.items():
            bpy_prop, bpy_prop_arguments = get_func_and_args(prop.bpy_props)
            bpy_prop_arguments['update'] = update_node
            rebuild_bpy_prop = blender_properties[bpy_prop](**bpy_prop_arguments)

            node_annotations[name] = rebuild_bpy_prop

get_func = lambda prop: get_func_and_args(prop)[0]

blender_properties = {
    # properties are functions which return tuples with themselves as first argument
    # it should help to rebuild properties with new arguments
    get_func(bpy.props.BoolProperty()): bpy.props.BoolProperty,
    get_func(bpy.props.BoolVectorProperty()): bpy.props.BoolVectorProperty,
    get_func(bpy.props.CollectionProperty()): bpy.props.CollectionProperty,
    get_func(bpy.props.EnumProperty()): bpy.props.EnumProperty,
    get_func(bpy.props.FloatProperty()): bpy.props.FloatProperty,
    get_func(bpy.props.FloatVectorProperty()): bpy.props.FloatVectorProperty,
    get_func(bpy.props.IntProperty()): bpy.props.IntProperty,
    get_func(bpy.props.IntVectorProperty()): bpy.props.IntVectorProperty,
    get_func(bpy.props.PointerProperty()): bpy.props.PointerProperty,
    get_func(bpy.props.StringProperty()): bpy.props.StringProperty
}