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/C15096732_Material_DefaultL...

285 lines
13 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 : C15096732
# Test Case Title : Verify Default material library works across different levels
# fmt: off
class Tests:
# Game Mode 2
enter_game_mode_2 = ("Entered game mode 2", "Failed to enter game mode 2")
sphere_found_2 = ("Test 2: Sphere was found", "Test 2: Sphere was not found")
terrain_found_2 = ("Test 2: Terrrain Entity found", "Test 2: Terrain Entity was not found")
trigger_found_2 = ("Test 2: trigger found", "Test 2: trigger not found")
sphere_initial_position_2 = ("Test 2: Sphere initial position valid", "Test 2: Sphere initial position not valid")
sphere_initial_velocity_2 = ("Test 2: Sphere initial velocity valid", "Test 2: Sphere initial velocity not valid")
sphere_collision_2 = ("Test 2: Sphere collided with Terrain", "Test 2: Sphere did not collide")
exit_game_mode_2 = ("Exited game mode 2", "Couldn't exit game mode 2")
# Game Mode 3
enter_game_mode_3 = ("Entered game mode 3", "Failed to enter game mode 3")
sphere_found_3 = ("Test 3: Sphere was found", "Test 3: Sphere was not found")
terrain_found_3 = ("Test 3: Terrrain Entity found", "Test 3: Terrain Entity was not found")
trigger_found_3 = ("Test 3: trigger found", "Test 3: trigger not found")
sphere_initial_position_3 = ("Test 3: Sphere initial position valid", "Test 3: Sphere initial position not valid")
sphere_initial_velocity_3 = ("Test 3: Sphere initial velocity valid", "Test 3: Sphere initial velocity not valid")
sphere_collision_3 = ("Test 3: Sphere collided with Terrain", "Test 3: Sphere did not collide")
exit_game_mode_3 = ("Exited game mode 3", "Couldn't exit game mode 3")
# Test Verification
levels_start_equal = ("Both levels are the same", "Both levels are not the same")
material_library_switch = ("Library switch updated the sphere", "Library switch didn't update sphere")
levels_stay_equal = ("Both levels are still the same", "Both levels are not the same post_change")
# fmt: on
def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after():
"""
Summary: Verify Default material library works across different levels, this is the second stage to the test.
The reload was required for the editor to pick up changes in default material library in the
default.physxconfiguration file. After the tests are run this script will load the data from the previous
script and compare it to the two new tests to see if changing the default material library progpogated
correctly. C15096732_Material_DefaultLibraryUpdatedAcrossLevels_b.physmaterial is the default material
file for these two tests.
Level Description: There are two levels indexed 1 and 2 each are completely identical to the other.
sphere - Placed between trigger and terrain with velocity in the negative z direction; has physx rigid body,
physx collider with sphere shape and useful_material_0 assigned (before change in default material library)
and sphere shape
trigger - A trigger sitting above the sphere and terrain; has physx rigid body, physx collider with box
shape, and box shape
terrain - Terrain placeholder with transform inline with default terrain height; has physx terrain
component with default characteristics
physxconfiguration files: The change in default material library is achieved by launching the editor twice and
overriding the default.physxconfiguration file with files that are nearly identical other than having
different default material libraries
Materials: no_bounce_0 and no_bounce_1 are set so that they do not bounce from the terrain. global
Default and bounce_0 and bounce_1 are set so that a bounce does occur. During the test the sphere first has
a no_bounce material applied after the change in default material library to one with the bounce material the
sphere has the global Default material applied. The bounce materials exist to avoid any current or future
issues with an empty material library.
Test run explanation:
Test 0: Collect baseline for default material library in the first level
Test 1: Collect baseline for default material library in the second level
Test 2: Collect resulting data for changed material library in the first level
Test 3: Collect resulting data for changed material library in the second level
Expected Behavior: For the two test run by this script the ball will bounce from the terrain and hit the trigger
as the material for spheres is now the global Default material.
Iterated Game Mode steps:
1) Open the correct level is open
2) Enter Game Mode
3) Create and Verify Entities
4) Wait for Sphere collision with Terrain Entity
5) Allow time to hit trigger
6) Log Final Values
7) Exit Game Mode
Test Steps:
1) Create Test Objects
2) Run Game Mode steps once for each test
3) Read results from local tmp file
4) Validate test wide results
5) 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 = 2.0
INITIAL_VELOCITY = math.Vector3(0.0, 0.0, -10.0)
# Helper Functions
class Entity:
def __init__(self, name, index):
self.id = general.find_game_entity(name)
self.name = name
self.index = index
# ID validation
self.found = Tests.__dict__["{}_found_{}".format(self.name, index)]
Report.critical_result(self.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)
class Material_Test:
def __init__(self, test_index, level):
self.test_index = test_index
self.level = level
self.entity_list = None
# Setting Flags
self.terrain_collision = False
self.trigger_triggered = False
def set_handlers(self):
trigger = self.entity_list[2]
# Set handler for collision
self.handler_0 = azlmbr.physics.CollisionNotificationBusHandler()
self.handler_0.connect(self.entity_list[0].id)
self.handler_0.add_callback("OnCollisionBegin", self.on_collision_begin)
# Set handler for trigger
self.handler = azlmbr.physics.TriggerNotificationBusHandler()
self.handler.connect(trigger.id)
self.handler.add_callback("OnTriggerEnter", self.on_trigger_enter)
def on_collision_begin(self, args):
if args[0].equal(self.entity_list[1].id):
self.terrain_collision = True
def on_trigger_enter(self, args):
if args[0].equal(self.entity_list[0].id):
self.trigger_triggered = True
def check_sphere_initial_position(self, position_valid):
initial_position = Tests.__dict__["sphere_initial_position_{}".format(self.test_index)]
Report.critical_result(initial_position, position_valid)
def check_sphere_initial_velocity(self):
initial_velocity_string = Tests.__dict__["sphere_initial_velocity_{}".format(self.test_index)]
Report.critical_result(initial_velocity_string, self.entity_list[0].velocity.IsClose(INITIAL_VELOCITY, 0.1))
def check_sphere_collision(self):
collision = Tests.__dict__["sphere_collision_{}".format(self.test_index)]
Report.result(collision, self.terrain_collision)
def default_material_library_changed_as_expected(velocity_list, hit_trigger_list):
hit_trigger_change = not hit_trigger_list[1] and hit_trigger_list[2]
velocity_change_valid = (
abs(velocity_list[1].x - velocity_list[2].x) < FLOAT_THRESHOLD
and abs(velocity_list[1].y - velocity_list[2].y) < FLOAT_THRESHOLD
and velocity_list[1].z <= velocity_list[2].z
)
return velocity_change_valid and hit_trigger_change
def compare_level_baseline(velocity_list, hit_trigger_list):
velocities_valid = (
abs(velocity_list[0].z - velocity_list[1].z) < FLOAT_THRESHOLD
and abs(velocity_list[0].y - velocity_list[1].y) < FLOAT_THRESHOLD
and abs(velocity_list[0].x - velocity_list[1].x) < FLOAT_THRESHOLD
)
hit_trigger_correct = hit_trigger_list[0] == hit_trigger_list[1]
return velocities_valid and hit_trigger_correct
def levels_coinsistent_after_modification(velocity_list, hit_trigger_list):
velocities_valid = (
abs(velocity_list[2].z - velocity_list[3].z) < 0.01
and abs(velocity_list[2].y - velocity_list[3].y) < FLOAT_THRESHOLD
and abs(velocity_list[2].x - velocity_list[3].x) < FLOAT_THRESHOLD
)
hit_trigger_correct = hit_trigger_list[2] == hit_trigger_list[3]
return velocities_valid and hit_trigger_correct
def get_data_from_previous_tests():
from ast import literal_eval
try:
with open(
os.path.join(
os.getcwd(), "AutomatedTesting", "Levels", "Physics", "C15096732_Material_DefaultLibraryUpdatedAcrossLevels", "_last_run_before_change_data.txt"
)) as data_file:
lines = data_file.readlines()
for i, line in enumerate(lines):
if i < 2:
line = literal_eval(line)
lines[i] = math.Vector3(float(line[0]), float(line[1]), float(line[2]))
else:
lines[i] = line == "True"
except Exception as e:
Report.info(e)
helper.fail_fast("Could not save data of first two tests.")
return lines[:2], lines[2:4]
helper.init_idle()
# 1) Create Test Objects
test_2 = Material_Test(test_index=2, level=0)
test_3 = Material_Test(test_index=3, level=1)
test_list = [test_2, test_3]
# 2) Run Game Mode steps once for each test
for test in test_list:
# 1) Open the correct level is open
helper.open_level(
"physics",
"C15096732_Material_DefaultLibraryUpdatedAcrossLevels.\\{}".format(
test.level
),
)
# 2) Enter Game Mode
helper.enter_game_mode(Tests.__dict__["enter_game_mode_{}".format(test.test_index)])
# 3) Create and Verify Entities
sphere = Entity("sphere", test.test_index)
terrain = Entity("terrain", test.test_index)
trigger = Entity("trigger", test.test_index)
test.entity_list = [sphere, terrain, trigger]
position_valid = terrain.position.z < sphere.position.z < trigger.position.z
test.check_sphere_initial_position(position_valid)
test.check_sphere_initial_velocity()
# 4) Wait for Sphere collision with Terrain Entity
test.set_handlers()
helper.wait_for_condition(lambda: test.terrain_collision, TIMEOUT)
test.check_sphere_collision()
# 5) Allow time for Sphere to hit trigger
helper.wait_for_condition(lambda: test.trigger_triggered, TIMEOUT)
# 6) Log Final Values
test.final_velocity = sphere.velocity
# 7) Exit Game Mode
helper.exit_game_mode(Tests.__dict__["exit_game_mode_{}".format(test.test_index)])
# 3) Verify that logged attributes show both levels are the same before and after the change in default material library
# and show that there was a change before and after the change in default material library
sphere_final_velocities_0, hit_trigger_list_0 = get_data_from_previous_tests()
sphere_final_velocities = sphere_final_velocities_0 + [test.final_velocity for test in test_list]
hit_trigger_list = hit_trigger_list_0 + [test.trigger_triggered for test in test_list]
Report.result(Tests.levels_start_equal, compare_level_baseline(sphere_final_velocities, hit_trigger_list))
Report.result(
Tests.material_library_switch,
default_material_library_changed_as_expected(sphere_final_velocities, hit_trigger_list),
)
Report.result(
Tests.levels_stay_equal, levels_coinsistent_after_modification(sphere_final_velocities, hit_trigger_list)
)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after)