diff --git a/release/scripts/op/io_scene_fbx/__init__.py b/release/scripts/op/io_scene_fbx/__init__.py index baf7e78014a..6a76cf0d756 100644 --- a/release/scripts/op/io_scene_fbx/__init__.py +++ b/release/scripts/op/io_scene_fbx/__init__.py @@ -34,6 +34,7 @@ class ExportFBX(bpy.types.Operator, ExportHelper): '''Selection to an ASCII Autodesk FBX''' bl_idname = "export_scene.fbx" bl_label = "Export FBX" + bl_options = {'PRESET'} filename_ext = ".fbx" filter_glob = StringProperty(default="*.fbx", options={'HIDDEN'}) diff --git a/release/scripts/op/io_scene_obj/__init__.py b/release/scripts/op/io_scene_obj/__init__.py index 8a35bb81dd9..b87c6b44347 100644 --- a/release/scripts/op/io_scene_obj/__init__.py +++ b/release/scripts/op/io_scene_obj/__init__.py @@ -65,6 +65,7 @@ class ExportOBJ(bpy.types.Operator, ExportHelper): bl_idname = "export_scene.obj" bl_label = 'Export OBJ' + bl_options = {'PRESET'} filename_ext = ".obj" filter_glob = StringProperty(default="*.obj;*.mtl", options={'HIDDEN'}) diff --git a/release/scripts/op/presets.py b/release/scripts/op/presets.py index b0dd7de3f1c..dd16a4ee5e0 100644 --- a/release/scripts/op/presets.py +++ b/release/scripts/op/presets.py @@ -301,6 +301,57 @@ class AddPresetKeyconfig(AddPresetBase, bpy.types.Operator): keyconfigs.remove(keyconfigs.active) +class AddPresetOperator(AddPresetBase, bpy.types.Operator): + '''Add an Application Interaction Preset''' + bl_idname = "wm.operator_preset_add" + bl_label = "Operator Preset" + preset_menu = "WM_MT_operator_presets" + + operator = bpy.props.StringProperty(name="Operator", maxlen=64, options={'HIDDEN'}) + + # XXX, not ideal + preset_defines = [ + "op = bpy.context.space_data.operator", + ] + + @property + def preset_subdir(self): + return __class__.operator_path(self.operator) + + @property + def preset_values(self): + properties_blacklist = bpy.types.Operator.bl_rna.properties.keys() + + prefix, suffix = self.operator.split("_OT_", 1) + operator_rna = getattr(getattr(bpy.ops, prefix.lower()), suffix).get_rna().bl_rna + + ret = [] + for prop_id, prop in operator_rna.properties.items(): + if (not prop.is_hidden) and 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)) + + +class WM_MT_operator_presets(bpy.types.Menu): + bl_label = "Operator Presets" + + def draw(self, context): + self.operator = context.space_data.operator.bl_idname + bpy.types.Menu.draw_preset(self, context) + + @property + def preset_subdir(self): + return AddPresetOperator.operator_path(self.operator) + + preset_operator = "script.execute_preset" + def register(): pass diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 559015715ef..46dfd34d2ba 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2702,7 +2702,26 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,in int empty; RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - + + /* menu */ + if(op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + row= uiLayoutRow(layout, TRUE); + uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NULL); + + WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + RNA_string_set(&op_ptr, "operator", op->type->idname); + op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + + WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", 1); + op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + } + /* main draw call */ empty= uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0; diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index b6b73b9885d..a7870243afc 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -265,6 +265,7 @@ EnumPropertyItem operator_flag_items[] = { {OPTYPE_BLOCKING, "BLOCKING", 0, "Finished", ""}, {OPTYPE_MACRO, "MACRO", 0, "Macro", ""}, {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer", ""}, + {OPTYPE_PRESET, "PRESET", 0, "Preset", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem operator_return_items[] = { diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 0ca8c5e7f4f..bbd22cae0f3 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -55,6 +55,7 @@ struct ImBuf; #define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */ #define OPTYPE_MACRO 8 #define OPTYPE_GRAB_POINTER 16 /* */ +#define OPTYPE_PRESET 32 /* show preset menu */ /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */