55df062ac83be1df9c075c109ed6507755bdecc5
[blender-staging.git] / release / scripts / modules / bpy_ops.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8-80 compliant>
20
21 # for slightly faster access
22 from bpy.__ops__ import add        as op_add
23 from bpy.__ops__ import remove     as op_remove
24 from bpy.__ops__ import dir        as op_dir
25 from bpy.__ops__ import call       as op_call
26 from bpy.__ops__ import as_string  as op_as_string
27 from bpy.__ops__ import get_rna    as op_get_rna
28
29 # Keep in sync with WM_types.h
30 context_dict = {
31     'INVOKE_DEFAULT': 0,
32     'INVOKE_REGION_WIN': 1,
33     'INVOKE_AREA': 2,
34     'INVOKE_SCREEN': 3,
35     'EXEC_DEFAULT': 4,
36     'EXEC_REGION_WIN': 5,
37     'EXEC_AREA': 6,
38     'EXEC_SCREEN': 7,
39 }
40
41
42 class bpy_ops(object):
43     '''
44     Fake module like class.
45
46      bpy.ops
47     '''
48
49     def __getattr__(self, module):
50         '''
51         gets a bpy.ops submodule
52         '''
53         if module.startswith('__'):
54             raise AttributeError(module)
55         return bpy_ops_submodule(module)
56
57     def add(self, pyop):
58         op_add(pyop)
59
60     def remove(self, pyop):
61         op_remove(pyop)
62
63     def __dir__(self):
64
65         submodules = set()
66
67         # add this classes functions
68         for id_name in dir(self.__class__):
69             if not id_name.startswith('__'):
70                 submodules.add(id_name)
71
72         for id_name in op_dir():
73             id_split = id_name.split('_OT_', 1)
74
75             if len(id_split) == 2:
76                 submodules.add(id_split[0].lower())
77             else:
78                 submodules.add(id_split[0])
79
80         return list(submodules)
81
82     def __repr__(self):
83         return "<module like class 'bpy.ops'>"
84
85
86 class bpy_ops_submodule(object):
87     '''
88     Utility class to fake submodules.
89
90     eg. bpy.ops.object
91     '''
92     __keys__ = ('module',)
93
94     def __init__(self, module):
95         self.module = module
96
97     def __getattr__(self, func):
98         '''
99         gets a bpy.ops.submodule function
100         '''
101         if func.startswith('__'):
102             raise AttributeError(func)
103         return bpy_ops_submodule_op(self.module, func)
104
105     def __dir__(self):
106
107         functions = set()
108
109         module_upper = self.module.upper()
110
111         for id_name in op_dir():
112             id_split = id_name.split('_OT_', 1)
113             if len(id_split) == 2 and module_upper == id_split[0]:
114                 functions.add(id_split[1])
115
116         return list(functions)
117
118     def __repr__(self):
119         return "<module like class 'bpy.ops.%s'>" % self.module
120
121
122 class bpy_ops_submodule_op(object):
123     '''
124     Utility class to fake submodule operators.
125
126     eg. bpy.ops.object.somefunc
127     '''
128
129     __keys__ = ('module', 'func')
130
131     def __init__(self, module, func):
132         self.module = module
133         self.func = func
134
135     def idname(self):
136         # submod.foo -> SUBMOD_OT_foo
137         return self.module.upper() + '_OT_' + self.func
138
139     def __call__(self, *args, **kw):
140
141         # Get the operator from blender
142         if len(args) > 2:
143             raise ValueError("1 or 2 args execution context is supported")
144
145         C_dict = None
146
147         if args:
148
149             C_exec = 'EXEC_DEFAULT'
150
151             if len(args) == 2:
152                 C_exec = args[0]
153                 C_dict = args[1]
154             else:
155                 if type(args[0]) != str:
156                     C_dict = args[0]
157                 else:
158                     C_exec = args[0]
159
160             try:
161                 context = context_dict[C_exec]
162             except:
163                 raise ValueError("Expected a single context argument in: " + \
164                  str(list(context_dict.keys())))
165
166             if len(args) == 2:
167                 C_dict = args[1]
168
169             return op_call(self.idname(), C_dict, kw, context)
170
171         else:
172             return op_call(self.idname(), C_dict, kw)
173
174     def get_rna(self):
175         '''
176         currently only used for 'bl_rna'
177         '''
178         return op_get_rna(self.idname())
179
180     def __repr__(self): # useful display, repr(op)
181         return op_as_string(self.idname())
182
183     def __str__(self): # used for print(...)
184         return "<function bpy.ops.%s.%s at 0x%x'>" % \
185                 (self.module, self.func, id(self))
186
187 import bpy
188 bpy.ops = bpy_ops()