Using Blender’s presets in Python

19.10.2018 @ Tutorials(Addon, Blender, Python)

Look­ing to add sup­port for pre­sets in your addon? Read on to find out how!

There’s a built-in pre­sets sys­tem in Blender used for oper­a­tors and pan­els. The good news is that it’s Python based and easy to use. Pre­sets are Python files that man­u­al­ly set val­ues. When you select a pre­set in the menu that par­tic­u­lar script is read from disk and run. Adding/removing pre­sets involves cre­at­ing or delet­ing py files from the pre­sets fold­er. This is han­dled for us, but you might want to keep it mind for oth­er things (like pack­ag­ing pre­sets). The pre­sets fold­er is inside your per­son­al Blender scripts fold­er. 

Lin­ux~/.config/blender/2.79/scripts/presets/
Mac/Users/{user}/Library/Application/Support/Blender/2.79/scripts/presets/
Win­dowsC:\Documents and Settings\%username%\Application Data\Blender Foundation\Blender\2.79\scripts\presets\

Unfor­tu­nate­ly there’s no way of importing/exporting pre­sets yet oth­er than man­u­al­ly copy­ing files (or mak­ing an oper­a­tor that does that). Also note that the built-in pre­sets sys­tem only includes the menu we often see on top of oper­a­tors and pan­els. If you want to have images, thumb­nails and oth­er advanced fea­tures you will have to roll your own sys­tem.

For operators

Adding pre­sets to oper­a­tors is as sim­ple as it gets. Just add the PRESET to the bl_options set and you’re done.

class My_OP(Operator):
    bl_idname = "my.operator"
    bl_label = 'My Cool OP'
    bl_options = {'PRESET'}

Blender will add the pre­set menu to the oper­a­tor UI for you. It will even cre­ate a fold­er for them in the pre­sets direc­to­ry! (note that you need to save at least one pre­set for that)

For panels

Using the pre­sets sys­tem on pan­els only takes a bit more work. It also brings some extra flex­i­bil­i­ty on the UI.

First we have to decide where to save the pre­sets. This could be your addons name, or a cat­e­go­ry with your addon as a sub­fold­er. For this exam­ple let’s use ‘object/my_presets’. The full path would then
be ~/.config/blender/2.79/scripts/presets/object/my_presets/.

Next we need to make an oper­a­tor to add/remove pre­sets. Let’s bring the AddPresetsBase mix­in into the mix (hah!).

from bl_operators.presets import AddPresetBase

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'

There’s no need to add an execute() or invoke() func­tion in this case, since the mix­in imple­ments them. If you want to take a peek at the code behind this mag­ic you can find it in [BLENDER_FOLDER]/bin/2.79/scripts/startup/bl_operators/presets.py We can also use this oper­a­tor to remove pre­sets by set­ting remove_active to True.

The meaty part of this code are the preset_defines and preset_values prop­er­ties. The first list lets you declare vari­ables com­mon to all the preset’s val­ues. This is only for con­ve­nience. It saves you from typ­ing bpy.blah.bla over and over. The sec­ond list are the actu­al val­ues that will be saved in the pre­set. With the oper­a­tor done and ready, we now have to make a class for the menu and add every­thing to the pan­el.

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

    # [...]
    # This code goes in the panel's draw()

    row = layout.row(align=True)
    row.menu('MT_MyPresets', text='Presets')
    row.operator('my.add_preset', text='', icon='ZOOMIN')
    row.operator('my.add_preset', text='',
                  icon='ZOOMOUT').remove_active = True

Don’t change the preset_operator and draw lines. These the lines make it look and work like a pre­sets menu.

Packaging presets

There’s no “offi­cial” way of pack­ag­ing pre­sets with addons. But since they are just files we can eas­i­ly do this our­selves. The process goes like this: First check if the pre­sets fold­er exists, if it doesn’t that means this is the first time the addon is enabled. In that case copy the addon files from the addon fold­er to the pre­sets fold­er. If it does exist we can assume the pre­sets have already been installed (in which case we don’t do any­thing).

We can do all this in the register() func­tion.

import os
import shutils

# [...]

my_presets = os.path.join(presets_folder, 'object', 'my_presets')

if not os.path.isdir(my_presets):
    # makedirs() will also create all the parent folders (like "object")
    os.makedirs(my_presets)

    # Get a list of all the files in your bundled presets folder
    files = os.listdir(my_bundled_presets)

    # Copy them
    [shutil.copy2(os.path.join(my_bundled_presets, f), my_presets)
     for f in files]

That’s all there is to know about Blender’s pre­sets sys­tem. Well, at least for the 2.7x series. The sys­tem is get­ting some love in 2.80 (most­ly UI). Hope­ful­ly there will be more improve­ments over the 2.8x series.

All the posts you can read

8 Comments

  1. Rombout Versluijs(5 months ago)

    NIce man! I have done this recent­ly and hacked parts of this into my addon i made for rigi­fy. Though your ver­sion of adding pre­sets is way sim­pler than what i did. My addon makes it pos­si­ble to save rigi­fy setups and rigi­fy pre­sets.

    1. Diego Gangl(5 months ago)

      Hey, awe­some! Did you roll your own sys­tem or did you build it on top of the builtin?

  2. Rusty(5 months ago)

    The path for Win­dows 10

    C:\Users\%username%\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\presets

  3. Rusty(5 months ago)

    Adden­dum to my pre­vi­ous post. If you want to mod­i­fiy an exist­ing pre­set, one that came with blender, they’re in

    C:\Program Files\Blender Foundation\Blender\2.79\scripts\presets

    Also note that in the path C:\Users\%username%\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\presets

    If you haven’t changed the set­ting in Win­dows to dis­play hid­den files the direc­to­ry App­Da­ta is hid­den.

  4. Campbell Barton(5 months ago)

    Note: the exam­ple that uses Menu.draw_preset isn’t cor­rect, you’re meant to sub­class Pre­set­Menu instead.

    1. Diego Gangl(5 months ago)

      Hey, thanks but is that class avail­able on 2.7x? I only found it in the 2.8 branch

  5. CampbellBarton(5 months ago)

    Ah, you’re right, should have checked the mas­ter branch.

    1. Diego Gangl(5 months ago)

      Np, I’ll make a note to update this when 2.8 comes out with all the new good­ness

Leave a Reply

Your email address will not be published.