ScriptCanvas_OverlapNode.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 : 12712454
  7. # Test Case Title : Verify overlap nodes in script canvas
  8. # fmt: off
  9. class Tests:
  10. enter_game_mode = ("Entered game mode", "Failed to enter game mode")
  11. exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
  12. # comm entities are used for communication between script canvas and the python script.
  13. comm_entities_found = ("All comm entities found", "All comm entities not found")
  14. script_canvas_entity_found = ("Script_Canvas_Entity Found", "Script_Canvas_Entity not found")
  15. test_array_found = ("8x8 entity array found", "8x8 entity array not found")
  16. all_tests_passed = ("All tests have expected results", "Some tests had unexpected results")
  17. # Test 0
  18. test_0_finished = ("Test 0 has ended", "Test 0 has not ended correctly")
  19. test_0_results_logged = ("Test 0 logged expected results", "Test 0 logged unexpected results")
  20. test_0_entity_reset = ("Test 0: entities moved back", "Test 0: not all entities moved back")
  21. # Test 1
  22. test_1_finished = ("Test 1 has ended", "Test 1 has not ended correctly")
  23. test_1_results_logged = ("Test 1 logged expected results", "Test 1 logged unexpected results")
  24. test_1_entity_reset = ("Test 1: entities moved back", "Test 1: not all entities moved back")
  25. # Test 2
  26. test_2_finished = ("Test 2 has ended", "Test 2 has not ended correctly")
  27. test_2_results_logged = ("Test 2 logged expected results", "Test 2 logged unexpected results")
  28. test_2_entity_reset = ("Test 2: entities moved back", "Test 2: not all entities moved back")
  29. # fmt: on
  30. def ScriptCanvas_OverlapNode():
  31. """
  32. Summary: Verifies that the three script canvas overlap nodes (box, sphere, capsule) work as expected. Test
  33. script starts and verifies each case one by one.
  34. Level Description:
  35. Test Array - 8x8 array of sphere entities lined up edge to edge along an y-z plane, they are names with
  36. 'Sphere_row_column' convention; has PhysX rigid body, sphere shaped PhysX collider, sphere shape.
  37. Comm From Test- 3 communication entities that start inactive, used by the test script to initiate each of the three cases
  38. by activation of the relevent sphere; has sphere shape.
  39. Comm To Test- 3 communication entities that start inactive, used by the script canvas to initiate when each of the three
  40. cases are completed by activation of the relevent sphere; has sphere shape.
  41. Script Canvas Entity - Entity is centered in the test array and oriented with a 90 degree angle along the y
  42. axis as to allow the capsule overlap node to overlap more entities; has script canvas component
  43. Script Canvas - Has three execution cases, one for each overlap node type. Each case goes through a similar path
  44. - Waits for relevant Comm From Test entity to be activated by the test script
  45. - Creates an array of all entities in Test Array that overlap
  46. - Uses this array to draw a blue sphere at every sphere that overlaps
  47. - Uses the same array to move each overlapping entity 5 m along the +x axis
  48. - Activates the relevant Comm To Test entity
  49. The test script then logs the results and resets the Test Array before activating the next path.
  50. Values for the overlaps:
  51. Box: x = 4.5, y = 4.5, z = 4.5
  52. Sphere: r = 4
  53. Capsule: r = 0.5, h = 5
  54. Note: For this script canvas to run properly it requires the custom .physxconfiguration file.
  55. Tests Runs - Each loop runs a different overlap node
  56. - test_0: Box
  57. - test_1: Sphere
  58. - test_2: Capsule
  59. Expected Behavior: The script canvas will run it's three different overlap nodes. Each run the overlapped
  60. spheres in the Test Array will be drawn in over in blue and then offset in the x direction so that this test
  61. script can confirm that it worked correctly.
  62. Test Steps:
  63. 1) Open Level
  64. 2) Enter Game Mode
  65. 3) Create Entity Objects
  66. 4) Validate Entities
  67. 5) Begin Testing
  68. 6) Signal Script Canvas to begin test
  69. 7) Wait until script canvas signals that it has completed the test
  70. 8) Check which entities in array have been moved
  71. 9) Validate and log results of test
  72. 10) Place all entities back into correct positions in entity array
  73. 11) Log results of all tests
  74. 12) Exit Game Mode
  75. 13) Close Editor
  76. Note:
  77. - This test file must be called from the Open 3D Engine Editor command terminal
  78. - Any passed and failed tests are written to the Editor.log file.
  79. Parsing the file or running a log_monitor are required to observe the test results.
  80. :return: None
  81. """
  82. import os
  83. import sys
  84. from editor_python_test_tools.utils import Report
  85. from editor_python_test_tools.utils import TestHelper as helper
  86. import azlmbr.legacy.general as general
  87. import azlmbr.bus
  88. import azlmbr.math as math
  89. # Constants
  90. FLOAT_THRESHOLD = 0.0001
  91. # Timeout for a failed test in seconds
  92. TIMEOUT = 1.0
  93. ARRAY_X = 500.0
  94. ARRAY_COLUMN_0 = 530.0
  95. ARRAY_ROW_0 = 45.0
  96. # Helper Functions
  97. class Entity:
  98. def __init__(self, name, activated):
  99. self.id = general.find_game_entity(name)
  100. self.name = name
  101. self.activated = activated
  102. self.handler = None
  103. def activate_entity(self):
  104. Report.info("Activating Entity : " + self.name)
  105. azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", self.id)
  106. self.activated = True
  107. def entity_activated(self, args):
  108. self.activated = True
  109. def set_handler(self):
  110. self.handler = azlmbr.entity.EntityBusHandler()
  111. self.handler.connect(self.id)
  112. self.handler.add_callback("OnEntityActivated", self.entity_activated)
  113. class Sphere_Entities:
  114. def __init__(self, row, column):
  115. self.name = "Sphere_{}_{}".format(row, column)
  116. self.id = general.find_game_entity(self.name)
  117. self.y = column + ARRAY_COLUMN_0
  118. self.z = ARRAY_ROW_0 - row
  119. self.array_position = math.Vector3(ARRAY_X, self.y, self.z)
  120. self.current_position = self.array_position
  121. def check_id(self):
  122. return self.id.isValid()
  123. def move_entity_back(self):
  124. azlmbr.components.TransformBus(azlmbr.bus.Event, "SetWorldTranslation", self.id, self.array_position)
  125. def in_position(self):
  126. current_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
  127. return abs(current_position.x - self.array_position.x) < FLOAT_THRESHOLD
  128. class Script_Canvas_Test:
  129. def __init__(self, index):
  130. self.index = index
  131. self.name = "test_{}".format(index)
  132. self.got_expected_result = False
  133. self.test_finish = None
  134. self.results_logged = None
  135. self.array_reset = None
  136. def report_test_start(self):
  137. Report.info("Test {} has begun".format(self.index))
  138. def report_test_finished(self, finished):
  139. self.test_finish = Tests.__dict__["test_{}_finished".format(self.index)]
  140. Report.result(self.test_finish, finished)
  141. def report_results_logged(self):
  142. self.results_logged = Tests.__dict__["test_{}_results_logged".format(self.index)]
  143. Report.result(self.results_logged, self.got_expected_result)
  144. def report_test_array_reset(self, entities_in_position):
  145. self.array_reset = Tests.__dict__["test_{}_entity_reset".format(self.index)]
  146. Report.result(self.array_reset, entities_in_position)
  147. # fmt: off
  148. class Result_Arrays:
  149. true_bool_array = [[True for column in range(8)] for row in range(8)]
  150. # Comparison Array for box overlap node
  151. test_0_bool_array = [
  152. [True, True, True, True, True, True, True, True],
  153. [True, False, False, False, False, False, False, True],
  154. [True, True, False, False, False, False, False, True],
  155. [True, False, False, False, False, False, False, True],
  156. [True, True, False, False, False, False, False, True],
  157. [True, True, False, False, False, False, False, True],
  158. [True, True, False, False, False, False, False, True],
  159. [True, True, True, True, True, True, True, True],
  160. ]
  161. # Comparison Array for sphere overlap node
  162. test_1_bool_array = [
  163. [True, True, True, True, True, True, True, True],
  164. [True, True, False, False, False, False, True, True],
  165. [True, False, False, False, False, False, False, True],
  166. [True, False, False, False, False, False, False, True],
  167. [True, False, False, False, False, False, False, True],
  168. [True, False, False, False, False, False, False, True],
  169. [True, True, False, False, False, False, True, True],
  170. [True, True, True, True, True, True, True, True],
  171. ]
  172. # Comparison Array for capsule overlap node
  173. test_2_bool_array = [
  174. [True, True, True, True, True, True, True, True],
  175. [True, True, True, False, False, True, True, True],
  176. [True, True, True, False, False, True, True, True],
  177. [True, True, True, False, False, True, True, True],
  178. [True, True, True, False, False, True, True, True],
  179. [True, True, True, False, False, True, True, True],
  180. [True, True, True, False, False, True, True, True],
  181. [True, True, True, True, True, True, True, True],
  182. ]
  183. # fmt on
  184. def create_test_Sphere_Entities():
  185. return [[Sphere_Entities(row, column) for column in range(8)] for row in range(8)]
  186. def sphere_array_isvalid(array):
  187. for row in range(len(array)):
  188. for column in range(len(array[0])):
  189. if not array[row][column].id.isValid():
  190. return False
  191. return True
  192. def check_comm_entities(comm_list):
  193. for entity in comm_list:
  194. if not entity.id.isValid():
  195. return False
  196. return True
  197. def check_array_movement(array):
  198. return [[True if entity.in_position() else False for entity in row] for row in array]
  199. def reset_array(array):
  200. for row in array:
  201. for entity in row:
  202. entity.move_entity_back()
  203. def is_array_in_position(array):
  204. return arrays_are_the_same(Result_Arrays.true_bool_array, check_array_movement(array))
  205. def arrays_are_the_same(array_0, array_1):
  206. differences = [row for row in array_0 if row not in array_1] + [row for row in array_1 if row not in array_0]
  207. return differences == []
  208. # Main Script
  209. helper.init_idle()
  210. # 1) Open Level
  211. helper.open_level("Physics", "ScriptCanvas_OverlapNode")
  212. # 2) Enter Game Mode
  213. helper.enter_game_mode(Tests.enter_game_mode)
  214. # 3) Create Entity and Script_Canvas_Test Objects
  215. test_Sphere_Entities = create_test_Sphere_Entities()
  216. script_canvas_entity = Entity("Script_Canvas_Entity", True)
  217. comm_from_test_0 = Entity("Comm_From_Test_0", False)
  218. comm_from_test_1 = Entity("Comm_From_Test_1", False)
  219. comm_from_test_2 = Entity("Comm_From_Test_2", False)
  220. comm_to_test_0 = Entity("Comm_To_Test_0", False)
  221. comm_to_test_1 = Entity("Comm_To_Test_1", False)
  222. comm_to_test_2 = Entity("Comm_To_Test_2", False)
  223. comm_from_entity_list = (comm_from_test_0, comm_from_test_1, comm_from_test_2)
  224. comm_to_entity_list = (comm_to_test_0, comm_to_test_1, comm_to_test_2)
  225. test_0 = Script_Canvas_Test(0)
  226. test_1 = Script_Canvas_Test(1)
  227. test_2 = Script_Canvas_Test(2)
  228. test_list = (test_0, test_1, test_2)
  229. # 4) Validate Entities
  230. Report.critical_result(Tests.script_canvas_entity_found, script_canvas_entity.id.isValid())
  231. Report.critical_result(
  232. Tests.comm_entities_found, check_comm_entities(comm_from_entity_list + comm_to_entity_list)
  233. )
  234. Report.critical_result(Tests.test_array_found, sphere_array_isvalid(test_Sphere_Entities))
  235. # 5) Begin Testing
  236. for test in test_list:
  237. # 6) Signal Script Canvas to begin test
  238. comm_from_entity_list[test.index].activate_entity()
  239. test.report_test_start()
  240. # 7) Wait until script canvas signals that it has completed the test
  241. comm_to_entity_list[test.index].set_handler()
  242. test.report_test_finished(helper.wait_for_condition(lambda: comm_to_entity_list[test.index].activated, TIMEOUT))
  243. # 8) Check which entities in array have been moved
  244. result_bool_array = check_array_movement(test_Sphere_Entities)
  245. # 9) Validate and log results of test
  246. test.got_expected_result = arrays_are_the_same(
  247. result_bool_array, Result_Arrays.__dict__["test_{}_bool_array".format(test.index)]
  248. )
  249. test.report_results_logged()
  250. if test.index == 0:
  251. Report.info(result_bool_array)
  252. # 10) Place all entities back into correct positions in entity array
  253. reset_array(test_Sphere_Entities)
  254. test.report_test_array_reset(is_array_in_position(test_Sphere_Entities))
  255. # 11) Log results of all tests
  256. Report.result(
  257. Tests.all_tests_passed, test_0.got_expected_result and test_1.got_expected_result and test_2.got_expected_result
  258. )
  259. # 12) Exit Game Mode
  260. helper.exit_game_mode(Tests.exit_game_mode)
  261. if __name__ == "__main__":
  262. from editor_python_test_tools.utils import Report
  263. Report.start_test(ScriptCanvas_OverlapNode)