0
$\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
    Mar 10 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
    Mar 10 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$

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.