Add-On Dev: Per-File Initialization (Issues Enabling Add-on After File Load) I've noticed a lot of add-on code using the load_post handler to serve as a sort of startup event. This makes a lot of sense, because many elements do not exist before that moment, and most add-ons need to associate with them.

But what about when an add-on is activated after the blend file is loaded? The normal startup sequence seems to be load_pre, addon.register, load_post, which allows us to sync with the file contents. But how do we detect when load_post happens before our add-on is registered?

I've tried accessing bpy.data.* and bpy.context.*, to try to detect any differences, but they are both restricted at normal startup. Is there a safe way to ask the environment if any scenes exist?

Edit: Just want to sum my problem up as a really simple question: How do I initialize add-on states that need to look at scene elements?
Add-ons can do per-file initialisation, if the add-on has some kind of panel in the UI somewhere.

You may notice various panels in Blender's UI have checkboxes next to the panel title. This is can be because they don't want to be active unless specifically turned on, but it can also be because they want to do some setup before being used:



This can be achieved in your own add-on by adding a draw_header function into the class that defines your panel:

def draw_header(self, context):

    self.layout.prop(context.scene, "addon_panel_enabled", text="")


The draw_header displays a boolean which I created and registered in the register function of the add-on:

bpy.types.Scene.addon_panel_enabled = bpy.props.BoolProperty(default=False, update=initialiseAddon)


The property has an update function called initialiseAddon which runs when the boolean is changed. It is in initialiseAddon that you can run your setup code.

Be aware, however, that this will run when the header checkbox is enabled and disabled. You could of course include code to make sure it only runs once by checking if the header boolean is true (the update function seems to be run after the value has been set):

def initialiseAddon(self, context):
    if context.scene.addon_panel_enabled:
        print("Only runs when enabling the checkbox")


Or just make another property which stores whether initialisation has been done or inspect your own data.

If you don't have a panel, then you should do initialisation in your operator when it first runs and again, have a scene property that stores whether setup has been done or not.

Full code (based on the UI Panel Simple template that comes with Blender):

import bpy

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw_header(self, context):

        self.layout.prop(context.scene, "addon_panel_enabled", text="")

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.label(text="Hello world!", icon='WORLD_DATA')

        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.operator("mesh.primitive_cube_add")

def initialiseAddon(self, context):
    #Per file initialisation code here
    if context.scene.addon_panel_enabled == True:
        print("Only runs when enabling the checkbox")

def register():
    bpy.types.Scene.addon_panel_enabled = bpy.props.BoolProperty(default=False, update=initialiseAddon)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    del bpy.types.Scene.addon_panel_enabled

if __name__ == "__main__":
    register()