GUI question about PRESET FUNCTIONALITY

I spend some time to lean how to create bleder gui elements like buttons and different menus. Noe it is clear for me, but PRESET functionality (see attachment) .
So please can some one provide me a simple code for this. Because I really stop in my studying.
Thx a lot)))


it is special menu + add/remove operators subclassed from (AddPresetBase, Operator)

The base class AddPresetBase provides the (de)serialization, the stock bpy.types.Menu class the draw method for the menu.

Menu code:

import bpy
from bpy.types import Menu, Panel

class RENDER_MT_presets(Menu):
    bl_label = "Render Presets"
    preset_subdir = "render" # you might wanna change this
    preset_operator = "script.execute_preset" # but not this
    draw = Menu.draw_preset # or that

In a panel, make the preset dropdown list + buttons visible by

        row = layout.row(align=True)
        row.menu("RENDER_MT_presets", text=bpy.types.RENDER_MT_presets.bl_label)
        row.operator("render.preset_add", text="", icon='ZOOMIN')
        row.operator("render.preset_add", text="", icon='ZOOMOUT').remove_active = True

And here’s the important, subclassed preset operator:

class AddPresetRender(AddPresetBase, Operator):
    """Add a Render Preset"""
    bl_idname = "render.preset_add"
    bl_label = "Add Render Preset"
    preset_menu = "RENDER_MT_presets" # your menu's name!

    # IMPORTANT: you need to specify below, what will be serialized to a preset file

    preset_defines = [
        "scene = bpy.context.scene"
    ]

    preset_values = [
        "scene.render.field_order",
        "scene.render.fps",
        "scene.render.fps_base",
        "scene.render.pixel_aspect_x",
        "scene.render.pixel_aspect_y",
        "scene.render.resolution_percentage",
        "scene.render.resolution_x",
        "scene.render.resolution_y",
        "scene.render.use_fields",
        "scene.render.use_fields_still",
    ]

    preset_subdir = "render" # make sure it's the same as in your menu class

Wow. Great. Thanks so murch =)))))))

Hey! I hope somebody can help with this. I just recently startet picking up python and I wanted to put some operator preset functionality into blender, because you know, Maya can do it and it’s convenient.
But I can’t get it to work and I can’t figure out why it’s not working.

Here’s the menu code from the 'scripts/startup/bl_operators/presets.py:


class WM_MT_operator_presets(Menu):
    bl_label = "Operator Presets"


    def draw(self, context):
        self.operator = context.active_operator.bl_idname


        # dummy 'default' menu item
        layout = self.layout
        layout.operator("wm.operator_defaults")
        layout.separator()


        Menu.draw_preset(self, context)


    @property
    def preset_subdir(self):
        return AddPresetOperator.operator_path(self.operator)


    preset_operator = "script.execute_preset"

This is the preset operator in the same file:


class AddPresetOperator(AddPresetBase, Operator):
    """Add or remove an Operator Preset"""
    bl_idname = "wm.operator_preset_add"
    bl_label = "Operator Preset"
    preset_menu = "WM_MT_operator_presets"


    operator = StringProperty(
            name="Operator",
            maxlen=64,
            options={'HIDDEN', 'SKIP_SAVE'},
            )


    preset_defines = [
        "op = bpy.context.active_operator",
    ]


    @property
    def preset_subdir(self):
        return AddPresetOperator.operator_path(self.operator)


    @property
    def preset_values(self):
        properties_blacklist = Operator.bl_rna.properties.keys()


        prefix, suffix = self.operator.split("_OT_", 1)
        op = getattr(getattr(bpy.ops, prefix.lower()), suffix)
        operator_rna = op.get_rna().bl_rna
        del op


        ret = []
        for prop_id, prop in operator_rna.properties.items():
            if not (prop.is_hidden or prop.is_skip_save):
                if prop_id not in properties_blacklist:
                    ret.append("op.%s" % prop_id)


        return ret


    @staticmethod
    def operator_path(operator):
        import os
        prefix, suffix = operator.split("_OT_", 1)
        return os.path.join("operator", "%s.%s" % (prefix.lower(), suffix))

And in my own file I have the panel in the TOOL_PROPS:

#bl_info stuff I didn't copy in here

import bpy


class OperatorPresetPanel(bpy.types.Panel):
    """Creates a Panel in the TOOL_PROPS region of the Tool Shelf"""
    bl_label = "Operator Presets"
    bl_idname = "OBJECT_PT_operator_preset"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOL_PROPS'


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


        if bpy.context.active_operator:
            row = layout.row(align=True)
            row.menu("WM_MT_operator_presets", text=bpy.types.WM_MT_operator_presets.bl_label)
            row.operator("wm.operator_preset_add", text="", icon="ZOOMIN")
            row.operator("wm.operator_preset_add", text="", icon="ZOOMOUT").remove_active = True        
        else:
            row = layout.row(align=True)
            row.label(text="No Active Operator")


def register():
    bpy.utils.register_class(OperatorPresetPanel)




def unregister():
    bpy.utils.unregister_class(OperatorPresetPanel)




if __name__ == "__main__":
    register()

When I try to add or remove a preset I get an error message. It’s this:

Traceback (most recent call last):
File “C:\Program Files\Blender\2.70\scripts\startup\bl_operators\presets.py”, line 76, in execute
target_path = os.path.join(“presets”, self.preset_subdir)
File “C:\Program Files\Blender\2.70\scripts\modules\bpy_types.py”, line 584, in getattribute
return super().getattribute(attr)
File “C:\Program Files\Blender\2.70\scripts\startup\bl_operators\presets.py”, line 552, in preset_subdir
return AddPresetOperator.operator_path(self.operator)
File “C:\Program Files\Blender\2.70\scripts\startup\bl_operators\presets.py”, line 574, in operator_path
prefix, suffix = operator.split(“OT”, 1)
ValueError: need more than 1 value to unpack

location: <unknown location>:-1

I also attached a screenshot.


In theory it should create a preset in “presets/operators/prefix.suffix/” (e.g. presets/operators/mesh.subdivide/mypreset1.py) which contains the key-value pairs of the rna properties that were not filtered. The recognition of the path works because when I create it manually I don’t get the missing paths message. If I create presets manually and put them in either the blender installation or in the user path on windows, it automatically appears in the dropdown and I can choose it. It adjusts the values accordingly but doesn’t re-apply them yet (until I change a value). “Restore Defaults” also restores the defaults (except ‘number_cuts’, I wonder why that is).

I am beginning to think that it has to do with administrative rights, because maybe it attempts to create a file in a system folder (Blender installation path on Windows). The addon itself is in the “%APPDATA%/Blender Foundation\Blender\2.70\scripts\addons”-folder. But starting Blender as administrator doesn’t do any good either.

Please someone tell me what’s missing! I appreciate it!

Big up:

Related: how can we know the name of the active preset ? and change it ?