diff --git a/release/scripts/io/export_3ds.py b/release/scripts/io/export_3ds.py index 163b683f60f..23fd44acc3f 100644 --- a/release/scripts/io/export_3ds.py +++ b/release/scripts/io/export_3ds.py @@ -1139,10 +1139,8 @@ class Export3DS(bpy.types.Operator): bpy.types.register(Export3DS) # Add to a menu -import dynamic_menu - def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".3ds") self.layout.operator(Export3DS.bl_idname, text="Autodesk 3DS...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +bpy.types.INFO_MT_file_export.append(menu_func) diff --git a/release/scripts/io/export_fbx.py b/release/scripts/io/export_fbx.py index 19a3345bd94..25e79bbf214 100644 --- a/release/scripts/io/export_fbx.py +++ b/release/scripts/io/export_fbx.py @@ -3462,13 +3462,9 @@ bpy.types.register(ExportFBX) # SMALL or COSMETICAL # - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version') - -# Add to a menu -import dynamic_menu - def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".fbx") self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +menu_item = bpy.types.INFO_MT_file_export.append(menu_func) diff --git a/release/scripts/io/export_mdd.py b/release/scripts/io/export_mdd.py index 66db8c14027..7d0e49d48ce 100644 --- a/release/scripts/io/export_mdd.py +++ b/release/scripts/io/export_mdd.py @@ -183,14 +183,11 @@ class ExportMDD(bpy.types.Operator): bpy.types.register(ExportMDD) # Add to a menu -import dynamic_menu - - def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".mdd") self.layout.operator(ExportMDD.bl_idname, text="Vertex Keyframe Animation (.mdd)...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +bpy.types.INFO_MT_file_export.append(menu_func) if __name__ == '__main__': bpy.ops.export.mdd(path="/tmp/test.mdd") diff --git a/release/scripts/io/export_obj.py b/release/scripts/io/export_obj.py index 85af371680a..5b55c5159a6 100644 --- a/release/scripts/io/export_obj.py +++ b/release/scripts/io/export_obj.py @@ -987,19 +987,13 @@ class ExportOBJ(bpy.types.Operator): wm.add_fileselect(self) return {'RUNNING_MODAL'} - - - - bpy.types.register(ExportOBJ) -import dynamic_menu - def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".obj") self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +menu_item = bpy.types.INFO_MT_file_export.append(menu_func) if __name__ == "__main__": bpy.ops.EXPORT_OT_obj(filename="/tmp/test.obj") diff --git a/release/scripts/io/export_ply.py b/release/scripts/io/export_ply.py index f27b76d2cbe..15b65e8d2fd 100644 --- a/release/scripts/io/export_ply.py +++ b/release/scripts/io/export_ply.py @@ -318,14 +318,11 @@ class ExportPLY(bpy.types.Operator): bpy.types.register(ExportPLY) -import dynamic_menu - - def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".ply") self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +bpy.types.INFO_MT_file_export.append(menu_func) if __name__ == "__main__": bpy.ops.export.ply(path="/tmp/test.ply") diff --git a/release/scripts/io/export_x3d.py b/release/scripts/io/export_x3d.py index c4f1b53146f..4c3540a458e 100644 --- a/release/scripts/io/export_x3d.py +++ b/release/scripts/io/export_x3d.py @@ -1242,13 +1242,12 @@ class ExportX3D(bpy.types.Operator): bpy.types.register(ExportX3D) -import dynamic_menu def menu_func(self, context): default_path = bpy.data.filename.replace(".blend", ".x3d") self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)...").path = default_path -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +bpy.types.INFO_MT_file_export.append(menu_func) # NOTES # - blender version is hardcoded diff --git a/release/scripts/io/import_anim_bvh.py b/release/scripts/io/import_anim_bvh.py index cd040012840..2afd2db3cb2 100644 --- a/release/scripts/io/import_anim_bvh.py +++ b/release/scripts/io/import_anim_bvh.py @@ -897,7 +897,5 @@ class BvhImporter(bpy.types.Operator): bpy.types.register(BvhImporter) - -import dynamic_menu menu_func = lambda self, context: self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)...") -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func) +bpy.types.INFO_MT_file_import.append(menu_func) diff --git a/release/scripts/io/import_scene_3ds.py b/release/scripts/io/import_scene_3ds.py index 3e174baa14c..4420f6ef6f0 100644 --- a/release/scripts/io/import_scene_3ds.py +++ b/release/scripts/io/import_scene_3ds.py @@ -1168,10 +1168,9 @@ class IMPORT_OT_autodesk_3ds(bpy.types.Operator): bpy.types.register(IMPORT_OT_autodesk_3ds) -import dynamic_menu menu_func = lambda self, context: self.layout.operator(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)...") -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func) +bpy.types.INFO_MT_file_import.append(menu_func) # NOTES: -# why add 1 extra vertex? and remove it when done? +# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D" # disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time) diff --git a/release/scripts/io/import_scene_obj.py b/release/scripts/io/import_scene_obj.py index f135bfbb6c0..228084561b8 100644 --- a/release/scripts/io/import_scene_obj.py +++ b/release/scripts/io/import_scene_obj.py @@ -1627,9 +1627,8 @@ class IMPORT_OT_obj(bpy.types.Operator): bpy.types.register(IMPORT_OT_obj) -import dynamic_menu menu_func = lambda self, context: self.layout.operator(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)...") -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func) +menu_item = bpy.types.INFO_MT_file_import.append(menu_func) # NOTES (all line numbers refer to 2.4x import_obj.py, not this file) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 15bf71e017e..50e8d8ded93 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -379,6 +379,32 @@ class Macro(StructRNA, metaclass=OrderedMeta): class Menu(StructRNA): __slots__ = () + + @classmethod + def _dyn_menu_initialize(cls): + draw_funcs = getattr(cls.draw, "_draw_funcs", None) + + if draw_funcs is None: + def draw_ls(*args): + for func in draw_ls._draw_funcs: + func(*args) + + draw_funcs = draw_ls._draw_funcs = [cls.draw] + cls.draw = draw_ls + + return draw_funcs + + @classmethod + def append(cls, draw_func): + """Prepend an draw function to this menu, takes the same arguments as the menus draw function.""" + draw_funcs = cls._dyn_menu_initialize() + draw_funcs.append(draw_func) + + @classmethod + def prepend(cls, draw_func): + """Prepend a draw function to this menu, takes the same arguments as the menus draw function.""" + draw_funcs = cls._dyn_menu_initialize() + draw_funcs.insert(0, draw_func) def path_menu(self, searchpaths, operator): layout = self.layout @@ -410,3 +436,4 @@ class Menu(StructRNA): """ import bpy self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator) + diff --git a/release/scripts/modules/dynamic_menu.py b/release/scripts/modules/dynamic_menu.py deleted file mode 100644 index 9583dae9bf4..00000000000 --- a/release/scripts/modules/dynamic_menu.py +++ /dev/null @@ -1,118 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# - -import bpy - - -def collect_baseclasses(_class, bases): - - if _class is type or _class is object: - return bases - - bases.append(_class) - for _superclass in _class.__bases__: - collect_baseclasses(_superclass, bases) - - return bases - - -def collect_subclasses(_class, subs): - - if _class is type or _class is object: - return subs - - subs.append(_class) - for _subclass in _class.__subclasses__(): - collect_subclasses(_subclass, subs) - - return subs - - -class DynMenu(bpy.types.Menu): - - def draw(self, context): - ''' - This is a draw function that is used to call all subclasses draw functions - starting from the registered classes draw function and working down. - - DynMenu.setup() must be called first. - - Sort/group classes could be nice - ''' - - subclass_ls = [] - collect_subclasses(self.__class__, subclass_ls) - # print(subclass_ls) - - for subclass in subclass_ls: - # print("drawwing", subclass) # , dir(subclass)) - subclass.internal_draw(self, context) - # print("subclass.internal_draw", subclass.internal_draw) - - -def setup(menu_class): - ''' - Setup subclasses (not needed when self.add() is used) - ''' - bases = collect_baseclasses(menu_class, []) - - # Incase 'DynMenu' isnt last - while bases[-1] is not DynMenu: - bases.pop() - bases.pop() # remove 'DynMenu' - - root_class = bases[-1] # this is the registered class - - for subclass in collect_subclasses(root_class, []): - #print(subclass) - - draw = getattr(subclass, 'draw', None) - if draw and not hasattr(subclass, 'internal_draw'): - # print("replace", subclass, draw) - try: - del subclass.draw - except: - pass - subclass.internal_draw = draw - - root_class.draw = DynMenu.draw - - -def add(menu_class, func): - ''' - Add a single function directly without having to make a class - - important that the returned value should be stored in the module that called it. - ''' - - newclass = type('', (menu_class,), {}) - newclass.internal_draw = func - setup(menu_class) - return newclass - -''' -# so we dont need to import this module -DynMenu.setup = setup -DynMenu.add = add - -# Only so we can access as bpy.types. -# dont ever use this directly! -bpy.types.register(DynMenu) -''' diff --git a/release/scripts/op/add_armature_human.py b/release/scripts/op/add_armature_human.py index 8696312eae0..e618ed51ee5 100644 --- a/release/scripts/op/add_armature_human.py +++ b/release/scripts/op/add_armature_human.py @@ -613,11 +613,9 @@ class AddHuman(bpy.types.Operator): bpy.types.register(AddHuman) # Add to a menu -import dynamic_menu - menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname, icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)")) -menu_item = dynamic_menu.add(bpy.types.INFO_MT_armature_add, menu_func) +bpy.types.INFO_MT_armature_add.append(menu_func) if __name__ == "__main__": bpy.ops.mesh.armature_human_advanced_add() diff --git a/release/scripts/op/add_mesh_torus.py b/release/scripts/op/add_mesh_torus.py index 685f1cae8a4..372afb3654f 100644 --- a/release/scripts/op/add_mesh_torus.py +++ b/release/scripts/op/add_mesh_torus.py @@ -127,13 +127,11 @@ class AddTorus(bpy.types.Operator): # Register the operator bpy.types.register(AddTorus) -# Add to a menu -import dynamic_menu - +# Add to the menu menu_func = (lambda self, context: self.layout.operator(AddTorus.bl_idname, text="Torus", icon='MESH_DONUT')) -menu_item = dynamic_menu.add(bpy.types.INFO_MT_mesh_add, menu_func) +bpy.types.INFO_MT_mesh_add.append(menu_func) if __name__ == "__main__": bpy.ops.mesh.primitive_torus_add() diff --git a/release/scripts/op/mesh_skin.py b/release/scripts/op/mesh_skin.py index 251cfb32b93..d442717afbf 100644 --- a/release/scripts/op/mesh_skin.py +++ b/release/scripts/op/mesh_skin.py @@ -650,8 +650,7 @@ class MESH_OT_skin(bpy.types.Operator): bpy.types.register(MESH_OT_skin) # Add to a menu -import dynamic_menu -menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_edit_mesh_faces, (lambda self, context: self.layout.operator("mesh.skin", text="Bridge Faces")) ) +bpy.types.VIEW3D_MT_edit_mesh_faces.append((lambda self, context: self.layout.operator("mesh.skin", text="Bridge Faces"))) if __name__ == "__main__": bpy.ops.mesh.skin() diff --git a/release/scripts/op/uvcalc_follow_active.py b/release/scripts/op/uvcalc_follow_active.py index 8ab5b8ec454..41f97f9cca5 100644 --- a/release/scripts/op/uvcalc_follow_active.py +++ b/release/scripts/op/uvcalc_follow_active.py @@ -262,11 +262,8 @@ class FollowActiveQuads(bpy.types.Operator): bpy.types.register(FollowActiveQuads) # Add to a menu -import dynamic_menu - menu_func = (lambda self, context: self.layout.operator(FollowActiveQuads.bl_idname)) - -menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_uv_map, menu_func) +bpy.types.VIEW3D_MT_uv_map.append(menu_func) if __name__ == '__main__': bpy.ops.uv.follow_active_quads() diff --git a/release/scripts/op/uvcalc_smart_project.py b/release/scripts/op/uvcalc_smart_project.py index 25840e04cf8..6da6020f85b 100644 --- a/release/scripts/op/uvcalc_smart_project.py +++ b/release/scripts/op/uvcalc_smart_project.py @@ -1135,13 +1135,10 @@ class SmartProject(bpy.types.Operator): bpy.types.register(SmartProject) # Add to a menu -import dynamic_menu - menu_func = (lambda self, context: self.layout.operator(SmartProject.bl_idname, text="Smart Project")) -menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_uv_map, menu_func) +bpy.types.VIEW3D_MT_uv_map.append(menu_func) if __name__ == '__main__': bpy.ops.uv.smart_project() - diff --git a/release/scripts/templates/operator.py b/release/scripts/templates/operator.py index 9402a931db8..f175ca06f28 100644 --- a/release/scripts/templates/operator.py +++ b/release/scripts/templates/operator.py @@ -49,10 +49,8 @@ class ExportSomeData(bpy.types.Operator): bpy.types.register(ExportSomeData) # Only needed if you want to add into a dynamic menu -import dynamic_menu menu_func = lambda self, context: self.layout.operator("export.some_data", text="Example Exporter...") -menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) +bpy.types.INFO_MT_file_export.append(menu_func) -# Use for running this script directly if __name__ == "__main__": bpy.ops.export.some_data(path="/tmp/test.ply") diff --git a/release/scripts/ui/properties_data_armature_rigify.py b/release/scripts/ui/properties_data_armature_rigify.py index c0270d9b8ca..9423997151b 100644 --- a/release/scripts/ui/properties_data_armature_rigify.py +++ b/release/scripts/ui/properties_data_armature_rigify.py @@ -313,11 +313,7 @@ class ActiveClear(bpy.types.Operator): return {'FINISHED'} -import space_info -import dynamic_menu - - -class INFO_MT_armature_metarig_add(dynamic_menu.DynMenu): +class INFO_MT_armature_metarig_add(bpy.types.Menu): bl_idname = "INFO_MT_armature_metarig_add" bl_label = "Meta-Rig" @@ -349,5 +345,6 @@ bpy.types.register(ActiveClear) bpy.types.register(INFO_MT_armature_metarig_add) +import space_info menu_func = (lambda self, context: self.layout.menu("INFO_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE')) -menu_item = dynamic_menu.add(bpy.types.INFO_MT_armature_add, menu_func) +space_info.INFO_MT_armature_add.append(menu_func) diff --git a/release/scripts/ui/space_info.py b/release/scripts/ui/space_info.py index 1f7ba15de61..3f35bbc06d8 100644 --- a/release/scripts/ui/space_info.py +++ b/release/scripts/ui/space_info.py @@ -19,9 +19,6 @@ # import bpy -import dynamic_menu -# reload(dynamic_menu) - class INFO_HT_header(bpy.types.Header): bl_space_type = 'INFO' @@ -115,21 +112,8 @@ class INFO_MT_file(bpy.types.Menu): layout.operator_context = 'EXEC_AREA' layout.operator("wm.exit_blender", text="Quit", icon='QUIT') -# test for expanding menus -''' -class INFO_MT_file_more(INFO_MT_file): - bl_label = "File" - def draw(self, context): - layout = self.layout - - layout.operator("wm.read_homefile", text="TESTING ") - -dynamic_menu.setup(INFO_MT_file_more) -''' - - -class INFO_MT_file_import(dynamic_menu.DynMenu): +class INFO_MT_file_import(bpy.types.Menu): bl_idname = "INFO_MT_file_import" bl_label = "Import" @@ -138,7 +122,7 @@ class INFO_MT_file_import(dynamic_menu.DynMenu): self.layout.operator("wm.collada_import", text="COLLADA (.dae)...") -class INFO_MT_file_export(dynamic_menu.DynMenu): +class INFO_MT_file_export(bpy.types.Menu): bl_idname = "INFO_MT_file_export" bl_label = "Export" @@ -164,7 +148,7 @@ class INFO_MT_file_external_data(bpy.types.Menu): layout.operator("file.find_missing_files") -class INFO_MT_mesh_add(dynamic_menu.DynMenu): +class INFO_MT_mesh_add(bpy.types.Menu): bl_idname = "INFO_MT_mesh_add" bl_label = "Mesh" @@ -183,7 +167,7 @@ class INFO_MT_mesh_add(dynamic_menu.DynMenu): layout.operator("mesh.primitive_monkey_add", icon='MESH_MONKEY', text="Monkey") -class INFO_MT_armature_add(dynamic_menu.DynMenu): +class INFO_MT_armature_add(bpy.types.Menu): bl_idname = "INFO_MT_armature_add" bl_label = "Armature" diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index 26f2953be40..831b900579a 100644 --- a/release/scripts/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py @@ -18,7 +18,6 @@ # import bpy -import dynamic_menu class VIEW3D_HT_header(bpy.types.Header): @@ -205,7 +204,7 @@ class VIEW3D_MT_snap(bpy.types.Menu): layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active") -class VIEW3D_MT_uv_map(dynamic_menu.DynMenu): +class VIEW3D_MT_uv_map(bpy.types.Menu): bl_label = "UV Mapping" def draw(self, context): @@ -1231,7 +1230,7 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu): layout.operator("mesh.region_to_loop") -class VIEW3D_MT_edit_mesh_faces(dynamic_menu.DynMenu): +class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu): bl_label = "Faces" bl_idname = "VIEW3D_MT_edit_mesh_faces" diff --git a/source/blender/python/sphinx_doc_gen.py b/source/blender/python/sphinx_doc_gen.py index 3c15c09403d..24910b911e4 100644 --- a/source/blender/python/sphinx_doc_gen.py +++ b/source/blender/python/sphinx_doc_gen.py @@ -27,8 +27,6 @@ This will generate python files in "./source/blender/python/doc/bpy/sphinx-in" Generate html docs by running... sphinx-build source/blender/python/doc/bpy/sphinx-in source/blender/python/doc/bpy/sphinx-out - - ''' # if you dont have graphvis installed ommit the --graph arg. @@ -75,7 +73,7 @@ def py_function_args(func): INVALID = py_function_args defaults = ([INVALID] * (len(names) - len(defaults))) + defaults - if names[0] == "self": + if names[0] in ("self", "cls"): # normal class function or classmethod del names[0] del defaults[0]