Changeset View
Changeset View
Standalone View
Standalone View
tests/python/modules/mesh_test.py
| Show All 38 Lines | |||||
| # is updated with the new test result. | # is updated with the new test result. | ||||
| # Tests are verbose when the environment variable BLENDER_VERBOSE is set. | # Tests are verbose when the environment variable BLENDER_VERBOSE is set. | ||||
| import bpy | import bpy | ||||
| import functools | import functools | ||||
| import inspect | import inspect | ||||
| import os | import os | ||||
| import shutil | |||||
| # Output from this module and from blender itself will occur during tests. | # Output from this module and from blender itself will occur during tests. | ||||
| # We need to flush python so that the output is properly interleaved, otherwise | # We need to flush python so that the output is properly interleaved, otherwise | ||||
| # blender's output for one test will end up showing in the middle of another test... | # blender's output for one test will end up showing in the middle of another test... | ||||
| print = functools.partial(print, flush=True) | print = functools.partial(print, flush=True) | ||||
| class ModifierSpec: | class ModifierSpec: | ||||
| ▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | def _add_modifier(self, test_object, modifier_spec: ModifierSpec): | ||||
| # Special case for Dynamic Paint, need to toggle Canvas on. | # Special case for Dynamic Paint, need to toggle Canvas on. | ||||
| if modifier.type == "DYNAMIC_PAINT": | if modifier.type == "DYNAMIC_PAINT": | ||||
| bpy.ops.dpaint.type_toggle(type='CANVAS') | bpy.ops.dpaint.type_toggle(type='CANVAS') | ||||
| self.set_parameters(modifier, modifier_spec.modifier_parameters) | self.set_parameters(modifier, modifier_spec.modifier_parameters) | ||||
| if modifier.type in bakers_list: | if modifier.type in bakers_list: | ||||
| self._bake_current_simulation(test_object, modifier.name, modifier_spec.frame_end) | self._bake_current_simulation(test_object, modifier.name, modifier_spec.frame_end) | ||||
zazizizou: if this raises an exception, cleanup won't happen. Probably unlikely to happen but this is a… | |||||
Done Inline ActionsYes I shifted it back again in the run_test method. Letting it get compared first before deleting. Deleting the cache right after baking was a bad idea. calra: Yes I shifted it back again in the `run_test` method. Letting it get compared first before… | |||||
| scene.frame_set(modifier_spec.frame_end) | scene.frame_set(modifier_spec.frame_end) | ||||
| def _apply_modifier(self, test_object, modifier_name): | def _apply_modifier(self, test_object, modifier_name): | ||||
| # Modifier automatically gets applied when converting from Curve to Mesh. | # Modifier automatically gets applied when converting from Curve to Mesh. | ||||
| if test_object.type == 'CURVE': | if test_object.type == 'CURVE': | ||||
| bpy.ops.object.convert(target='MESH') | bpy.ops.object.convert(target='MESH') | ||||
| elif test_object.type == 'MESH': | elif test_object.type == 'MESH': | ||||
| Show All 22 Lines | def _bake_current_simulation(self, test_object, test_modifier_name, frame_end): | ||||
| elif modifier.type == 'DYNAMIC_PAINT': | elif modifier.type == 'DYNAMIC_PAINT': | ||||
| dynamic_paint_setting = modifier.canvas_settings.canvas_surfaces.active | dynamic_paint_setting = modifier.canvas_settings.canvas_surfaces.active | ||||
| override_setting = dynamic_paint_setting.point_cache | override_setting = dynamic_paint_setting.point_cache | ||||
| override = {'scene': scene, 'active_object': test_object, 'point_cache': override_setting} | override = {'scene': scene, 'active_object': test_object, 'point_cache': override_setting} | ||||
| bpy.ops.ptcache.bake(override, bake=True) | bpy.ops.ptcache.bake(override, bake=True) | ||||
| break | break | ||||
| def __del__(self): | |||||
| """ | |||||
| Clean up cache directory. | |||||
| :return: None | |||||
| """ | |||||
| filepath = bpy.data.filepath | |||||
| dir_path = os.path.dirname(filepath) | |||||
| current_file_name = bpy.path.display_name_from_filepath(filepath) | |||||
| cache_dir_name = "blendcache_" + current_file_name | |||||
| path_to_cache_dir = os.path.join(dir_path, cache_dir_name) | |||||
| if os.path.exists(path_to_cache_dir): | |||||
| shutil.rmtree(path_to_cache_dir) | |||||
| def _apply_particle_system(self, test_object, particle_sys_spec: ParticleSystemSpec): | def _apply_particle_system(self, test_object, particle_sys_spec: ParticleSystemSpec): | ||||
| """ | """ | ||||
| Applies Particle System settings to test objects | Applies Particle System settings to test objects | ||||
| """ | """ | ||||
| bpy.context.scene.frame_set(1) | bpy.context.scene.frame_set(1) | ||||
| bpy.ops.object.select_all(action='DESELECT') | bpy.ops.object.select_all(action='DESELECT') | ||||
| test_object.modifiers.new(particle_sys_spec.modifier_name, particle_sys_spec.modifier_type) | test_object.modifiers.new(particle_sys_spec.modifier_name, particle_sys_spec.modifier_type) | ||||
| ▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
| selected_evaluatated_verts = [v.index for v in evaluated_test_mesh.vertices if v.select] | selected_evaluatated_verts = [v.index for v in evaluated_test_mesh.vertices if v.select] | ||||
| selected_expected_verts = [v.index for v in expected_mesh.vertices if v.select] | selected_expected_verts = [v.index for v in expected_mesh.vertices if v.select] | ||||
| if selected_evaluatated_verts != selected_expected_verts: | if selected_evaluatated_verts != selected_expected_verts: | ||||
| compare_result = "Selection doesn't match" | compare_result = "Selection doesn't match" | ||||
| compare_success = False | compare_success = False | ||||
| # Also check if invalid geometry (which is never expected) had to be corrected... | # Also check if invalid geometry (which is never expected) had to be corrected... | ||||
| validation_success = not evaluated_test_mesh.validate(verbose=True) | validation_success = not evaluated_test_mesh.validate(verbose=True) | ||||
| if compare_success and validation_success: | if compare_success and validation_success: | ||||
Done Inline ActionsOh this is not exactly what I meant. Defining __del__ above should be enough. It should get called automatically when MeshTest instance is not needed anymore, the same way you don't call __init__ explicitly anywhere. So I thought cleaning up in MeshTest is fine. zazizizou: Oh this is not exactly what I meant. Defining `__del__` above should be enough. It should get… | |||||
| if self.verbose: | if self.verbose: | ||||
| print("Success!") | print("Success!") | ||||
| # Clean up. | # Clean up. | ||||
| if self.verbose: | if self.verbose: | ||||
| print("Cleaning up...") | print("Cleaning up...") | ||||
| # Delete evaluated_test_object. | # Delete evaluated_test_object. | ||||
| bpy.ops.object.delete() | bpy.ops.object.delete() | ||||
| ▲ Show 20 Lines • Show All 120 Lines • Show Last 20 Lines | |||||
if this raises an exception, cleanup won't happen. Probably unlikely to happen but this is a test suite so... Maybe it's better to do cleanup in __del__() method?
One more question. I'm not very familiar with baking modifiers, but you want to change a frame later to do comparison, will this affect it in some way (e.g. make test slower, or even generate cache again)?