You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712452_ScriptCanvas_Coll...

201 lines
9.5 KiB
Python

"""
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 C12712452_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", "C12712452_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(C12712452_ScriptCanvas_CollisionEvents)