forked from bartvdbraak/blender
replace dynamic_menu.py with Menu classmethods much less complicated.
access append/prepend eg. bpy.types.INFO_MT_file_import.append(lambda self, context: self.layout.operator("import_some.format"))
This commit is contained in:
parent
695677914a
commit
5afd084513
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
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('<menuclass>', (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)
|
||||
'''
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -19,9 +19,6 @@
|
||||
# <pep8 compliant>
|
||||
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"
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
# <pep8 compliant>
|
||||
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"
|
||||
|
||||
|
@ -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]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user