Blender : propriétés personnalisées

Les propriétés personnalisées (custom properties) sont un moyen simple que les devs blender ont trouvé pour permettre d'ajouter des propriétés aux objets existants. On peut le faire via l'interface graphique mais quand vous en avez plusieurs dizaines à créer, mieux vaut passer par du python.

Créer

La création d'une propriété personnalisée est plutôt simple :

my_obj["my_property"] = 25

Maintenant, si on veut définir des valeurs minimale et maximale, et rendre la propriété surchargeable (overridable), on doit faire un peu plus :

def create_custom_property(obj, prop, value, min, max):
    '''
    obj: bpy_struct             Object to edit
    prop: str                   Name of the custom property
    value: str | int | Float    Value of the property
    min: str | int | Float      Min value
    max: str | int | Float      Max value
    '''
    obj[prop] = value
    prop_ui = obj.id_properties_ui(prop)
    prop_ui.update(min=min, max=max,)
    obj.property_overridable_library_set(f'["{prop}"]', True)

Il y a plus de lignes de commentaires que de lignes de code :-D

Ajouter à un panneau

Les propriétés personnalisées d'un objet apparaitront dans le panneau « custom properties » ; c'est même là qu'on peut en créer de nouvelles graphiquement. Pour les ajouter dans un nouveau panneau :

obj_props = ["prop1", "prop2", "prop3"]

class My_ADDON_PT_properties(bpy.types.Panel):
    bl_label = "My addon custom properties"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Tool"
    
    def draw(self, context):
        obj = context.object
        for name in obj_props:
            row = self.layout.row()
            row.prop(obj, f'["{name}"]', text=name, slider=True)

Ajouter un driver

def add_driver_to_custom_property(obj, prop):
    '''
    obj: bpy_struct     Object to edit
    prop: str           Name of the custom property
    '''
    fcurve = obj.driver_add(f'["{prop}"]')
    driver = fcurve.driver
    # customize driver

Copier une propriété

Il est parfois utile de reprendre les données d'une propriété pour en construire une autre :

# Récupérer les données de la propriété originale
original_ui = object.id_properties_ui("original_prop")
original_dict = original_ui.as_dict()

# Créer une nouvelle propriété
object["new_prop"] = object["original_prop"]

# Copier les données
new_ui = object.id_properties_ui("new_prop")
new_ui.update(
    min=original_dict["min"], 
    max=original_dict["max"], 
    default=original_dict["default"]
)

Ressources et références