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/material/C4925580_Material_RagdollBo...

194 lines
9.2 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 : C4925580
# Test Case Title : Verify that Material can be assigned to Ragdoll Bones and they behave as per their material
# 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")
concrete_ragdoll_found_valid = ("Concrete Ragdoll found and validated", "Concrete Ragdoll not found and validated")
rubber_ragdoll_found_valid = ("Rubber Ragdoll found and validated", "Rubber Ragdoll not found and validated")
concrete_ragdoll_above_terrain = ("Concrete Ragdoll is above terrain", "Concrete Ragdoll is not above terrain")
rubber_ragdoll_above_terrain = ("Rubber Ragdoll is above terrain", "Rubber Ragdoll is not above terrain")
terrain_collision_detected = ("Collision was detected on a ragdoll with terrain", "Collision detection timed out")
concrete_ragdoll_contacted_terrain = ("Concrete Ragdoll contacted terrain", "Concrete Ragdoll did not contact terrain")
rubber_ragdoll_contacted_terrain = ("Rubber Ragdoll contacted terrain", "Rubber Ragdoll did not contact terrain")
rubber_ragdoll_bounced_higher = ("Rubber Ragdoll bounced higher than Concrete Ragdoll", "Rubber Ragdoll did not bounce higher than Concrete Ragdoll")
concrete_ragdoll_bounced_as_expected = ("Concrete ragdoll bounced to expected height", "Concrete ragdoll did not bounce to expected height")
rubber_ragdoll_bounced_as_expected = ("Rubber ragdoll bounced to expected height", "Rubber ragdoll did not bounce to expected height")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
# fmt: on
def C4925580_Material_RagdollBonesMaterial():
"""
Summary:
This script runs an automated test to verify that assigning material to the skeleton of an actor entity with PhysX
ragdoll will cause the entity to behave according to the nature of the material.
Level Description:
Two ragdoll entities (entity: Concrete Ragdoll) and (entity: Rubber Ragdoll) are above a PhysX terrain (entity:
PhysX Terrain). Each ragdoll has an actor, an animation graph, and a PhysX ragdoll component. Gravity is enabled for
each joint which is present on the ragdolls. The ragdolls are identical except for their textures, skeleton
materials, and x-positions. Concrete Ragdoll's texture is blue, while Rubber Ragdoll's texture is red. Concrete
Ragdoll's skeleton material is concrete, while Rubber Ragdoll's skeleton material is rubber.
Expected behavior:
The ragdolls will fall and hit the terrain at the same time. The rubber ragdoll will bounce higher than the concrete
ragdoll.
Test Steps:
1) Open level and enter game mode
2) Retrieve and validate entities
3) Check that each ragdoll is above the terrain
4) Wait for the initial collision between a ragdoll and the terrain or timeout
5) Check for the maximum bounce height of each ragdoll for a given period of time
6) Verify that the rubber ragdoll bounced higher than the concrete ragdoll
7) Verify that each ragdoll bounced approximately to its expected maximum height
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.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
CONCRETE_EXPECTED_MAX_BOUNCE_HEIGHT = 0.039
RUBBER_EXPECTED_MAX_BOUNCE_HEIGHT = 1.2
TOLERANCE = 0.5
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 Ragdoll(Entity):
def __init__(self, name, found_valid_test, target_terrain, above_terrain_test, contacted_terrain_test):
Entity.__init__(self, name, found_valid_test)
self.target_terrain = target_terrain
self.above_terrain_test = above_terrain_test
self.contacted_terrain_test = contacted_terrain_test
self.contacted_terrain = False
self.max_bounce_height = 0
self.reached_max_bounce = False
# Set up collision notification handler
self.handler = azlmbr.physics.CollisionNotificationBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnCollisionBegin", self.on_collision_begin)
def get_z_position(self):
z_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldZ", self.id)
return z_position
# Set up collision detection with the terrain
def on_collision_begin(self, args):
other_id = args[0]
if other_id.Equal(self.target_terrain.id):
Report.info("{} collision began with {}".format(self.name, self.target_terrain.name))
if not self.contacted_terrain:
self.hit_terrain_z = self.get_z_position()
self.contacted_terrain = True
# 1) Open level and enter game mode
helper.init_idle()
helper.open_level("Physics", "C4925580_Material_RagdollBonesMaterial")
helper.enter_game_mode(Tests.enter_game_mode)
# 2) Retrieve and validate entities
terrain = Entity("PhysX Terrain", Tests.terrain_found_valid)
Report.critical_result(terrain.found_valid_test, terrain.id.IsValid())
concrete_ragdoll = Ragdoll(
"Concrete Ragdoll",
Tests.concrete_ragdoll_found_valid,
terrain,
Tests.concrete_ragdoll_above_terrain,
Tests.concrete_ragdoll_contacted_terrain,
)
rubber_ragdoll = Ragdoll(
"Rubber Ragdoll",
Tests.rubber_ragdoll_found_valid,
terrain,
Tests.rubber_ragdoll_above_terrain,
Tests.rubber_ragdoll_contacted_terrain,
)
ragdolls = [concrete_ragdoll, rubber_ragdoll]
for ragdoll in ragdolls:
Report.critical_result(ragdoll.found_valid_test, ragdoll.id.IsValid())
# 3) Check that each ragdoll is above the terrain
Report.critical_result(ragdoll.above_terrain_test, ragdoll.get_z_position() > TERRAIN_START_Z)
# 4) Wait for the initial collision between the ragdolls and the terrain or timeout
terrain_collision_detected = helper.wait_for_condition(
lambda: concrete_ragdoll.contacted_terrain and rubber_ragdoll.contacted_terrain, TIME_OUT_SECONDS
)
Report.critical_result(Tests.terrain_collision_detected, terrain_collision_detected)
for ragdoll in ragdolls:
Report.result(ragdoll.contacted_terrain_test, ragdoll.contacted_terrain)
# 5) Check for the maximum bounce height of each ragdoll for a given period of time
def check_for_max_bounce_heights(ragdolls):
for ragdoll in ragdolls:
if ragdoll.contacted_terrain:
bounce_height = ragdoll.get_z_position() - ragdoll.hit_terrain_z
if bounce_height >= ragdoll.max_bounce_height:
ragdoll.max_bounce_height = bounce_height
elif ragdoll.max_bounce_height > 0.0:
ragdoll.reached_max_bounce = True
return concrete_ragdoll.reached_max_bounce and rubber_ragdoll.reached_max_bounce
helper.wait_for_condition(lambda: check_for_max_bounce_heights(ragdolls), TIME_OUT_SECONDS)
for ragdoll in ragdolls:
Report.info("{}'s maximum bounce height: {}".format(ragdoll.name, ragdoll.max_bounce_height))
# 6) Verify that the rubber ragdoll bounced higher than the concrete ragdoll
Report.result(
Tests.rubber_ragdoll_bounced_higher, rubber_ragdoll.max_bounce_height > concrete_ragdoll.max_bounce_height
)
# 7) Verify that each ragdoll bounced approximately to its expected maximum height
Report.result(
Tests.concrete_ragdoll_bounced_as_expected,
abs(concrete_ragdoll.max_bounce_height - CONCRETE_EXPECTED_MAX_BOUNCE_HEIGHT) < TOLERANCE,
)
Report.result(
Tests.rubber_ragdoll_bounced_as_expected,
abs(rubber_ragdoll.max_bounce_height - RUBBER_EXPECTED_MAX_BOUNCE_HEIGHT) < TOLERANCE,
)
# 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(C4925580_Material_RagdollBonesMaterial)