Blender V2.61 - r43446

bl_mesh_modifiers.py

Go to the documentation of this file.
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 # ##### END GPL LICENSE BLOCK #####
00018 
00019 # <pep8 compliant>
00020 
00021 # Currently this script only generates images from different modifier
00022 # combinations and does not validate they work correctly,
00023 # this is because we dont get 1:1 match with bmesh.
00024 #
00025 # Later, we may have a way to check the results are valid.
00026 
00027 
00028 # ./blender.bin --factory-startup --python source/tests/bl_mesh_modifiers.py
00029 #
00030 
00031 import math
00032 
00033 USE_QUICK_RENDER = False
00034 
00035 
00036 # -----------------------------------------------------------------------------
00037 # utility funcs
00038 
00039 def render_gl(context, filepath, shade):
00040 
00041     def ctx_viewport_shade(context, shade):
00042         for area in context.window.screen.areas:
00043             if area.type == 'VIEW_3D':
00044                 space = area.spaces.active
00045                 # rv3d = space.region_3d
00046                 space.viewport_shade = shade
00047 
00048     import bpy
00049     scene = context.scene
00050     render = scene.render
00051     render.filepath = filepath
00052     render.image_settings.file_format = 'PNG'
00053     render.image_settings.color_mode = 'RGB'
00054     render.use_file_extension = True
00055     render.use_antialiasing = False
00056 
00057     # render size
00058     render.resolution_percentage = 100
00059     render.resolution_x = 512
00060     render.resolution_y = 512
00061 
00062     ctx_viewport_shade(context, shade)
00063 
00064     bpy.ops.render.opengl(write_still=True,
00065                           view_context=True)
00066 
00067 
00068     # stop to inspect!
00069     #~ if filepath == "test_cube_like_subsurf_single_wp_wire":
00070         #~ assert(0)
00071 
00072 
00073 def render_gl_all_modes(context, obj, filepath=""):
00074 
00075     assert(obj != None)
00076     assert(filepath != "")
00077 
00078     scene = context.scene
00079 
00080     # avoid drawing outline/center dot
00081     bpy.ops.object.select_all(action='DESELECT')
00082     scene.objects.active = None
00083 
00084     # editmode
00085     scene.tool_settings.mesh_select_mode = False, True, False
00086 
00087     # render
00088     render_gl(context, filepath + "_ob_solid", shade='SOLID')
00089 
00090     if USE_QUICK_RENDER:
00091         return
00092 
00093     render_gl(context, filepath + "_ob_wire", shade='WIREFRAME')
00094     render_gl(context, filepath + "_ob_textured", shade='TEXTURED')
00095 
00096     # -------------------------------------------------------------------------
00097     # not just draw modes, but object modes!
00098     scene.objects.active = obj
00099 
00100     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
00101     bpy.ops.mesh.select_all(action='DESELECT')
00102     render_gl(context, filepath + "_edit_wire", shade='WIREFRAME')
00103     render_gl(context, filepath + "_edit_solid", shade='SOLID')
00104     render_gl(context, filepath + "_edit_textured", shade='TEXTURED')
00105     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
00106 
00107     bpy.ops.object.mode_set(mode='WEIGHT_PAINT', toggle=False)
00108 
00109     render_gl(context, filepath + "_wp_wire", shade='WIREFRAME')
00110 
00111     assert(1)
00112 
00113     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
00114 
00115     scene.objects.active = None
00116 
00117 
00118 def ctx_clear_scene():  # copied from batch_import.py
00119     import bpy
00120     unique_obs = set()
00121     for scene in bpy.data.scenes:
00122         for obj in scene.objects[:]:
00123             scene.objects.unlink(obj)
00124             unique_obs.add(obj)
00125 
00126     # remove obdata, for now only worry about the startup scene
00127     for bpy_data_iter in (bpy.data.objects,
00128                           bpy.data.meshes,
00129                           bpy.data.lamps,
00130                           bpy.data.cameras,
00131                           ):
00132 
00133         for id_data in bpy_data_iter:
00134             bpy_data_iter.remove(id_data)
00135 
00136 
00137 def ctx_viewport_camera(context):
00138     # because gl render without view_context has no shading option.
00139     for area in context.window.screen.areas:
00140         if area.type == 'VIEW_3D':
00141             space = area.spaces.active
00142             space.region_3d.view_perspective = 'CAMERA'
00143 
00144 
00145 def ctx_camera_setup(context,
00146                      location=(0.0, 0.0, 0.0),
00147                      lookat=(0.0, 0.0, 0.0),
00148                      # most likely the followuing vars can be left as defaults
00149                      up=(0.0, 0.0, 1.0),
00150                      lookat_axis='-Z',
00151                      up_axis='Y',
00152                      ):
00153 
00154     camera = bpy.data.cameras.new(whoami())
00155     obj = bpy.data.objects.new(whoami(), camera)
00156 
00157     scene = context.scene
00158     scene.objects.link(obj)
00159     scene.camera = obj
00160 
00161     from mathutils import Vector, Matrix
00162 
00163     # setup transform
00164     view_vec = Vector(lookat) - Vector(location)
00165     rot_mat = view_vec.to_track_quat(lookat_axis, up_axis).to_matrix().to_4x4()
00166     tra_mat = Matrix.Translation(location)
00167 
00168     obj.matrix_world = tra_mat * rot_mat
00169 
00170     ctx_viewport_camera(context)
00171 
00172     return obj
00173 
00174 
00175 # -----------------------------------------------------------------------------
00176 # inspect functions
00177 
00178 import inspect
00179 
00180 
00181 # functions
00182 
00183 def whoami():
00184     return inspect.stack()[1][3]
00185 
00186 
00187 def whosdaddy():
00188     return inspect.stack()[2][3]
00189 
00190 
00191 # -----------------------------------------------------------------------------
00192 # models (defaults)
00193 
00194 def defaults_object(obj):
00195     obj.show_wire = True
00196 
00197     if obj.type == 'MESH':
00198         mesh = obj.data
00199         mesh.show_all_edges = True
00200 
00201         mesh.show_normal_vertex = True
00202 
00203         # lame!
00204         for face in mesh.faces:
00205             face.use_smooth = True
00206 
00207 
00208 def defaults_modifier(mod):
00209     mod.show_in_editmode = True
00210     mod.show_on_cage = True
00211 
00212 
00213 # -----------------------------------------------------------------------------
00214 # models (utils)
00215 
00216 def mesh_bounds(mesh):
00217     xmin = ymin = zmin = +100000000.0
00218     xmax = ymax = zmax = -100000000.0
00219 
00220     for v in mesh.vertices:
00221         x, y, z = v.co
00222         xmax = max(x, xmax)
00223         ymax = max(y, ymax)
00224         zmax = max(z, zmax)
00225 
00226         xmin = min(x, xmin)
00227         ymin = min(y, ymin)
00228         zmin = min(z, zmin)
00229 
00230     return (xmin, ymin, zmin), (xmax, ymax, zmax)
00231 
00232 
00233 def mesh_uv_add(obj):
00234     uv_lay = obj.data.uv_textures.new()
00235     for uv in uv_lay.data:
00236         uv.uv1 = 0.0, 0.0
00237         uv.uv2 = 0.0, 1.0
00238         uv.uv3 = 1.0, 1.0
00239         uv.uv4 = 1.0, 0.0
00240 
00241     return uv_lay
00242 
00243 
00244 def mesh_vcol_add(obj, mode=0):
00245     vcol_lay = obj.data.vertex_colors.new()
00246     for col in vcol_lay.data:
00247         col.color1 = 1.0, 0.0, 0.0
00248         col.color2 = 0.0, 1.0, 0.0
00249         col.color3 = 0.0, 0.0, 1.0
00250         col.color4 = 0.0, 0.0, 0.0
00251 
00252     return vcol_lay
00253 
00254 
00255 def mesh_vgroup_add(obj, name="Group", axis=0, invert=False, mode=0):
00256     mesh = obj.data
00257     vgroup = obj.vertex_groups.new(name=name)
00258     vgroup.add(list(range(len(mesh.vertices))), 1.0, 'REPLACE')
00259     group_index = len(obj.vertex_groups) - 1
00260 
00261     min_bb, max_bb = mesh_bounds(mesh)
00262 
00263     range_axis = max_bb[axis] - min_bb[axis]
00264 
00265     # gradient
00266     for v in mesh.vertices:
00267         for vg in v.groups:
00268             if vg.group == group_index:
00269                 f = (v.co[axis] - min_bb[axis]) / range_axis
00270                 vg.weight = 1.0 - f if invert else f
00271 
00272     return vgroup
00273 
00274 
00275 def mesh_shape_add(obj, mode=0):
00276     pass
00277 
00278 
00279 def mesh_armature_add(obj, mode=0):
00280     pass
00281 
00282 
00283 # -----------------------------------------------------------------------------
00284 # modifiers
00285 
00286 def modifier_subsurf_add(scene, obj, levels=2):
00287     mod = obj.modifiers.new(name=whoami(), type='SUBSURF')
00288     defaults_modifier(mod)
00289 
00290     mod.levels = levels
00291     mod.render_levels = levels
00292     return mod
00293 
00294 
00295 def modifier_armature_add(scene, obj):
00296     mod = obj.modifiers.new(name=whoami(), type='ARMATURE')
00297     defaults_modifier(mod)
00298 
00299     arm_data = bpy.data.armatures.new(whoami())
00300     obj_arm = bpy.data.objects.new(whoami(), arm_data)
00301 
00302     scene.objects.link(obj_arm)
00303 
00304     obj_arm.select = True
00305     scene.objects.active = obj_arm
00306 
00307     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
00308     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
00309 
00310     # XXX, annoying, remove bone.
00311     while arm_data.edit_bones:
00312         obj_arm.edit_bones.remove(arm_data.edit_bones[-1])
00313 
00314     bone_a = arm_data.edit_bones.new("Bone.A")
00315     bone_b = arm_data.edit_bones.new("Bone.B")
00316     bone_b.parent = bone_a
00317 
00318     bone_a.head = -1, 0, 0
00319     bone_a.tail = 0, 0, 0
00320     bone_b.head = 0, 0, 0
00321     bone_b.tail = 1, 0, 0
00322 
00323     # Get armature animation data
00324     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
00325 
00326     # 45d armature
00327     obj_arm.pose.bones["Bone.B"].rotation_quaternion = 1, -0.5, 0, 0
00328 
00329     # set back to the original
00330     scene.objects.active = obj
00331 
00332     # display options
00333     obj_arm.show_x_ray = True
00334     arm_data.draw_type = 'STICK'
00335 
00336     # apply to modifier
00337     mod.object = obj_arm
00338 
00339     mesh_vgroup_add(obj, name="Bone.A", axis=0, invert=True)
00340     mesh_vgroup_add(obj, name="Bone.B", axis=0, invert=False)
00341 
00342     return mod
00343 
00344 
00345 def modifier_mirror_add(scene, obj):
00346     mod = obj.modifiers.new(name=whoami(), type='MIRROR')
00347     defaults_modifier(mod)
00348 
00349     return mod
00350 
00351 
00352 def modifier_solidify_add(scene, obj, thickness=0.25):
00353     mod = obj.modifiers.new(name=whoami(), type='SOLIDIFY')
00354     defaults_modifier(mod)
00355 
00356     mod.thickness = thickness
00357 
00358     return mod
00359 
00360 
00361 def modifier_hook_add(scene, obj, use_vgroup=True):
00362     scene.objects.active = obj
00363 
00364     # no nice way to add hooks from py api yet
00365     # assume object mode, hook first face!
00366     mesh = obj.data
00367     
00368     if use_vgroup:
00369         for v in mesh.vertices:
00370             v.select = True
00371     else:
00372         for v in mesh.vertices:
00373             v.select = False
00374         for i in mesh.faces[0].vertices:
00375             mesh.vertices[i].select = True
00376 
00377     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
00378     bpy.ops.object.hook_add_newob()
00379     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
00380 
00381     # mod = obj.modifiers.new(name=whoami(), type='HOOK')
00382     mod = obj.modifiers[-1]
00383     defaults_modifier(mod)
00384 
00385     obj_hook = mod.object
00386     obj_hook.rotation_euler = 0, math.radians(45), 0
00387     obj_hook.show_x_ray = True
00388 
00389     if use_vgroup:
00390         mod.vertex_group = obj.vertex_groups[0].name
00391 
00392     return mod
00393 
00394 
00395 def modifier_decimate_add(scene, obj):
00396     mod = obj.modifiers.new(name=whoami(), type='DECIMATE')
00397     defaults_modifier(mod)
00398 
00399     mod.ratio = 1 / 3
00400 
00401     return mod
00402 
00403 
00404 def modifier_build_add(scene, obj):
00405     mod = obj.modifiers.new(name=whoami(), type='BUILD')
00406     defaults_modifier(mod)
00407 
00408     # ensure we display some faces
00409     totface = len(obj.data.faces)
00410     mod.frame_start = totface // 2
00411     mod.frame_duration = totface
00412 
00413     return mod
00414 
00415 
00416 def modifier_mask_add(scene, obj):
00417     mod = obj.modifiers.new(name=whoami(), type='MASK')
00418     defaults_modifier(mod)
00419 
00420     mod.vertex_group = obj.vertex_groups[0].name
00421 
00422     return mod
00423 
00424 
00425 # -----------------------------------------------------------------------------
00426 # models
00427 
00428 # useful since its solid boxy shape but simple enough to debug errors
00429 cube_like_vertices = (
00430     (1, 1, -1),
00431     (1, -1, -1),
00432     (-1, -1, -1),
00433     (-1, 1, -1),
00434     (1, 1, 1),
00435     (1, -1, 1),
00436     (-1, -1, 1),
00437     (-1, 1, 1),
00438     (0, -1, -1),
00439     (1, 0, -1),
00440     (0, 1, -1),
00441     (-1, 0, -1),
00442     (1, 0, 1),
00443     (0, -1, 1),
00444     (-1, 0, 1),
00445     (0, 1, 1),
00446     (1, -1, 0),
00447     (1, 1, 0),
00448     (-1, -1, 0),
00449     (-1, 1, 0),
00450     (0, 0, -1),
00451     (0, 0, 1),
00452     (1, 0, 0),
00453     (0, -1, 0),
00454     (-1, 0, 0),
00455     (2, 0, 0),
00456     (2, 0, -1),
00457     (2, 1, 0),
00458     (2, 1, -1),
00459     (0, 1, 2),
00460     (0, 0, 2),
00461     (-1, 0, 2),
00462     (-1, 1, 2),
00463     (-1, 0, 3),
00464     (-1, 1, 3),
00465     (0, 1, 3),
00466     (0, 0, 3),
00467     )
00468 
00469 
00470 cube_like_faces = (
00471     (0, 9, 20, 10),
00472     (0, 10, 17),
00473     (0, 17, 27, 28),
00474     (1, 16, 23, 8),
00475     (2, 18, 24, 11),
00476     (3, 19, 10),
00477     (4, 15, 21, 12),
00478     (4, 17, 15),
00479     (7, 14, 31, 32),
00480     (7, 15, 19),
00481     (8, 23, 18, 2),
00482     (9, 0, 28, 26),
00483     (9, 1, 8, 20),
00484     (9, 22, 16, 1),
00485     (10, 20, 11, 3),
00486     (11, 24, 19, 3),
00487     (12, 21, 13, 5),
00488     (13, 6, 18),
00489     (14, 21, 30, 31),
00490     (15, 7, 32, 29),
00491     (15, 17, 10, 19),
00492     (16, 5, 13, 23),
00493     (17, 4, 12, 22),
00494     (17, 22, 25, 27),
00495     (18, 6, 14, 24),
00496     (20, 8, 2, 11),
00497     (21, 14, 6, 13),
00498     (21, 15, 29, 30),
00499     (22, 9, 26, 25),
00500     (22, 12, 5, 16),
00501     (23, 13, 18),
00502     (24, 14, 7, 19),
00503     (28, 27, 25, 26),
00504     (29, 32, 34, 35),
00505     (30, 29, 35, 36),
00506     (31, 30, 36, 33),
00507     (32, 31, 33, 34),
00508     (35, 34, 33, 36),
00509     )
00510 
00511 
00512 # useful since its a shell for solidify and it can be mirrored
00513 cube_shell_vertices = (
00514     (0, 0, 1),
00515     (0, 1, 1),
00516     (-1, 1, 1),
00517     (-1, 0, 1),
00518     (0, 0, 0),
00519     (0, 1, 0),
00520     (-1, 1, 0),
00521     (-1, 0, 0),
00522     (-1, -1, 0),
00523     (0, -1, 0),
00524     (0, 0, -1),
00525     (0, 1, -1),
00526     )
00527 
00528 
00529 cube_shell_face = (
00530     (0, 1, 2, 3),
00531     (0, 3, 8, 9),
00532     (1, 5, 6, 2),
00533     (2, 6, 7, 3),
00534     (3, 7, 8),
00535     (4, 7, 10),
00536     (6, 5, 11),
00537     (7, 4, 9, 8),
00538     (10, 7, 6, 11),
00539     )
00540 
00541 
00542 def make_cube(scene):
00543     bpy.ops.mesh.primitive_cube_add(view_align=False,
00544                                     enter_editmode=False,
00545                                     location=(0, 0, 0),
00546                                     rotation=(0, 0, 0),
00547                                     )
00548 
00549     obj = scene.objects.active
00550 
00551     defaults_object(obj)
00552     return obj
00553 
00554 
00555 def make_cube_extra(scene):
00556     obj = make_cube(scene)
00557 
00558     # extra data layers
00559     mesh_uv_add(obj)
00560     mesh_vcol_add(obj)
00561     mesh_vgroup_add(obj)
00562 
00563     return obj
00564 
00565 
00566 def make_cube_like(scene):
00567     mesh = bpy.data.meshes.new(whoami())
00568 
00569     mesh.from_pydata(cube_like_vertices, (), cube_like_faces)
00570     mesh.update()  # add edges
00571     obj = bpy.data.objects.new(whoami(), mesh)
00572     scene.objects.link(obj)
00573 
00574     defaults_object(obj)
00575     return obj
00576 
00577 
00578 def make_cube_like_extra(scene):
00579     obj = make_cube_like(scene)
00580 
00581     # extra data layers
00582     mesh_uv_add(obj)
00583     mesh_vcol_add(obj)
00584     mesh_vgroup_add(obj)
00585 
00586     return obj
00587 
00588 
00589 def make_cube_shell(scene):
00590     mesh = bpy.data.meshes.new(whoami())
00591 
00592     mesh.from_pydata(cube_shell_vertices, (), cube_shell_face)
00593     mesh.update()  # add edges
00594     obj = bpy.data.objects.new(whoami(), mesh)
00595     scene.objects.link(obj)
00596 
00597     defaults_object(obj)
00598     return obj
00599 
00600 
00601 def make_cube_shell_extra(scene):
00602     obj = make_cube_shell(scene)
00603 
00604     # extra data layers
00605     mesh_uv_add(obj)
00606     mesh_vcol_add(obj)
00607     mesh_vgroup_add(obj)
00608 
00609     return obj
00610 
00611 
00612 def make_monkey(scene):
00613     bpy.ops.mesh.primitive_monkey_add(view_align=False,
00614                                       enter_editmode=False,
00615                                       location=(0, 0, 0),
00616                                       rotation=(0, 0, 0),
00617                                       )
00618     obj = scene.objects.active
00619 
00620     defaults_object(obj)
00621     return obj
00622 
00623 
00624 def make_monkey_extra(scene):
00625     obj = make_monkey(scene)
00626 
00627     # extra data layers
00628     mesh_uv_add(obj)
00629     mesh_vcol_add(obj)
00630     mesh_vgroup_add(obj)
00631 
00632     return obj
00633 
00634 
00635 # -----------------------------------------------------------------------------
00636 # tests (utils)
00637 
00638 global_tests = []
00639 
00640 global_tests.append(("none",
00641     (),
00642     ))
00643 
00644 # single
00645 global_tests.append(("subsurf_single",
00646     ((modifier_subsurf_add, dict(levels=2)), ),
00647     ))
00648 
00649 
00650 global_tests.append(("armature_single",
00651     ((modifier_armature_add, dict()), ),
00652     ))
00653 
00654 
00655 global_tests.append(("mirror_single",
00656     ((modifier_mirror_add, dict()), ),
00657     ))
00658 
00659 global_tests.append(("hook_single",
00660     ((modifier_hook_add, dict()), ),
00661     ))
00662 
00663 global_tests.append(("decimate_single",
00664     ((modifier_decimate_add, dict()), ),
00665     ))
00666 
00667 global_tests.append(("build_single",
00668     ((modifier_build_add, dict()), ),
00669     ))
00670 
00671 global_tests.append(("mask_single",
00672     ((modifier_mask_add, dict()), ),
00673     ))
00674 
00675 
00676 # combinations
00677 global_tests.append(("mirror_subsurf",
00678     ((modifier_mirror_add, dict()),
00679      (modifier_subsurf_add, dict(levels=2))),
00680     ))
00681 
00682 global_tests.append(("solidify_subsurf",
00683     ((modifier_solidify_add, dict()),
00684      (modifier_subsurf_add, dict(levels=2))),
00685     ))
00686 
00687 
00688 def apply_test(test, scene, obj,
00689                render_func=None,
00690                render_args=None,
00691                render_kwargs=None,
00692                ):
00693 
00694     test_name, test_funcs = test
00695 
00696     for cb, kwargs in test_funcs:
00697         cb(scene, obj, **kwargs)
00698 
00699     render_kwargs_copy = render_kwargs.copy()
00700 
00701     # add test name in filepath
00702     render_kwargs_copy["filepath"] += "_%s" % test_name
00703 
00704     render_func(*render_args, **render_kwargs_copy)
00705 
00706 
00707 # -----------------------------------------------------------------------------
00708 # tests themselves!
00709 # having the 'test_' prefix automatically means these functions are called
00710 # for testing
00711 
00712 
00713 def test_cube(context, test):
00714     scene = context.scene
00715     obj = make_cube_extra(scene)
00716     ctx_camera_setup(context, location=(3, 3, 3))
00717 
00718     apply_test(test, scene, obj,
00719                render_func=render_gl_all_modes,
00720                render_args=(context, obj),
00721                render_kwargs=dict(filepath=whoami()))
00722 
00723 
00724 def test_cube_like(context, test):
00725     scene = context.scene
00726     obj = make_cube_like_extra(scene)
00727     ctx_camera_setup(context, location=(5, 5, 5))
00728 
00729     apply_test(test, scene, obj,
00730                render_func=render_gl_all_modes,
00731                render_args=(context, obj),
00732                render_kwargs=dict(filepath=whoami()))
00733 
00734 
00735 def test_cube_shell(context, test):
00736     scene = context.scene
00737     obj = make_cube_shell_extra(scene)
00738     ctx_camera_setup(context, location=(4, 4, 4))
00739 
00740     apply_test(test, scene, obj,
00741                render_func=render_gl_all_modes,
00742                render_args=(context, obj),
00743                render_kwargs=dict(filepath=whoami()))
00744 
00745 
00746 # -----------------------------------------------------------------------------
00747 # call all tests
00748 
00749 def main():
00750     print("Calling main!")
00751     #render_gl(bpy.context, "/testme")
00752     #ctx_clear_scene()
00753 
00754     context = bpy.context
00755 
00756     ctx_clear_scene()
00757 
00758     # run all tests
00759     for key, val in sorted(globals().items()):
00760         if key.startswith("test_") and hasattr(val, "__call__"):
00761             print("calling:", key)
00762             for t in global_tests:
00763                 val(context, test=t)
00764                 ctx_clear_scene()
00765 
00766 
00767 # -----------------------------------------------------------------------------
00768 # annoying workaround for theme initialization
00769 
00770 if __name__ == "__main__":
00771     import bpy
00772     from bpy.app.handlers import persistent
00773 
00774     @persistent
00775     def load_handler(dummy):
00776         print("Load Handler:", bpy.data.filepath)
00777         if load_handler.first == False:
00778             bpy.app.handlers.scene_update_post.remove(load_handler)
00779             try:
00780                 main()
00781                 import sys
00782                 sys.exit(0)
00783             except:
00784                 import traceback
00785                 traceback.print_exc()
00786 
00787                 import sys
00788                 # sys.exit(1)  # comment to debug
00789 
00790         else:
00791             load_handler.first = False
00792 
00793     load_handler.first = True
00794     bpy.app.handlers.scene_update_post.append(load_handler)