It appears that this is not supported by blender. So here is my workaround.
I made a little script that will allow you to execute a function when the property of an object changes. I'm not used to blender modules so I didn't made a downloadable module out of it. But it's still pretty easy to set up.
Create the observer module
first, we need to execute a function every frame, this function will check if any property has changed and call the corresponding observer function.
- Add an empty to the scene.
- Add a pydriver to the empty (open the property panel (n) and then right clic on the location and select "Add Single Driver")
- Go in the graph window and open the "Drivers" display (clic on f-curve editor button in the bottom).
- Open the properties (n)
- Select the added driver in the list on the left.
- Remove any variable and modifier in the properties panel.
Just below the "Scripted Expression" button there is the "Expr" field enter in it the following :
update(frame)
This will call our frameUpdate function at every frame change.
Now that we are setup
create a new file in the text editor named
observer.py
check the "register" option (this will create a new module loaded automatically with .blend) and add the following to the file:
#author : Vincent Picard
import bpy
import bpy.app
#list of all the observers.
observers = []
print("test")
#This is to function to call in your scripts. use it to have your function called everytime an object property changes.
#object : Object to watch,
#property : property to be wathed.
#function to execute every time the property of the given object changes.
#function will be given this parameters :
# object : the object.
# value : new value of the property
# old : old value of the property.
# frame : current frame.
def observe(object, property, function):
observers.append(Observer(object,property,function))
#Called at every frame. This will call the function that are listening.
def frameUpdate(frame):
for observer in observers:
observer.update(frame)
return 0.0
#make the function visible to scripted driver.
bpy.app.driver_namespace['update'] = frameUpdate
#Each time we call observe we create an observer object.
class Observer:
def __init__(self, object, property, function):
#if the property object needs deep copy
try :
self.oldValue = getattr(object, property).copy()
self.newValue = getattr(object, property).copy()
#if the property object doesn't need it (and don't have a copy method).
except AttributeError:
self.oldValue = getattr(object, property)
self.newValue = getattr(object, property)
self.object = object
self.property = property
self.function = function
#Call the function if the object property changed.
def update(self, frame):
#if the object needs deep copy
try :
self.oldValue = self.newValue.copy()
self.newValue = getattr(self.object, self.property).copy()
#if the object doesn't need it (and don't have a copy method).
except AttributeError:
self.oldValue = self.newValue
self.newValue = getattr(self.object, self.property)
if self.oldValue != self.newValue:
self.function(object = self.object, value = self.newValue, old = self.oldValue, frame = frame)
How to create an observer and use it.
- You now need to reopen you .blend, that way the "observer" module will be available.
You can now observe object properties and make a function to be call when it changes.
Create your script file (example) :
import bpy
import observer
#define the function you want to be executed. this one as an example simply print old and new value when they are changed.
def updateAnimation(object, value, old, frame):
print(value)
print(old)
#register your observer.
observer.observe(bpy.data.objects["Cube.031"], "location", updateAnimation)
Run it, it will register your observer.
Potential Problems
do not run the observer.py file, if you do then it will stop working and you will need to reopen the .blend
.