Blender V2.61 - r43446
|
00001 # ***** BEGIN GPL LICENSE BLOCK ***** 00002 # 00003 # This program is free software; you can redistribute it and/or 00004 # modify it under the terms of the GNU General Public License 00005 # as published by the Free Software Foundation; either version 2 00006 # of the License, or (at your option) any later version. 00007 # 00008 # This program is distributed in the hope that it will be useful, 00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 # GNU General Public License for more details. 00012 # 00013 # You should have received a copy of the GNU General Public License 00014 # along with this program; if not, write to the Free Software Foundation, 00015 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00016 # 00017 # Contributor(s): Campbell Barton 00018 # 00019 # ***** END GPL LICENSE BLOCK ***** 00020 00021 # screenshot panels, corrently only works for render, scene and world. 00022 # needs some further work to setup blender contexts for all possible panels. 00023 00024 import os 00025 00026 REMOVE_CMP_IMAGES = True 00027 TEMP_DIR = "/tmp" 00028 00029 PROPERTY_MAPPING = { 00030 "armature_edit": 'DATA', 00031 "bone": 'BONE', 00032 "bone_constraint": '', 00033 "constraint": '', 00034 "curve_edit": '', 00035 "data": '', 00036 "imagepaint": '', 00037 "lattice_edit": 'DATA', 00038 "material": 'MATERIAL', 00039 "mball_edit": '', 00040 "mesh_edit": '', 00041 "modifier": '', 00042 "object": 'OBJECT', 00043 "objectmode": '', 00044 "particle": '', 00045 "particlemode": '', 00046 "physics": '', 00047 "posemode": '', # toolbar 00048 "render": 'RENDER', 00049 "scene": 'SCENE', 00050 "surface_edit": '', 00051 "text_edit": '', 00052 "texture": '', 00053 "vertexpaint": '', 00054 "weightpaint": '', 00055 "world": 'WORLD', 00056 } 00057 00058 # format: % (new, blank, out) 00059 magick_command = 'convert "%s" "%s" \( -clone 0 -clone 1 -compose difference -composite -threshold 0 \) -delete 1 -alpha off -compose copy_opacity -composite -trim "%s" ' 00060 00061 import bpy 00062 00063 00064 def clear_startup_blend(): 00065 import bpy 00066 if bpy.ops.object.mode_set.poll(): 00067 bpy.ops.object.mode_set(mode='OBJECT') 00068 00069 import bpy 00070 00071 for scene in bpy.data.scenes: 00072 for obj in scene.objects: 00073 scene.objects.unlink(obj) 00074 00075 00076 def force_redraw(): 00077 bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) 00078 00079 def fake_poll(cls, context): 00080 return True 00081 00082 def screenshot(path): 00083 force_redraw() 00084 bpy.ops.screen.screenshot(filepath=path) 00085 00086 def context_setup(bl_context, class_name): 00087 if bl_context == "object": 00088 bpy.ops.object.add(type='EMPTY') 00089 elif bl_context == "bone": 00090 bpy.ops.object.armature_add() 00091 bpy.ops.object.mode_set(mode='EDIT') 00092 elif bl_context == "armature_edit": 00093 bpy.ops.object.armature_add() 00094 bpy.ops.object.mode_set(mode='EDIT') 00095 elif bl_context == "posemode": 00096 bpy.ops.object.armature_add() 00097 bpy.ops.object.mode_set(mode='POSE') 00098 elif bl_context == "lattice_edit": 00099 bpy.ops.object.add(type='LATTICE') 00100 bpy.ops.object.mode_set(mode='EDIT') 00101 elif bl_context == "material": 00102 bpy.ops.object.add(type='MESH') 00103 bpy.context.object.data.materials.append(bpy.data.materials.new("Material")) 00104 bpy.ops.object.mode_set(mode='EDIT') 00105 00106 00107 def main(): 00108 panel_subclasses = [] 00109 00110 for cls_name in dir(bpy.types): 00111 cls = getattr(bpy.types, cls_name) 00112 if issubclass(cls, bpy.types.Panel): 00113 if bpy.types.Panel is cls: 00114 continue 00115 00116 panel_subclasses.append((cls, getattr(cls, "poll", None))) 00117 00118 for cls, poll in panel_subclasses: 00119 cls.poll = classmethod(fake_poll) 00120 cls.bl_options = set() # so we dont get 'DEFAULT_CLOSED' 00121 bpy.utils.unregister_class(cls) 00122 00123 # collect context types 00124 button_contexts = {None} 00125 for cls, poll in panel_subclasses: 00126 button_contexts.add(getattr(cls, "bl_context", None)) 00127 button_contexts.remove(None) 00128 00129 # get the properties space 00130 space_props = None 00131 for sa in bpy.context.screen.areas: 00132 space = sa.spaces.active 00133 if space.type == 'PROPERTIES': 00134 space_props = space 00135 break 00136 if space_props is None: 00137 raise Exception("no properties space type found") 00138 00139 for bl_context in sorted(button_contexts): 00140 print(list(sorted(button_contexts))) 00141 # TODO 00142 # if bl_context in PROPERTY_SKIP: 00143 # continue 00144 00145 ## TESTING ONLY 00146 #if bl_context != "material": 00147 # continue 00148 00149 prop_context = PROPERTY_MAPPING[bl_context] 00150 if not prop_context: 00151 print(" TODO, skipping", bl_context) 00152 continue 00153 00154 space_props.context = prop_context 00155 00156 for cls, poll in panel_subclasses: 00157 if cls.bl_space_type == 'PROPERTIES': 00158 if cls.bl_region_type == 'WINDOW': 00159 if cls.bl_context == bl_context: 00160 00161 clear_startup_blend() 00162 context_setup(bl_context, cls.__name__) 00163 00164 file_base = os.path.join(TEMP_DIR, "%s_%s" % (bl_context, "_" + cls.__name__.replace(".", "_"))) 00165 file_old = file_base + "_old.png" 00166 file_new = file_base + "_new.png" 00167 file_crop = file_base + ".png" 00168 00169 screenshot(file_old) 00170 00171 # we need a new unique name so old 'closed' settings dont get applied 00172 idname = getattr(cls, "bl_idname", cls.__name__.split(".")[-1]) 00173 cls.bl_idname = idname + "_" 00174 00175 bpy.utils.register_class(cls) 00176 00177 screenshot(file_new) 00178 00179 bpy.utils.unregister_class(cls) 00180 00181 # screenshot magic 00182 from os import system 00183 system(magick_command % (file_new, file_old, file_crop)) 00184 00185 if REMOVE_CMP_IMAGES: 00186 from os import remove 00187 remove(file_old) 00188 remove(file_new) 00189 00190 00191 if __name__ == "__main__": 00192 main()