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.
296 lines
16 KiB
Python
296 lines
16 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 : C15096737
|
|
# Test Case Title : Verify that a change in the default material library material information
|
|
# affects all the materials that reference it, even non-defaulted
|
|
# exactly like if the library was selected
|
|
|
|
|
|
# fmt: off
|
|
class Tests:
|
|
# level
|
|
enter_game_mode_0 = ("Entered game mode 0", "Failed to enter game mode 0")
|
|
exit_game_mode_0 = ("Exited game mode 0", "Couldn't exit game mode 0")
|
|
enter_game_mode_1 = ("Entered game mode 1", "Failed to enter game mode 1")
|
|
exit_game_mode_1 = ("Exited game mode 1", "Couldn't exit game mode 1")
|
|
|
|
# targets
|
|
terrain_found = ("Terrain found in each test", "TERRAIN NOT FOUND in a test")
|
|
target_character_rubber_found = ("target_character_rubber found in each test", "target_character_rubber NOT FOUND in a test")
|
|
target_character_concrete_found = ("target_character_concrete found in each test", "target_character_concrete NOT FOUND in a test")
|
|
|
|
# collider activity
|
|
rubber_sphere_found = ("rubber_sphere found in each test", "rubber_sphere NOT FOUND in a test in a test")
|
|
rubber_sphere_trigger_found = ("rubber_sphere_trigger found in each test", "rubber_sphere_trigger NOT FOUND in a test")
|
|
rubber_sphere_collided = ("rubber_sphere collided in each test", "rubber_sphere DIDN'T COLLIDE in a test")
|
|
|
|
concrete_sphere_found = ("concrete_sphere found in each test", "concrete_sphere NOT FOUND in a test")
|
|
concrete_sphere_trigger_found = ("concrete_sphere_trigger found in each test", "concrete_sphere_trigger NOT FOUND in a test")
|
|
concrete_sphere_collided = ("concrete_sphere collided in each test", "concrete_sphere DIDN'T COLLIDE in a test")
|
|
|
|
character_rubber_found = ("character_rubber found in each test", "character_rubber NOT FOUND in a test")
|
|
character_rubber_trigger_found = ("character_rubber_trigger found in each test", "character_rubber_trigger NOT FOUND in a test")
|
|
character_rubber_collided = ("character_rubber collided in each test", "character_rubber DIDN'T COLLIDE in a test")
|
|
|
|
character_concrete_found = ("character_concrete found in each test", "character_concrete NOT FOUND in a test")
|
|
character_concrete_trigger_found = ("character_concrete_trigger found in each test", "character_concrete_trigger NOT FOUND in a test")
|
|
character_concrete_collided = ("character_concrete collided in each test", "character_concrete DIDN'T COLLIDE in a test")
|
|
|
|
terrain_rubber_found = ("terrain_rubber found in each test", "terrain_rubber NOT FOUND in a test")
|
|
terrain_rubber_trigger_found = ("terrain_rubber_trigger found in each test", "terrain_rubber_trigger NOT FOUND in a test")
|
|
terrain_rubber_collided = ("terrain_rubber collided in each test", "terrain_rubber DIDN'T COLLIDE in a test")
|
|
|
|
terrain_concrete_found = ("terrain_concrete found in each test", "terrain_concrete NOT FOUND in a test")
|
|
terrain_concrete_trigger_found = ("terrain_concrete_trigger found in each test", "terrain_concrete_trigger NOT FOUND in a test")
|
|
terrain_concrete_collided = ("terrain_concrete collided in each test", "terrain_concrete DIDN'T COLLIDE in a test")
|
|
|
|
ragdoll_rubber_found = ("ragdoll_rubber found in each test", "ragdoll_rubber NOT FOUND in a test")
|
|
ragdoll_rubber_trigger_found = ("ragdoll_rubber_trigger found in each test", "ragdoll_rubber_trigger NOT FOUND in a test")
|
|
ragdoll_rubber_collided = ("ragdoll_rubber collided in each test", "ragdoll_rubber DIDN'T COLLIDE in a test")
|
|
|
|
ragdoll_concrete_found = ("ragdoll_concrete found in each test", "ragdoll_concrete NOT FOUND in a test")
|
|
ragdoll_concrete_trigger_found = ("ragdoll_concrete_trigger found in each test", "ragdoll_concrete_trigger NOT FOUND in a test")
|
|
ragdoll_concrete_collided = ("ragdoll_concrete collided in each test", "ragdoll_concrete DIDN'T COLLIDE in a test")
|
|
|
|
# Verification
|
|
material_library_updated = ("Default material library updated", "Default material library not updated")
|
|
rubber_material_changed = ("Rubber material changed correctly", "Rubber didn't react correctly")
|
|
concrete_material_changed = ("Concrete material changed correctly", "Concrete didn't react correctly")
|
|
# fmt: on
|
|
|
|
def C15096737_Materials_DefaultMaterialLibraryChanges():
|
|
"""
|
|
Summary: Runs an automated test to verify that material selected in the default material library is applied to PhysX
|
|
colliders, character controller, terrain texture layers and ragdolls and that material can respond to change.
|
|
|
|
PhysX Config Description:
|
|
A PhysX material library called all_ones is set as the default material library in PhysX Config File.
|
|
The library has two materials surfaces: rubber with Restitution = 1.0, Restitution Combine = Maximum
|
|
and concrete with Restitution = 0.0, Restitution combine = Multiply.
|
|
The custom config file is loaded before editor is launched.
|
|
|
|
Level Description:
|
|
Consists of 4 sets of entities.
|
|
Each entity has either rubber or concrete material assigned to it. Each entity has a corresponding trigger placed
|
|
between the entity and its collision target entity (terrain or character controller).
|
|
The entities, their triggers and their target are colored blue if they have rubber material, or red for concrete.
|
|
|
|
Expected Behavior:
|
|
The entities start their movement once the level is loaded. They should touch their corresponding triggers first,
|
|
then collide with their target entity. The ones with rubber material are supposed to bounce back and touch the
|
|
triggers. The ones with concrete material are supposed to stick to the target and stop moving, therefore not
|
|
touching the triggers anymore. After the edits to material library the affect will be swapped.
|
|
|
|
Main Script Steps:
|
|
1) Loads the level
|
|
2) Setup targets and colliders
|
|
3) Run Test 0
|
|
4) Edit Material Library
|
|
5) Run Test 1
|
|
6) Validate Results
|
|
7) Close editor
|
|
|
|
Test Steps:
|
|
1) Enter Game Mode
|
|
2) Validate target Id's
|
|
3) Validate all Colliders and setup targets
|
|
4) Wait for Collision, Report Results
|
|
5) Allow Time to Hit trigger
|
|
6) Exit Game Mode
|
|
"""
|
|
|
|
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
|
|
from Physmaterial_Editor import Physmaterial_Editor
|
|
|
|
# Constants
|
|
TIME_OUT = 2.0
|
|
PROPAGATION_FRAMES = 180
|
|
|
|
def get_test(entity_name, suffix):
|
|
return Tests.__dict__[entity_name + suffix]
|
|
|
|
# Base class for triggers, targets and colliders
|
|
class Entity(object):
|
|
# Global Holding Variable for test index
|
|
current_test = None
|
|
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.found_in_before_test = False
|
|
|
|
# Validates entity ids reports if the ids are valid for both test cases
|
|
# Fast fails if any id is invalid
|
|
def validate_id(self):
|
|
self.id = general.find_game_entity(self.name)
|
|
if Entity.current_test == 0 and self.id.IsValid():
|
|
self.found_in_before_test = True
|
|
elif Entity.current_test == 1:
|
|
Report.critical_result(get_test(self.name, "_found"), self.id.IsValid() and self.found_in_before_test)
|
|
else:
|
|
helper.fail_fast("{} was not found in test {}".format(self.name, Entity.current_test))
|
|
|
|
@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 Collider(Entity):
|
|
def __init__(self, name, target):
|
|
Entity.__init__(self, name)
|
|
self.target = target
|
|
# Data holding variables
|
|
self.collided_with_target_0 = False
|
|
self.collided_with_target_1 = False
|
|
self.hit_trigger_0 = False
|
|
self.hit_trigger_1 = False
|
|
|
|
# Initialized target collisions
|
|
def setup_target(self):
|
|
self.target.validate_id
|
|
# Watch target for collision with collider
|
|
self.collision_handler = azlmbr.physics.CollisionNotificationBusHandler()
|
|
self.collision_handler.connect(self.id)
|
|
self.collision_handler.add_callback("OnCollisionBegin", self.detect_collision_target)
|
|
|
|
def activate_trigger(self):
|
|
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", self.trigger.id)
|
|
Report.info("{} activated".format(self.trigger.name))
|
|
|
|
# Sets up trigger and activates it post-collision with target
|
|
def setup_trigger(self):
|
|
if Entity.current_test == 0:
|
|
self.trigger = Entity(self.name + "_trigger")
|
|
self.trigger.validate_id()
|
|
self.activate_trigger()
|
|
# Watch for collider entrance
|
|
self.trigger.handler = azlmbr.physics.TriggerNotificationBusHandler()
|
|
self.trigger.handler.connect(self.trigger.id)
|
|
self.trigger.handler.add_callback("OnTriggerEnter", self.on_trigger_enter)
|
|
|
|
def on_trigger_enter(self, args):
|
|
if self.id.equal(args[0]) and not getattr(self, "hit_trigger_{}".format(Entity.current_test)):
|
|
Report.info("{} entered {} in test {}".format(self.name, self.trigger.name, Entity.current_test))
|
|
setattr(self, "hit_trigger_{}".format(Entity.current_test), True)
|
|
|
|
def detect_collision_target(self, args):
|
|
print("Collision_going_on")
|
|
if self.target.id.equal(args[0]) and not getattr(self, "collided_with_target_{}".format(Entity.current_test)):
|
|
Report.info("{} collided with {}".format(self.name, self.target.name))
|
|
setattr(self, "collided_with_target_{}".format(Entity.current_test), True)
|
|
self.setup_trigger()
|
|
|
|
def edit_material_library():
|
|
# Flips the Restitution values of rubber and concrete
|
|
material_library = Physmaterial_Editor("all_ones_1.physmaterial")
|
|
rubber_restitution = material_library.modify_material("rubber", "Restitution", 0)
|
|
rubber_restitution_combine = material_library.modify_material("rubber", "RestitutionCombine", "Multiply")
|
|
concrete_restitution = material_library.modify_material("concrete", "Restitution", 1)
|
|
concrete_restitution_combine = material_library.modify_material("concrete", "RestitutionCombine", "Average")
|
|
|
|
material_library.save_changes()
|
|
return rubber_restitution and rubber_restitution_combine and concrete_restitution and concrete_restitution_combine
|
|
|
|
def check_rubber_material_updated(rubber_colliders):
|
|
# Checks that all rubber colliders hit the trigger on test 0 and not on test 1
|
|
before_test_passed = all([collider.hit_trigger_0 for collider in rubber_colliders])
|
|
after_test_passed = all([not collider.hit_trigger_1 for collider in rubber_colliders])
|
|
|
|
return before_test_passed and after_test_passed
|
|
|
|
def check_concrete_material_updated(concrete_colliders):
|
|
# Checks that all concrete colliders didn't hit the trigger on test 0 and did on test 1
|
|
before_test_passed = all([not collider.hit_trigger_0 for collider in concrete_colliders])
|
|
after_test_passed = all([collider.hit_trigger_1 for collider in concrete_colliders])
|
|
|
|
return before_test_passed and after_test_passed
|
|
|
|
def test_run(index, all_colliders):
|
|
Entity.current_test = index
|
|
# 1) Enter Game Mode
|
|
helper.enter_game_mode(get_test("enter_game_mode_", str(index)))
|
|
|
|
# 2) Validate target Ids
|
|
terrain.validate_id()
|
|
target_character_concrete.validate_id()
|
|
target_character_rubber.validate_id()
|
|
|
|
# 3) Validate all Colliders and setup targets
|
|
for collider in all_colliders:
|
|
collider.validate_id()
|
|
collider.setup_target()
|
|
|
|
# 4) Wait for Collision, Report Results
|
|
if not helper.wait_for_condition(lambda: all([getattr(collider, "collided_with_target_{}".format(index)) for collider in all_colliders]), TIME_OUT):
|
|
failed_colliders = ", ".join([collider.name for collider in all_colliders if not getattr(collider, "collided_with_target_{}".format(index))])
|
|
helper.fail_fast("A collision with target did not occur for these colliders: {}".format(failed_colliders))
|
|
elif index == 1:
|
|
for collider in all_colliders:
|
|
Report.result(get_test(collider.name, "_collided"), collider.collided_with_target_0 and collider.collided_with_target_1)
|
|
|
|
# 5) Allow time to hit trigger
|
|
general.idle_wait_frames(PROPAGATION_FRAMES)
|
|
|
|
# 6) Exit Game Mode
|
|
helper.exit_game_mode(get_test("exit_game_mode_", str(index)))
|
|
|
|
# Main Script
|
|
helper.init_idle()
|
|
# 1) Load the level
|
|
helper.open_level("Physics", "C15096737_Materials_DefaultMaterialLibraryChanges")
|
|
|
|
# 2) Setup targets and colliders
|
|
terrain = Entity("terrain")
|
|
target_character_rubber = Entity("target_character_rubber")
|
|
target_character_concrete = Entity("target_character_concrete")
|
|
|
|
rubber_sphere = Collider(name="rubber_sphere", target=terrain)
|
|
concrete_sphere = Collider(name="concrete_sphere", target=terrain)
|
|
character_rubber = Collider(name="character_rubber", target=target_character_rubber)
|
|
character_concrete = Collider(name="character_concrete", target=target_character_concrete)
|
|
terrain_rubber = Collider(name="terrain_rubber", target=terrain)
|
|
terrain_concrete = Collider(name="terrain_concrete", target=terrain)
|
|
ragdoll_rubber = Collider(name="ragdoll_rubber", target=terrain)
|
|
ragdoll_concrete = Collider(name="ragdoll_concrete", target=terrain)
|
|
|
|
rubber_test_entities = [rubber_sphere, character_rubber, terrain_rubber, ragdoll_rubber]
|
|
concrete_test_entities = [concrete_sphere, character_concrete, terrain_concrete, ragdoll_concrete]
|
|
test_entities = rubber_test_entities + concrete_test_entities
|
|
|
|
# 3) Run test 0
|
|
test_run(index=0, all_colliders=test_entities)
|
|
|
|
# 4) Edit Material Library
|
|
Report.critical_result(Tests.material_library_updated, edit_material_library())
|
|
|
|
# Wait for material library changes to propagate
|
|
general.idle_wait_frames(PROPAGATION_FRAMES)
|
|
|
|
# 5) Run test 1
|
|
test_run(index=1, all_colliders=test_entities)
|
|
|
|
# 6) Validate Results
|
|
Report.result(Tests.concrete_material_changed, check_concrete_material_updated(concrete_test_entities))
|
|
Report.result(Tests.rubber_material_changed, check_rubber_material_updated(rubber_test_entities))
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from editor_python_test_tools.utils import Report
|
|
Report.start_test(C15096737_Materials_DefaultMaterialLibraryChanges)
|