Skip to content
Snippets Groups Projects
Select Git revision
  • 5e7debcecf9abfd3ac441d5e5fd8cfca69c5dc34
  • master default protected
  • blender2.8
  • collada
  • topbar
  • greasepencil-object
  • temp-modifier-rm-cddm
  • blender2.8-workbench
  • hair_guides
  • fracture_modifier
  • temp-tab_drag_drop
  • asset-engine
  • soc-2017-normal-tools
  • cycles_embree
  • userpref_redesign
  • fluid-mantaflow
  • blender-v2.79b-release
  • cycles_embree3
  • temp-object-multi-mode
  • cycles_bvh8
  • blender-v2.79a-release
  • v2.79b
  • v2.79a
  • v2.79
  • v2.79-rc2
  • v2.79-rc1
  • v2.78c
  • v2.78b
  • v2.78a
  • v2.78
  • v2.78-rc2
  • v2.78-rc1
  • v2.77a
  • v2.77
  • v2.77-rc2
  • v2.77-rc1
  • v2.76b
  • v2.76a
  • v2.76
  • v2.76-rc3
  • v2.76-rc2
41 results

dynamic_menu.py

Blame
  • dynamic_menu.py 3.12 KiB
    # ##### 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('<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)
    '''