Blender V2.61 - r43446
|
00001 #!/usr/bin/env python 00002 00003 # ***** BEGIN GPL LICENSE BLOCK ***** 00004 # 00005 # This program is free software; you can redistribute it and/or 00006 # modify it under the terms of the GNU General Public License 00007 # as published by the Free Software Foundation; either version 2 00008 # of the License, or (at your option) any later version. 00009 # 00010 # This program is distributed in the hope that it will be useful, 00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 # GNU General Public License for more details. 00014 # 00015 # You should have received a copy of the GNU General Public License 00016 # along with this program; if not, write to the Free Software Foundation, 00017 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 # 00019 # Contributor(s): Campbell Barton 00020 # 00021 # ***** END GPL LICENSE BLOCK ***** 00022 00023 # <pep8 compliant> 00024 00025 # This script dumps ui definitions as XML. 00026 # useful for finding bad api usage. 00027 00028 # Example usage: 00029 # python intern/tools/bpy_introspect_ui.py 00030 00031 import sys 00032 ModuleType = type(sys) 00033 00034 00035 def module_add(name): 00036 mod = sys.modules[name] = ModuleType(name) 00037 return mod 00038 00039 00040 class AttributeBuilder(object): 00041 """__slots__ = ( 00042 "_attr", "_attr_list", "_item_set", "_args", 00043 "active", "operator_context", "enabled", "index", "data" 00044 )""" 00045 00046 def _as_py(self): 00047 data = [self._attr_single, self._args, [child._as_py() for child in self._attr_list]] 00048 return data 00049 00050 def _as_xml(self, indent=" "): 00051 00052 def to_xml_str(value): 00053 if type(value) == str: 00054 # quick shoddy clean 00055 value = value.replace("&", " ") 00056 value = value.replace("<", " ") 00057 value = value.replace(">", " ") 00058 00059 return '"' + value + '"' 00060 else: 00061 return '"' + str(value) + '"' 00062 00063 def dict_to_kw(args, dict_args): 00064 args_str = "" 00065 if args: 00066 # args_str += " ".join([to_xml_str(a) for a in args]) 00067 for i, a in enumerate(args): 00068 args_str += "arg" + str(i + 1) + "=" + to_xml_str(a) + " " 00069 00070 if dict_args: 00071 args_str += " ".join(["%s=%s" % (key, to_xml_str(value)) for key, value in sorted(dict_args.items())]) 00072 00073 if args_str: 00074 return " " + args_str 00075 00076 return "" 00077 00078 lines = [] 00079 00080 def py_to_xml(item, indent_ctx): 00081 if item._attr_list: 00082 lines.append("%s<%s%s>" % (indent_ctx, item._attr_single, dict_to_kw(item._args_tuple, item._args))) 00083 for child in item._attr_list: 00084 # print(child._attr) 00085 py_to_xml(child, indent_ctx + indent) 00086 lines.append("%s</%s>" % (indent_ctx, item._attr_single)) 00087 else: 00088 lines.append("%s<%s%s/>" % (indent_ctx, item._attr_single, dict_to_kw(item._args_tuple, item._args))) 00089 00090 py_to_xml(self, indent) 00091 00092 return "\n".join(lines) 00093 00094 def __init__(self, attr, attr_single): 00095 self._attr = attr 00096 self._attr_single = attr_single 00097 self._attr_list = [] 00098 self._item_set = [] 00099 self._args = {} 00100 self._args_tuple = () 00101 00102 def __call__(self, *args, **kwargs): 00103 # print(self._attr, args, kwargs) 00104 self._args_tuple = args 00105 self._args = kwargs 00106 return self 00107 00108 def __getattr__(self, attr): 00109 attr_obj = NewAttr(self._attr + "." + attr, attr) 00110 self._attr_list.append(attr_obj) 00111 return attr_obj 00112 00113 # def __setattr__(self, attr, value): 00114 # setatte 00115 00116 def __getitem__(self, item): 00117 item_obj = NewAttr(self._attr + "[" + repr(item) + "]", item) 00118 self._item_set.append(item_obj) 00119 return item_obj 00120 00121 def __setitem__(self, item, value): 00122 pass # TODO? 00123 00124 def __repr__(self): 00125 return self._attr 00126 00127 def __iter__(self): 00128 return iter([]) 00129 00130 #def __len__(self): 00131 # return 0 00132 00133 def __int__(self): 00134 return 0 00135 00136 def __cmp__(self, other): 00137 return -1 00138 00139 def __lt__(self, other): 00140 return -1 00141 00142 def __gt__(self, other): 00143 return -1 00144 00145 def __le__(self, other): 00146 return -1 00147 00148 def __add__(self, other): 00149 return self 00150 00151 def __sub__(self, other): 00152 return self 00153 00154 # Custom functions 00155 def lower(self): 00156 return "" 00157 00158 def upper(self): 00159 return "" 00160 00161 def keys(self): 00162 return [] 00163 00164 00165 def NewAttr(attr, attr_single): 00166 obj = AttributeBuilder(attr, attr_single) 00167 return obj 00168 00169 00170 class BaseFakeUI(): 00171 def __init__(self): 00172 self.layout = NewAttr("self.layout", "layout") 00173 00174 00175 class Panel(BaseFakeUI): 00176 pass 00177 00178 00179 class Header(BaseFakeUI): 00180 pass 00181 00182 00183 class Menu(BaseFakeUI): 00184 def draw_preset(self, context): 00185 pass 00186 00187 def path_menu(self, a, b, c): 00188 pass 00189 00190 00191 class Operator(BaseFakeUI): 00192 pass 00193 00194 00195 class PropertyGroup(): 00196 pass 00197 00198 00199 # setup fake module 00200 def fake_main(): 00201 bpy = module_add("bpy") 00202 00203 bpy.types = module_add("bpy.types") 00204 bpy.types.Panel = Panel 00205 bpy.types.Header = Header 00206 bpy.types.Menu = Menu 00207 bpy.types.PropertyGroup = PropertyGroup 00208 bpy.types.Operator = Operator 00209 00210 bpy.types.Armature = type("Armature", (), {}) 00211 bpy.types.Bone = type("Bone", (), {}) 00212 bpy.types.EditBone = type("EditBone", (), {}) 00213 bpy.types.PoseBone = type("PoseBone", (), {}) 00214 bpy.types.Material = type("Material", (), {}) 00215 bpy.types.Lamp = type("Lamp", (), {}) 00216 bpy.types.Camera = type("Camera", (), {}) 00217 bpy.types.Curve = type("Curve", (), {}) 00218 bpy.types.Lattice = type("Lattice", (), {}) 00219 bpy.types.Mesh = type("Mesh", (), {}) 00220 bpy.types.MetaBall = type("MetaBall", (), {}) 00221 bpy.types.Object = type("Object", (), {}) 00222 bpy.types.Texture = type("Texture", (), {}) 00223 bpy.types.ParticleSettings = type("ParticleSettings", (), {}) 00224 bpy.types.World = type("World", (), {}) 00225 bpy.types.Brush = type("Brush", (), {}) 00226 bpy.types.WindowManager = type("WindowManager", (), {}) 00227 bpy.types.Scene = type("Scene", (), {}) 00228 bpy.types.Scene.EnumProperty = NewAttr("bpy.types.Scene.EnumProperty", "EnumProperty") 00229 bpy.types.Scene.StringProperty = NewAttr("bpy.types.Scene.StringProperty", "StringProperty") 00230 00231 bpy.props = module_add("bpy.props") 00232 bpy.props.StringProperty = dict 00233 bpy.props.BoolProperty = dict 00234 bpy.props.IntProperty = dict 00235 bpy.props.EnumProperty = dict 00236 00237 bpy.data = module_add("bpy.data") 00238 bpy.data.scenes = () 00239 bpy.data.groups = () 00240 bpy.data.meshes = () 00241 bpy.data.shape_keys = () 00242 bpy.data.materials = () 00243 bpy.data.lamps = () 00244 bpy.data.textures = () 00245 bpy.data.cameras = () 00246 bpy.data.curves = () 00247 bpy.data.metaballs = () 00248 bpy.data.armatures = () 00249 bpy.data.particles = () 00250 00251 bpy.data.file_is_saved = True 00252 00253 bpy.utils = module_add("bpy.utils") 00254 bpy.utils.smpte_from_frame = lambda f: "" 00255 bpy.utils.script_paths = lambda f: [] 00256 00257 bpy.app = module_add("bpy.app") 00258 bpy.app.debug = False 00259 bpy.app.version = 2, 55, 1 00260 00261 bpy.path = module_add("bpy.path") 00262 bpy.path.display_name = lambda f: "" 00263 00264 00265 def fake_helper(): 00266 00267 class PropertyPanel(): 00268 pass 00269 00270 rna_prop_ui = module_add("rna_prop_ui") 00271 rna_prop_ui.PropertyPanel = PropertyPanel 00272 rna_prop_ui.draw = NewAttr("rna_prop_ui.draw", "draw") 00273 00274 rigify = module_add("rigify") 00275 rigify.get_submodule_types = lambda: [] 00276 00277 00278 fake_main() 00279 fake_helper() 00280 00281 import bpy 00282 00283 sys.path.insert(0, "/b/release/scripts/ui/") 00284 00285 00286 def module_classes(mod): 00287 classes = [] 00288 for value in mod.__dict__.values(): 00289 try: 00290 is_subclass = issubclass(value, BaseFakeUI) 00291 except: 00292 is_subclass = False 00293 00294 if is_subclass: 00295 classes.append(value) 00296 00297 return classes 00298 00299 00300 def main(): 00301 import os 00302 00303 base = os.path.join(os.path.dirname(__file__), "..", "..") 00304 base = os.path.normpath(base) 00305 base = os.path.abspath(base) 00306 00307 scripts_dir = os.path.join(base, "release", "scripts", "ui") 00308 for f in sorted(os.listdir(scripts_dir)): 00309 if f.endswith(".py"): 00310 # print(f) 00311 mod = __import__(f[:-3]) 00312 00313 classes = module_classes(mod) 00314 00315 for cls in classes: 00316 setattr(bpy.types, cls.__name__, cls) 00317 00318 # print("running...") 00319 print("<ui>") 00320 for f in sorted(os.listdir(scripts_dir)): 00321 if f.endswith(".py"): 00322 # print(f) 00323 mod = __import__(f[:-3]) 00324 00325 classes = module_classes(mod) 00326 00327 for cls in classes: 00328 # want to check if the draw function is directly in the class 00329 # print("draw") 00330 if "draw" in cls.__dict__: 00331 self = cls() 00332 self.draw(NewAttr("context", "context")) 00333 # print(self.layout._as_py()) 00334 self.layout._args['id'] = mod.__name__ + "." + cls.__name__ 00335 print(self.layout._as_xml()) 00336 print("</ui>") 00337 00338 00339 if __name__ == "__main__": 00340 main()