Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dynamic_menu.py « modules « scripts « release - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ce51dc9937b68946306c54d6b7ccaf09607a4eab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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)
'''