Merge from 2.5 r20991 through r21037
[blender.git] / release / ui / space_script.py
1 import sys
2 import os
3 import imp
4 # import glob
5 import bpy
6
7 operators = []
8
9 def register_op(opclass):
10     if (hasattr(bpy.ops, opclass.__name__)):
11         bpy.ops.remove(getattr(bpy.ops, opclass.__name__))
12
13     bpy.ops.add(opclass)
14
15     global operators
16     if opclass.__name__ not in operators:
17         operators.append(opclass.__name__)
18
19
20 # hint for myself: for interface api documentation, see source/blender/editors/interface/interface_api.c
21 # another hint: reloading ui scripts in scripts window is Shift + P
22
23 class SCRIPT_HT_header(bpy.types.Header):
24         __space_type__ = "SCRIPTS_WINDOW"
25         __idname__ = "SCRIPT_HT_header"
26
27         def draw(self, context):
28                 st = context.space_data
29                 layout = self.layout
30
31                 layout.template_header(context)
32
33                 if context.area.show_menus:
34                         row = layout.row(align=True)
35                         row.itemM(context, "SCRIPT_MT_scripts")
36
37 class SCRIPT_MT_scripts(bpy.types.Menu):
38     __space_type__ = "SCRIPTS_WINDOW"
39     __label__ = "Scripts"
40
41     def draw(self, context):
42         layout = self.layout
43         layout.column()
44         layout.itemM(context, "SCRIPT_MT_export")
45         layout.itemO("SCRIPT_OT_reload_scripts")
46
47 class SCRIPT_MT_export(bpy.types.Menu):
48     __space_type__ = "SCRIPTS_WINDOW"
49     __label__ = "Export"
50
51     def draw(self, context):
52         global operators
53
54         print("drawing {0} operators: {1}".format(len(operators), operators))
55
56         layout = self.layout
57         layout.column()
58         for opname in operators:
59             layout.itemO(opname)
60
61 class SCRIPT_OT_reload_scripts(bpy.types.Operator):
62     __label__ = 'Reload Scripts'
63
64     def execute(self, context):
65         print("SCRIPT_OT_reload_scripts: execute")
66
67         # add ../io to sys.path
68
69         # this module's absolute path
70         abspath = os.path.abspath(sys.modules[__name__].__file__)
71         print("Current abspath: {0}".format(abspath))
72
73         # ../io
74         io = os.path.normpath(os.path.dirname(abspath) + "/../io")
75         print("abspath = " + io)
76
77         if io not in sys.path:
78             sys.path.append(io)
79
80         # for each .py file in release/io,
81         # import/reload module, in the module:
82         # find subclasses of bpy.types.Operator,
83         # for each subclass create menus under "Export"
84         # with (row.)itemO
85
86         global operators
87         operators = []
88
89         # glob unavailable :(
90 #         for path in glob.glob("../io/*.py"):
91         for path in os.listdir(io):
92             modname, ext = os.path.splitext(os.path.basename(path))
93
94             if ext != ".py":
95                 continue
96
97             print("Found module {0}.".format(modname))
98
99             if modname in sys.modules:
100                 mod = imp.reload(sys.modules[modname])
101                 print("Reloaded it.")
102             else:
103                 mod = __import__(modname)
104                 print("Imported it.")
105
106             for attr in dir(mod):
107                 cls = getattr(mod, attr)
108                 
109                 # XXX is there a better way to check that cls is a class?
110                 if type(cls) == bpy.types.Operator.__class__ and issubclass(cls, bpy.types.Operator):
111                     print("Found class {0}.".format(cls.__name__))
112                     register_op(cls)
113                     print("Registered it.")
114
115         return ('FINISHED',)
116
117     def invoke(self, context, event):
118         print("SCRIPT_OT_reload_scripts: invoke")
119         return self.execute(context)
120
121     def poll(self, context):
122         pass
123
124 bpy.types.register(SCRIPT_HT_header)
125 bpy.types.register(SCRIPT_MT_scripts)
126 bpy.types.register(SCRIPT_MT_export)
127
128 if (hasattr(bpy.ops, "SCRIPT_OT_reload_scripts")):
129     bpy.ops.remove(bpy.ops.SCRIPT_OT_reload_scripts)
130
131 bpy.ops.add(SCRIPT_OT_reload_scripts)
132