ScriptCanvas_SetKinematicTargetTransform.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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
  7. # ID : C14976308
  8. # Title : Verify that SetKinematicTarget on PhysX rigid body updates transform for kinematic entities and vice versa
  9. # fmt: off
  10. class Tests:
  11. enter_game_mode = ("Entered game mode", "Failed to enter game mode")
  12. sphere_found_valid = ("Sphere found and validated", "Sphere not found and validated")
  13. kinematic_target_found_valid = ("Kinematic_Target found and validated", "Kinematic_Target not found and validated")
  14. transform_target_found_valid = ("Transform_Target found and validated", "Transform_Target not found and validated")
  15. signal_found_valid = ("Signal found and validated", "Signal not found and validated")
  16. sphere_gravity_disabled = ("Gravity is disabled on Sphere", "Gravity is not disabled on Sphere")
  17. sphere_kinematic = ("Sphere is kinematic", "Sphere is not kinematic")
  18. entity_translations_differ = ("Each entity has a different initial translation", "Each entity does not have a different initial translation")
  19. entity_rotations_differ = ("Each entity has a different initial rotation", "Each entity does not have a different initial rotation")
  20. entity_scales_differ = ("Each entity has a different initial scale", "Each entity does not have a different initial scale")
  21. sphere_translation_1_valid = ("Set Kinematic Target updated Sphere's translation to the new value", "Set Kinematic Target failed to update Sphere's translation to the new value")
  22. sphere_rotation_1_valid = ("Set Kinematic Target updated Sphere's rotation to the new value", "Set Kinematic Target failed to update Sphere's rotation to the new value")
  23. sphere_transform_2_valid = ("Set World Transform updated Sphere's transform to the new value", "Set World Transform failed to update Sphere's transform to the new value")
  24. exit_game_mode = ("Exited game mode", "Failed to exit game mode")
  25. # fmt: on
  26. def ScriptCanvas_SetKinematicTargetTransform():
  27. """
  28. Summary:
  29. This script runs an automated test to verify the results of two Script Canvas nodes acting on a kinematic rigid
  30. body:
  31. 1) Set Kinematic Target will update the kinematic rigid body's translation and rotation to those of the transform
  32. which the node passes to it.
  33. 2) Set World Transform will update a kinematic rigid body's transform to the transform which the node passes to it.
  34. Level Description:
  35. Entity: Sphere: PhysX Rigid Body, PhysX Collider with sphere shape, and Mesh with sphere asset
  36. Gravity disabled, kinematic enabled
  37. Translate (79.0, 39.0, 34.0) in meters
  38. Rotate (1.0, 2.0, 3.0) in degrees
  39. Scale (1.0, 1.0, 1.0)
  40. Entity: Kinematic_Target: Mesh with cube asset
  41. Translate (48.0, 56.0, 36.0) in meters
  42. Rotate (11.0, 12.0, 13.0) in degrees
  43. Scale (1.1, 1.2, 1.3)
  44. Entity: Transform_Target: Mesh with cube asset
  45. Translate (72.0, 80.0, 38.0) in meters
  46. Rotate (21.0, 22.0, 23.0) in degrees
  47. Scale (2.1, 2.2, 2.3)
  48. Entity: Signal: Start inactive, attached Script Canvas asset which will cause the following:
  49. On Signal Activated will Set Kinematic Target on Sphere to Kinematic_Target's transform
  50. On Signal Deactivated will Set World Transform on Sphere to Transform_Target's transform
  51. Other than the signal, the entities all have different translations, rotations, and scales.
  52. Expected behavior:
  53. When the script activates Signal, Sphere's translation and rotation will update to those of Kinematic_Target. When
  54. the script deactivates Signal, Sphere's transform will update to that of Transform_Target.
  55. NOTE: There is a known bug (LY-107723) which causes the rotation to update to a value that is not sufficiently close
  56. to the expected result when using Set Kinematic Target which will cause the test to fail:
  57. LY-107723
  58. Test Steps:
  59. 1) Open level and enter game mode
  60. 2) Retrieve and validate entities
  61. 3) Check that gravity is disabled on the sphere
  62. 4) Check that the sphere is kinematic
  63. 5) Check that each entity except the signal has a different initial translation
  64. 6) Check that each entity except the signal has a different initial rotation
  65. 7) Check that each entity except the signal has a different initial scale
  66. 8) Activate the signal entity to trigger the Set Kinematic Target node in Script Canvas
  67. 9) Wait one frame and check that the sphere's translation has updated to that of Kinematic_Target
  68. 10) Check that the sphere's rotation has updated to that of Kinematic_Target
  69. 11) Deactivate the signal entity to trigger the Set World Transform node in Script Canvas
  70. 12) Check that the sphere's transform has updated to that of Transform_Target
  71. 13) Exit game mode and close editor
  72. Note:
  73. - This test file must be called from the Open 3D Engine Editor command terminal
  74. - Any passed and failed tests are written to the Editor.log file.
  75. Parsing the file or running a log_monitor are required to observe the test results.
  76. :return: None
  77. """
  78. # Setup path
  79. import os
  80. import sys
  81. import azlmbr.legacy.general as general
  82. import azlmbr.bus
  83. import azlmbr.components
  84. import azlmbr.math
  85. import azlmbr.physics
  86. from editor_python_test_tools.utils import Report
  87. from editor_python_test_tools.utils import TestHelper as helper
  88. import itertools
  89. class Entity:
  90. def __init__(self, name):
  91. self.name = name
  92. self.id = general.find_game_entity(name)
  93. self.found_valid_test = Tests.__dict__[self.name.lower() + "_found_valid"]
  94. Report.critical_result(self.found_valid_test, self.id.IsValid())
  95. def is_gravity_disabled(self):
  96. return not azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
  97. def is_kinematic(self):
  98. return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsKinematic", self.id)
  99. def get_world_transform(self):
  100. transform = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", self.id)
  101. Report.info_vector3(transform.position, "{}'s position:".format(self.name))
  102. Report.info_vector3(transform.basisX, "{}'s basisX:".format(self.name))
  103. Report.info_vector3(transform.basisY, "{}'s basisY:".format(self.name))
  104. Report.info_vector3(transform.basisZ, "{}'s basisZ:".format(self.name))
  105. return transform
  106. def get_world_translation(self):
  107. translation = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
  108. Report.info_vector3(translation, "{}'s Translation:".format(self.name))
  109. return translation
  110. def get_world_rotation(self):
  111. rotation = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldRotation", self.id)
  112. Report.info_vector3(rotation, "{}'s Rotation:".format(self.name))
  113. return rotation
  114. def get_world_scale(self):
  115. scale = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldScale", self.id)
  116. Report.info_vector3(scale, "{}'s Scale:".format(self.name))
  117. return scale
  118. def transform_matches(self, other):
  119. return self.get_world_transform().Equal(other.get_world_transform())
  120. def translation_matches(self, other):
  121. return self.get_world_translation().Equal(other.get_world_translation())
  122. def rotation_matches(self, other):
  123. return self.get_world_rotation().Equal(other.get_world_rotation())
  124. def scale_matches(self, other):
  125. return self.get_world_scale().Equal(other.get_world_scale())
  126. def entities_translations_differ(entities):
  127. for entity_a, entity_b in itertools.combinations(entities, 2):
  128. if entity_a.translation_matches(entity_b):
  129. return False
  130. return True
  131. def entities_rotations_differ(entities):
  132. for entity_a, entity_b in itertools.combinations(entities, 2):
  133. if entity_a.rotation_matches(entity_b):
  134. return False
  135. return True
  136. def entities_scales_differ(entities):
  137. for entity_a, entity_b in itertools.combinations(entities, 2):
  138. if entity_a.scale_matches(entity_b):
  139. return False
  140. return True
  141. # 1) Open level and enter game mode
  142. helper.init_idle()
  143. helper.open_level("Physics", "ScriptCanvas_SetKinematicTargetTransform")
  144. helper.enter_game_mode(Tests.enter_game_mode)
  145. # 2) Retrieve and validate entities
  146. sphere = Entity("Sphere")
  147. kinematic_target = Entity("Kinematic_Target")
  148. transform_target = Entity("Transform_Target")
  149. signal = Entity("Signal")
  150. non_signal_entities = (sphere, kinematic_target, transform_target)
  151. # 3) Check that gravity is disabled on the sphere
  152. Report.critical_result(Tests.sphere_gravity_disabled, sphere.is_gravity_disabled())
  153. # 4) Check that the sphere is kinematic
  154. Report.critical_result(Tests.sphere_kinematic, sphere.is_kinematic())
  155. # 5) Check that each entity except the signal has a different initial translation
  156. Report.critical_result(Tests.entity_translations_differ, entities_translations_differ(non_signal_entities))
  157. # 6) Check that each entity except the signal has a different initial rotation
  158. Report.critical_result(Tests.entity_rotations_differ, entities_rotations_differ(non_signal_entities))
  159. # 7) Check that each entity except the signal has a different initial scale
  160. Report.critical_result(Tests.entity_scales_differ, entities_scales_differ(non_signal_entities))
  161. # 8) Activate the signal entity to trigger the Set Kinematic Target node in Script Canvas
  162. azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", signal.id)
  163. # 9) Wait one frame and check that the sphere's translation has updated to that of Kinematic_Target
  164. general.idle_wait_frames(1)
  165. Report.result(Tests.sphere_translation_1_valid, sphere.translation_matches(kinematic_target))
  166. # 10) Check that the sphere's rotation has updated to that of Kinematic_Target
  167. # NOTE: This test currently fails due to a known bug (LY-107723)
  168. Report.result(Tests.sphere_rotation_1_valid, sphere.rotation_matches(kinematic_target))
  169. # 11) Deactivate the signal entity to trigger the Set World Transform node in Script Canvas
  170. azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "DeactivateGameEntity", signal.id)
  171. # 12) Check that the sphere's transform has updated to that of Transform_Target
  172. Report.result(Tests.sphere_transform_2_valid, sphere.transform_matches(transform_target))
  173. # 13) Exit game mode and close editor
  174. helper.exit_game_mode(Tests.exit_game_mode)
  175. if __name__ == "__main__":
  176. from editor_python_test_tools.utils import Report
  177. Report.start_test(ScriptCanvas_SetKinematicTargetTransform)