7
$\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$

1 Answer 1

9
$\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$
3
  • $\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
    Commented May 25, 2015 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$ Commented Mar 17, 2018 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$ Commented Mar 17, 2018 at 8:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .