rename to tmp name

This commit is contained in:
AMZN-AlexOteiza
2021-09-10 14:28:40 +02:00
parent c3e285cff7
commit ddd662f6b9
160 changed files with 0 additions and 0 deletions
@@ -0,0 +1,200 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test Case ID : C12712452
# Test Case Title : Verify ScriptCanvas Collision Events
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
terrain_found_valid = ("PhysX Terrain found and validated", "PhysX Terrain not found and validated")
sphere_found_valid = ("Sphere found and validated", "Sphere not found and validated")
begin_signal_found_valid = ("Begin Signal found and validated", "Begin Signal not found and validated")
persist_signal_found_valid = ("Persist Signal found and validated", "Persist Signal not found and validated")
end_signal_found_valid = ("End Signal found and validated", "End Signal not found and validated")
sphere_above_terrain = ("Sphere is above terrain", "Sphere is not above terrain")
sphere_gravity_enabled = ("Gravity is enabled on Sphere", "Gravity is not enabled on Sphere")
sphere_started_bouncing = ("Sphere started bouncing", "Sphere did not start bouncing")
sphere_stopped_bouncing = ("Sphere stopped bouncing", "Sphere did not stop bouncing")
event_records_match = ("Event records match", "Event records do not match")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
# fmt: on
def ScriptCanvas_CollisionEvents():
"""
Summary:
This script runs an automated test to verify that the Script Canvas nodes "On Collision Begin", "On Collision
Persist", and "On Collision End" will function as intended for the entity to which their Script Canvas is attached.
Level Description:
A sphere (entity: Sphere) is above a terrain (entity: PhysX Terrain). The sphere has a PhysX Rigid Body, a PhysX
Collider with shape Sphere, and gravity enabled. The sphere has a Script Canvas attached to it which will toggle the
activation of three signal entities (entity: Begin Signal), (entity: Persist Signal), and (entity: End Signal).
Begin Signal's activation will toggle (switch from activated to deactivated or vice versa) when a collision begins
with the sphere, Persist Signal's activation will toggle when a collision persists with the sphere, and End Signal's
activation will toggle when a collision ends with the sphere.
Expected behavior:
The sphere will fall toward and collide with the terrain. The sphere will bounce until it comes to rest. The Script
Canvas will cause the signal entities to activate and deactivate in the same pattern as the collision events which
occur on the sphere.
Test Steps:
1) Open level and enter game mode
2) Retrieve and validate entities
3) Check that the sphere is above the terrain
4) Check that gravity is enabled on the sphere
5) Wait for the initial collision between the sphere and the terrain or timeout
6) Wait for the sphere to stop bouncing
7 Check that the event records match
8) Exit game mode and close editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Setup path
import os
import sys
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.components
import azlmbr.entity
import azlmbr.physics
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
# Constants
TIME_OUT_SECONDS = 3.0
TERRAIN_START_Z = 32.0
SPHERE_RADIUS = 1.0
class Entity:
def __init__(self, name, found_valid_test):
self.name = name
self.id = general.find_game_entity(name)
self.found_valid_test = found_valid_test
class Sphere(Entity):
def __init__(self, name, found_valid_test, event_records_match_test):
Entity.__init__(self, name, found_valid_test)
self.event_records_match_test = event_records_match_test
self.collided = False
self.stopped_bouncing = False
self.collision_event_record = []
self.script_canvas_event_record = []
# Set up collision notification handler
self.handler = azlmbr.physics.CollisionNotificationBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnCollisionBegin", self.on_collision_begin)
self.handler.add_callback("OnCollisionPersist", self.on_collision_persist)
self.handler.add_callback("OnCollisionEnd", self.on_collision_end)
def get_z_position(self):
z_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldZ", self.id)
Report.info("{}'s z-position: {}".format(self.name, z_position))
return z_position
def is_gravity_enabled(self):
return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
# Set up reporting of the event records and whether they match
def match_event_records(self):
Report.info("{} collision event record: {}".format(self.name, self.collision_event_record))
Report.info("Script Canvas event record: {}".format(self.script_canvas_event_record))
return self.collision_event_record == self.script_canvas_event_record
# Set up collision event detection and update collision event record
def on_collision(self, event, other_id):
if not self.collided:
self.collided = True
other_name = azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "GetEntityName", other_id)
Report.info("{} collision {}s with {}".format(self.name, event, other_name))
self.collision_event_record.append(event)
def on_collision_begin(self, args):
self.on_collision("begin", args[0])
def on_collision_persist(self, args):
self.on_collision("persist", args[0])
def on_collision_end(self, args):
self.on_collision("end", args[0])
# Set up detection of the sphere coming to rest
def bouncing_stopped(self):
if not azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsAwake", self.id):
self.stopped_bouncing = True
return self.stopped_bouncing
class SignalEntity(Entity):
def __init__(self, name, found_valid_test, monitored_entity, event):
Entity.__init__(self, name, found_valid_test)
self.monitored_entity = monitored_entity
self.event = event
# Set up activation and deactivation notification handler
self.handler = azlmbr.entity.EntityBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnEntityActivated", self.on_entity_activated)
self.handler.add_callback("OnEntityDeactivated", self.on_entity_deactivated)
# Set up activation and deactivation detection and update Script Canvas event record
def on_entity_activated(self, args):
self.monitored_entity.script_canvas_event_record.append(self.event)
def on_entity_deactivated(self, args):
self.monitored_entity.script_canvas_event_record.append(self.event)
# 1) Open level and enter game mode
helper.init_idle()
helper.open_level("Physics", "ScriptCanvas_CollisionEvents")
helper.enter_game_mode(Tests.enter_game_mode)
# 2) Retrieve and validate entities
terrain = Entity("PhysX Terrain", Tests.terrain_found_valid)
sphere = Sphere("Sphere", Tests.sphere_found_valid, Tests.event_records_match)
begin_signal = SignalEntity("Begin Signal", Tests.begin_signal_found_valid, sphere, "begin")
persist_signal = SignalEntity("Persist Signal", Tests.persist_signal_found_valid, sphere, "persist")
end_signal = SignalEntity("End Signal", Tests.end_signal_found_valid, sphere, "end")
entities = [terrain, sphere, begin_signal, persist_signal, end_signal]
for entity in entities:
Report.critical_result(entity.found_valid_test, entity.id.IsValid())
# 3) Check that the sphere is above the terrain
Report.critical_result(Tests.sphere_above_terrain, sphere.get_z_position() - SPHERE_RADIUS > TERRAIN_START_Z)
# 4) Check that gravity is enabled on the sphere
Report.critical_result(Tests.sphere_gravity_enabled, sphere.is_gravity_enabled())
# 5) Wait for the initial collision between the sphere and the terrain or timeout
helper.wait_for_condition(lambda: sphere.collided, TIME_OUT_SECONDS)
Report.critical_result(Tests.sphere_started_bouncing, sphere.collided)
# 6) Wait for the sphere to stop bouncing
helper.wait_for_condition(sphere.bouncing_stopped, TIME_OUT_SECONDS)
Report.result(Tests.sphere_stopped_bouncing, sphere.stopped_bouncing)
# 7 Check that the event records match
Report.result(Tests.event_records_match, sphere.match_event_records())
# 8) Exit game mode and close editor
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_CollisionEvents)
@@ -0,0 +1,68 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
Test case ID : C19536274
Test Case Title : Verify that the Get Collision Layer Name node prints the name of the collision layer
"""
# fmt: off
class Tests():
test_entity_enabled = ("Test entity was enabled", "Test entity failed to enable")
game_mode_entered = ("Successfully entered Game Mode", "Failed to enter Game Mode")
# fmt: on
def ScriptCanvas_GetCollisionNameReturnsName():
"""
Summary:
Loads a level that contains an entity with script canvas and PhysX Collider components
Level Description:
Mostly empty level that contains a few different entities (one for each test using the level).
Each entity is named after the testrail id for the respective test. Each entity contains PhysX Collider component
and a Script Canvas Component with a matching .scriptcanvas file provided in the testrail.
Expected Behavior:
The level loads, enters game mode, and the script canvas prints out "Layer Name: Right"
Test Steps:
1) Load the test level
2) Find and enable the test entity
3) Enter game mode
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Helper Files
from editor_python_test_tools.utils import Report
from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity
from editor_python_test_tools.utils import TestHelper as helper
ACTIVE_STATUS = azlmbr.globals.property.EditorEntityStartStatus_StartActive
helper.init_idle()
# 1) Load the test level
helper.open_level("Physics", "NameNode_Prints")
# 2) Find and enable the test entity
test_entity = Entity.find_editor_entity("C19536274")
test_entity.set_start_status("active")
Report.result(Tests.test_entity_enabled, test_entity.get_start_status() == ACTIVE_STATUS)
# 3) Enter game mode
helper.enter_game_mode(Tests.game_mode_entered)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_GetCollisionNameReturnsName)
@@ -0,0 +1,68 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
Test case ID : C19536277
Test Case Title : Verify that when a group is modified using ToggleCollisionLayer node such that the new group is not in the pre-existing groups, GetCollisionGroupName node prints no value
"""
# fmt: off
class Tests():
test_entity_enabled = ("Test Entity successfully enabled", "Failed to enable Test Entity")
game_mode_entered = ("Successfully entered Game Mode", "Failed to enter Game Mode")
# fmt: on
def ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer():
"""
Summary:
Loads a level that contains an entity with script canvas and PhysX Collider components
Level Description:
Mostly empty level that contains a few different entities (one for each test using the level).
Each entity is named after the testrail id for the respective test. Each entity contains PhysX Collider component
and a Script Canvas Component with a matching .scriptcanvas file provided in the testrail.
Expected Behavior:
The level loads, enters game mode, and the script canvas prints out "GroupName: "
Test Steps:
1) Load the test level
2) Find and enable the test entity
3) Enter game mode
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Helper Files
from editor_python_test_tools.utils import Report
from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity
from editor_python_test_tools.utils import TestHelper as helper
ACTIVE_STATUS = azlmbr.globals.property.EditorEntityStartStatus_StartActive
helper.init_idle()
# 1) Load the test level
helper.open_level("Physics", "NameNode_Prints")
# 2) Find and enable the test entity
test_entity = Entity.find_editor_entity("C19536277")
test_entity.set_start_status("active")
Report.result(Tests.test_entity_enabled, test_entity.get_start_status() == ACTIVE_STATUS)
# 3) Enter game mode
helper.enter_game_mode(Tests.game_mode_entered)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer)
@@ -0,0 +1,198 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C12712453
# Test Case Title : Verify Raycast Multiple Node
# fmt:off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
test_completed = ("The test successfully completed", "The test timed out")
# entities found
caster_found = ("Caster entity found", "Caster entity NOT found")
multi_target_close_found = ("Multicast close target entity found", "Multicast close target NOT found")
multi_target_far_found = ("Multicast far target entity found", "Multicast far target NOT found")
single_target_found = ("Single close target entity found", "Single close target NOT found")
fail_entities_found = ("Found all fail entities", "Failed to find at least one fail entities")
# entity results
caster_result = ("Caster was activated", "Caster was NOT activated")
multi_target_close_result = ("Multicast close target was hit with a ray", "Multicast close target WAS NOT hit with a ray")
multi_target_far_result = ("Multicast far target was hit with a ray", "Multicast far target WAS NOT hit with a ray")
single_target_result = ("Single target was hit with a ray", "Single target WAS NOT hit with a ray")
# fmt:on
# Lines to search for by the log monitor
class Lines:
# FAILURE (in all caps) is used as the failure flag for both this python script and ScriptCanvas.
# If this is present in the log, something has gone fatally wrong and the test will fail.
# Additional details as to why the test fails will be printed in the log accompanying this entry.
unexpected = ["FAILURE"]
def ScriptCanvas_MultipleRaycastNode():
"""
Summary:
Uses script canvas to cast two types of rays in game mode (multiple raycast and single raycast). Script canvas
validates the results from the raycasts, then deactivates any entities hit. This python script ensures only
the expected entities were deactivated.
Level Description:
Caster - A sphere with gravity disabled and a scriptcanvas component for emitting raycasts. Caster starts inactive.
Targets - Three spheres with gravity disabled. They are the expected targets of the raycasts.
Fail Boxes - These boxes are positioned in various places where no ray should collide with them. They are set
up print a fail message if any ray should hit them.
ScriptCanvas - The ScriptCanvas script is attached to the Caster entity, and is set to start on entity Activation.
The script will activate two different raycast nodes, a single raycast and a multiple raycast. For every raycast
hit, the script validates all properties of a raycast (while printing to log) and then deactivates any entity
that is [raycast] hit. This ScriptCanvas file can be found in this test's level folder named
"Raycast.scrpitcanvas".
Expected Behavior:
The level should load and appear to instantly close. After setup the Caster sphere should emit the raycasts which
should deactivate all expected Targets (via script canvas). The python script waits for the Targets to be
deactivated then prints the results.
Steps:
1) Load level / enter game mode
2) Retrieve entities
3) Start the test (activate the caster entity)
4) Wait for Target entities to deactivate
5) Exit game mode and close the editor
:return: None
"""
# Disabled until Script Canvas merges the new backend
return
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr
# Constants
TIME_OUT = 1.0
FAIL_ENTITIES = 5
# Entity base class handles very general entity initialization
class EntityBase:
def __init__(self, name):
# type: (str) -> None
self.name = name
self.id = general.find_game_entity(name)
# Stores entity "is active" state. Most entities start as "Active"
self.activated = True
# Caster starts deactivated. When the caster is activated the script canvas test will begin.
class Caster(EntityBase):
def __init__(self, name):
# type: (str) -> None
EntityBase.__init__(self, name)
found_tuple = Tests.__dict__[name.lower() + "_found"]
Report.critical_result(found_tuple, self.id.isValid())
# Caster starts as "Inactive" because the script canvas starts when Caster is Activated
self.activated = False
# Activates the Caster which starts it's ScriptCanvas script (and the test)
def activate(self):
# type: () -> None
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", self.id)
self.activated = True
Report.success(Tests.__dict__[self.name + "_result"])
# Targets start activated and only get deactivated by the ScriptCanvas script.
# Successful execution means every Target gets deactivated via ScriptCanvas
class Target(EntityBase):
def __init__(self, name):
# type: (str) -> None
EntityBase.__init__(self, name)
found_tuple = Tests.__dict__[name.lower() + "_found"]
Report.critical_result(found_tuple, self.id.isValid())
self.handler = azlmbr.entity.EntityBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnEntityDeactivated", self.on_deactivation)
# Callback: gets called when entity is deactivated. This is expected for Target entities.
def on_deactivation(self, args):
# type: ([EntityId, ...]) -> None
if args[0].Equal(self.id):
Report.success(Tests.__dict__[self.name + "_result"])
self.activated = False
# Disconnects event handler.
# (Needed so the deactivation callback doesn't not get called on level clean up)
def disconnect(self):
# type: () -> None
self.handler.disconnect()
self.handler = None
# Failure entities start activated and get deactivated via the ScriptCanvas. Ideally none will be deactivated
# during the test. If one is deactivated, and Failure message is logged that will be caught by the log monitor.
class Failure(EntityBase):
def __init__(self, num):
# type: (int) -> None
EntityBase.__init__(self, "fail_" + str(num))
if not self.id.IsValid():
Report.info("FAILURE: {} could not be found".format(self.name))
self.handler = azlmbr.entity.EntityBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnEntityDeactivated", self.on_deactivation)
# Callback: gets called when entity is deactivated. This is expected for Target entities.
def on_deactivation(self, args):
# type: ([EntityId, ...]) -> None
if args[0].Equal(self.id):
Report.info("{}: FAILURE".format(self.name))
self.activated = False
# Disconnects event handler.
# (Needed so the deactivation callback doesn't not get called on level clean up)
def disconnect(self):
# type: () -> None
self.handler.disconnect()
self.handler = None
# 1) Open level
helper.init_idle()
helper.open_level("Physics", "ScriptCanvas_MultipleRaycastNode")
helper.enter_game_mode(Tests.enter_game_mode)
# 2) Retrieve entities
caster = Caster("caster")
targets = [Target("multi_target_close"), Target("multi_target_far"), Target("single_target")]
fails = [Failure(i) for i in range(FAIL_ENTITIES)]
Report.critical_result(Tests.fail_entities_found, all(entity.id.isValid() for entity in fails))
# 3) Start the test
caster.activate()
# 4) Wait for Target entities to deactivate
test_completed = helper.wait_for_condition(lambda: all(not target.activated for target in targets), TIME_OUT)
Report.result(Tests.test_completed, test_completed)
# Disconnect all "on deactivated" event handlers so they don't get called implicitly on level cleanup
for entity in targets + fails:
entity.disconnect()
# 5) Close test
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_MultipleRaycastNode)
@@ -0,0 +1,319 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : 12712454
# Test Case Title : Verify overlap nodes in script canvas
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
# comm entities are used for communication between script canvas and the python script.
comm_entities_found = ("All comm entities found", "All comm entities not found")
script_canvas_entity_found = ("Script_Canvas_Entity Found", "Script_Canvas_Entity not found")
test_array_found = ("8x8 entity array found", "8x8 entity array not found")
all_tests_passed = ("All tests have expected results", "Some tests had unexpected results")
# Test 0
test_0_finished = ("Test 0 has ended", "Test 0 has not ended correctly")
test_0_results_logged = ("Test 0 logged expected results", "Test 0 logged unexpected results")
test_0_entity_reset = ("Test 0: entities moved back", "Test 0: not all entities moved back")
# Test 1
test_1_finished = ("Test 1 has ended", "Test 1 has not ended correctly")
test_1_results_logged = ("Test 1 logged expected results", "Test 1 logged unexpected results")
test_1_entity_reset = ("Test 1: entities moved back", "Test 1: not all entities moved back")
# Test 2
test_2_finished = ("Test 2 has ended", "Test 2 has not ended correctly")
test_2_results_logged = ("Test 2 logged expected results", "Test 2 logged unexpected results")
test_2_entity_reset = ("Test 2: entities moved back", "Test 2: not all entities moved back")
# fmt: on
def ScriptCanvas_OverlapNode():
"""
Summary: Verifies that the three script canvas overlap nodes (box, sphere, capsule) work as expected. Test
script starts and verifies each case one by one.
Level Description:
Test Array - 8x8 array of sphere entities lined up edge to edge along an y-z plane, they are names with
'Sphere_row_column' convention; has PhysX rigid body, sphere shaped PhysX collider, sphere shape.
Comm From Test- 3 communication entities that start inactive, used by the test script to initiate each of the three cases
by activation of the relevent sphere; has sphere shape.
Comm To Test- 3 communication entities that start inactive, used by the script canvas to initiate when each of the three
cases are completed by activation of the relevent sphere; has sphere shape.
Script Canvas Entity - Entity is centered in the test array and oriented with a 90 degree angle along the y
axis as to allow the capsule overlap node to overlap more entities; has script canvas component
Script Canvas - Has three execution cases, one for each overlap node type. Each case goes through a similar path
- Waits for relevant Comm From Test entity to be activated by the test script
- Creates an array of all entities in Test Array that overlap
- Uses this array to draw a blue sphere at every sphere that overlaps
- Uses the same array to move each overlapping entity 5 m along the +x axis
- Activates the relevant Comm To Test entity
The test script then logs the results and resets the Test Array before activating the next path.
Values for the overlaps:
Box: x = 4.5, y = 4.5, z = 4.5
Sphere: r = 4
Capsule: r = 0.5, h = 5
Note: For this script canvas to run properly it requires the custom .physxconfiguration file.
Tests Runs - Each loop runs a different overlap node
- test_0: Box
- test_1: Sphere
- test_2: Capsule
Expected Behavior: The script canvas will run it's three different overlap nodes. Each run the overlapped
spheres in the Test Array will be drawn in over in blue and then offset in the x direction so that this test
script can confirm that it worked correctly.
Test Steps:
1) Open Level
2) Enter Game Mode
3) Create Entity Objects
4) Validate Entities
5) Begin Testing
6) Signal Script Canvas to begin test
7) Wait until script canvas signals that it has completed the test
8) Check which entities in array have been moved
9) Validate and log results of test
10) Place all entities back into correct positions in entity array
11) Log results of all tests
12) Exit Game Mode
13) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.math as math
# Constants
FLOAT_THRESHOLD = 0.0001
# Timeout for a failed test in seconds
TIMEOUT = 1.0
ARRAY_X = 500.0
ARRAY_COLUMN_0 = 530.0
ARRAY_ROW_0 = 45.0
# Helper Functions
class Entity:
def __init__(self, name, activated):
self.id = general.find_game_entity(name)
self.name = name
self.activated = activated
self.handler = None
def activate_entity(self):
Report.info("Activating Entity : " + self.name)
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", self.id)
self.activated = True
def entity_activated(self, args):
self.activated = True
def set_handler(self):
self.handler = azlmbr.entity.EntityBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnEntityActivated", self.entity_activated)
class Sphere_Entities:
def __init__(self, row, column):
self.name = "Sphere_{}_{}".format(row, column)
self.id = general.find_game_entity(self.name)
self.y = column + ARRAY_COLUMN_0
self.z = ARRAY_ROW_0 - row
self.array_position = math.Vector3(ARRAY_X, self.y, self.z)
self.current_position = self.array_position
def check_id(self):
return self.id.isValid()
def move_entity_back(self):
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetWorldTranslation", self.id, self.array_position)
def in_position(self):
current_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
return abs(current_position.x - self.array_position.x) < FLOAT_THRESHOLD
class Script_Canvas_Test:
def __init__(self, index):
self.index = index
self.name = "test_{}".format(index)
self.got_expected_result = False
self.test_finish = None
self.results_logged = None
self.array_reset = None
def report_test_start(self):
Report.info("Test {} has begun".format(self.index))
def report_test_finished(self, finished):
self.test_finish = Tests.__dict__["test_{}_finished".format(self.index)]
Report.result(self.test_finish, finished)
def report_results_logged(self):
self.results_logged = Tests.__dict__["test_{}_results_logged".format(self.index)]
Report.result(self.results_logged, self.got_expected_result)
def report_test_array_reset(self, entities_in_position):
self.array_reset = Tests.__dict__["test_{}_entity_reset".format(self.index)]
Report.result(self.array_reset, entities_in_position)
# fmt: off
class Result_Arrays:
true_bool_array = [[True for column in range(8)] for row in range(8)]
# Comparison Array for box overlap node
test_0_bool_array = [
[True, True, True, True, True, True, True, True],
[True, False, False, False, False, False, False, True],
[True, True, False, False, False, False, False, True],
[True, False, False, False, False, False, False, True],
[True, True, False, False, False, False, False, True],
[True, True, False, False, False, False, False, True],
[True, True, False, False, False, False, False, True],
[True, True, True, True, True, True, True, True],
]
# Comparison Array for sphere overlap node
test_1_bool_array = [
[True, True, True, True, True, True, True, True],
[True, True, False, False, False, False, True, True],
[True, False, False, False, False, False, False, True],
[True, False, False, False, False, False, False, True],
[True, False, False, False, False, False, False, True],
[True, False, False, False, False, False, False, True],
[True, True, False, False, False, False, True, True],
[True, True, True, True, True, True, True, True],
]
# Comparison Array for capsule overlap node
test_2_bool_array = [
[True, True, True, True, True, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, False, False, True, True, True],
[True, True, True, True, True, True, True, True],
]
# fmt on
def create_test_Sphere_Entities():
return [[Sphere_Entities(row, column) for column in range(8)] for row in range(8)]
def sphere_array_isvalid(array):
for row in range(len(array)):
for column in range(len(array[0])):
if not array[row][column].id.isValid():
return False
return True
def check_comm_entities(comm_list):
for entity in comm_list:
if not entity.id.isValid():
return False
return True
def check_array_movement(array):
return [[True if entity.in_position() else False for entity in row] for row in array]
def reset_array(array):
for row in array:
for entity in row:
entity.move_entity_back()
def is_array_in_position(array):
return arrays_are_the_same(Result_Arrays.true_bool_array, check_array_movement(array))
def arrays_are_the_same(array_0, array_1):
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]
return differences == []
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("Physics", "ScriptCanvas_OverlapNode")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Create Entity and Script_Canvas_Test Objects
test_Sphere_Entities = create_test_Sphere_Entities()
script_canvas_entity = Entity("Script_Canvas_Entity", True)
comm_from_test_0 = Entity("Comm_From_Test_0", False)
comm_from_test_1 = Entity("Comm_From_Test_1", False)
comm_from_test_2 = Entity("Comm_From_Test_2", False)
comm_to_test_0 = Entity("Comm_To_Test_0", False)
comm_to_test_1 = Entity("Comm_To_Test_1", False)
comm_to_test_2 = Entity("Comm_To_Test_2", False)
comm_from_entity_list = (comm_from_test_0, comm_from_test_1, comm_from_test_2)
comm_to_entity_list = (comm_to_test_0, comm_to_test_1, comm_to_test_2)
test_0 = Script_Canvas_Test(0)
test_1 = Script_Canvas_Test(1)
test_2 = Script_Canvas_Test(2)
test_list = (test_0, test_1, test_2)
# 4) Validate Entities
Report.critical_result(Tests.script_canvas_entity_found, script_canvas_entity.id.isValid())
Report.critical_result(
Tests.comm_entities_found, check_comm_entities(comm_from_entity_list + comm_to_entity_list)
)
Report.critical_result(Tests.test_array_found, sphere_array_isvalid(test_Sphere_Entities))
# 5) Begin Testing
for test in test_list:
# 6) Signal Script Canvas to begin test
comm_from_entity_list[test.index].activate_entity()
test.report_test_start()
# 7) Wait until script canvas signals that it has completed the test
comm_to_entity_list[test.index].set_handler()
test.report_test_finished(helper.wait_for_condition(lambda: comm_to_entity_list[test.index].activated, TIMEOUT))
# 8) Check which entities in array have been moved
result_bool_array = check_array_movement(test_Sphere_Entities)
# 9) Validate and log results of test
test.got_expected_result = arrays_are_the_same(
result_bool_array, Result_Arrays.__dict__["test_{}_bool_array".format(test.index)]
)
test.report_results_logged()
if test.index == 0:
Report.info(result_bool_array)
# 10) Place all entities back into correct positions in entity array
reset_array(test_Sphere_Entities)
test.report_test_array_reset(is_array_in_position(test_Sphere_Entities))
# 11) Log results of all tests
Report.result(
Tests.all_tests_passed, test_0.got_expected_result and test_1.got_expected_result and test_2.got_expected_result
)
# 12) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_OverlapNode)
@@ -0,0 +1,109 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C14902098
# Test Case Title : Check that force region simulation with Postsimulate works independently from rendering tick
# fmt: off
class Tests():
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
find_sphere = ("Sphere found", "Sphere not found")
find_force_region = ("Force Region is found", "Force Region is not found")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
# fmt: on
class LogLines:
"""
These lines are added to the expected lines in the test suite.
"""
expected_lines = [
"OnTick Event: The Sphere position did not change from previous position",
"OnTick Event: The Sphere position changed from previous position",
"OnPostPhysicsSubtick Event: The Sphere position changed from previous position",
]
unexpected_lines = ["OnPostPhysicsSubtick Event: The Sphere position did not change from previous position"]
def ScriptCanvas_PostPhysicsUpdate():
"""
Summary:
Check that force region simulation with Postsimulate works independently from rendering tick.
Level Description:
A Sphere is placed inside a Force Region. The "Fixed Time Step" in PhysX Configuration is set to 0.05.
ForceRegion (entity) - Entity with PhysX Collider, PhysX Force Region (World Space force with magnitude 5.0) and
Box Shape components
Sphere (entity) - Entity with PhysX Rigid Body, PhysX Collider, Mesh and 2 Script Canvas components
Script Canvas:
onpostphysicsupdate - The script checks the position of the sphere on every On Postsimulate event and prints
debug statements as per the position of the sphere relative to its previous position.
ontick - The script checks the position of the sphere on every On Tick event and prints
debug statements as per the position of the sphere relative to its previous position.
Expected Behavior:
The position of the sphere needs to be changed relative to its previous position for every
OnPostPhysicsSubtick event.
The position of the sphere sometimes change and sometimes remains in the same position as before
for OnTick event.
Test Steps:
1) Open level
2) Enter game mode
3) Retrieve and validate entities
4) Wait for WAIT_TIME for the events to occur
5) Exit game mode
6) Close the editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
# Constants
WAIT_TIME = 0.5
helper.init_idle()
# 1) Open level
helper.open_level("Physics", "ScriptCanvas_PostPhysicsUpdate")
# 2) Enter game mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Retrieve and validate entities
sphere_id = general.find_game_entity("Sphere")
Report.critical_result(Tests.find_sphere, sphere_id.IsValid())
force_region_id = general.find_game_entity("ForceRegion")
Report.critical_result(Tests.find_force_region, force_region_id.IsValid())
# 4) Wait for WAIT_TIME for the events to occur
general.idle_wait(WAIT_TIME)
# 5) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_PostPhysicsUpdate)
@@ -0,0 +1,181 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C14195074
# Test Case Title : Verify Postsimulate Events
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
lead_sphere_found = ("Lead_Sphere is valid", "Lead_Sphere is not valid")
follow_sphere_found = ("Follow_Sphere is valid", "Follow_Sphere is not valid")
no_movement = ("Spheres start with no movement", "Spheres not stationary")
initial_position = ("Initial position is valid", "Initial position is not valid")
lead_sphere_velocity = ("Lead_Sphere has valid velocity", "Lead_Sphere velocity not valid")
spheres_moving = ("Spheres have both moved", "Both sphere have not moved before timeout")
follow_condition_true = ("Follow_Sphere is correctly trailing", "Follow_Sphere follow distance not valid")
# fmt: on
def ScriptCanvas_PostUpdateEvent():
"""
Summary: Verifies that Postsimulate Event node in Script Canvas works as expected.
Level Description:
Lead_Sphere - Directly next to Follow_sphere on the +x axis; has rigid body(gravity disabled), sphere shape
collider, sphere shape
Follow_Sphere - Directly next to Lead_Sphere on the -x axis; has rigid body (gravity disabled, kinematic
enabled), sphere shape collider, sphere shape, script canvas
Script Canvas - After every PhysX frame is calculated Follow_Sphere is moved to directly next to the
Lead_sphere before being presented in the viewer
PhysX Configuration - The PhysX configuration file was modified to lower the frame rate to 20 Hz for visual debug
Expected Behavior: Follow_Sphere follows Lead_spheres position, staying within direct contact no matter the speed
Test Steps:
1) Open Level
2) Enter Game Mode
3) Create and Validate entities
4) Validate spheres are not moving
5) Check Position of Spheres
6) Start moving sphere and check that it acts correctly
7) Wait until Lead_Sphere has moved a set distance
8) Verify Follow_Sphere follow distance
9) Log results
10) Exit Game Mode
11) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.math as math
# Constants
FLOAT_THRESHOLD = sys.float_info.epsilon
TIMEOUT = 5
INITIAL_OFFSET = 1
REQUIRED_MOVEMENT = 2
LEAD_SPHERE_VELOCITY = 10.0
FINAL_OFFSET = INITIAL_OFFSET
# Helper Functions
class Entity:
def __init__(self, name):
self.id = general.find_game_entity(name)
self.name = name
self.initial_position = self.position
self.final_position = None
# Validate Entities
found = Tests.__dict__[self.name.lower() + "_found"]
Report.critical_result(found, self.id.isValid())
@property
def position(self):
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
@property
def velocity(self):
return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetLinearVelocity", self.id)
def set_velocity(self, x_velocity, y_velocity, z_velocity):
velocity = math.Vector3(x_velocity, y_velocity, z_velocity)
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearVelocity", self.id, velocity)
def moved_enough(self):
current_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
return abs(self.initial_position.x - current_position.x) >= REQUIRED_MOVEMENT
def report_values(self):
Report.info_vector3(self.initial_position, "{} initial position: ".format(self.name))
Report.info_vector3(self.final_position, "{} final position: ".format(self.name))
def check_relative_position(lead_sphere_position, follow_sphere_position, offset):
return (
abs((lead_sphere_position.x - follow_sphere_position.x) - offset) < FLOAT_THRESHOLD
and abs(lead_sphere_position.y - follow_sphere_position.y) < FLOAT_THRESHOLD
and abs(lead_sphere_position.z - follow_sphere_position.z) < FLOAT_THRESHOLD
)
def velocity_zero(sphere_velocity):
return (
abs(sphere_velocity.x) < FLOAT_THRESHOLD
and abs(sphere_velocity.y) < FLOAT_THRESHOLD
and abs(sphere_velocity.z) < FLOAT_THRESHOLD
)
def velocity_valid(lead_sphere_velocity):
return (
lead_sphere_velocity.x == LEAD_SPHERE_VELOCITY
and abs(lead_sphere_velocity.y) < FLOAT_THRESHOLD
and abs(lead_sphere_velocity.z) < FLOAT_THRESHOLD
)
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("Physics", "ScriptCanvas_PostUpdateEvent")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Create and validate entities
lead_sphere = Entity("Lead_Sphere")
follow_sphere = Entity("Follow_Sphere")
# 4) Validate Spheres are not moving
Report.critical_result(
Tests.no_movement, velocity_zero(lead_sphere.velocity) and velocity_zero(follow_sphere.velocity)
)
# 5) Check Position of Spheres
Report.result(
Tests.initial_position,
check_relative_position(lead_sphere.initial_position, follow_sphere.initial_position, INITIAL_OFFSET),
)
# 6) Start moving sphere and check that it acts correctly
lead_sphere.set_velocity(LEAD_SPHERE_VELOCITY, 0.0, 0.0)
Report.result(Tests.lead_sphere_velocity, velocity_valid(lead_sphere.velocity))
# 7) Wait until Lead_Sphere has moved a set distance
Report.result(Tests.spheres_moving, helper.wait_for_condition(lead_sphere.moved_enough, TIMEOUT))
# 8) Verify Follow_Sphere follow distance
lead_sphere.final_position = lead_sphere.position
follow_sphere.final_position = follow_sphere.position
Report.result(
Tests.follow_condition_true, check_relative_position(lead_sphere.final_position, follow_sphere.final_position, FINAL_OFFSET)
)
# 9) Log results
lead_sphere.report_values()
follow_sphere.report_values()
# 10) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_PostUpdateEvent)
@@ -0,0 +1,191 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C14902097
# Test Case Title : Verify Presimulate Events
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
lead_sphere_found = ("Lead_Sphere is valid", "Lead_Sphere is not valid")
follow_sphere_found = ("Follow_Sphere is valid", "Follow_Sphere is not valid")
no_movement = ("Spheres start with no movement", "Spheres not stationary")
initial_position = ("Initial position is valid", "Initial position isn't valid")
lead_sphere_velocity = ("Lead_Sphere has valid velocity", "Lead_Sphere velocity not valid")
spheres_moving = ("Spheres have both moved", "Both sphere have not moved before timeout")
follow_condition_true = ("Follow_Sphere is correctly trailing", "Follow_Sphere follow distance not valid")
# fmt: on
def ScriptCanvas_PreUpdateEvent():
"""
Summary: Verifies that Presimulate node in Script Canvas works as expected.
Level Description:
Lead_Sphere - Directly next to Follow_sphere on the +x axis; has rigid body (gravity disabled), sphere shape
collider, sphere shape
Follow_Sphere - Directly next to Lead_Sphere on the -x axis; has rigid body (gravity disabled, kinematic
enabled), sphere shape collider, sphere shape, script canvas
Script Canvas - Before every frame of PhysX calculation the Follow_Sphere is moved directly next to the
Lead_Sphere, then PhysX calculates and moves the Lead_Sphere to a new position before presenting to
the viewer
PhysX Configuration - The PhysX configuration file was modified to lower the frame rate to 20 Hz for visual debug
Expected Behavior: Follow_Sphere follows Lead_spheres position with a lag that is dependent on the speed and the
inverse frame rate
Test Steps:
1) Open Level
2) Enter Game Mode
3) Create and Validate entities
4) Validate Spheres are not moving
5) Check Position of Spheres
6) Start moving sphere and check that it acts correctly
7) Wait until Lead_Sphere has moved a set distance
8) Verify Follow_Sphere follow distance
9) Log results
10) Exit Game Mode
11) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.math as math
# Constants
FLOAT_THRESHOLD = 0.1
TIMEOUT = 5
INITIAL_OFFSET = 1
REQUIRED_MOVEMENT = 2
FIXED_TIME_STEP = 0.05 # must be changed in level as well
LEAD_SPHERE_VELOCITY = 10.0
FINAL_OFFSET = (LEAD_SPHERE_VELOCITY * FIXED_TIME_STEP) + INITIAL_OFFSET
OFFSET_TOLERANCE = FINAL_OFFSET * 0.25
# Helper Functions
class Entity:
def __init__(self, name):
self.id = general.find_game_entity(name)
self.name = name
self.initial_position = self.position
self.final_position = None
# Validate Entities
found = Tests.__dict__[self.name.lower() + "_found"]
Report.critical_result(found, self.id.isValid())
@property
def position(self):
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
@property
def velocity(self):
return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetLinearVelocity", self.id)
def set_velocity(self, x_velocity, y_velocity, z_velocity):
velocity = math.Vector3(x_velocity, y_velocity, z_velocity)
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearVelocity", self.id, velocity)
def moved_enough(self):
current_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
return abs(self.initial_position.x - current_position.x) >= REQUIRED_MOVEMENT
def report_values(self):
Report.info_vector3(self.initial_position, "{} initial position: ".format(self.name))
Report.info_vector3(self.final_position, "{} final position: ".format(self.name))
def check_relative_position(lead_sphere_position, follow_sphere_position, offset):
return (
abs((lead_sphere_position.x - follow_sphere_position.x) - offset) < OFFSET_TOLERANCE
and abs(lead_sphere_position.y - follow_sphere_position.y) < FLOAT_THRESHOLD
and abs(lead_sphere_position.z - follow_sphere_position.z) < FLOAT_THRESHOLD
)
def velocity_zero(sphere_velocity):
return (
abs(sphere_velocity.x) < FLOAT_THRESHOLD
and abs(sphere_velocity.y) < FLOAT_THRESHOLD
and abs(sphere_velocity.z) < FLOAT_THRESHOLD
)
def velocity_valid(lead_sphere_velocity):
return (
lead_sphere_velocity.x == LEAD_SPHERE_VELOCITY
and abs(lead_sphere_velocity.y) < FLOAT_THRESHOLD
and abs(lead_sphere_velocity.z) < FLOAT_THRESHOLD
)
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("Physics", "ScriptCanvas_PreUpdateEvent")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Create and validate entities
lead_sphere = Entity("Lead_Sphere")
follow_sphere = Entity("Follow_Sphere")
# 4) Validate Spheres are not moving
Report.critical_result(
Tests.no_movement, velocity_zero(lead_sphere.velocity) and velocity_zero(follow_sphere.velocity)
)
# 5) Check Position of Sphere
Report.result(
Tests.initial_position,
check_relative_position(lead_sphere.initial_position, follow_sphere.initial_position, INITIAL_OFFSET),
)
# 6) Start moving sphere and check that it acts correctly
lead_sphere.set_velocity(LEAD_SPHERE_VELOCITY, 0.0, 0.0)
Report.result(Tests.lead_sphere_velocity, velocity_valid(lead_sphere.velocity))
# 7) Wait until Lead_Sphere has moved a set distance
Report.result(Tests.spheres_moving, helper.wait_for_condition(lead_sphere.moved_enough, TIMEOUT))
# 8) Verify Follow_Sphere follow distance
lead_sphere.final_position = lead_sphere.position
follow_sphere.final_position = follow_sphere.position
Report.result(
Tests.follow_condition_true, check_relative_position(lead_sphere.final_position, follow_sphere.final_position, FINAL_OFFSET)
)
# 9) Log results
lead_sphere.report_values()
follow_sphere.report_values()
Report.info("Offset:" + str(FINAL_OFFSET))
# 10) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_PreUpdateEvent)
@@ -0,0 +1,219 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test Case
# ID : C14976308
# Title : Verify that SetKinematicTarget on PhysX rigid body updates transform for kinematic entities and vice versa
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
sphere_found_valid = ("Sphere found and validated", "Sphere not found and validated")
kinematic_target_found_valid = ("Kinematic_Target found and validated", "Kinematic_Target not found and validated")
transform_target_found_valid = ("Transform_Target found and validated", "Transform_Target not found and validated")
signal_found_valid = ("Signal found and validated", "Signal not found and validated")
sphere_gravity_disabled = ("Gravity is disabled on Sphere", "Gravity is not disabled on Sphere")
sphere_kinematic = ("Sphere is kinematic", "Sphere is not kinematic")
entity_translations_differ = ("Each entity has a different initial translation", "Each entity does not have a different initial translation")
entity_rotations_differ = ("Each entity has a different initial rotation", "Each entity does not have a different initial rotation")
entity_scales_differ = ("Each entity has a different initial scale", "Each entity does not have a different initial scale")
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")
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")
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")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
# fmt: on
def ScriptCanvas_SetKinematicTargetTransform():
"""
Summary:
This script runs an automated test to verify the results of two Script Canvas nodes acting on a kinematic rigid
body:
1) Set Kinematic Target will update the kinematic rigid body's translation and rotation to those of the transform
which the node passes to it.
2) Set World Transform will update a kinematic rigid body's transform to the transform which the node passes to it.
Level Description:
Entity: Sphere: PhysX Rigid Body, PhysX Collider with sphere shape, and Mesh with sphere asset
Gravity disabled, kinematic enabled
Translate (79.0, 39.0, 34.0) in meters
Rotate (1.0, 2.0, 3.0) in degrees
Scale (1.0, 1.0, 1.0)
Entity: Kinematic_Target: Mesh with cube asset
Translate (48.0, 56.0, 36.0) in meters
Rotate (11.0, 12.0, 13.0) in degrees
Scale (1.1, 1.2, 1.3)
Entity: Transform_Target: Mesh with cube asset
Translate (72.0, 80.0, 38.0) in meters
Rotate (21.0, 22.0, 23.0) in degrees
Scale (2.1, 2.2, 2.3)
Entity: Signal: Start inactive, attached Script Canvas asset which will cause the following:
On Signal Activated will Set Kinematic Target on Sphere to Kinematic_Target's transform
On Signal Deactivated will Set World Transform on Sphere to Transform_Target's transform
Other than the signal, the entities all have different translations, rotations, and scales.
Expected behavior:
When the script activates Signal, Sphere's translation and rotation will update to those of Kinematic_Target. When
the script deactivates Signal, Sphere's transform will update to that of Transform_Target.
NOTE: There is a known bug (LY-107723) which causes the rotation to update to a value that is not sufficiently close
to the expected result when using Set Kinematic Target which will cause the test to fail:
LY-107723
Test Steps:
1) Open level and enter game mode
2) Retrieve and validate entities
3) Check that gravity is disabled on the sphere
4) Check that the sphere is kinematic
5) Check that each entity except the signal has a different initial translation
6) Check that each entity except the signal has a different initial rotation
7) Check that each entity except the signal has a different initial scale
8) Activate the signal entity to trigger the Set Kinematic Target node in Script Canvas
9) Wait one frame and check that the sphere's translation has updated to that of Kinematic_Target
10) Check that the sphere's rotation has updated to that of Kinematic_Target
11) Deactivate the signal entity to trigger the Set World Transform node in Script Canvas
12) Check that the sphere's transform has updated to that of Transform_Target
13) Exit game mode and close editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Setup path
import os
import sys
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.components
import azlmbr.math
import azlmbr.physics
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import itertools
class Entity:
def __init__(self, name):
self.name = name
self.id = general.find_game_entity(name)
self.found_valid_test = Tests.__dict__[self.name.lower() + "_found_valid"]
Report.critical_result(self.found_valid_test, self.id.IsValid())
def is_gravity_disabled(self):
return not azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
def is_kinematic(self):
return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsKinematic", self.id)
def get_world_transform(self):
transform = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", self.id)
Report.info_vector3(transform.position, "{}'s position:".format(self.name))
Report.info_vector3(transform.basisX, "{}'s basisX:".format(self.name))
Report.info_vector3(transform.basisY, "{}'s basisY:".format(self.name))
Report.info_vector3(transform.basisZ, "{}'s basisZ:".format(self.name))
return transform
def get_world_translation(self):
translation = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
Report.info_vector3(translation, "{}'s Translation:".format(self.name))
return translation
def get_world_rotation(self):
rotation = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldRotation", self.id)
Report.info_vector3(rotation, "{}'s Rotation:".format(self.name))
return rotation
def get_world_scale(self):
scale = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldScale", self.id)
Report.info_vector3(scale, "{}'s Scale:".format(self.name))
return scale
def transform_matches(self, other):
return self.get_world_transform().Equal(other.get_world_transform())
def translation_matches(self, other):
return self.get_world_translation().Equal(other.get_world_translation())
def rotation_matches(self, other):
return self.get_world_rotation().Equal(other.get_world_rotation())
def scale_matches(self, other):
return self.get_world_scale().Equal(other.get_world_scale())
def entities_translations_differ(entities):
for entity_a, entity_b in itertools.combinations(entities, 2):
if entity_a.translation_matches(entity_b):
return False
return True
def entities_rotations_differ(entities):
for entity_a, entity_b in itertools.combinations(entities, 2):
if entity_a.rotation_matches(entity_b):
return False
return True
def entities_scales_differ(entities):
for entity_a, entity_b in itertools.combinations(entities, 2):
if entity_a.scale_matches(entity_b):
return False
return True
# 1) Open level and enter game mode
helper.init_idle()
helper.open_level("Physics", "ScriptCanvas_SetKinematicTargetTransform")
helper.enter_game_mode(Tests.enter_game_mode)
# 2) Retrieve and validate entities
sphere = Entity("Sphere")
kinematic_target = Entity("Kinematic_Target")
transform_target = Entity("Transform_Target")
signal = Entity("Signal")
non_signal_entities = (sphere, kinematic_target, transform_target)
# 3) Check that gravity is disabled on the sphere
Report.critical_result(Tests.sphere_gravity_disabled, sphere.is_gravity_disabled())
# 4) Check that the sphere is kinematic
Report.critical_result(Tests.sphere_kinematic, sphere.is_kinematic())
# 5) Check that each entity except the signal has a different initial translation
Report.critical_result(Tests.entity_translations_differ, entities_translations_differ(non_signal_entities))
# 6) Check that each entity except the signal has a different initial rotation
Report.critical_result(Tests.entity_rotations_differ, entities_rotations_differ(non_signal_entities))
# 7) Check that each entity except the signal has a different initial scale
Report.critical_result(Tests.entity_scales_differ, entities_scales_differ(non_signal_entities))
# 8) Activate the signal entity to trigger the Set Kinematic Target node in Script Canvas
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", signal.id)
# 9) Wait one frame and check that the sphere's translation has updated to that of Kinematic_Target
general.idle_wait_frames(1)
Report.result(Tests.sphere_translation_1_valid, sphere.translation_matches(kinematic_target))
# 10) Check that the sphere's rotation has updated to that of Kinematic_Target
# NOTE: This test currently fails due to a known bug (LY-107723)
Report.result(Tests.sphere_rotation_1_valid, sphere.rotation_matches(kinematic_target))
# 11) Deactivate the signal entity to trigger the Set World Transform node in Script Canvas
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "DeactivateGameEntity", signal.id)
# 12) Check that the sphere's transform has updated to that of Transform_Target
Report.result(Tests.sphere_transform_2_valid, sphere.transform_matches(transform_target))
# 13) Exit game mode and close editor
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_SetKinematicTargetTransform)
@@ -0,0 +1,136 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C12712455
# Test Case Title : Verify shape cast nodes in SC
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
Ball_0_found = ("Ball_0 entity is found", "Ball_0 entity is not found")
Ball_1_found = ("Ball_1 entity is found", "Ball_1 entity is not found")
Notification_Entity_0_found = ("Notification_Entity_0 entity found", "Notification_Entity_0 entity invalid")
Notification_Entity_1_found = ("Notification_Entity_1 entity found", "Notification_Entity_1 entity invalid")
Notification_Entity_2_found = ("Notification_Entity_2 entity found", "Notification_Entity_2 entity invalid")
Ball_0_gravity = ("Ball_0 gravity is disabled", "Ball_0 gravity is enabled")
Ball_1_gravity = ("Ball_1 gravity is disabled", "Ball_1 gravity is enabled")
Notification_Entity_0_gravity = ("Notification_Entity_0 gravity disabled", "Notification_Entity_0 gravity enabled")
Notification_Entity_1_gravity = ("Notification_Entity_1 gravity disabled", "Notification_Entity_1 gravity enabled")
Notification_Entity_2_gravity = ("Notification_Entity_2 gravity disabled", "Notification_Entity_2 gravity enabled")
script_canvas_translation_node = ("Script canvas through translation node", "Script canvas failed translation node")
script_canvas_sphere_cast_node = ("Script canvas through sphere cast node", "Script canvas failed sphere cast node")
script_canvas_draw_sphere_node = ("Script canvas through draw sphere node", "Script canvas failed draw sphere node")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
# fmt: on
def ScriptCanvas_ShapeCast():
"""
Summary: Verifies that shape cast nodes in script editor function properly.
Level Description:
Ball_0 - Starts stationary with gravity disabled on -y axis from Ball_1; has Sphere shape collider, Rigid Body,
Sphere Shape, Script Canvas
Ball_1 - Starts stationary with gravity disabled on +y axis from Ball_0; has Sphere shape collider, Rigid Body,
Sphere Shape
Notification_Entity_0 - Starts stationary with gravity disabled; has rigid body, Sphere shape
Notification_Entity_1 - Starts stationary with gravity disabled; has rigid body, Sphere shape
Notification_Entity_2 - Starts stationary with gravity disabled; has rigid body, Sphere shape
Script Canvas - Creates a sphere cast from Ball_0 to Ball_1 and draws the sphere in. As the script progresses
through the translation, sphere cast, and sphere draw nodes it enables gravity on the spheres in order to
show that each node has been passed.
Expected Behavior: A sphere will be drawn on ball_1 in from ball_0. The three notification_entities will fall as
gravity is enabled on them in order.
Test Steps:
1) Open Level
2) Enter Game Mode
3) Create entity objects
4) Verify entities and check gravity
5) Wait for conditions or timeout
6) Log results
7) Exit Game Mode
8) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
# Helper Functions
class Entity:
# Constants
GRAVITY_WAIT_TIMEOUT = 1
def __init__(self, name, expected_initial_velocity=None, expected_final_velocity=None):
self.id = general.find_game_entity(name)
self.name = name
self.gravity_was_enabled = False
self.handler = None
# 4) Verify entities and check gravity
try:
self.found_test = Tests.__dict__[self.name + "_found"]
self.gravity_disabled_test = Tests.__dict__[self.name + "_gravity"]
except Exception as e:
Report.info("Can not find specified tuples in Tests class")
Report.info(e)
raise ValueError
Report.critical_result(self.found_test, self.id.isValid())
gravity_enabled = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
Report.critical_result(self.gravity_disabled_test, not gravity_enabled)
def check_gravity_enabled(self):
self.gravity_was_enabled = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
return self.gravity_was_enabled
def wait_for_gravity_enabled(self):
helper.wait_for_condition(self.check_gravity_enabled, Entity.GRAVITY_WAIT_TIMEOUT)
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("Physics", "ScriptCanvas_ShapeCast")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Create entity objects
ball_0 = Entity("Ball_0")
ball_1 = Entity("Ball_1")
notification_entity_0 = Entity("Notification_Entity_0")
notification_entity_1 = Entity("Notification_Entity_1")
notification_entity_2 = Entity("Notification_Entity_2")
# 5) Wait for conditions or timeout
notification_list = [notification_entity_0, notification_entity_1, notification_entity_2]
for entity in notification_list:
entity.wait_for_gravity_enabled()
# 6) Log results
Report.result(Tests.script_canvas_translation_node, notification_entity_0.gravity_was_enabled)
Report.result(Tests.script_canvas_sphere_cast_node, notification_entity_1.gravity_was_enabled)
Report.result(Tests.script_canvas_draw_sphere_node, notification_entity_2.gravity_was_enabled)
# 7) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_ShapeCast)
@@ -0,0 +1,143 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C6224408
# Test Case Title : Entity using PhysX nodes in Script Canvas can be spawned.
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
spawn_point_position = ("Spawn_Point is above the terrain", "Spawn_Point is below the terrain")
Ball_0_found = ("Ball_0 entity is valid", "Ball_0 entity is not valid")
Spawn_Point_found = ("Spawn_Point entity is valid", "Spawn_Point entity is not valid")
Terrain_found = ("Terrain entity is valid", "Terrain entity is not valid")
ball_spawned = ("A ball has been spawned", "A ball has not been spawned")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
# fmt: on
def ScriptCanvas_SpawnEntityWithPhysComponents():
"""
Summary:
A spawner is set to spawn a sphere with downward velocity after a set amount of time. This action is controlled
by a scriptcanvas.
Level Description:
Ball_0 - Existing only for user reference, a dynamic slice is taken from Ball_0 and used by the Spawn_point entity.
Is set with velocity in the negative -z direction; has sphere shaped Collider, Rigid Body, Sphere shape, and
Script Canvas (can be placed anywhere on the level). Velocity set to zero and script canvas added after dynamic
slice taken.
Spawn_Point - Activated by the associated Script canvas to spawn the associated dynamic slice; has spawner
Terrain - Surface for spawned ball to bounce against; has terrain
Script Canvas - The script canvas after a delay of 0.5 seconds tells the Spawn_Point entity to spawn.
Expected Behavior:
After a set amount of time dictated by the script canvas a ball will spawn and collide with the terrain component.
Test Steps:
1) Open Level
2) Enter Game Mode
3) Initialize and validate entities
4) Set up handler for terrain collision
5) Wait for terrain collision
6) Log Results
7) Exit Game Mode
8) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
import azlmbr.entity
# Constants
FLOAT_THRESHOLD = sys.float_info.epsilon
TIMEOUT = 3.0
# Global Variables
id_list = []
# Helper Functions
class Collision:
collision_on_terrain = False
class Entity:
def __init__(self, name, has_rigid_body):
self.id = general.find_game_entity(name)
self.name = name
self.initial_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
id_list.append(self.id)
class Tests:
found = None
def validate_entity(self):
self.Tests.found = Tests.__dict__[self.name + "_found"]
Report.critical_result(self.Tests.found, self.id.isValid())
def spawn_point_position_check(spawn_point, terrain):
position_valid = (
spawn_point.initial_position.z > terrain.initial_position.z
)
Report.critical_result(Tests.spawn_point_position, position_valid)
def on_terrain_collision(arg):
if arg[0] not in id_list: # ensures that the collision is with a new entity
Collision.collision_on_terrain = True
Report.info("Something new has collided with the Terrain")
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("physics", "ScriptCanvas_SpawnEntityWithPhysComponents")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Initialize and validated entities
ball_0 = Entity("Ball_0", True)
spawn_point = Entity("Spawn_Point", False)
terrain = Entity("Terrain", False)
entity_list = [ball_0, spawn_point, terrain]
for entity in entity_list:
entity.validate_entity()
spawn_point_position_check(spawn_point, terrain)
# 4) Set up handler for terrain collision
handler = azlmbr.physics.CollisionNotificationBusHandler()
handler.connect(terrain.id)
handler.add_callback("OnCollisionBegin", on_terrain_collision)
# 5) Wait for terrain collision
helper.wait_for_condition(lambda: Collision.collision_on_terrain, TIMEOUT)
# 6) Log Results
Report.result(Tests.ball_spawned, Collision.collision_on_terrain)
# 7) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_SpawnEntityWithPhysComponents)
@@ -0,0 +1,127 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C6274125
# Test Case Title : Verify ScriptCanvas Trigger Events.
# fmt: off
class Tests():
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
find_box = ("Box entity found", "Box entity not found")
find_sphere = ("Sphere entity found", "Sphere entity not found")
sphere_enter_triggerarea = ("Sphere entered the trigger area", "Sphere did not entered trigger area")
sphere_exit_triggerarea = ("Sphere exited the trigger area", "Sphere did not exited the trigger area")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
# fmt: on
class LogLines:
"""
These lines are added to the expected lines in the test suite.
"""
expected_lines = [
"Scriptcanvas:Sphere entered the trigger Area",
"Scriptcanvas:Sphere exited the trigger Area",
]
def ScriptCanvas_TriggerEvents():
"""
Summary:
Verify ScriptCanvas Trigger Events.
Level Description:
BoxCollider (entity) - Entity contains PhysX Collider (Box shape) and trigger is enabled for it.
ScriptCanvas is attached to the PhysX box shape collider entity. ScriptCanvas has two trigger events.
ScriptCanvas trigger events are OnTriggerEnter and OnTriggerExit.
Sphere (entity) - Entity contains PhysX Collider(Sphere shape) with PhysX Rigid Body.
Expected Behavior:
When game mode is entered, Sphere should enter and exit from ScriptCanvas Trigger area. ScriptCanvas prints
the name of the entity when it enters and exits the ScriptCanvas trigger area.
Test Steps:
1) Open level
2) Enter game mode
3) Retrieve and validate entities
4) Verify Sphere enter and exit from ScriptCanvas Trigger area
5) Exit game mode
6) Close the editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
import azlmbr.legacy.general as general
import azlmbr.bus
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
helper.init_idle()
# Constants
TIMEOUT = 2.5
# 1) Open level
helper.open_level("Physics", "ScriptCanvas_TriggerEvents")
# 2) Enter game mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Retrieve and validate entities
box_id = general.find_game_entity("Box")
Report.critical_result(Tests.find_box, box_id.IsValid())
sphere_id = general.find_game_entity("Sphere")
Report.critical_result(Tests.find_sphere, sphere_id.IsValid())
# 4) Verify Sphere enter and exit from ScriptCanvas Trigger area
class BoxTrigger:
entered = False
exited = False
def on_enter(args):
other_id = args[0]
if other_id.Equal(sphere_id):
Report.info("Trigger entered")
BoxTrigger.entered = True
def on_exit(args):
other_id = args[0]
if other_id.Equal(sphere_id):
Report.info("Trigger exited")
BoxTrigger.exited = True
handler = azlmbr.physics.TriggerNotificationBusHandler()
handler.connect(box_id)
handler.add_callback("OnTriggerEnter", on_enter)
handler.add_callback("OnTriggerExit", on_exit)
helper.wait_for_condition(lambda: BoxTrigger.entered, TIMEOUT)
Report.result(Tests.sphere_enter_triggerarea, BoxTrigger.entered)
helper.wait_for_condition(lambda: BoxTrigger.exited, TIMEOUT)
Report.result(Tests.sphere_exit_triggerarea, BoxTrigger.exited)
# 5) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(ScriptCanvas_TriggerEvents)