4
$\begingroup$

Python has two ways to define your own properties.


Via bpy.props
Accessible from data-editor, or via buttons defined in scripts:

# define the property
bpy.types.Scene.my_prop = bpy.props.BoolProperty()
# set the property
bpy.context.scene.my_prop = True

Via Python's __getitem__/__setitem__
Accessible from custom-properties panel:

# no need to declare it.

# set the property
bpy.context.scene["my_prop"] = True

What should be considered when choosing which one to use?

$\endgroup$
4
$\begingroup$

Definition

bpy.props need to be defined. eg scene.myprop is not available to scripts until it is defined via bpy.types.Scene.myprop = bpy.props.BoolProperty() It is however saved, once set in a file, and the set value can be retrieved once defined again.

Type Casting

Properties defined using bpy.props are type cast, and expect a value of that type, or are converted

>>> C.scene.my_prop = 1
>>> C.scene.my_prop
True
>>> C.scene.my_prop = "XXXX"
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
TypeError: bpy_struct: item.attr = val: Scene.my_prop expected True/False or 0/1, not str

Custom props

scene["my_prop"] = 1
scene["my_prop"] = "XXXX"

Scope

bpy.props are defined for all objects of that blender type, for your example scene.my_prop will be available to all scenes, whereas scene["myprop"] only for the scene instance it is defined on. I choose custom props for more "one off" usage.

Update Method

An update callback method is available to bpy.props properties. This is a very useful tool, that is not available to custom properties. Similar to using an "on_change" event handler.

def jangle(self, context):
    print("update called on scene ", self.name)
    # do something based on the value of "my_prop"
    if self.my_prop:
        print("It's on")
    else:
        print("It's off")
    return None # always return None from an update.

bpy.types.Scene.my_prop = bpy.props.BoolProperty(update=jangle)

UI

both can be decorated in the UI, to some extent. To add a name and description to each.

bpy.types.Scene.my_prop = bpy.props.BoolProperty(name="My Property",
                       description="This is my bpy.props boolean prop")

and for custom props

    rna = {"name": "My Property"
           "description": "This is my custom boolean prop",
           # can also store other data that can be set by script
           # and used as a driver var
           "anyolthing": 13
          }

    scene["my_prop"] = False
    if "_RNA_UI" not in scene.keys(): #  keys() returns a list of id props
        self["_RNA_UI"] = {}

    # define the UI propeties of "my_prop"
    self["_RNA_UI"]["my_prop"] = rna

note the rna_ui dictionary can have self defined property names, as long as the data type is int, float, bool, string. They will not effect the UI, but are a handy way to store "hidden" data. The rna dictionary is a handy way to update the min and max and description on a per property basis, to make descriptive and effective visual sliders for instance.

rna Access

Once a custom property is set, the property name will be a member of the, in this case, scene.keys() list, or as name/value pairs in scene.items()

All bpy.props properties will be available via scene.bl_rna.properties.keys() but only in the scene.keys() list once initialized, ie given a value other than the default.

$\endgroup$
1
$\begingroup$

The simple difference is:

  • custom properties have to be defined by script first, then they are available to all the instances of the type of object they were defined for. Plenty of data types available (arrays, bools, ..)

  • ID property can be assigned to single instance of object. There are less data types available.

Both will be saved with the file. Also both will show in the UI, the custom prop will show as "API Defined":

enter image description here

When you open such file and don't define the custom property, it will be converted into ID property:

enter image description here

When you run bpy.types.Scene.prop = bpy.props.IntProperty() it will turn back into custom property.

There is a bug in 2.77a however. If you happen to define bpy.types.Scene.prop you are not able to create any ID properties for scenes - the default name for them is "prop". This was reported and fixed for further releases.

Last very important thing - as custom properties are heavily used to store values for rigs

  • Pose Libraries do not store custom prop data automatically, but they will store ID properties values. Custom prop can be keyframed or driven by driver the same way is ID property can though.
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.