0
$\begingroup$

The problem is very simple. I wrote an addon and the property looks like this:

class MyObjectSettings(bpy.types.PropertyGroup):
    @classmethod
    def register(cls):
        bpy.types.Object.my_addon = PointerProperty(
            name="my_addon Object Settings",
            description="my_addon object settings",
            type=cls,
        )
        cls.is_instance = BoolProperty(
            name="Is Instance",
            default=False,
        )

That is, objects have an obj.my_addon.is_instance bool property.

And of course this is exposed to the UI so that users can toggle it on/off.

This is all working well so far. A couple of Blender files are already using this addon.

The problem is that I changed my mind. I now want to have 3 states:

enum_blender_obj_type = (
    ('NONE', "None", "Description for None")
    ('INSTANCE', "Instance", "This is an instance")
    ('ALTERNATE', "Alternate", "This object is an Alternate")
)

class MyObjectSettings(bpy.types.PropertyGroup):
    @classmethod
    def register(cls):
        bpy.types.Object.my_addon = PointerProperty(
            name="my_addon Object Settings",
            description="my_addon object settings",
            type=cls,
        )
        cls.object_type = EnumProperty(
            name="Type",
            items=enum_blender_obj_type,
            default='NONE',
        )

So whereas in plugin v1.0 we had obj.my_addon.is_instance bool, now in v2.0 I wish to use obj.my_addon.object_type == "INSTANCE" because it's now an enum.

So the question is: Is there a way to transparently migrate this setting?

In other words, when the user loads a Blender file created with an older version of the addon, my plugin automatically runs the following code:

# Migrate the old variable into the new variable
if obj.my_addon.is_instance:
    obj.my_addon.object_type = 'INSTANCE'

Is there an established workflow for such addon upgrade migration?

Thanks!

$\endgroup$

1 Answer 1

0
$\begingroup$

OK I don't know if there is a better way or an official API to deal with this.

But the solution I went with is to hook a Post File Open Handler and then unset is_instance so that further opening of the same file won't overwrite already existing settings:

import bpy
from bpy.app.handlers import persistent

@persistent
def load_handler(dummy):
    # When opening Blender files, migrate all objects to new settings.
    for scene in bpy.data.scenes:
        for obj in scene.objects:
            if obj.my.is_instance and obj.my.object_type == 'UNDEFINED':
                obj.my.object_type = 'GAMEOBJECT_INSTANCE'
            obj.my.is_instance = False

def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.app.handlers.load_post.append(load_handler)

def unregister():
    bpy.app.handlers.load_post.remove(load_handler)
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)
$\endgroup$

You must log in to answer this question.

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