bl_mesh_modifiers.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8 compliant>
  19. # Currently this script only generates images from different modifier
  20. # combinations and does not validate they work correctly,
  21. # this is because we don't get 1:1 match with bmesh.
  22. #
  23. # Later, we may have a way to check the results are valid.
  24. # ./blender.bin --factory-startup --python tests/python/bl_mesh_modifiers.py
  25. #
  26. import math
  27. USE_QUICK_RENDER = False
  28. # -----------------------------------------------------------------------------
  29. # utility functions
  30. def render_gl(context, filepath, shade):
  31. def ctx_shading_type(context, shade):
  32. for area in context.window.screen.areas:
  33. if area.type == 'VIEW_3D':
  34. space = area.spaces.active
  35. # rv3d = space.region_3d
  36. space.shading.type = shade
  37. import bpy
  38. scene = context.scene
  39. render = scene.render
  40. render.filepath = filepath
  41. render.image_settings.file_format = 'PNG'
  42. render.image_settings.color_mode = 'RGB'
  43. render.use_file_extension = True
  44. render.use_antialiasing = False
  45. # render size
  46. render.resolution_percentage = 100
  47. render.resolution_x = 512
  48. render.resolution_y = 512
  49. ctx_shading_type(context, shade)
  50. # stop to inspect!
  51. # if filepath == "test_cube_shell_solidify_subsurf_wp_wire":
  52. # assert(0)
  53. # else:
  54. # return
  55. bpy.ops.render.opengl(write_still=True,
  56. view_context=True)
  57. def render_gl_all_modes(context, obj, filepath=""):
  58. assert(obj is not None)
  59. assert(filepath != "")
  60. scene = context.scene
  61. # avoid drawing outline/center dot
  62. bpy.ops.object.select_all(action='DESELECT')
  63. scene.objects.active = None
  64. # editmode
  65. scene.tool_settings.mesh_select_mode = False, True, False
  66. # render
  67. render_gl(context, filepath + "_ob_solid", shade='SOLID')
  68. if USE_QUICK_RENDER:
  69. return
  70. render_gl(context, filepath + "_ob_wire", shade='WIREFRAME')
  71. render_gl(context, filepath + "_ob_textured", shade='TEXTURED')
  72. # -------------------------------------------------------------------------
  73. # not just draw modes, but object modes!
  74. scene.objects.active = obj
  75. bpy.ops.object.mode_set(mode='EDIT', toggle=False)
  76. bpy.ops.mesh.select_all(action='DESELECT')
  77. render_gl(context, filepath + "_edit_wire", shade='WIREFRAME')
  78. render_gl(context, filepath + "_edit_solid", shade='SOLID')
  79. render_gl(context, filepath + "_edit_textured", shade='TEXTURED')
  80. bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  81. bpy.ops.object.mode_set(mode='WEIGHT_PAINT', toggle=False)
  82. render_gl(context, filepath + "_wp_wire", shade='WIREFRAME')
  83. assert(1)
  84. bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  85. scene.objects.active = None
  86. def ctx_clear_scene(): # copied from batch_import.py
  87. import bpy
  88. unique_obs = set()
  89. for scene in bpy.data.scenes:
  90. for obj in scene.objects[:]:
  91. scene.objects.unlink(obj)
  92. unique_obs.add(obj)
  93. # remove obdata, for now only worry about the startup scene
  94. for bpy_data_iter in (bpy.data.objects,
  95. bpy.data.meshes,
  96. bpy.data.lights,
  97. bpy.data.cameras,
  98. ):
  99. for id_data in bpy_data_iter:
  100. bpy_data_iter.remove(id_data)
  101. def ctx_viewport_camera(context):
  102. # because gl render without view_context has no shading option.
  103. for area in context.window.screen.areas:
  104. if area.type == 'VIEW_3D':
  105. space = area.spaces.active
  106. space.region_3d.view_perspective = 'CAMERA'
  107. def ctx_camera_setup(context,
  108. location=(0.0, 0.0, 0.0),
  109. lookat=(0.0, 0.0, 0.0),
  110. # most likely the following vars can be left as defaults
  111. up=(0.0, 0.0, 1.0),
  112. lookat_axis='-Z',
  113. up_axis='Y',
  114. ):
  115. camera = bpy.data.cameras.new(whoami())
  116. obj = bpy.data.objects.new(whoami(), camera)
  117. scene = context.scene
  118. scene.objects.link(obj)
  119. scene.camera = obj
  120. from mathutils import Vector, Matrix
  121. # setup transform
  122. view_vec = Vector(lookat) - Vector(location)
  123. rot_mat = view_vec.to_track_quat(lookat_axis, up_axis).to_matrix().to_4x4()
  124. tra_mat = Matrix.Translation(location)
  125. obj.matrix_world = tra_mat * rot_mat
  126. ctx_viewport_camera(context)
  127. return obj
  128. # -----------------------------------------------------------------------------
  129. # inspect functions
  130. import inspect
  131. # functions
  132. def whoami():
  133. return inspect.stack()[1][3]
  134. def whosdaddy():
  135. return inspect.stack()[2][3]
  136. # -----------------------------------------------------------------------------
  137. # models (defaults)
  138. def defaults_object(obj):
  139. obj.show_wire = True
  140. if obj.type == 'MESH':
  141. obj.show_all_edges = True
  142. mesh = obj.data
  143. mesh.show_normal_vertex = True
  144. for poly in mesh.polygons:
  145. poly.use_smooth = True
  146. def defaults_modifier(mod):
  147. mod.show_in_editmode = True
  148. mod.show_on_cage = True
  149. # -----------------------------------------------------------------------------
  150. # models (utils)
  151. def mesh_bmesh_poly_elems(poly, elems):
  152. vert_start = poly.loop_start
  153. vert_total = poly.loop_total
  154. return elems[vert_start:vert_start + vert_total]
  155. def mesh_bmesh_poly_vertices(poly):
  156. return [loop.vertex_index
  157. for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)]
  158. def mesh_bounds(mesh):
  159. xmin = ymin = zmin = +100000000.0
  160. xmax = ymax = zmax = -100000000.0
  161. for v in mesh.vertices:
  162. x, y, z = v.co
  163. xmax = max(x, xmax)
  164. ymax = max(y, ymax)
  165. zmax = max(z, zmax)
  166. xmin = min(x, xmin)
  167. ymin = min(y, ymin)
  168. zmin = min(z, zmin)
  169. return (xmin, ymin, zmin), (xmax, ymax, zmax)
  170. def mesh_uv_add(obj):
  171. uvs = ((0.0, 0.0),
  172. (0.0, 1.0),
  173. (1.0, 1.0),
  174. (1.0, 0.0))
  175. uv_lay = obj.data.uv_layers.new()
  176. # XXX, odd that we need to do this. until UV's and texface
  177. # are separated we will need to keep it
  178. uv_loops = obj.data.uv_layers[-1]
  179. uv_list = uv_loops.data[:]
  180. for poly in obj.data.polygons:
  181. poly_uvs = mesh_bmesh_poly_elems(poly, uv_list)
  182. for i, c in enumerate(poly_uvs):
  183. c.uv = uvs[i % 4]
  184. return uv_lay
  185. def mesh_vcol_add(obj, mode=0):
  186. colors = ((0.0, 0.0, 0.0), # black
  187. (1.0, 0.0, 0.0), # red
  188. (0.0, 1.0, 0.0), # green
  189. (0.0, 0.0, 1.0), # blue
  190. (1.0, 1.0, 0.0), # yellow
  191. (0.0, 1.0, 1.0), # cyan
  192. (1.0, 0.0, 1.0), # magenta
  193. (1.0, 1.0, 1.0), # white
  194. )
  195. def colors_get(i):
  196. return colors[i % len(colors)]
  197. vcol_lay = obj.data.vertex_colors.new()
  198. mesh = obj.data
  199. col_list = vcol_lay.data[:]
  200. for poly in mesh.polygons:
  201. face_verts = mesh_bmesh_poly_vertices(poly)
  202. poly_cols = mesh_bmesh_poly_elems(poly, col_list)
  203. for i, c in enumerate(poly_cols):
  204. c.color = colors_get(face_verts[i])
  205. return vcol_lay
  206. def mesh_vgroup_add(obj, name="Group", axis=0, invert=False, mode=0):
  207. mesh = obj.data
  208. vgroup = obj.vertex_groups.new(name=name)
  209. vgroup.add(list(range(len(mesh.vertices))), 1.0, 'REPLACE')
  210. group_index = len(obj.vertex_groups) - 1
  211. min_bb, max_bb = mesh_bounds(mesh)
  212. range_axis = max_bb[axis] - min_bb[axis]
  213. # gradient
  214. for v in mesh.vertices:
  215. for vg in v.groups:
  216. if vg.group == group_index:
  217. f = (v.co[axis] - min_bb[axis]) / range_axis
  218. vg.weight = 1.0 - f if invert else f
  219. return vgroup
  220. def mesh_shape_add(obj, mode=0):
  221. pass
  222. def mesh_armature_add(obj, mode=0):
  223. pass
  224. # -----------------------------------------------------------------------------
  225. # modifiers
  226. def modifier_subsurf_add(scene, obj, levels=2):
  227. mod = obj.modifiers.new(name=whoami(), type='SUBSURF')
  228. defaults_modifier(mod)
  229. mod.levels = levels
  230. mod.render_levels = levels
  231. return mod
  232. def modifier_armature_add(scene, obj):
  233. mod = obj.modifiers.new(name=whoami(), type='ARMATURE')
  234. defaults_modifier(mod)
  235. arm_data = bpy.data.armatures.new(whoami())
  236. obj_arm = bpy.data.objects.new(whoami(), arm_data)
  237. scene.objects.link(obj_arm)
  238. obj_arm.select = True
  239. scene.objects.active = obj_arm
  240. bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  241. bpy.ops.object.mode_set(mode='EDIT', toggle=False)
  242. # XXX, annoying, remove bone.
  243. while arm_data.edit_bones:
  244. obj_arm.edit_bones.remove(arm_data.edit_bones[-1])
  245. bone_a = arm_data.edit_bones.new("Bone.A")
  246. bone_b = arm_data.edit_bones.new("Bone.B")
  247. bone_b.parent = bone_a
  248. bone_a.head = -1, 0, 0
  249. bone_a.tail = 0, 0, 0
  250. bone_b.head = 0, 0, 0
  251. bone_b.tail = 1, 0, 0
  252. # Get armature animation data
  253. bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  254. # 45d armature
  255. obj_arm.pose.bones["Bone.B"].rotation_quaternion = 1, -0.5, 0, 0
  256. # set back to the original
  257. scene.objects.active = obj
  258. # display options
  259. obj_arm.show_in_front = True
  260. arm_data.draw_type = 'STICK'
  261. # apply to modifier
  262. mod.object = obj_arm
  263. mesh_vgroup_add(obj, name="Bone.A", axis=0, invert=True)
  264. mesh_vgroup_add(obj, name="Bone.B", axis=0, invert=False)
  265. return mod
  266. def modifier_mirror_add(scene, obj):
  267. mod = obj.modifiers.new(name=whoami(), type='MIRROR')
  268. defaults_modifier(mod)
  269. return mod
  270. def modifier_solidify_add(scene, obj, thickness=0.25):
  271. mod = obj.modifiers.new(name=whoami(), type='SOLIDIFY')
  272. defaults_modifier(mod)
  273. mod.thickness = thickness
  274. return mod
  275. def modifier_hook_add(scene, obj, use_vgroup=True):
  276. scene.objects.active = obj
  277. # no nice way to add hooks from py api yet
  278. # assume object mode, hook first face!
  279. mesh = obj.data
  280. if use_vgroup:
  281. for v in mesh.vertices:
  282. v.select = True
  283. else:
  284. for v in mesh.vertices:
  285. v.select = False
  286. for i in mesh.faces[0].vertices:
  287. mesh.vertices[i].select = True
  288. bpy.ops.object.mode_set(mode='EDIT', toggle=False)
  289. bpy.ops.object.hook_add_newob()
  290. bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
  291. # mod = obj.modifiers.new(name=whoami(), type='HOOK')
  292. mod = obj.modifiers[-1]
  293. defaults_modifier(mod)
  294. obj_hook = mod.object
  295. obj_hook.rotation_euler = 0, math.radians(45), 0
  296. obj_hook.show_in_front = True
  297. if use_vgroup:
  298. mod.vertex_group = obj.vertex_groups[0].name
  299. return mod
  300. def modifier_decimate_add(scene, obj):
  301. mod = obj.modifiers.new(name=whoami(), type='DECIMATE')
  302. defaults_modifier(mod)
  303. mod.ratio = 1 / 3
  304. return mod
  305. def modifier_build_add(scene, obj):
  306. mod = obj.modifiers.new(name=whoami(), type='BUILD')
  307. defaults_modifier(mod)
  308. # ensure we display some faces
  309. totface = len(obj.data.polygons)
  310. mod.frame_start = totface // 2
  311. mod.frame_duration = totface
  312. return mod
  313. def modifier_mask_add(scene, obj):
  314. mod = obj.modifiers.new(name=whoami(), type='MASK')
  315. defaults_modifier(mod)
  316. mod.vertex_group = obj.vertex_groups[0].name
  317. return mod
  318. # -----------------------------------------------------------------------------
  319. # models
  320. # useful since its solid boxy shape but simple enough to debug errors
  321. cube_like_vertices = (
  322. (1, 1, -1),
  323. (1, -1, -1),
  324. (-1, -1, -1),
  325. (-1, 1, -1),
  326. (1, 1, 1),
  327. (1, -1, 1),
  328. (-1, -1, 1),
  329. (-1, 1, 1),
  330. (0, -1, -1),
  331. (1, 0, -1),
  332. (0, 1, -1),
  333. (-1, 0, -1),
  334. (1, 0, 1),
  335. (0, -1, 1),
  336. (-1, 0, 1),
  337. (0, 1, 1),
  338. (1, -1, 0),
  339. (1, 1, 0),
  340. (-1, -1, 0),
  341. (-1, 1, 0),
  342. (0, 0, -1),
  343. (0, 0, 1),
  344. (1, 0, 0),
  345. (0, -1, 0),
  346. (-1, 0, 0),
  347. (2, 0, 0),
  348. (2, 0, -1),
  349. (2, 1, 0),
  350. (2, 1, -1),
  351. (0, 1, 2),
  352. (0, 0, 2),
  353. (-1, 0, 2),
  354. (-1, 1, 2),
  355. (-1, 0, 3),
  356. (-1, 1, 3),
  357. (0, 1, 3),
  358. (0, 0, 3),
  359. )
  360. cube_like_faces = (
  361. (0, 9, 20, 10),
  362. (0, 10, 17),
  363. (0, 17, 27, 28),
  364. (1, 16, 23, 8),
  365. (2, 18, 24, 11),
  366. (3, 19, 10),
  367. (4, 15, 21, 12),
  368. (4, 17, 15),
  369. (7, 14, 31, 32),
  370. (7, 15, 19),
  371. (8, 23, 18, 2),
  372. (9, 0, 28, 26),
  373. (9, 1, 8, 20),
  374. (9, 22, 16, 1),
  375. (10, 20, 11, 3),
  376. (11, 24, 19, 3),
  377. (12, 21, 13, 5),
  378. (13, 6, 18),
  379. (14, 21, 30, 31),
  380. (15, 7, 32, 29),
  381. (15, 17, 10, 19),
  382. (16, 5, 13, 23),
  383. (17, 4, 12, 22),
  384. (17, 22, 25, 27),
  385. (18, 6, 14, 24),
  386. (20, 8, 2, 11),
  387. (21, 14, 6, 13),
  388. (21, 15, 29, 30),
  389. (22, 9, 26, 25),
  390. (22, 12, 5, 16),
  391. (23, 13, 18),
  392. (24, 14, 7, 19),
  393. (28, 27, 25, 26),
  394. (29, 32, 34, 35),
  395. (30, 29, 35, 36),
  396. (31, 30, 36, 33),
  397. (32, 31, 33, 34),
  398. (35, 34, 33, 36),
  399. )
  400. # useful since its a shell for solidify and it can be mirrored
  401. cube_shell_vertices = (
  402. (0, 0, 1),
  403. (0, 1, 1),
  404. (-1, 1, 1),
  405. (-1, 0, 1),
  406. (0, 0, 0),
  407. (0, 1, 0),
  408. (-1, 1, 0),
  409. (-1, 0, 0),
  410. (-1, -1, 0),
  411. (0, -1, 0),
  412. (0, 0, -1),
  413. (0, 1, -1),
  414. )
  415. cube_shell_face = (
  416. (0, 1, 2, 3),
  417. (0, 3, 8, 9),
  418. (1, 5, 6, 2),
  419. (2, 6, 7, 3),
  420. (3, 7, 8),
  421. (4, 7, 10),
  422. (6, 5, 11),
  423. (7, 4, 9, 8),
  424. (10, 7, 6, 11),
  425. )
  426. def make_cube(scene):
  427. bpy.ops.mesh.primitive_cube_add(align='WORLD',
  428. enter_editmode=False,
  429. location=(0, 0, 0),
  430. rotation=(0, 0, 0),
  431. )
  432. obj = scene.objects.active
  433. defaults_object(obj)
  434. return obj
  435. def make_cube_extra(scene):
  436. obj = make_cube(scene)
  437. # extra data layers
  438. mesh_uv_add(obj)
  439. mesh_vcol_add(obj)
  440. mesh_vgroup_add(obj)
  441. return obj
  442. def make_cube_like(scene):
  443. mesh = bpy.data.meshes.new(whoami())
  444. mesh.from_pydata(cube_like_vertices, (), cube_like_faces)
  445. mesh.update() # add edges
  446. obj = bpy.data.objects.new(whoami(), mesh)
  447. scene.objects.link(obj)
  448. defaults_object(obj)
  449. return obj
  450. def make_cube_like_extra(scene):
  451. obj = make_cube_like(scene)
  452. # extra data layers
  453. mesh_uv_add(obj)
  454. mesh_vcol_add(obj)
  455. mesh_vgroup_add(obj)
  456. return obj
  457. def make_cube_shell(scene):
  458. mesh = bpy.data.meshes.new(whoami())
  459. mesh.from_pydata(cube_shell_vertices, (), cube_shell_face)
  460. mesh.update() # add edges
  461. obj = bpy.data.objects.new(whoami(), mesh)
  462. scene.objects.link(obj)
  463. defaults_object(obj)
  464. return obj
  465. def make_cube_shell_extra(scene):
  466. obj = make_cube_shell(scene)
  467. # extra data layers
  468. mesh_uv_add(obj)
  469. mesh_vcol_add(obj)
  470. mesh_vgroup_add(obj)
  471. return obj
  472. def make_monkey(scene):
  473. bpy.ops.mesh.primitive_monkey_add(align='WORLD',
  474. enter_editmode=False,
  475. location=(0, 0, 0),
  476. rotation=(0, 0, 0),
  477. )
  478. obj = scene.objects.active
  479. defaults_object(obj)
  480. return obj
  481. def make_monkey_extra(scene):
  482. obj = make_monkey(scene)
  483. # extra data layers
  484. mesh_uv_add(obj)
  485. mesh_vcol_add(obj)
  486. mesh_vgroup_add(obj)
  487. return obj
  488. # -----------------------------------------------------------------------------
  489. # tests (utils)
  490. global_tests = []
  491. global_tests.append(
  492. ("none",
  493. (),
  494. )
  495. )
  496. # single
  497. global_tests.append(
  498. ("subsurf_single",
  499. ((modifier_subsurf_add, dict(levels=2)), ),
  500. )
  501. )
  502. global_tests.append(
  503. ("armature_single",
  504. ((modifier_armature_add, dict()), ),
  505. )
  506. )
  507. global_tests.append(
  508. ("mirror_single",
  509. ((modifier_mirror_add, dict()), ),
  510. )
  511. )
  512. global_tests.append(
  513. ("hook_single",
  514. ((modifier_hook_add, dict()), ),
  515. )
  516. )
  517. global_tests.append(
  518. ("decimate_single",
  519. ((modifier_decimate_add, dict()), ),
  520. )
  521. )
  522. global_tests.append(
  523. ("build_single",
  524. ((modifier_build_add, dict()), ),
  525. )
  526. )
  527. global_tests.append(
  528. ("mask_single",
  529. ((modifier_mask_add, dict()), ),
  530. )
  531. )
  532. # combinations
  533. global_tests.append(
  534. ("mirror_subsurf",
  535. ((modifier_mirror_add, dict()),
  536. (modifier_subsurf_add, dict(levels=2))),
  537. )
  538. )
  539. global_tests.append(
  540. ("solidify_subsurf",
  541. ((modifier_solidify_add, dict()),
  542. (modifier_subsurf_add, dict(levels=2))),
  543. )
  544. )
  545. def apply_test(
  546. test, scene, obj,
  547. render_func=None,
  548. render_args=None,
  549. render_kwargs=None,
  550. ):
  551. test_name, test_funcs = test
  552. for cb, kwargs in test_funcs:
  553. cb(scene, obj, **kwargs)
  554. render_kwargs_copy = render_kwargs.copy()
  555. # add test name in filepath
  556. render_kwargs_copy["filepath"] += "_%s" % test_name
  557. render_func(*render_args, **render_kwargs_copy)
  558. # -----------------------------------------------------------------------------
  559. # tests themselves!
  560. # having the 'test_' prefix automatically means these functions are called
  561. # for testing
  562. def test_cube(context, test):
  563. scene = context.scene
  564. obj = make_cube_extra(scene)
  565. ctx_camera_setup(context, location=(3, 3, 3))
  566. apply_test(
  567. test, scene, obj,
  568. render_func=render_gl_all_modes,
  569. render_args=(context, obj),
  570. render_kwargs=dict(filepath=whoami())
  571. )
  572. def test_cube_like(context, test):
  573. scene = context.scene
  574. obj = make_cube_like_extra(scene)
  575. ctx_camera_setup(context, location=(5, 5, 5))
  576. apply_test(
  577. test, scene, obj,
  578. render_func=render_gl_all_modes,
  579. render_args=(context, obj),
  580. render_kwargs=dict(filepath=whoami())
  581. )
  582. def test_cube_shell(context, test):
  583. scene = context.scene
  584. obj = make_cube_shell_extra(scene)
  585. ctx_camera_setup(context, location=(4, 4, 4))
  586. apply_test(
  587. test, scene, obj,
  588. render_func=render_gl_all_modes,
  589. render_args=(context, obj),
  590. render_kwargs=dict(filepath=whoami())
  591. )
  592. # -----------------------------------------------------------------------------
  593. # call all tests
  594. def main():
  595. print("Calling main!")
  596. # render_gl(bpy.context, "/testme")
  597. # ctx_clear_scene()
  598. context = bpy.context
  599. ctx_clear_scene()
  600. # run all tests
  601. for key, val in sorted(globals().items()):
  602. if key.startswith("test_") and hasattr(val, "__call__"):
  603. print("calling:", key)
  604. for t in global_tests:
  605. val(context, test=t)
  606. ctx_clear_scene()
  607. # -----------------------------------------------------------------------------
  608. # annoying workaround for theme initialization
  609. if __name__ == "__main__":
  610. import bpy
  611. from bpy.app.handlers import persistent
  612. @persistent
  613. def load_handler(dummy):
  614. print("Load Handler:", bpy.data.filepath)
  615. if load_handler.first is False:
  616. bpy.app.handlers.scene_update_post.remove(load_handler)
  617. try:
  618. main()
  619. import sys
  620. sys.exit(0)
  621. except:
  622. import traceback
  623. traceback.print_exc()
  624. # import sys
  625. # sys.exit(1) # comment to debug
  626. else:
  627. load_handler.first = False
  628. load_handler.first = True
  629. bpy.app.handlers.scene_update_post.append(load_handler)