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 # ##### 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)