Custom Install Path for Library in Addon

I’m on my final hurdle to making my first addon…

So I have a Blender file for my addon that has the assets that get imported from a library. I’m now compiling the script to work on other peoples computers no matter where they have this file, so I’ve created an install preference to let the user have the file where they want it.

I don’t know how to use the variable in other classes, I know I have to register it. I have done a property group for my addon which is include in the code excerpt but for the life of me I don’t know how to register the variable filepath in the AddonPreferences to use in my Operators.

Thanks in advance!

bl_info = {
    "name" : "DCD",
    "author" : "David Cherrie Design",
    "description" : "",
    "blender" : (3, 2, 1),
    "version" : (0, 0, 1),
    "location" : "View3d > Tool",
    "warning" : "",
    "wiki_url" : "",
    "category" : "Generic"
}

import bpy

from bpy.types import Panel, Operator, PropertyGroup, AddonPreferences
from math import pi

class MOVINGLIGHTS_AP_preferences(AddonPreferences):
    bl_idname = __name__

    filepath : bpy.props.StringProperty(name="Library Path", subtype="DIR_PATH")

    def draw(self, context):
        row = self.layout.row()
        row.scale_y = 2
        row.scale_x = 2
        row.prop(self, "filepath")

class MOVINGLIGHTS_PG_properties(PropertyGroup):

    fixture_count : bpy.props.IntProperty(name= "Amount:", min= 1, soft_max= 100, default= 1)
    fixture_rotation : bpy.props.FloatVectorProperty(name= "Rotation", default= (0,0,0))
    fixture_offset : bpy.props.FloatVectorProperty(name= "Offset", default= (0,0,0))

class MOVINGLIGHTS_OT_test(Operator):
    """Test"""
    bl_label = "Test"
    bl_idname = "object.test"
    bl_options = {"REGISTER", "UNDO"}
    bl_context = "objectmode"

    def execute(self, context):

        bpy.ops.wm.appennd(filename="Spot Mover", directory=filepath, active_collection=True, autoselect=True, use_recursive=True)

        return {"FINISHED"}

======================

class MOVINGLIGHTS_PT_MainPanel(Panel):
    """Tool tip thingy"""
    bl_label = "Moving Lights"
    bl_category = "DCD"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = "objectmode"

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

        layout.label(text= "Import Fixture:")
        layout.prop(moverTool, "fixture_count")
        layout.prop(moverTool, "fixture_rotation")
        layout.prop(moverTool, "fixture_offset")

        col = layout.column()

        col.operator("object.addspotmover",
            text="Spot Mover",
            icon="LIGHT"
        )
        col.operator("object.addwashmover",
            text="Wash Mover",
            icon="LIGHT"
        )

classes = [MOVINGLIGHTS_AP_preferences, MOVINGLIGHTS_PG_properties, MOVINGLIGHTS_PT_MainPanel, MOVINGLIGHTS_OT_addSpotMover, MOVINGLIGHTS_OT_addWashMover, MOVINGLIGHTS_OT_test]

def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.moverTool = bpy.props.PointerProperty(type= MOVINGLIGHTS_PG_properties)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    del bpy.types.Scene.moverTool

if __name__ == "__main__":
    register()

Normally you would use a StringProperty (eg: attached to scene)
bpy.types.Scene.filepath = bpy.types.StringProperty()

However since they are saved per ‘blend file’ you would need to have them more permanent as AddonPreferences, for the better. You declare the string property in the same way but now is attached to the addon itself.
https://docs.blender.org/api/current/bpy.types.AddonPreferences.html

1 Like

You can access your addon’s preferences like this:

preferences = context.preferences.addons[addon_name].preferences

# Then you can do e.g.
filepath = preferences.filepath
...
1 Like

Thanks!

I notice the use of [__package__] and [__name__] in the documentation. Should these all be removed and reference my addon name as just part of that variable? And if so, what is it that I’m matching too exactly?

# this must match the add-on name, use '__package__'

the bl_idname of the AddonPreferences class must the the same as the addon folder name. The same string is also used as the key to get the addon preferences from context.preferences.addons.

In the top-level __init__.py file, __package__ and __name__ will both be the same as the addon folder name automatically, so it doesn’t matter what you use. But keep it in mind when accessing them from other files, e.g. from a submodule. The actual string should be the same as the folder name, like “Moving Lights” in your case.