# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### # # for slightly faster access from _bpy import ops as ops_module # op_add = ops_module.add op_dir = ops_module.dir op_poll = ops_module.poll op_call = ops_module.call op_as_string = ops_module.as_string op_get_rna = ops_module.get_rna op_get_instance = ops_module.get_instance class BPyOps(object): """ Fake module like class. bpy.ops """ def __getattr__(self, module): """ gets a bpy.ops submodule """ if module.startswith('__'): raise AttributeError(module) return BPyOpsSubMod(module) def __dir__(self): submodules = set() # add this classes functions for id_name in dir(self.__class__): if not id_name.startswith('__'): submodules.add(id_name) for id_name in op_dir(): id_split = id_name.split('_OT_', 1) if len(id_split) == 2: submodules.add(id_split[0].lower()) else: submodules.add(id_split[0]) return list(submodules) def __repr__(self): return "" class BPyOpsSubMod(object): """ Utility class to fake submodules. eg. bpy.ops.object """ __keys__ = ("module",) def __init__(self, module): self.module = module def __getattr__(self, func): """ gets a bpy.ops.submodule function """ if func.startswith('__'): raise AttributeError(func) return BPyOpsSubModOp(self.module, func) def __dir__(self): functions = set() module_upper = self.module.upper() for id_name in op_dir(): id_split = id_name.split('_OT_', 1) if len(id_split) == 2 and module_upper == id_split[0]: functions.add(id_split[1]) return list(functions) def __repr__(self): return "" % self.module class BPyOpsSubModOp(object): """ Utility class to fake submodule operators. eg. bpy.ops.object.somefunc """ __keys__ = ("module", "func") def _get_doc(self): return op_as_string(self.idname()) @staticmethod def _parse_args(args): C_dict = None C_exec = 'EXEC_DEFAULT' C_undo = False is_dict = is_exec = is_undo = False for i, arg in enumerate(args): if is_dict is False and isinstance(arg, dict): if is_exec is True or is_undo is True: raise ValueError("dict arg must come first") C_dict = arg is_dict = True elif is_exec is False and isinstance(arg, str): if is_undo is True: raise ValueError("string arg must come before the boolean") C_exec = arg is_exec = True elif is_undo is False and isinstance(arg, int): C_undo = arg is_undo = True else: raise ValueError("1-3 args execution context is supported") return C_dict, C_exec, C_undo @staticmethod def _scene_update(context): scene = context.scene if scene: # None in background mode scene.update() else: import bpy for scene in bpy.data.scenes: scene.update() __doc__ = property(_get_doc) def __init__(self, module, func): self.module = module self.func = func def poll(self, *args): C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args) return op_poll(self.idname_py(), C_dict, C_exec) def idname(self): # submod.foo -> SUBMOD_OT_foo return self.module.upper() + "_OT_" + self.func def idname_py(self): # submod.foo -> SUBMOD_OT_foo return self.module + "." + self.func def __call__(self, *args, **kw): import bpy context = bpy.context # Get the operator from blender wm = context.window_manager # run to account for any rna values the user changes. BPyOpsSubModOp._scene_update(context) if args: C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args) ret = op_call(self.idname_py(), C_dict, kw, C_exec, C_undo) else: ret = op_call(self.idname_py(), None, kw) if 'FINISHED' in ret and context.window_manager == wm: BPyOpsSubModOp._scene_update(context) return ret def get_rna(self): """Internal function for introspection""" return op_get_rna(self.idname()) def get_instance(self): """Internal function for introspection""" return op_get_instance(self.idname()) def __repr__(self): # useful display, repr(op) import bpy idname = self.idname() as_string = op_as_string(idname) op_class = getattr(bpy.types, idname) descr = op_class.bl_rna.description # XXX, workaround for not registering # every __doc__ to save time on load. if not descr: descr = op_class.__doc__ if not descr: descr = "" return "# %s\n%s" % (descr, as_string) def __str__(self): # used for print(...) return ("" % (self.module, self.func, id(self))) ops_fake_module = BPyOps()