1
$\begingroup$

I have a simple script that instantiates random objects from specific collections. In order to make sure I always do this correctly, I've created a class with some internal variables to access those collections. But if I hit UNDO it appears that Blender deletes them, at least until the script is manually run again. The variables I've made are:

  • master_collection: A Collection for directly getting the topmost collection by name.

  • sub_collections: A List of Collections for dynamically getting all of the immediate child collections inside of the master.

The simplified version of the problem is shown here:

class GFC_gen_start(bpy.types.Operator):
    bl_options = {'REGISTER', 'UNDO'}

    # The collections that go missing on UNDO
    master_collection = bpy.data.collections['MasterCollection']
    sub_collections = []

    def execute(self, context):
        self.initCollections()

    def initCollections(self):
        """Initialize references to subcollections"""
        
        # Clear list if any data from last use still exists
        if (len(self.sub_collections) > 0):
            self.sub_collections[:] = []   
        
        self.sub_collections = self.master_collection.children

The error message that occurs when running this after hitting undo is: "ReferenceError: StructRNA of type Collection has been removed", which points to the very last line of the script.

As long as I never UNDO, this code works and continues to work on subsequent executes. What would be a good way to secure these variables? I am considering moving everything into execute and handing them down as function arguments instead of easily accessing with "self.", but I am curious to know if there is a better way to handle this before I start hammering it into shape.

$\endgroup$
2
  • $\begingroup$ try removing UNDO from bl_options = {'REGISTER', 'UNDO'} $\endgroup$
    – Karan
    Commented Mar 10, 2023 at 17:34
  • $\begingroup$ This is not how you serialize data in Blender. You need to use a CollectionProperty and a PointerProperty. But operators can't reference these, so you either need to store them on another object, eg the current scene, or reference these by name using a StringProperty. To answer your question, python pointers to blender objects are lost on undo / redo and on save / load unless you save them using the supported property system $\endgroup$
    – Gorgious
    Commented Mar 10, 2023 at 18:32

1 Answer 1

0
$\begingroup$

An answer was posted by Gorgius as a comment on my question, so I'll just quote it here and mark it as closed for anyone searching for this in the future:

This is not how you serialize data in Blender. You need to use a CollectionProperty and a PointerProperty. But operators can't reference these, so you either need to store them on another object, eg the current scene, or reference these by name using a StringProperty. To answer your question, python pointers to blender objects are lost on undo / redo and on save / load unless you save them using the supported property system

Thanks for the help! If anyone needs more to go by, I recommend checking out this video on PropertyGroups by Darkfall.

$\endgroup$

You must log in to answer this question.

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