Retaining Classes when Reloading Scenes

As part of a plugin i’ve been working on that does a bunch of stuff for specific types of armatures, i use a single class to store a lot of information. You select an armature and then it gathers info from it for use in a bunch of operations, and it works perfectly fine on its own, everything works as intended. Except i’ve encountered a problem that causes the whole plugin to break, and that’s as soon as you reload the blend file with an armature selected in the plugin.

For reference, this is how it should look like
image

However, this is how it looks like when a blend file is loaded with an armature still selected by the time you saved it
image

This is caused by the class that’s used to store all that information no longer existing, meaning it doesn’t have any info to display many things and that messes everything up. Of course, if i select an armature in that messed state it fixes itself, but my question is, how can i retain a class so this doesn’t happen when loading a blend file? Or if that’s not possible, how can i check if said class exists as soon as i load a blend file? So it’s able to remake it

Oh, just because, here’s what happens if i try to do any function in that disfunctional state

Thanks in advance!

Note that I am setting what will be the instance to ‘None’ first.

f = None

# Sample class
class Fun():
    def __init__(self):
        location = 0,0,0
        angle = 90
        
# Create an instance
f = Fun()

# Test if it exists
if(f):
    print('Exists')
This prints:
Exists

# Make it not exist
f = None
if(f):
    print('Exists')

This does not pass the test, because f now equals 'None' again.
    

If you just take any name for your class instance without initializing it to None, it will error out,
rather than passing though the IF statement as it did in the example.

Alternately, one of the things you could do instead of loading a new scene, is simple delete everything in the scene and start over.

bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()

I don’t think i explained myself well enough when explaining the issue, apologies for that.

the class errors out because it does not exist when a blend file is loaded after saving, i should not have used the word “scene” since i was not referring to scenes inside a blend file, i am referring to the blend file itself, apologies.

The way my addon works is that when an armature is selected, that property uses the update parameter to call the function that creates that class with the value from that property, however, once you reload the blend file with an armature selected, the code breaks because that class no longers exists, and the property cannot call that function that creates the class because there has been no update, and it’s not possible to call that function on script startup because nothing seemingly happens, even if i define arm as none and execute it only if arm is none; arm is still not defined. At the same time, i cannot give arm the value of the property on startup either since the ‘_RestrictContext’ error shows up (And it’s clearly not the ideal solution).

With that said, my question is if it’s possible to store the class in the blend file so it can be picked up by the addon when the blend file is reloaded, or if it’s possible to reassign that variable with the class that has a property as its only parameter.

target_armature : bpy.props.PointerProperty(type=bpy.types.Object, name="Armature", description="Armature that will be used to perform operations on", poll=armature_poll, update=functions.create_armature)

This is the parameter that calls the function.

def create_armature(self, context): #Creates new armature class
    global vatproperties
    vatproperties = bpy.context.scene.vatproperties
    if vatproperties.target_armature:
        global arm
        arm = Armature(vatproperties.target_armature)

And this is the function itself that creates the class.

Thanks again.

Generally, that would be referred to as persisting a class, and I have no clue how to do that. As far as I know, there is no way to save a class and retrieve it, unless perhaps you saved the class properties in a separate file. Obviously, Blender does store information when it saves a file, but I am not sure how you would go about storing custom information within the Blender file itself. I think I read some post a long time ago on the internet about the problem, and if I recall correctly there was some off-beat work-around, but I was not able to find anything like that doing a search. I dislike the way that Blender uses custom properties, it complicates the whole process, and in the current project I am working on, I am instead using class properties that I do not need to persist, because they are simply pre-initialized, static values whenever they load. Interestingly, Blender saves bone positions when it saves and loads files, I suppose it would be possible to do something off the wall like use the position as a property itself by parking it at a value that matches the value of what you want to persist, but that is a gawdawful hack, that I doubt any sane person would use. Not that I claim to be sane . . . :japanese_ogre:

1 Like

You can store custom properties on the scene and object data blocks. For example this add-on adds a boolproperty to the Scene block.

bpy.types.Scene.inactive_wire_shading = bpy.props.BoolProperty(name="Inactive Wire Shading", default=False, update=update_inactive_shading)

(It also makes use of a @persistent decorator and some handlers to keep running across file loads and blender restarts.)

And here a property is being added onto an object:

If you need to store several bits of info you could use multiple props or maybe search around and see if you can store a dict on the Scene (or the armature itself?) to hold all your armature info.

1 Like

I’ll make sure to test these when i have the time, thanks a lot!