ScriptCanvas_PreUpdateEvent.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 : C14902097
  7. # Test Case Title : Verify Presimulate Events
  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", "Failed to exit game mode")
  12. lead_sphere_found = ("Lead_Sphere is valid", "Lead_Sphere is not valid")
  13. follow_sphere_found = ("Follow_Sphere is valid", "Follow_Sphere is not valid")
  14. no_movement = ("Spheres start with no movement", "Spheres not stationary")
  15. initial_position = ("Initial position is valid", "Initial position isn't valid")
  16. lead_sphere_velocity = ("Lead_Sphere has valid velocity", "Lead_Sphere velocity not valid")
  17. spheres_moving = ("Spheres have both moved", "Both sphere have not moved before timeout")
  18. follow_condition_true = ("Follow_Sphere is correctly trailing", "Follow_Sphere follow distance not valid")
  19. # fmt: on
  20. def ScriptCanvas_PreUpdateEvent():
  21. """
  22. Summary: Verifies that Presimulate node in Script Canvas works as expected.
  23. Level Description:
  24. Lead_Sphere - Directly next to Follow_sphere on the +x axis; has rigid body (gravity disabled), sphere shape
  25. collider, sphere shape
  26. Follow_Sphere - Directly next to Lead_Sphere on the -x axis; has rigid body (gravity disabled, kinematic
  27. enabled), sphere shape collider, sphere shape, script canvas
  28. Script Canvas - Before every frame of PhysX calculation the Follow_Sphere is moved directly next to the
  29. Lead_Sphere, then PhysX calculates and moves the Lead_Sphere to a new position before presenting to
  30. the viewer
  31. PhysX Configuration - The PhysX configuration file was modified to lower the frame rate to 20 Hz for visual debug
  32. Expected Behavior: Follow_Sphere follows Lead_spheres position with a lag that is dependent on the speed and the
  33. inverse frame rate
  34. Test Steps:
  35. 1) Open Level
  36. 2) Enter Game Mode
  37. 3) Create and Validate entities
  38. 4) Validate Spheres are not moving
  39. 5) Check Position of Spheres
  40. 6) Start moving sphere and check that it acts correctly
  41. 7) Wait until Lead_Sphere has moved a set distance
  42. 8) Verify Follow_Sphere follow distance
  43. 9) Log results
  44. 10) Exit Game Mode
  45. 11) Close Editor
  46. Note:
  47. - This test file must be called from the Open 3D Engine Editor command terminal
  48. - Any passed and failed tests are written to the Editor.log file.
  49. Parsing the file or running a log_monitor are required to observe the test results.
  50. :return: None
  51. """
  52. import os
  53. import sys
  54. from editor_python_test_tools.utils import Report
  55. from editor_python_test_tools.utils import TestHelper as helper
  56. import azlmbr
  57. import azlmbr.legacy.general as general
  58. import azlmbr.bus
  59. import azlmbr.math as math
  60. # Constants
  61. FLOAT_THRESHOLD = 0.1
  62. TIMEOUT = 5
  63. INITIAL_OFFSET = 1
  64. REQUIRED_MOVEMENT = 2
  65. FIXED_TIME_STEP = 0.05 # must be changed in level as well
  66. LEAD_SPHERE_VELOCITY = 10.0
  67. FINAL_OFFSET = (LEAD_SPHERE_VELOCITY * FIXED_TIME_STEP) + INITIAL_OFFSET
  68. OFFSET_TOLERANCE = FINAL_OFFSET * 0.25
  69. # Helper Functions
  70. class Entity:
  71. def __init__(self, name):
  72. self.id = general.find_game_entity(name)
  73. self.name = name
  74. self.initial_position = self.position
  75. self.final_position = None
  76. # Validate Entities
  77. found = Tests.__dict__[self.name.lower() + "_found"]
  78. Report.critical_result(found, self.id.isValid())
  79. @property
  80. def position(self):
  81. return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
  82. @property
  83. def velocity(self):
  84. return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetLinearVelocity", self.id)
  85. def set_velocity(self, x_velocity, y_velocity, z_velocity):
  86. velocity = math.Vector3(x_velocity, y_velocity, z_velocity)
  87. azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearVelocity", self.id, velocity)
  88. def moved_enough(self):
  89. current_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
  90. return abs(self.initial_position.x - current_position.x) >= REQUIRED_MOVEMENT
  91. def report_values(self):
  92. Report.info_vector3(self.initial_position, "{} initial position: ".format(self.name))
  93. Report.info_vector3(self.final_position, "{} final position: ".format(self.name))
  94. def check_relative_position(lead_sphere_position, follow_sphere_position, offset):
  95. return (
  96. abs((lead_sphere_position.x - follow_sphere_position.x) - offset) < OFFSET_TOLERANCE
  97. and abs(lead_sphere_position.y - follow_sphere_position.y) < FLOAT_THRESHOLD
  98. and abs(lead_sphere_position.z - follow_sphere_position.z) < FLOAT_THRESHOLD
  99. )
  100. def velocity_zero(sphere_velocity):
  101. return (
  102. abs(sphere_velocity.x) < FLOAT_THRESHOLD
  103. and abs(sphere_velocity.y) < FLOAT_THRESHOLD
  104. and abs(sphere_velocity.z) < FLOAT_THRESHOLD
  105. )
  106. def velocity_valid(lead_sphere_velocity):
  107. return (
  108. lead_sphere_velocity.x == LEAD_SPHERE_VELOCITY
  109. and abs(lead_sphere_velocity.y) < FLOAT_THRESHOLD
  110. and abs(lead_sphere_velocity.z) < FLOAT_THRESHOLD
  111. )
  112. # Main Script
  113. helper.init_idle()
  114. # 1) Open Level
  115. helper.open_level("Physics", "ScriptCanvas_PreUpdateEvent")
  116. # 2) Enter Game Mode
  117. helper.enter_game_mode(Tests.enter_game_mode)
  118. # 3) Create and validate entities
  119. lead_sphere = Entity("Lead_Sphere")
  120. follow_sphere = Entity("Follow_Sphere")
  121. # 4) Validate Spheres are not moving
  122. Report.critical_result(
  123. Tests.no_movement, velocity_zero(lead_sphere.velocity) and velocity_zero(follow_sphere.velocity)
  124. )
  125. # 5) Check Position of Sphere
  126. Report.result(
  127. Tests.initial_position,
  128. check_relative_position(lead_sphere.initial_position, follow_sphere.initial_position, INITIAL_OFFSET),
  129. )
  130. # 6) Start moving sphere and check that it acts correctly
  131. lead_sphere.set_velocity(LEAD_SPHERE_VELOCITY, 0.0, 0.0)
  132. Report.result(Tests.lead_sphere_velocity, velocity_valid(lead_sphere.velocity))
  133. # 7) Wait until Lead_Sphere has moved a set distance
  134. Report.result(Tests.spheres_moving, helper.wait_for_condition(lead_sphere.moved_enough, TIMEOUT))
  135. # 8) Verify Follow_Sphere follow distance
  136. lead_sphere.final_position = lead_sphere.position
  137. follow_sphere.final_position = follow_sphere.position
  138. Report.result(
  139. Tests.follow_condition_true, check_relative_position(lead_sphere.final_position, follow_sphere.final_position, FINAL_OFFSET)
  140. )
  141. # 9) Log results
  142. lead_sphere.report_values()
  143. follow_sphere.report_values()
  144. Report.info("Offset:" + str(FINAL_OFFSET))
  145. # 10) Exit Game Mode
  146. helper.exit_game_mode(Tests.exit_game_mode)
  147. if __name__ == "__main__":
  148. from editor_python_test_tools.utils import Report
  149. Report.start_test(ScriptCanvas_PreUpdateEvent)