0
$\begingroup$

I'm trying to expose the VIEW_3D location of my Add-on in its preferences. So far I got the user input working showing in the preferences of my Add-on.

# Input Variable 
class preferences_props(bpy.types.PropertyGroup):
        location_name: bpy.props.StringProperty(
        name="Path",
        default="Toolbox",
        description="Define location of the Add-on in 3D View Menu.",
        )
# Define Location in 3D View
class PT_mossifier_preferences(bpy.types.AddonPreferences):
        bl_idname = __package__
        bl_label = "Preferences"
        bl_description = "Add-on Configurations"
        bl_options = {'REGISTER', 'UNDO'}


        def draw(self, context):
            props = context.scene.preferences_props
            layout = self.layout
            layout.label(text='Under which 3D View tab to store the Add-on')
            row = layout.row()
            row.prop(props, "location_name")

enter image description here

Now I want to get location_name in my UI module, so I can set the bl_category = location_name. F.e. like this.

# Create Dropdown in Toolbox Tab
    class PT_addon_ui(bpy.types.Panel):
        bl_label = "Addon"
        bl_idname = "PT_Addon"
        bl_space_type = 'VIEW_3D'
        bl_region_type = 'UI'
        bl_category = location_name

However I cannot get the actual variable value out of my preferences module. This is how I'm initialy trying to import it. And I'm using print to see if the value is what I need. However print returns "None" all the time.

import bpy
addon_prefs = bpy.context.preferences.addons[__package__].preferences
print(addon_prefs)

Also using other methos to import a variable don't work. I get the error "AttributeError: type object 'preferences_props' has no attribute 'location_name'"

from .mossifier_preferences import preferences_props
print(preferences_props.location_name)

What would be the actual way to get location_name into my UI module?

Thank you in advance!

$\endgroup$
1
  • $\begingroup$ Hello. I would suggest not storing the preference props on a scene object, you can add properties directly to the AddonPreferences class as if it were a property group. That way you can access the prop from bpy.context.preferences.addons["your_addon_name"].preferences.props $\endgroup$
    – Gorgious
    Commented Apr 14 at 18:09

2 Answers 2

0
$\begingroup$

To be accessible via bpy.context.preferences.addons[__package__].preferences a property must be a part of the corresponding bpy.types.AddonPreferences subclass.

from .mossifier_preferences import preferences_props raises AttributeError: type object 'preferences_props' has no attribute 'location_name' because the property does not exists yet. For that the group property must be instantiated. With location_name: bpy.props.StringProperty you only set the __annotations__. It is only a class definition that is later used to create the actual property.

In the draw function you access the property bpy.context.scene.preferences_props and this is how it is accessed everywhere else.

bpy.context.preferences.addons[__package__].preferences is available only after the addon's bpy.types.AddonPreferences subclass is registered so the module containing the user specified bl_category should be imported inside register() after the AddonPreferences registration.

bl_category must be set at the class definition evaluation time so if it is changed the panel should be re-registered.

$\endgroup$
0
$\begingroup$

thank you for your answers. You pointed me in the right direction. After placing the property into the AddonPreferences class, I was able to retrieve it in my UI module with:

#Instantiate Ppreferences
def preferences():
bpy.context.preferences.addons.get(__package__)
return bpy.context.preferences.addons[__package__].preferences

#Access the preferences
prefs = preferences()

And inside the UI class use the function to define the category.

bl_category = prefs.location_name

However at the end I still had the trouble to update the UI with the new location_name, so I additionally found this way to do it all inside the preferences module.

I added the update function to my StringProperty & defined a new function, where I drectly set the bl_category of my UI module while also unregistering & registering the class again:

# Define addon preferences
class preferences(bpy.types.AddonPreferences):
bl_idname = __package__
bl_label = "Preferences"
bl_description = "Add-on Configurations"
bl_options = {'REGISTER', 'UNDO'}

def update_ui(self, context):
    from . import ui
    bpy.utils.unregister_class(ui.PT_ui)
    ui.PT_ui.bl_category = bpy.context.preferences.addons[__package__].preferences.location_name
    bpy.utils.register_class(ui.PT_ui)

location_name: bpy.props.StringProperty(
    name="Path",
    default="Toolbox",
    description="Define location of the Add-on in 3D View Menu.",
    update=update_ui
)

Now I'm able to dynamically change the UI location with the setup in the preferences and trough the function in the UI it actually remembers these changes after Blender was restarted.

$\endgroup$

You must log in to answer this question.

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