I’m fairly new to the Blender API so forgive me if I am missing something obvious.
My problem is like so: I have multiple objects that I want to reference in code for later.
As an example, say I want to make a list that stores every selected object so I’ll create a list using my list = bpy.context.selected_objects
This usually works fine up until Undo causes invalidation.
The only solution I can think of right now is to find the objects again through their names using a for loop and bpy.data.objects.get("Suzanne") but this is less than ideal.
What if the user changes the name?
Sadly, this makes using this option unusable for the addon I want to create.
My question is: what is the best / most correct way of handling a situation like this?
There’s not a whole lot you can do unfortunately. I wish there were more events we could subscribe to in python but there aren’t, and there is no event callback for undo/redo. The best you could do is subscribe to depsgraph update and manually check if something has changed.
One way to track objects across undo is to tag them using their custom property (ID property).
This example sets a simple hash on the selected objects using set_hash() and a string as the hash key.
To retrieve the objects, you can use objs_from_hash() and supply the same key. It doesn’t have to be a hash, it could be any value as long as it’s unique enough to not collide, but also easily retrievable.
import bpy
def set_hash(prop, key):
for o in bpy.context.selected_objects:
o[prop] = float(hash(key))
def objs_from_hash(prop, key):
objects = bpy.data.objects
val = float(hash(key))
return [o for o in objects if prop in o and o[prop] == val]
prop = "my_addon"
key = "some_seed"
if __name__ == "__main__":
# toggle between these
# set_hash(prop, key)
print(objs_from_hash(prop, key))
will this work in edit mode, in between bmesh changes? I’m assuming not since data.objects don’t get updated until you either leave edit mode or push the changes back to object mode manually.
ID properties exist on almost all bpy.types.ID subclass and were designed to be serialized along the with blend file. If a custom property is stored on the object data block, what happens to a mesh data block would not have any impact.
I wanted to post a quick update to this- at the time there were NOT any event callbacks for undo/redo, but in the last couple of weeks both have been added to bpy.app.handlers. happy day! Application Handlers (bpy.app.handlers) — Blender Python API
Here’s hoping we get a much wider variety of events to subsribe to (fingers crossed for a bmesh update event)
Me too
Unfortunately, this is pretty common in blender. You have to do a lot of manual state / memory management in blender even when that should work out of the box. Besides that, undo/redo sits at the very core of blender and it is used even for things which are not suppose to be handled like that. For example: operators use undo/redo to create the illusion of interactivity when you scrub sliders in the UI. If you choose to run some backgroud scripting during this undo/redo process, blender will most likely crash without giving you a good reason to do so…