6
$\begingroup$

Is it possible to execute a function every time the user does something? I want the function to check what the last user interaction was and then, if the interaction was to rename something, to give me the previous name and the new name.

$\endgroup$
7
$\begingroup$

Blender doesn't have a way to explicitly catch user events, but there is a workaround if the user interaction causes the scene to update (which renaming an object does).
You can do this:

import bpy

class Watcher:
    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):
        try :
            self.oldValue = self.newValue.copy()
            self.newValue = getattr(self.object, self.property).copy()
        except AttributeError:
            self.oldValue = self.newValue
            self.newValue = getattr(self.object, self.property)

        if self.oldValue != self.newValue:
            self.function(object=self.object, new=self.newValue, old=self.oldValue)

# this holds all the watchers
watchers = []
def add_watcher(object, property, function):
    watchers.append(Watcher(object,property,function))

# create the function to be called when name changes
# it can change scene property or whatever
def name_change(object, new, old):
    print("old value: " + str(old))
    print("new value: " + str(new))
    return

# lets watch your_object_name's name
add_watcher(bpy.data.objects["YOUR OBJECT NAME"], "name", name_change)

def watcher(scene):
    """This function will be run everytime after scene updates"""
    global watchers
    for watcher in watchers:
        watcher.update()
    return

# add handler if not in app.handlers
if watcher not in bpy.app.handlers.scene_update_post:
    bpy.app.handlers.scene_update_post.append(watcher)
$\endgroup$
  • $\begingroup$ very nice code example which has reminded me to go back and review all the handlers which are available to python devs $\endgroup$ – patmo141 May 25 '15 at 19:39
  • $\begingroup$ Okay excellent Thanks! I'm trying that route and reviewing the other handlers too docs.blender.org/api/blender_python_api_2_74_0/… $\endgroup$ – Master James Mar 17 '18 at 7:09
  • $\begingroup$ Can the app handler's appended function pass arguments other then scene like 'self' for relative instance variables? scene_update_post.append(watcher, self) $\endgroup$ – Master James Mar 17 '18 at 8:01

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.