I'm trying to create a custom property and do some work as the property is set. I previously used the update function; which worked great, except it never got called on updates resulting from drivers or the animation system. set does appear to get called in all cases, but I can't figure out how to store to the underlying property.

I obviously can't store to is directly as I get an infinite loop and the answers I've found on the internet are wrong e.g. they suggest you can just store it using a dictionary indexing and it will set the property - but that doesn't work.

>>> def cb(self, value):
...     print(self, value)
...     self['param'] = value
>>> bpy.types.Object.param = bpy.props.FloatProperty(set=cb)
>>> bpy.context.scene.objects['Cube']

>>> bpy.context.scene.objects['Cube'].param

>>> bpy.context.scene.objects['Cube'].param = 1.0
<bpy_struct, Object("Cube")> 1.0

>>> bpy.context.scene.objects['Cube'].param  # I want this to reflect the new value

>>> bpy.context.scene.objects['Cube']['param']  # I don't want this to exist
  • $\begingroup$ The solution to this, as hinted at in the linked answer, is that you need to provide a get method as well. Given you can access your declared property with ['param'] even if you don't provide a custom setter it's clearly the same thing - but I can't figure out why the default getter doesn't work. Anyway, use self.get('param', 0) and it will work $\endgroup$ – mountainstorm Sep 5 '20 at 14:41

Browse other questions tagged or ask your own question.