3
$\begingroup$

The question is very short, so it is simply this:

How can I save user preferences, without using bpy.ops.wm.save_userpref()?

I'd like to create a function that would save everything or some part of the preferences, without the use of the operator. I don't know if this is possible.

The main intention is to save only some preferences, for example some custom preferences in a bpy.types.AddonPreferences pointer property

$\endgroup$
2
  • 1
    $\begingroup$ It's not possible to save the preferences as userpref, that is, in the preferences file, without using save_userpref() but it is possible to write a utility that saves them to a separate file and then restores them before using them. If that's a suitable approach I can write up an example. $\endgroup$ Commented Jul 1, 2022 at 23:58
  • $\begingroup$ I think it would be interesting, if you are sure there is no other way (And I think so too) $\endgroup$
    – Noob Cat
    Commented Jul 2, 2022 at 0:27

1 Answer 1

4
+25
$\begingroup$

Blender does not export a low level interface to the preferences file, nor is the format of the file documented. The interface is documented under Preference Operators and the contents, but not layout, of the preferences are documented starting at bpy.types.Preferences.

However, you can use Blender's presets facility to maintain your own settings in files that are stored with your add-on. This mechanism is described in Using Blender's presets in Python and you can find a skeleton add-on that demonstrates presets in my Skeleton github repository

A preset is a Python file containing a collection of settings values. Here's an example from my skeleton add-on:

import bpy
scene = bpy.context.scene

scene.name_from = 'Alice'
scene.name_to = 'Bob'
scene.message_text = 'whatcher?'

It's just a collection of statements that set the values of properties, in this case three string properties that I've added to scene called name_from, name_to, and message_text.

A collection of related presets is stored in a single directory under you addon. These preferences are used in a panel, so they're store in skeleton/skeleton.panel.

Operator presets are described to blender by deriving a class from AddPresetBase:

from bl_operators.presets import AddPresetBase

class MT_MyPresets(Menu): 
    bl_label = 'My Presets' 
    preset_subdir = 'object/my_presets' 
    preset_operator = 'script.execute_preset' 
    draw = Menu.draw_preset

class OT_AddMyPreset(AddPresetBase, Operator):
    bl_idname = 'my.add_preset'
    bl_label = 'Add A preset'
    preset_menu = 'MT_MyPresets'

    # Common variable used for all preset values
    preset_defines = [
                        'obj = bpy.context.object',
                        'scene = bpy.context.scene'
                     ]

    # Properties to store in the preset
    preset_values = [
                        'obj.show_axis',
                        'obj.show_name',
                        'obj.show_bounds',
                        'scene.world'
                    ]

    # Directory to store the presets
    preset_subdir = 'object/my_presets'

Blender will handle the I/O between your operator and the presets.

Panel presets are created by deriving a class from Panel and PresetPanel:

from bl_ui.utils import PresetPanel
from bpy.types import Panel, Menu

# [...]

class MY_PT_presets(PresetPanel, Panel):
    bl_label = 'My Presets'
    preset_subdir = 'object/my_presets'
    preset_operator = 'script.execute_preset'
    preset_add_operator = 'my.add_preset'

# Now we need to make our actual panel draw the header from the presets panel

class My_PT_Panel(Panel):
    bl_label = 'My Panel'
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = 'output'

    def draw_header_preset(self, _context):
        MY_PT_presets.draw_panel_header(self.layout)

    def draw(self, context):    
        # The rest of our panel's code 
        pass

You can also use a helper function to copy predefined presets to their starting points, or you can zip your add-on with the predefined presets included.

$\endgroup$

You must log in to answer this question.

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