Material_LibraryChangesReflectInstantly.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. """
  6. # Test case ID : 4044455
  7. # Test Case Title : Verify that any change in any of the values including the name of the material,
  8. # once saved, is immediately reflected in the component and functionality
  9. # fmt: off
  10. class Tests:
  11. enter_game_mode_0 = ("Entered game mode 0", "Failed to enter game mode 0")
  12. exit_game_mode_0 = ("Exited game mode 0", "Couldn't exit game mode 0")
  13. enter_game_mode_1 = ("Entered game mode 1", "Failed to enter game mode 1")
  14. exit_game_mode_1 = ("Exited game mode 1", "Couldn't exit game mode 1")
  15. terrain_found_0 = ("terrain entity found 0", "terrain entity not found 0")
  16. block_found_0 = ("block entity found 0", "block entity not found 0")
  17. trigger_found_0 = ("trigger entity found 0", "trigger entity not found 0")
  18. terrain_found_1 = ("terrain entity found 1", "terrain entity not found 1")
  19. block_found_1 = ("block entity found 1", "block entity not found 1")
  20. trigger_found_1 = ("trigger entity found 1", "trigger entity not found 1")
  21. material_changes = ("material changes were made", "material changes couldn't be made")
  22. # Material Modifications
  23. static_friction = ("Static friction was modified", "Static friction wasn't modified")
  24. dynamic_friction = ("Dynamic friction was modified", "Dynamic friction wasn't modified")
  25. restitution = ("Restitution was modified", "Restition wasn't modified")
  26. friction_combine = ("Friction combine was modified", "Friction combine wasn't modified")
  27. restitution_combine = ("Restition combine was modified", "Restitution combine wasn't modified")
  28. delete_material = ("Material deleted successfully", "Material wasn't deleted")
  29. # sphere_0 test 0
  30. sphere_0_found_0 = ("Test 0: sphere_0 found", "Test 0: sphere_0 not found")
  31. sphere_0_initial_position_0 = ("Test 0: sphere_0 is in valid position", "Test 0: sphere_0 isn't in valid position")
  32. sphere_0_initial_velocity_0 = ("Test 0: sphere_0 initial velocity valid", "Test 0: sphere_0 initial velocity invalid")
  33. sphere_0_collision_0 = ("Test 0: sphere_0 collided with terrain", "Test 0: sphere_0 collided with terrain")
  34. sphere_0_final_position_0 = ("Test 0: sphere_0 final position valid", "Test 0: sphere_0 final position invalid")
  35. sphere_0_final_velocity_0 = ("Test 0: sphere_0 final velocity valid", "Test 0: sphere_0 final velocity invalid")
  36. # sphere_0 test 1
  37. sphere_0_found_1 = ("Test 1: sphere_0 found", "Test 1: sphere_0 not found")
  38. sphere_0_initial_position_1 = ("Test 1: sphere_0 is in valid position", "Test 1: sphere_0 isn't in valid position")
  39. sphere_0_initial_velocity_1 = ("Test 1: sphere_0 initial velocity valid", "Test 1: sphere_0 initial velocity invalid")
  40. sphere_0_collision_1 = ("Test 1: sphere_0 collided with terrain", "Test 1: sphere_0 collided with terrain")
  41. sphere_0_final_position_1 = ("Test 1: sphere_0 final position valid", "Test 1: sphere_0 final position invalid")
  42. sphere_0_final_velocity_1 = ("Test 1: sphere_0 final velocity valid", "Test 1: sphere_0 final velocity invalid")
  43. # sphere_1 test 0
  44. sphere_1_found_0 = ("Test 0: sphere_1 found", "Test 0: sphere_1 not found")
  45. sphere_1_initial_position_0 = ("Test 0: sphere_1 is in valid position", "Test 0: sphere_1 isn't in valid position")
  46. sphere_1_initial_velocity_0 = ("Test 0: sphere_1 initial velocity valid", "Test 0: sphere_1 initial velocity invalid")
  47. sphere_1_collision_0 = ("Test 0: sphere_1 collided with terrain", "Test 0: sphere_1 collided with terrain")
  48. sphere_1_final_position_0 = ("Test 0: sphere_1 final position valid", "Test 0: sphere_1 final position invalid")
  49. sphere_1_final_velocity_0 = ("Test 0: sphere_1 final velocity valid", "Test 0: sphere_1 final velocity invalid")
  50. # sphere_1 test 1
  51. sphere_1_found_1 = ("Test 1: sphere_1 found", "Test 1: sphere_1 not found")
  52. sphere_1_initial_position_1 = ("Test 1: sphere_1 is in valid position", "Test 1: sphere_1 isn't in valid position")
  53. sphere_1_initial_velocity_1 = ("Test 1: sphere_1 initial velocity valid", "Test 1: sphere_1 initial velocity invalid")
  54. sphere_1_collision_1 = ("Test 1: sphere_1 collided with terrain", "Test 1: sphere_1 collided with terrain")
  55. sphere_1_final_position_1 = ("Test 1: sphere_1 final position valid", "Test 1: sphere_1 final position invalid")
  56. sphere_1_final_velocity_1 = ("Test 1: sphere_1 final velocity valid", "Test 1: sphere_1 final velocity invalid")
  57. # sphere_2 test 0
  58. sphere_2_found_0 = ("Test 0: sphere_2 found", "Test 0: sphere_2 not found")
  59. sphere_2_initial_position_0 = ("Test 0: sphere_2 is in valid position", "Test 0: sphere_2 isn't in valid position")
  60. sphere_2_initial_velocity_0 = ("Test 0: sphere_2 initial velocity valid", "Test 0: sphere_2 initial velocity invalid")
  61. sphere_2_collision_0 = ("Test 0: sphere_2 collided with terrain", "Test 0: sphere_2 collided with terrain")
  62. sphere_2_final_position_0 = ("Test 0: sphere_2 final position valid", "Test 0: sphere_2 final position invalid")
  63. sphere_2_final_velocity_0 = ("Test 0: sphere_2 final velocity valid", "Test 0: sphere_2 final velocity invalid")
  64. # sphere_2 test 1
  65. sphere_2_found_1 = ("Test 1: sphere_2 found", "Test 1: sphere_2 not found")
  66. sphere_2_initial_position_1 = ("Test 1: sphere_2 is in valid position", "Test 1: sphere_2 isn't in valid position")
  67. sphere_2_initial_velocity_1 = ("Test 1: sphere_2 initial velocity valid", "Test 1: sphere_2 initial velocity invalid")
  68. sphere_2_collision_1 = ("Test 1: sphere_2 collided with terrain", "Test 1: sphere_2 collided with terrain")
  69. sphere_2_final_position_1 = ("Test 1: sphere_2 final position valid", "Test 1: sphere_2 final position invalid")
  70. sphere_2_final_velocity_1 = ("Test 1: sphere_2 final velocity valid", "Test 1: sphere_2 final velocity invalid")
  71. # cube_0 test 0
  72. cube_0_found_0 = ("Test 0: cube_0 found", "Test 0: cube_0 not found")
  73. cube_0_initial_position_0 = ("Test 0: cube_0 is in correct position", "Test 0: cube_0 isn't in correct position")
  74. cube_0_initial_velocity_0 = ("Test 0: cube_0 initial velocity valid", "Test 0: cube_0 initial velocity invalid")
  75. cube_0_final_position_0 = ("Test 0: cube_0 has stopped moving", "Test 0: cube_0 hasn't stopped moving")
  76. cube_0_final_velocity_0 = ("Test 0: cube_0 final velocity valid", "Test 0: cube_0 final velocity invalid")
  77. # cube_0 test 1
  78. cube_0_found_1 = ("Test 1: cube_0 found", "Test 1: cube_0 not found")
  79. cube_0_initial_position_1 = ("Test 1: cube_0 is in correct position", "Test 1: cube_0 isn't in correct position")
  80. cube_0_initial_velocity_1 = ("Test 1: cube_0 initial velocity valid", "Test 1: cube_0 initial velocity invalid")
  81. cube_0_final_position_1 = ("Test 1: cube_0 has stopped moving", "Test 1: cube_0 has not stopped moving")
  82. cube_0_final_velocity_1 = ("Test 1: cube_0 final velocity valid", "Test 1: cube_0 final velocity invalid")
  83. # cube_1 test 0
  84. cube_1_found_0 = ("Test 0: cube_1 found", "Test 0: cube_1 not found")
  85. cube_1_initial_position_0 = ("Test 0: cube_1 is in correct position", "Test 0: cube_1 isn't in correct position")
  86. cube_1_initial_velocity_0 = ("Test 0: cube_1 initial velocity valid", "Test 0: cube_1 initial velocity invalid")
  87. cube_1_final_position_0 = ("Test 0: cube_1 has stopped moving", "Test 0: cube_1 hasn't stopped moving")
  88. cube_1_final_velocity_0 = ("Test 0: cube_1 final velocity valid", "Test 0: cube_1 final velocity invalid")
  89. # cube_1 test 1
  90. cube_1_found_1 = ("Test 1: cube_1 found", "Test 1: cube_1 not found")
  91. cube_1_initial_position_1 = ("Test 1: cube_1 is in correct position", "Test 1: cube_1 isn't in correct position")
  92. cube_1_initial_velocity_1 = ("Test 1: cube_1 initial velocity valid", "Test 1: cube_1 initial velocity invalid")
  93. cube_1_final_position_1 = ("Test 1: cube_1 has stopped moving", "Test 1: cube_1 hasn't stopped moving")
  94. cube_1_final_velocity_1 = ("Test 1: cube_1 final velocity valid", "Test 1: cube_1 final velocity invalid")
  95. # cube_2 test 0
  96. cube_2_found_0 = ("Test 0: cube_2 found", "Test 0: cube_2 not found")
  97. cube_2_initial_position_0 = ("Test 0: cube_2 is in correct position", "Test 0: cube_2 isn't in correct position")
  98. cube_2_initial_velocity_0 = ("Test 0: cube_2 initial velocity valid", "Test 0: cube_2 initial velocity invalid")
  99. cube_2_final_position_0 = ("Test 0: cube_2 has stopped moving", "Test 0: cube_2 hasn't stopped moving")
  100. cube_2_final_velocity_0 = ("Test 0: cube_2 final velocity valid", "Test 0: cube_2 final velocity invalid")
  101. # cube_2 test 1
  102. cube_2_found_1 = ("Test 1: cube_2 found", "Test 1: cube_2 not found")
  103. cube_2_initial_position_1 = ("Test 1: cube_2 is in correct position", "Test 1: cube_2 isn't in correct position")
  104. cube_2_initial_velocity_1 = ("Test 1: cube_2 initial velocity valid", "Test 1: cube_2 initial velocity invalid")
  105. cube_2_final_position_1 = ("Test 1: cube_2 has stopped moving", "Test 1: cube_2 hasn't stopped moving")
  106. cube_2_final_velocity_1 = ("Test 1: cube_2 final velocity valid", "Test 1: cube_2 final velocity invalid")
  107. # fmt: on
  108. def Material_LibraryChangesReflectInstantly():
  109. """
  110. Summary: Verify that any change in any of the values of the material, once saved, is immediately reflected
  111. in the component and functionality
  112. Level Description:
  113. Three sphere entities (sphere_0, sphere_1, sphere_2) - They start between the terrain and trigger with
  114. velocity of 10 m/s in the negative z direction; has physx collider with sphere shape, physx rigid body,
  115. sphere shape, has "to_change_restitution", "to_change_restitution_combine", and "to_delete" materials
  116. applied respectively.
  117. Three cube entities (cube_0, cube_1, cube_2) - On top of the negative y side of the block, gravity enabled, no
  118. initial velocity, 0.0 linear damping; has physx collider with box shape, physx rigid body, box shape, and
  119. has "to_change_static_friction", "to_change_dynamic_friction", and "to_change_friction_combine" materials
  120. applied respectively
  121. trigger - Stationary trigger above the three spheres, used to indicate if the material was modified correctly; has
  122. physx collider with box shape (20.0, 5.0, 0.25) and trigger enabled and box shape (20.0, 5.0, 0.25)
  123. block - Stationary block that has all cubes sitting on it. Used as a controlled surface for friction testing; has
  124. physx collider with box shape (10.0, 10.0, 10.0) and box shape (10.0, 10.0, 10.0)
  125. terrain - terrain component holder lined up with terrain default height; has terrain component
  126. Material Library: Contains a different material for each entity with distinct collider shape. These materials are
  127. designed to provide the largest difference in result after change (sphere: velocity, cube: distance). All spheres
  128. should not bounce off of the terrain initially but will be able to hit the trigger post change. The cubes will
  129. experience higher friction after the change and not travel as far along the ramp entity.
  130. Expected Behavior: Before editing the material library the spheres in both levels will not bounce off of the terrain
  131. and the cubes will go some distance along the ramp. After the material file is edited the spheres will bounce off
  132. of the terrain and hit the trigger and the cubes will travel a smaller distance than before
  133. Main Script Steps:
  134. 1) Open Level
  135. 2) Create test objects
  136. 3) Run test 0
  137. 4) Modify material library
  138. 5) Run test 1
  139. 6) Validate results
  140. 7) Close Editor
  141. Test Loop Steps:
  142. 1) Enter game mode
  143. 2) Find and Validate entities
  144. 3) Wait for spheres to collide with terrain
  145. 4) Wait for spheres to enter the trigger
  146. 5) Log sphere results
  147. 6) Push cubes
  148. 7) Wait for cubes to stop moving
  149. 8) Log and validate cube results
  150. 9) Exit game mode
  151. Note:
  152. - This test file must be called from the Open 3D Engine Editor command terminal
  153. - Any passed and failed tests are written to the Editor.log file.
  154. Parsing the file or running a log_monitor are required to observe the test results.
  155. :return: None
  156. """
  157. import os
  158. import sys
  159. from editor_python_test_tools.utils import Report
  160. from editor_python_test_tools.utils import TestHelper as helper
  161. import azlmbr.legacy.general as general
  162. import azlmbr.bus
  163. import azlmbr.math as math
  164. from Physmaterial_Editor import Physmaterial_Editor
  165. # Constants
  166. FLOAT_THRESHOLD = 0.001
  167. # Timeout in seconds
  168. TIMEOUT = 2.0
  169. CUBE_IMPULSE = math.Vector3(0.0, 5.0, 0.0)
  170. CUBE_Y_POSITION = 536.0
  171. CUBE_INITIAL_VELOCITY = math.Vector3(0.0, 0.0, 0.0)
  172. PROPAGATION_FRAMES = 500
  173. # Helper Functions
  174. class Entity:
  175. terrain_id = None
  176. def __init__(self, name, test_index):
  177. # Type (str, int, int, Entity) -> None
  178. self.id = general.find_game_entity(name)
  179. self.name = name
  180. self.test_index = test_index
  181. self.collision_happened = False
  182. self.hit_trigger = False
  183. # Check Entity ID
  184. found = Tests.__dict__["{}_found_{}".format(self.name, self.test_index)]
  185. Report.critical_result(found, self.id.IsValid())
  186. @property
  187. def position(self):
  188. return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
  189. @property
  190. def velocity(self):
  191. return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetLinearVelocity", self.id)
  192. @property
  193. def is_moving_up(self):
  194. # Type () -> bool
  195. return (
  196. abs(self.velocity.x) < FLOAT_THRESHOLD
  197. and abs(self.velocity.y) < FLOAT_THRESHOLD
  198. and self.velocity.z > 0.0
  199. )
  200. @property
  201. def is_not_moving(self):
  202. # Type () -> bool
  203. return (
  204. abs(self.velocity.x) < FLOAT_THRESHOLD
  205. and abs(self.velocity.y) < FLOAT_THRESHOLD
  206. and abs(self.velocity.z) < FLOAT_THRESHOLD
  207. )
  208. def on_collision_begin(self, args):
  209. # Type ([]) -> None
  210. if Entity.terrain_id.equal(args[0]):
  211. self.collision_happened = True
  212. class Sphere(Entity):
  213. def __init__(self, name, test_index):
  214. Entity.__init__(self, name, test_index)
  215. self.handler = azlmbr.physics.CollisionNotificationBusHandler()
  216. self.handler.connect(self.id)
  217. self.handler.add_callback("OnCollisionBegin", self.on_collision_begin)
  218. class Material_Test:
  219. def __init__(self, index):
  220. self.index = index
  221. self.sphere_list = None
  222. # List to hold how far the cube traveled
  223. self.cube_distances = []
  224. # List to hold wether the sphere hit the trigger and its velocities
  225. self.sphere_values = []
  226. def verify_sphere_initial_position(self, sphere, terrain, trigger):
  227. # Type (Entity, Entity, Entity) -> None
  228. # Validates sphere is where it should be
  229. position_valid = terrain.position.z < sphere.position.z < trigger.position.z
  230. initial_position = Tests.__dict__["{}_initial_position_{}".format(sphere.name, self.index)]
  231. Report.critical_result(initial_position, position_valid)
  232. def verify_sphere_initial_velocity(self, sphere):
  233. # Type (Entity) -> None
  234. # Validates that sphere in moving in the correct direction
  235. initial_velocity = Tests.__dict__["{}_initial_velocity_{}".format(sphere.name, self.index)]
  236. Report.critical_result(initial_velocity, not sphere.is_moving_up)
  237. def verify_sphere_collision(self, sphere):
  238. # Type (Entity) -> None
  239. # Reports sphere collision, ends test if it hasn't occurred
  240. collision = Tests.__dict__["{}_collision_{}".format(sphere.name, self.index)]
  241. Report.critical_result(collision, sphere.collision_happened)
  242. def verify_sphere_final_velocity(self, sphere):
  243. # Type (Entity) -> None
  244. # Validates that sphere is moving in the correct direction
  245. final_velocity = Tests.__dict__["{}_final_velocity_{}".format(sphere.name, self.index)]
  246. Report.result(final_velocity, sphere.is_moving_up or sphere.is_not_moving)
  247. def verify_sphere_final_position(self, sphere, terrain):
  248. # Type (Entity, Entity) -> None
  249. # Validats that sphere is not where it shouldn't be
  250. final_position = Tests.__dict__["{}_final_position_{}".format(sphere.name, self.index)]
  251. Report.result(final_position, sphere.position.z > terrain.position.z)
  252. def verify_cube_initial_position(self, cube, block):
  253. # Type (Entity, Entity) -> None
  254. # Cube initially starts at a standstill
  255. initial_position = Tests.__dict__["{}_initial_position_{}".format(cube.name, self.index)]
  256. Report.result(
  257. initial_position,
  258. cube.position.z > block.position.z and abs(cube.position.y - CUBE_Y_POSITION) < FLOAT_THRESHOLD,
  259. )
  260. def verify_cube_initial_velocity(self, cube):
  261. # Type (Entity) -> None
  262. # Ensures that the cube starts not moving
  263. initial_velocity = Tests.__dict__["{}_initial_velocity_{}".format(cube.name, self.index)]
  264. Report.result(initial_velocity, cube.velocity.IsClose(CUBE_INITIAL_VELOCITY, 0.01))
  265. def push_cubes(self, cube_list):
  266. # Type ([Entity]) -> None
  267. # Imparts a velocity into each cube in the y-direction
  268. for cube in cube_list:
  269. azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearVelocity", cube.id, CUBE_IMPULSE)
  270. def verify_cube_final_velocity(self, cube):
  271. # Type (Entity) -> None
  272. # Ensures that cube has stopped moving
  273. final_velocity = Tests.__dict__["{}_final_velocity_{}".format(cube.name, self.index)]
  274. Report.result(final_velocity, cube.velocity.IsClose(CUBE_INITIAL_VELOCITY, 0.01))
  275. def verify_cube_final_position(self, cube, block):
  276. # Type (Entity, Entity) -> None
  277. # Validates that cube is not somewhere it shouldn't be
  278. final_position = Tests.__dict__["{}_final_position_{}".format(cube.name, self.index)]
  279. Report.result(final_position, cube.position.z > block.position.z)
  280. def log_values(self, entity):
  281. # Type (Entity) -> None
  282. # Logs needed values for comparison
  283. if isinstance(entity, Sphere):
  284. self.sphere_values.append([entity.velocity, entity.hit_trigger])
  285. else:
  286. self.cube_distances.append(entity.position)
  287. def set_trigger(self, trigger):
  288. self.handler = azlmbr.physics.TriggerNotificationBusHandler()
  289. self.handler.connect(trigger.id)
  290. self.handler.add_callback("OnTriggerEnter", self.on_trigger_enter)
  291. def on_trigger_enter(self, args):
  292. for sphere in self.sphere_list:
  293. if sphere.id.equal(args[0]):
  294. sphere.hit_trigger = True
  295. def modify_material_library():
  296. # Type () -> bool
  297. # Uses a Physmaterial_Editor option to modify the material library associated with this level.
  298. # Changes are made to maximize the in level affect.
  299. material_library = Physmaterial_Editor("c4044455_material_librarychangesinstantly.physmaterial")
  300. dynamic_friction_modified = material_library.modify_material("to_change_dynamic_friction", "DynamicFriction", 10.0)
  301. static_friction_modified = material_library.modify_material("to_change_static_friction", "StaticFriction", 10.0)
  302. friction_combine_modified = material_library.modify_material(
  303. "to_change_friction_combine", "FrictionCombine", "Maximum"
  304. )
  305. restitution_combine_modified = material_library.modify_material(
  306. "to_change_restitution_combine", "RestitutionCombine", "Maximum"
  307. )
  308. restitution_modified = material_library.modify_material("to_change_restitution", "Restitution", 1.0)
  309. material_deleted = material_library.delete_material("to_delete")
  310. material_library.save_changes()
  311. return (
  312. material_deleted
  313. and dynamic_friction_modified
  314. and static_friction_modified
  315. and friction_combine_modified
  316. and restitution_combine_modified
  317. and restitution_modified
  318. )
  319. def check_sphere(sphere_values_0, sphere_values_1, index):
  320. # Type ([[vector3, bool]], [[vector3, bool]]) -> bool
  321. hit_trigger = not sphere_values_0[index][1] and sphere_values_1[index][1]
  322. velocity_valid = sphere_values_0[index][0].z < sphere_values_1[index][0].z
  323. return hit_trigger and velocity_valid
  324. def check_static_friction(cube_distances_0, cube_distances_1):
  325. # Type ([float],[float]) -> bool
  326. return cube_distances_0[0].y > cube_distances_1[0].y
  327. def check_dynamic_friction(cube_distances_0, cube_distances_1):
  328. # Type ([float],[float]) -> bool
  329. return cube_distances_0[1].y > cube_distances_1[1].y
  330. def check_friction_combine(cube_distances_0, cube_distances_1):
  331. # Type ([float],[float]) -> bool
  332. return cube_distances_0[2].y > cube_distances_1[2].y
  333. def run_test(test):
  334. # Type (Material_Test) -> None
  335. # This loop runs the test steps and logs data to the given Material_Test object
  336. # 1) Enter game mode
  337. helper.enter_game_mode(Tests.__dict__["enter_game_mode_{}".format(test.index)])
  338. # 2) Find and Validate entities
  339. terrain = Entity("terrain", test.index)
  340. Entity.terrain_id = terrain.id
  341. block = Entity("block", test.index)
  342. trigger = Entity("trigger", test.index)
  343. sphere_0 = Sphere("sphere_0", test.index)
  344. sphere_1 = Sphere("sphere_1", test.index)
  345. sphere_2 = Sphere("sphere_2", test.index)
  346. sphere_list = [sphere_0, sphere_1, sphere_2]
  347. cube_0 = Entity("cube_0", test.index)
  348. cube_1 = Entity("cube_1", test.index)
  349. cube_2 = Entity("cube_2", test.index)
  350. cube_list = [cube_0, cube_1, cube_2]
  351. test.sphere_list = sphere_list
  352. test.set_trigger(trigger)
  353. for sphere in sphere_list:
  354. test.verify_sphere_initial_position(sphere, terrain, trigger)
  355. test.verify_sphere_initial_velocity(sphere)
  356. for cube in cube_list:
  357. test.verify_cube_initial_position(cube, block)
  358. test.verify_cube_initial_velocity(cube)
  359. # 3) Wait for spheres to collide with terrain
  360. helper.wait_for_condition(lambda: all([sphere.collision_happened for sphere in sphere_list]), TIMEOUT)
  361. # 4) Wait for spheres to enter the trigger
  362. helper.wait_for_condition(lambda: all([sphere.hit_trigger for sphere in sphere_list]), TIMEOUT)
  363. for sphere in sphere_list:
  364. test.log_values(sphere)
  365. # 5) Log sphere results
  366. for sphere in sphere_list:
  367. test.verify_sphere_collision(sphere)
  368. test.verify_sphere_final_position(sphere, terrain)
  369. test.verify_sphere_final_velocity(sphere)
  370. # 6) Push cubes
  371. test.push_cubes(cube_list)
  372. # 7) Wait for cubes to stop moving
  373. helper.wait_for_condition(lambda: all([cube.is_not_moving for cube in cube_list]), TIMEOUT)
  374. # 8) Log and validate cube results
  375. for cube in cube_list:
  376. test.verify_cube_final_position(cube, block)
  377. test.verify_cube_final_velocity(cube)
  378. test.log_values(cube)
  379. # 9) Exit game mode
  380. helper.exit_game_mode(Tests.__dict__["exit_game_mode_{}".format(test.index)])
  381. # Main Script
  382. helper.init_idle()
  383. # 1) Open Level
  384. helper.open_level("Physics", "C4044455_Material_LibraryChangesInstantly")
  385. # 2) Create test objects
  386. test_0 = Material_Test(0)
  387. test_1 = Material_Test(1)
  388. # 3) Run test 0
  389. run_test(test_0)
  390. # 4) Modify material library
  391. Report.result(Tests.material_changes, modify_material_library())
  392. # Wait for modifications to the material library to propagate.
  393. general.idle_wait_frames(PROPAGATION_FRAMES)
  394. # 5) Run test 1
  395. run_test(test_1)
  396. # 6) Validate results
  397. # Restitution Modification Successful
  398. Report.result(Tests.restitution, check_sphere(test_0.sphere_values, test_1.sphere_values, index=0))
  399. # Static Friction Modification Successful
  400. Report.result(Tests.static_friction, check_static_friction(test_0.cube_distances, test_1.cube_distances))
  401. # Dynamic Friction Modification Successful
  402. Report.result(Tests.dynamic_friction, check_dynamic_friction(test_0.cube_distances, test_1.cube_distances))
  403. # Friction Combine Modification Successful
  404. Report.result(Tests.friction_combine, check_friction_combine(test_0.cube_distances, test_1.cube_distances))
  405. # Restitution Combine Modification Successful
  406. Report.result(Tests.restitution_combine, check_sphere(test_0.sphere_values, test_1.sphere_values, index=1))
  407. # Material Delete Successful
  408. Report.result(Tests.delete_material, check_sphere(test_0.sphere_values, test_1.sphere_values, index=2))
  409. if __name__ == "__main__":
  410. from editor_python_test_tools.utils import Report
  411. Report.start_test(Material_LibraryChangesReflectInstantly)