Integrating latest 47acbe8
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4814463 - Altitude Filter overrides function as expected
|
||||
C4847477 - Altitude Min/Max can be manually set
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAltitudeFilterComponentAndOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AltitudeFilterComponentAndOverrides", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new level is created. A spawner entity is added, along with a planting surface at 32 on Z, and another at 36
|
||||
on Z. An Altitude Filter is added to the spawner entity, and Altitude Min/Max values are set. Instance counts
|
||||
are validated. The same test is then performed for Altitude Filter overrides.
|
||||
|
||||
Expected Behavior:
|
||||
Instances are only spawned within the specified altitude ranges.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create an instance spawner entity
|
||||
3) Create surfaces to plant on, one at 32 on Z and another at 36 on Z.
|
||||
4) Initial instance counts pre-filter are verified.
|
||||
5) Altitude Min/Max is set on the Vegetation Altitude Filter component.
|
||||
6) Instance counts post-filter are verified.
|
||||
7) Altitude Min/Max is set on descriptor overrides.
|
||||
8) Instance counts post-filter are verified.
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 32.0, 32.0, 32.0, asset_path)
|
||||
|
||||
# Add a Vegetation Altitude Filter
|
||||
spawner_entity.add_component("Vegetation Altitude Filter")
|
||||
|
||||
# 3) Add surfaces to plant on
|
||||
dynveg.create_surface_entity("Planting Surface", center_point, 32.0, 32.0, 1.0)
|
||||
elevated_surface_center_point = math.Vector3(512.0, 512.0, 36.0)
|
||||
dynveg.create_surface_entity("Planting Surface Elevated", elevated_surface_center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# Set instances to spawn on a center snap point to avoid unexpected instances around the edges of the box shape
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 4) Verify initial instance counts pre-filter
|
||||
num_expected = (40 * 40) * 2 # 20 instances per 16m per side x 2 surfaces
|
||||
spawner_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and spawner_success
|
||||
|
||||
# 5) Set min/max vegetation altitude, instances should now only appear between 35-37m on the Z-axis
|
||||
spawner_entity.get_set_test(3, "Configuration|Altitude Min", 35)
|
||||
spawner_entity.get_set_test(3, "Configuration|Altitude Max", 37)
|
||||
|
||||
# 6) Validate expected instance counts
|
||||
num_expected = 40 * 40 # Instances should now only plant on the elevated surface
|
||||
altitude_min_max_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and altitude_min_max_success
|
||||
|
||||
# Resize Spawner Entity's Box Shape component to allow monitoring for a different instance count
|
||||
box_size = math.Vector3(16.0, 16.0, 16.0)
|
||||
spawner_entity.get_set_test(1, "Box Shape|Box Configuration|Dimensions", box_size)
|
||||
|
||||
# 7) Allow overrides on Altitude Filter and set Altitude Filter Min/Max overrides on descriptor
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Altitude Filter|Override Enabled", True)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Altitude Filter|Min", 35)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Altitude Filter|Max", 37)
|
||||
|
||||
# 8) Validate expected instances at specified elevations
|
||||
num_expected = 20 * 20 # 20 instances per 16m per side
|
||||
overrides_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and overrides_success
|
||||
|
||||
|
||||
test = TestAltitudeFilterComponentAndOverrides()
|
||||
test.run()
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAltitudeFilterFilterStageToggle(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AltitudeFilter_FilterStageToggle", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Filter Stage toggle affects final vegetation position
|
||||
|
||||
Expected Result:
|
||||
Vegetation instances plant differently depending on the Filter Stage setting.
|
||||
PostProcess should cause some number of plants that appear above and below the desired altitude range to disappear.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
PREPROCESS_INSTANCE_COUNT = 16
|
||||
POSTPROCESS_INSTANCE_COUNT = 13
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
vegetation = dynveg.create_vegetation_area("vegetation", position, 16.0, 16.0, 16.0, asset_path)
|
||||
|
||||
# Add a Vegetation Altitude Filter to the vegetation area entity
|
||||
vegetation.add_component("Vegetation Altitude Filter")
|
||||
|
||||
# Create Surface for instances to plant on
|
||||
dynveg.create_surface_entity("Surface_Entity_Parent", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# Add entity with Mesh to replicate creation of hills
|
||||
dynveg.create_mesh_surface_entity_with_slopes("hill", position, 40.0, 40.0, 40.0)
|
||||
|
||||
# Increase Box Shape size to encompass the hills
|
||||
vegetation.get_set_test(1, "Box Shape|Box Configuration|Dimensions", math.Vector3(100.0, 100.0, 100.0))
|
||||
|
||||
# Set a Min Altitude of 38 and Max of 40 in Vegetation Altitude Filter
|
||||
vegetation.get_set_test(3, "Configuration|Altitude Min", 38.0)
|
||||
vegetation.get_set_test(3, "Configuration|Altitude Max", 40.0)
|
||||
|
||||
# Create a new entity as a child of the vegetation area entity with Random Noise Gradient Generator, Gradient Transform Modifier,
|
||||
# and Box Shape component
|
||||
random_noise = hydra.Entity("random_noise")
|
||||
random_noise.create_entity(position, ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"])
|
||||
random_noise.set_test_parent_entity(vegetation)
|
||||
|
||||
# Add a Vegetation Position Modifier to the vegetation area entity.
|
||||
vegetation.add_component("Vegetation Position Modifier")
|
||||
|
||||
# Pin the Random Noise entity to the Gradient Entity Id field of the Position Modifier's Gradient X
|
||||
vegetation.get_set_test(4, "Configuration|Position X|Gradient|Gradient Entity Id", random_noise.id)
|
||||
|
||||
# Toggle between PreProcess and PostProcess in Vegetation Altitude Filter
|
||||
vegetation.get_set_test(3, "Configuration|Filter Stage", 1)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 30.0, PREPROCESS_INSTANCE_COUNT), 2.0)
|
||||
self.log(f"Vegetation instances count equal to expected value for PREPROCESS filter stage: {result}")
|
||||
vegetation.get_set_test(3, "Configuration|Filter Stage", 2)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 30.0, POSTPROCESS_INSTANCE_COUNT), 2.0)
|
||||
self.log(f"Vegetation instances count equal to expected value for POSTPROCESS filter stage: {result}")
|
||||
|
||||
|
||||
test = TestAltitudeFilterFilterStageToggle()
|
||||
test.run()
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAltitudeFilterShapeSample(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AltitudeFilterShapeSample", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new level is created. A spawner entity is added, along with a planting surface at 32 on Z, and another at 36
|
||||
on Z. An Altitude Filter is added to the spawner entity, and set to sample a shape entity. Instance counts are
|
||||
validated.
|
||||
|
||||
Expected Behavior:
|
||||
Instances are only spawned within the altitude range specified by the sampled shape.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create an instance spawner entity
|
||||
3) Create surfaces to plant on, one at 32 on Z and another at 36 on Z.
|
||||
4) Initial instance counts pre-filter are verified.
|
||||
5) A new entity with shape is created, an sampled on the Vegetation Altitude Filter.
|
||||
6) Instance counts post-filter are verified.
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 16.0, 16.0, 16.0, asset_path)
|
||||
|
||||
# Add a Vegetation Altitude Filter
|
||||
spawner_entity.add_component("Vegetation Altitude Filter")
|
||||
|
||||
# 3) Add surfaces to plant on
|
||||
dynveg.create_surface_entity("Planting Surface", center_point, 32.0, 32.0, 1.0)
|
||||
elevated_surface_center_point = math.Vector3(512.0, 512.0, 36.0)
|
||||
dynveg.create_surface_entity("Planting Surface Elevated", elevated_surface_center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# Set instances to spawn on a center snap point to avoid unexpected instances around the edges of the box shape
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 4) Verify initial instance counts pre-filter
|
||||
num_expected = (20 * 20) * 2 # 20 instances per 16m per side x 2 surfaces
|
||||
spawner_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and spawner_success
|
||||
|
||||
# 5) Create a new entity with a shape at 36 on the Z-axis, and pin the entity to the Vegetation Altitude Filter
|
||||
shape_sampler_center_point = math.Vector3(512.0, 512.0, 36.0)
|
||||
shape_sampler = hydra.Entity("Shape Sampler")
|
||||
shape_sampler.create_entity(
|
||||
shape_sampler_center_point,
|
||||
["Box Shape"]
|
||||
)
|
||||
if shape_sampler.id.IsValid():
|
||||
print(f"'{shape_sampler.name}' created")
|
||||
spawner_entity.get_set_test(3, 'Configuration|Pin To Shape Entity Id', shape_sampler.id)
|
||||
|
||||
# 6) Validate expected instance counts
|
||||
num_expected = 20 * 20 # Instances should now only plant on the elevated surface
|
||||
sampler_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and sampler_success
|
||||
|
||||
|
||||
test = TestAltitudeFilterShapeSample()
|
||||
test.run()
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.math as math
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.slice as slice
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAreaComponentsSliceCreationAndVisibilityToggle(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(
|
||||
self, log_prefix="AreaComponentSlices_SliceCreationAndVisibilityToggle", args=["level"]
|
||||
)
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C2627900 Verifies if a slice containing the component can be created.
|
||||
C2627905 A slice containing the Vegetation Layer Blender component can be created.
|
||||
C2627904: Hiding a slice containing the component clears any visuals from the Viewport.
|
||||
|
||||
Expected Result:
|
||||
C2627900, C2627905: Slice is created, and is properly processed in the Asset Processor.
|
||||
C2627904: Vegetation area visuals are hidden from the Viewport.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def path_is_valid_asset(asset_path):
|
||||
asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", asset_path, math.Uuid(), False)
|
||||
return asset_id.invoke("IsValid")
|
||||
|
||||
# 1) Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) C2627900 Verifies if a slice containing the Vegetation Layer Spawner component can be created.
|
||||
# 2.1) Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
veg_1 = dynveg.create_vegetation_area("vegetation_1", position, 16.0, 16.0, 16.0, asset_path)
|
||||
|
||||
# 2.2) Create slice from the entity
|
||||
slice_path = os.path.join("slices", "TestSlice_1.slice")
|
||||
slice.SliceRequestBus(bus.Broadcast, "CreateNewSlice", veg_1.id, slice_path)
|
||||
|
||||
# 2.3) Verify if the slice has been created successfully
|
||||
self.wait_for_condition(lambda: path_is_valid_asset(slice_path), 5.0)
|
||||
self.log(
|
||||
f"Slice has been created successfully (entity with spawner component): {path_is_valid_asset(slice_path)}"
|
||||
)
|
||||
|
||||
# 3) C2627904: Hiding a slice containing the component clears any visuals from the Viewport
|
||||
# 3.1) Create Surface for instances to plant on
|
||||
dynveg.create_surface_entity("Surface_Entity", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# 3.2) Initially verify instance count before hiding slice
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 16.0, 400))
|
||||
self.log(
|
||||
f"Vegetation plants initially when slice is shown: {dynveg.validate_instance_count(position, 16.0, 400)}"
|
||||
)
|
||||
|
||||
# 3.3) Hide the slice and verify instance count
|
||||
editor.EditorEntityAPIBus(bus.Event, "SetVisibilityState", veg_1.id, False)
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 16.0, 0))
|
||||
self.log(f"Vegetation is cleared when slice is hidden: {dynveg.validate_instance_count(position, 16.0, 0)}")
|
||||
|
||||
# 3.4) Unhide the slice
|
||||
editor.EditorEntityAPIBus(bus.Event, "SetVisibilityState", veg_1.id, True)
|
||||
|
||||
# 4) C2627905 A slice containing the Vegetation Layer Blender component can be created.
|
||||
# 4.1) Create another vegetation entity to add to blender component
|
||||
veg_2 = dynveg.create_vegetation_area("vegetation_2", position, 1.0, 1.0, 1.0, "")
|
||||
|
||||
# 4.2) Create entity with Vegetation Layer Blender
|
||||
components_to_add = ["Box Shape", "Vegetation Layer Blender"]
|
||||
blender_entity = hydra.Entity("blender_entity")
|
||||
blender_entity.create_entity(position, components_to_add)
|
||||
|
||||
# 4.3) Pin both the vegetation areas to the blender entity
|
||||
pte = hydra.get_property_tree(blender_entity.components[1])
|
||||
path = "Configuration|Vegetation Areas"
|
||||
pte.update_container_item(path, 0, veg_1.id)
|
||||
pte.add_container_item(path, 1, veg_2.id)
|
||||
|
||||
# 4.4) Drag the simple vegetation areas under the Vegetation Layer Blender entity to create an entity hierarchy.
|
||||
veg_1.set_test_parent_entity(blender_entity)
|
||||
veg_2.set_test_parent_entity(blender_entity)
|
||||
|
||||
# 4.5) Create slice from blender entity
|
||||
slice_path = os.path.join("slices", "TestSlice_2.slice")
|
||||
slice.SliceRequestBus(bus.Broadcast, "CreateNewSlice", blender_entity.id, slice_path)
|
||||
|
||||
# 4.6) Verify if the slice has been created successfully
|
||||
self.wait_for_condition(lambda: path_is_valid_asset(slice_path), 5.0)
|
||||
self.log(
|
||||
f"Slice has been created successfully (entity with blender component): {path_is_valid_asset(slice_path)}"
|
||||
)
|
||||
|
||||
|
||||
test = TestAreaComponentsSliceCreationAndVisibilityToggle()
|
||||
test.run()
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.vegetation as vegetation
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAssetListCombiner(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AssetListCombiner_CombinedDescriptors", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Combined descriptors appear as expected in a vegetation area. Also verifies remove/replace of assigned Asset
|
||||
Lists.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation fills in the area using the assets assigned to both Vegetation Asset Lists.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new, temporary level
|
||||
2) Create 3 entities with Vegetation Asset List components set to spawn different descriptors
|
||||
3) Create a planting surface and add a Vegetation System Settings level component with instances set to spawn
|
||||
on center instead of corner
|
||||
4) Create a spawner using a Vegetation Asset List Combiner component and a Weight Selector, and disallow
|
||||
spawning empty assets
|
||||
5) Add 2 of the Asset List entities to the Vegetation Asset List Combiner component (PinkFlower and Empty)
|
||||
6) Create a Constant Gradient entity as a child of the spawner entity, and a Dither Gradient Modifier entity
|
||||
as a child of the Constant Gradient entity, and configure for a checkerboard pattern
|
||||
7) Pin the Dither Gradient Entity to the Asset Weight Selector of the spawner entity
|
||||
8) Validate instance count with configured Asset List Combiner
|
||||
9) Replace the reference to the 2nd asset list on the Vegetation Asset List Combiner component and validate
|
||||
instance count
|
||||
10) Remove the referenced Asset Lists on the Asset List Combiner, Disable/Re-enable the Asset List
|
||||
Combiner component to force a refresh, and validate instance count
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
def create_asset_list_entity(name, center, dynamic_slice_asset_path):
|
||||
asset_list_entity = hydra.Entity(name)
|
||||
asset_list_entity.create_entity(
|
||||
center,
|
||||
["Vegetation Asset List"]
|
||||
)
|
||||
if asset_list_entity.id.IsValid():
|
||||
print(f"'{asset_list_entity.name}' created")
|
||||
|
||||
# Set the Asset List to a Dynamic Slice spawner with a specific slice asset selected
|
||||
dynamic_slice_spawner = vegetation.DynamicSliceInstanceSpawner()
|
||||
dynamic_slice_spawner.SetSliceAssetPath(dynamic_slice_asset_path)
|
||||
descriptor = hydra.get_component_property_value(asset_list_entity.components[0],
|
||||
"Configuration|Embedded Assets|[0]")
|
||||
descriptor.spawner = dynamic_slice_spawner
|
||||
asset_list_entity.get_set_test(0, "Configuration|Embedded Assets|[0]", descriptor)
|
||||
return asset_list_entity
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create 3 entities with Vegetation Asset List components set to spawn different descriptors
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
asset_path2 = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
asset_list_entity = create_asset_list_entity("Asset List 1", center_point, asset_path)
|
||||
asset_list_entity2 = create_asset_list_entity("Asset List 2", center_point, None)
|
||||
asset_list_entity3 = create_asset_list_entity("Asset List 3", center_point, asset_path2)
|
||||
|
||||
# 3) Create a planting surface and add a Vegetation System Settings level component with instances set to spawn
|
||||
# on center instead of corner
|
||||
dynveg.create_surface_entity("Surface Entity", center_point, 32.0, 32.0, 1.0)
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 4) Create a spawner using a Vegetation Asset List Combiner component and a Weight Selector, and disallow
|
||||
# spawning empty assets
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Entity", center_point, 16.0, 16.0, 16.0, None)
|
||||
spawner_entity.remove_component("Vegetation Asset List")
|
||||
spawner_entity.add_component("Vegetation Asset List Combiner")
|
||||
spawner_entity.add_component("Vegetation Asset Weight Selector")
|
||||
spawner_entity.get_set_test(0, "Configuration|Allow Empty Assets", False)
|
||||
|
||||
# 5) Add the Asset List entities to the Vegetation Asset List Combiner component
|
||||
asset_list_entities = [asset_list_entity.id, asset_list_entity2.id]
|
||||
spawner_entity.get_set_test(2, "Configuration|Descriptor Providers", asset_list_entities)
|
||||
|
||||
# 6) Create a Constant Gradient entity as a child of the spawner entity, and a Dither Gradient Modifier entity
|
||||
# as a child of the Constant Gradient entity, and configure for a checkerboard pattern
|
||||
components_to_add = ["Constant Gradient"]
|
||||
constant_gradient_entity = hydra.Entity("Constant Gradient Entity")
|
||||
constant_gradient_entity.create_entity(center_point, components_to_add, parent_id=spawner_entity.id)
|
||||
constant_gradient_entity.get_set_test(0, "Configuration|Value", 0.5)
|
||||
|
||||
components_to_add = ["Dither Gradient Modifier"]
|
||||
dither_gradient_entity = hydra.Entity("Dither Gradient Entity")
|
||||
dither_gradient_entity.create_entity(center_point, components_to_add, parent_id=constant_gradient_entity.id)
|
||||
dither_gradient_entity.get_set_test(0, "Configuration|Gradient|Gradient Entity Id", constant_gradient_entity.id)
|
||||
|
||||
# 7) Pin the Dither Gradient Entity to the Asset Weight Selector of the spawner entity
|
||||
spawner_entity.get_set_test(3, "Configuration|Gradient|Gradient Entity Id", dither_gradient_entity.id)
|
||||
|
||||
# 8) Validate instance count. We should now have 200 instances in the spawner area as every other instance
|
||||
# should be an empty asset which the spawner is set to disallow
|
||||
num_expected = 20 * 20 / 2
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
# 9) Replace the reference to the 2nd asset list on the Vegetation Asset List Combiner component and validate
|
||||
# instance count. Should now be 400 instances as the empty spaces can now be claimed by the new descriptor
|
||||
spawner_entity.get_set_test(2, "Configuration|Descriptor Providers|[1]", asset_list_entity3.id)
|
||||
num_expected = 20 * 20
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
# 10) Remove the referenced Asset Lists on the Asset List Combiner, Disable/Re-enable the Asset List
|
||||
# Combiner component to force a refresh, and validate instance count. We should now have 0 instances.
|
||||
pte = hydra.get_property_tree(spawner_entity.components[2])
|
||||
path = "Configuration|Descriptor Providers"
|
||||
pte.reset_container(path)
|
||||
# Component refresh is currently necessary due to container operations not causing a refresh (LY-120947)
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [spawner_entity.components[2]])
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "EnableComponents", [spawner_entity.components[2]])
|
||||
num_expected = 0
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
|
||||
test = TestAssetListCombiner()
|
||||
test.run()
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C6269654: Vegetation areas using weight selectors properly distribute instances according to Sort By Weight setting
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestAssetWeightSelectorSortByWeight(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AssetWeightSelector_SortByWeight", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Vegetation areas using weight selectors properly distribute instances according to Sort By Weight setting
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation is planted in the area according to the generated gradient pattern.
|
||||
Higher weight assets are more likely to express when "Descending (highest first)" is selected.
|
||||
Lower weight assets are more likely to express when "Ascending (lowest first)" is selected.
|
||||
|
||||
Test Steps:
|
||||
1) Create new level
|
||||
2) Create instance spawner with 2 descriptors, one with an Empty Asset
|
||||
3) Create a planting surface
|
||||
4) Create a child entity of the instance spawner with a Constant Gradient component with default values (1.0)
|
||||
5) Pin the child entity to Vegetation Asset Weight Selector of the instance spawner entity
|
||||
6) Set first descriptor to a higher weight, and toggle off Allow Empty Assets
|
||||
7) Validate instance count with initial setup/sort values
|
||||
8) Change sort values and validate instance count
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new instance spawner entity with multiple Dynamic Slice Instance Spawner descriptors, one set to a
|
||||
# valid slice entity, and one set to None
|
||||
spawner_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
desc_asset = hydra.get_component_property_value(spawner_entity.components[2],
|
||||
"Configuration|Embedded Assets")[0]
|
||||
desc_list = [desc_asset, desc_asset]
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets", desc_list)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[1]|Instance|Slice Asset", None)
|
||||
|
||||
# Add an Asset Weight Selector component to the spawner entity
|
||||
spawner_entity.add_component("Vegetation Asset Weight Selector")
|
||||
|
||||
# 3) Create a planting surface
|
||||
dynveg.create_surface_entity("Planting Surface", spawner_center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# 4) Create a child entity of the spawner entity with a Constant Gradient component
|
||||
components_to_add = ["Constant Gradient"]
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(spawner_center_point, components_to_add, parent_id=spawner_entity.id)
|
||||
|
||||
# 5) Pin the Constant Gradient to the Vegetation Asset Weight Selector
|
||||
spawner_entity.get_set_test(3, 'Configuration|Gradient|Gradient Entity Id', gradient_entity.id)
|
||||
|
||||
# 6) Set the first descriptor weight to a higher value and toggle off Allow Empty Assets on the Layer Spawner
|
||||
# component
|
||||
spawner_entity.get_set_test(2, 'Configuration|Embedded Assets|[0]|Weight', 50)
|
||||
spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
|
||||
|
||||
# 7) Query for expected instances with default settings. We should have 0 instances with default Constant
|
||||
# Gradient setup sorting by higher weight first
|
||||
num_expected = 0
|
||||
initial_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = initial_success and self.test_success
|
||||
|
||||
# 8) Sort by lowest weight first, and verify instance counts. We should now have 400 instances as the highest
|
||||
# priority instance won't be allowed to claim space due to "Allow Empty Assets" being False
|
||||
spawner_entity.get_set_test(3, 'Configuration|Sort By Weight', 1)
|
||||
num_expected = 20 * 20
|
||||
final_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = final_success and self.test_success
|
||||
|
||||
|
||||
test = TestAssetWeightSelectorSortByWeight()
|
||||
test.run()
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestDebuggerDebugCVarsWorks(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="Debugger_DebugCVarsWorks", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C2789148 Vegetation Debug CVars are enabled when the Debugger component is present
|
||||
|
||||
Expected Result:
|
||||
The following commands are available in the Editor only when the Vegetation Debugger Level component is present:
|
||||
veg_debugDumpReport (Command)
|
||||
veg_debugRefreshAllAreas (Command)
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Initially run the command in console without Debugger component
|
||||
general.run_console("veg_debugDumpReport")
|
||||
|
||||
# Add the Vegetation Debugger component to the Level Inspector
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# Run a command again after adding the Vegetation debugger
|
||||
general.run_console("veg_debugRefreshAllAreas")
|
||||
|
||||
|
||||
test = TestDebuggerDebugCVarsWorks()
|
||||
test.run()
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestDistanceBetweenFilterComponentOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DistanceBetweenFilterComponentOverrides", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary: Creates a level with a simple vegetation area. A Vegetation Distance Between Filter is
|
||||
added and the min radius is changed as an override on the descriptor. Instance counts at specific points are
|
||||
validated.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create a vegetation area
|
||||
3) Create a surface for planting
|
||||
4) Add the Vegetation System Settings component and setup for the test
|
||||
5-8) Add the Distance Between Filter, setup overrides on both the component and descriptor, and validate
|
||||
expected instance counts with a few different Radius values
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
instance_query_point_a = math.Vector3(512.5, 512.5, 32.0)
|
||||
instance_query_point_b = math.Vector3(514.0, 512.5, 32.0)
|
||||
instance_query_point_c = math.Vector3(515.0, 512.5, 32.0)
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
spawner_center_point = math.Vector3(520.0, 520.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "1m_cube.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Create a surface to plant on
|
||||
surface_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
dynveg.create_surface_entity("Planting Surface", surface_center_point, 128.0, 128.0, 1.0)
|
||||
|
||||
# 4) Add a Vegetation System Settings Level component and set Sector Point Snap Mode to Center
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Density', 16)
|
||||
|
||||
# Add a Vegetation Debugger component to allow area refreshes
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# 5) Add a Vegetation Distance Between Filter, toggle overrides on both the component and descriptor,
|
||||
# and verify initial instance counts are accurate
|
||||
spawner_entity.add_component("Vegetation Distance Between Filter")
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Override Enabled", True)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 2), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 2), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 6) Change Radius Min to 1.0, refresh, and verify instance counts are accurate
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min", 1.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 0), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 1), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 7) Change Radius Min to 2.0, refresh, and verify instance counts are accurate
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min", 2.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 0), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 0), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 8) Change Radius Min to 16.0, refresh, and verify instance counts are accurate, only a single instance should plant
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min", 16.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
num_expected_instances = 1
|
||||
final_check_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_instances), 5.0)
|
||||
self.test_success = final_check_success and self.test_success
|
||||
|
||||
|
||||
test = TestDistanceBetweenFilterComponentOverrides()
|
||||
test.run()
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestDistanceBetweenFilterComponent(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DistanceBetweenFilterComponent", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary: Creates a level with a simple vegetation area. A Vegetation Distance Between Filter is
|
||||
added and the min radius is changed. Instance counts at specific points are validated.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create a vegetation area
|
||||
3) Create a surface for planting
|
||||
4) Add the Vegetation System Settings component and setup for the test
|
||||
5-8) Add the Distance Between Filter, and validate expected instance counts with a few different Radius values
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
instance_query_point_a = math.Vector3(512.5, 512.5, 32.0)
|
||||
instance_query_point_b = math.Vector3(514.0, 512.5, 32.0)
|
||||
instance_query_point_c = math.Vector3(515.0, 512.5, 32.0)
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
spawner_center_point = math.Vector3(520.0, 520.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "1m_cube.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Create a surface to plant on
|
||||
surface_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
dynveg.create_surface_entity("Planting Surface", surface_center_point, 128.0, 128.0, 1.0)
|
||||
|
||||
# 4) Add a Vegetation System Settings Level component and set Sector Point Snap Mode to Center
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Density', 16)
|
||||
|
||||
# Add a Vegetation Debugger component to allow area refreshes
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# 5) Add a Vegetation Distance Between Filter and verify initial instance counts are accurate
|
||||
spawner_entity.add_component("Vegetation Distance Between Filter")
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 2), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 2), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 6) Change Radius Min to 1.0, refresh, and verify instance counts are accurate
|
||||
spawner_entity.get_set_test(3, "Configuration|Radius Min", 1.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 0), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 1), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 7) Change Radius Min to 2.0, refresh, and verify instance counts are accurate
|
||||
spawner_entity.get_set_test(3, "Configuration|Radius Min", 2.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_a, 0.5, 1), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_b, 0.5, 0), 5.0) and \
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(instance_query_point_c, 0.5, 0), 5.0) and \
|
||||
self.test_success
|
||||
|
||||
# 8) Change Radius Min to 16.0, refresh, and verify instance counts are accurate
|
||||
spawner_entity.get_set_test(3, "Configuration|Radius Min", 16.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
num_expected_instances = 1
|
||||
final_check_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_instances), 5.0)
|
||||
self.test_success = final_check_success and self.test_success
|
||||
|
||||
|
||||
test = TestDistanceBetweenFilterComponent()
|
||||
test.run()
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestDynamicSliceInstanceSpawner(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DynamicSliceInstanceSpawner", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Test aspects of the DynamicSliceInstanceSpawner through the BehaviorContext and the Property Tree.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# 1) Open an empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Grab the UUID that we need for creating an Dynamic Slice Instance Spawner
|
||||
dynamic_slice_spawner_uuid = azlmbr.math.Uuid_CreateString('{BBA5CC1E-B4CA-4792-89F7-93711E98FBD1}', 0)
|
||||
|
||||
# Grab a path to a test dynamic slice asset
|
||||
test_slice_asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
# 2) Test DynamicSliceInstanceSpawner BehaviorContext
|
||||
behavior_context_test_success = True
|
||||
dynamic_slice_spawner = azlmbr.vegetation.DynamicSliceInstanceSpawner()
|
||||
behavior_context_test_success = behavior_context_test_success and (dynamic_slice_spawner is not None)
|
||||
behavior_context_test_success = behavior_context_test_success and (dynamic_slice_spawner.typename == 'DynamicSliceInstanceSpawner')
|
||||
# Try to get/set the slice asset path with a valid asset
|
||||
dynamic_slice_spawner.SetSliceAssetPath(test_slice_asset_path)
|
||||
validate_path = dynamic_slice_spawner.GetSliceAssetPath()
|
||||
# We expect the path to get lowercased and normalized with a forward slash, so we compare our result
|
||||
# vs that instead of directly against test_slice_asset_path.
|
||||
behavior_context_test_success = behavior_context_test_success and hydra.compare_values('slices/pinkflower.dynamicslice', validate_path, 'GetSliceAssetPath - valid')
|
||||
# Try to get/set the slice asset path with an empty path
|
||||
dynamic_slice_spawner.SetSliceAssetPath('')
|
||||
validate_path = dynamic_slice_spawner.GetSliceAssetPath()
|
||||
behavior_context_test_success = behavior_context_test_success and hydra.compare_values('', validate_path, 'GetSliceAssetPath - empty')
|
||||
self.test_success = self.test_success and behavior_context_test_success
|
||||
self.log(f'DynamicSliceInstanceSpawner() BehaviorContext test: {behavior_context_test_success}')
|
||||
|
||||
# 3) Test Descriptor BehaviorContext - setting spawnerType sets spawner too
|
||||
spawner_type_test_success = True
|
||||
descriptor = azlmbr.vegetation.Descriptor()
|
||||
spawner_type_test_success = spawner_type_test_success and hydra.get_set_property_test(descriptor, 'spawnerType', dynamic_slice_spawner_uuid)
|
||||
spawner_type_test_success = spawner_type_test_success and (descriptor.spawner.typename == 'DynamicSliceInstanceSpawner')
|
||||
self.test_success = self.test_success and spawner_type_test_success
|
||||
self.log(f'Descriptor() BehaviorContext spawnerType test: {spawner_type_test_success}')
|
||||
|
||||
# 4) Test Descriptor BehaviorContext - setting spawner sets spawnerType too
|
||||
spawner_test_success = True
|
||||
descriptor = azlmbr.vegetation.Descriptor()
|
||||
descriptor.spawner = dynamic_slice_spawner
|
||||
spawner_test_success = spawner_test_success and (descriptor.spawnerType.Equal(dynamic_slice_spawner_uuid))
|
||||
spawner_test_success = spawner_test_success and (descriptor.spawner.typename == 'DynamicSliceInstanceSpawner')
|
||||
self.test_success = self.test_success and spawner_test_success
|
||||
self.log(f'Descriptor() BehaviorContext spawner test: {spawner_test_success}')
|
||||
|
||||
### Setup for Property Tree set of tests
|
||||
|
||||
# Create a new entity with required vegetation area components
|
||||
spawner_entity = hydra.Entity("Veg Area")
|
||||
spawner_entity.create_entity(
|
||||
math.Vector3(512.0, 512.0, 32.0),
|
||||
["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
|
||||
)
|
||||
if (spawner_entity.id.IsValid()):
|
||||
self.log(f"'{spawner_entity.name}' created")
|
||||
|
||||
# Resize the Box Shape component
|
||||
new_box_dimensions = math.Vector3(16.0, 16.0, 16.0)
|
||||
box_dimensions_path = "Box Shape|Box Configuration|Dimensions"
|
||||
spawner_entity.get_set_test(1, box_dimensions_path, new_box_dimensions)
|
||||
|
||||
# Create a surface to plant on
|
||||
dynveg.create_surface_entity("Surface Entity", math.Vector3(512.0, 512.0, 32.0), 1024.0, 1024.0, 1.0)
|
||||
|
||||
# 5) Descriptor Property Tree test: spawner type can be set
|
||||
|
||||
# - Validate the dynamic slice spawner type can be set correctly.
|
||||
property_tree_success = True
|
||||
property_tree_success = property_tree_success and spawner_entity.get_set_test(2, 'Configuration|Embedded Assets|[0]|Instance Spawner', dynamic_slice_spawner_uuid)
|
||||
|
||||
# This should result in 400 instances, since our box is 16 m x 16 m and by default the veg system plants
|
||||
# 20 instances per 16 meters
|
||||
spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', True)
|
||||
general.idle_wait(1.0)
|
||||
num_expected_instances = 20 * 20
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
property_tree_success = property_tree_success and (num_found == num_expected_instances)
|
||||
self.test_success = self.test_success and property_tree_success
|
||||
self.log(f'Property Tree spawner type test: {property_tree_success}')
|
||||
|
||||
# 6) Validate that the "Allow Empty Assets" setting affects the DynamicSliceInstanceSpawner
|
||||
allow_empty_assets_success = True
|
||||
# Since we have an empty slice path, we should have 0 instances once we disable 'Allow Empty Assets'
|
||||
num_expected_instances = 0
|
||||
allow_empty_assets_success = allow_empty_assets_success and spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
|
||||
general.idle_wait(1.0)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f'Allow Empty Assets test: Found {num_found} instances -- Expected {num_expected_instances} instances')
|
||||
allow_empty_assets_success = allow_empty_assets_success and (num_found == num_expected_instances)
|
||||
self.test_success = self.test_success and allow_empty_assets_success
|
||||
self.log(f'Allow Empty Assets test: {allow_empty_assets_success}')
|
||||
|
||||
# 7) Validate that with 'Allow Empty Assets' set to False, a non-empty slice asset gives us the number
|
||||
# of instances we expect.
|
||||
spawns_slices_success = True
|
||||
num_expected_instances = 20 * 20
|
||||
dynamic_slice_spawner.SetSliceAssetPath(test_slice_asset_path)
|
||||
spawns_slices_success = spawns_slices_success and spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
|
||||
descriptor = hydra.get_component_property_value(spawner_entity.components[2], 'Configuration|Embedded Assets|[0]')
|
||||
descriptor.spawner = dynamic_slice_spawner
|
||||
spawns_slices_success = spawns_slices_success and spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]", descriptor)
|
||||
general.idle_wait(1.0)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f'Spawn dynamic slices test: Found {num_found} instances -- Expected {num_expected_instances} instances')
|
||||
spawns_slices_success = spawns_slices_success and (num_found == num_expected_instances)
|
||||
self.test_success = self.test_success and spawns_slices_success
|
||||
self.log(f'Spawn dynamic slices test: {spawns_slices_success}')
|
||||
|
||||
|
||||
test = TestDynamicSliceInstanceSpawner()
|
||||
test.run()
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestDynamicSliceInstanceSpawnerEmbeddedEditor(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DynamicSliceInstanceSpawnerEmbeddedEditor", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new temporary level is created. Surface for planting is created. Simple vegetation area is created using
|
||||
Dynamic Slice Instance Spawner type.
|
||||
|
||||
Expected Behavior:
|
||||
Instances plant as expected in the assigned area.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a Vegetation Layer Spawner setup using Dynamic Slice Instance Spawner type assets
|
||||
3) Create a surface to plant on
|
||||
4) Verify expected instance counts
|
||||
5) Add a camera component looking at the planting area for visual debugging
|
||||
6) Save and export to engine
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and Script Canvas component for launcher test
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 16.0, 16.0, 1.0, asset_path)
|
||||
spawner_entity.add_component("Script Canvas")
|
||||
instance_counter_path = os.path.join("scriptcanvas", "instance_counter.scriptcanvas")
|
||||
instance_counter_script = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", instance_counter_path,
|
||||
math.Uuid(), False)
|
||||
spawner_entity.get_set_test(3, "Script Canvas Asset|Script Canvas Asset", instance_counter_script)
|
||||
|
||||
# 3) Create a surface to plant on
|
||||
dynveg.create_surface_entity("Planting Surface", center_point, 128.0, 128.0, 1.0)
|
||||
|
||||
# 4) Verify instance counts are accurate
|
||||
general.idle_wait(3.0) # Allow a few seconds for instances to spawn
|
||||
num_expected_instances = 20 * 20
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
||||
cam_position = math.Vector3(512.0, 500.0, 35.0)
|
||||
camera_component = ["Camera"]
|
||||
new_entity_id2 = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", cam_position, EntityId.EntityId()
|
||||
)
|
||||
if new_entity_id2.IsValid():
|
||||
self.log("Camera entity created")
|
||||
camera_entity = hydra.Entity("Camera Entity", new_entity_id2)
|
||||
camera_entity.components = []
|
||||
for component in camera_component:
|
||||
camera_entity.components.append(hydra.add_component(component, new_entity_id2))
|
||||
|
||||
# 6) Save and export to engine
|
||||
general.save_level()
|
||||
general.idle_wait(1.0)
|
||||
general.export_to_engine()
|
||||
general.idle_wait(1.0)
|
||||
|
||||
|
||||
test = TestDynamicSliceInstanceSpawnerEmbeddedEditor()
|
||||
test.run()
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DynamicSliceInstanceSpawnerExternalEditor", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new temporary level is created. Surface for planting is created. Simple vegetation area is created using
|
||||
Dynamic Slice Instance Spawner type using external assets.
|
||||
|
||||
Expected Behavior:
|
||||
Instances plant as expected in the assigned area.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a Vegetation Layer Spawner setup using Dynamic Slice Instance Spawner type assets
|
||||
3) Create a surface to plant on
|
||||
4) Verify expected instance counts
|
||||
5) Add a camera component looking at the planting area for visual debugging
|
||||
6) Save and export to engine
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and switch the Vegetation Asset List Source
|
||||
# Type to External
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
veg_area_required_components = ["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List",
|
||||
"Script Canvas"]
|
||||
new_entity_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
if new_entity_id.IsValid():
|
||||
self.log("Spawner entity created")
|
||||
spawner_entity = hydra.Entity("Spawner Entity", new_entity_id)
|
||||
spawner_entity.components = []
|
||||
for component in veg_area_required_components:
|
||||
spawner_entity.components.append(hydra.add_component(component, new_entity_id))
|
||||
hydra.get_set_test(spawner_entity, 2, "Configuration|Source Type", 1)
|
||||
|
||||
# Add a Script Canvas component with instance_counter script for launcher tests
|
||||
instance_counter_path = os.path.join("scriptcanvas", "instance_counter.scriptcanvas")
|
||||
instance_counter_script = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", instance_counter_path,
|
||||
math.Uuid(), False)
|
||||
spawner_entity.get_set_test(3, "Script Canvas Asset|Script Canvas Asset", instance_counter_script)
|
||||
|
||||
# Assign a Vegetation Descriptor List asset to the Vegetation Asset List component
|
||||
descriptor_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("Assets", "VegDescriptorLists", "flower_pink.vegdescriptorlist"), math.Uuid(),
|
||||
False)
|
||||
hydra.get_set_test(spawner_entity, 2, "Configuration|External Assets", descriptor_asset)
|
||||
|
||||
# Resize the Box Shape component
|
||||
new_box_dimensions = math.Vector3(16.0, 16.0, 16.0)
|
||||
box_dimensions_path = "Box Shape|Box Configuration|Dimensions"
|
||||
hydra.get_set_test(spawner_entity, 1, box_dimensions_path, new_box_dimensions)
|
||||
|
||||
# 3) Create a surface to plant on
|
||||
dynveg.create_surface_entity("Planting Surface", entity_position, 128.0, 128.0, 1.0)
|
||||
|
||||
# 4) Verify instance counts are accurate
|
||||
general.idle_wait(3.0) # Allow a few seconds for instances to spawn
|
||||
num_expected_instances = 20 * 20
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
||||
entity_position = math.Vector3(512.0, 500.0, 35.0)
|
||||
camera_component = ["Camera"]
|
||||
new_entity_id2 = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
if new_entity_id2.IsValid():
|
||||
self.log("Camera entity created")
|
||||
camera_entity = hydra.Entity("Camera Entity", new_entity_id2)
|
||||
camera_entity.components = []
|
||||
for component in camera_component:
|
||||
camera_entity.components.append(hydra.add_component(component, new_entity_id2))
|
||||
|
||||
# 6) Save and export to engine
|
||||
general.save_level()
|
||||
general.idle_wait(1.0)
|
||||
general.export_to_engine()
|
||||
general.idle_wait(1.0)
|
||||
|
||||
|
||||
test = TestDynamicSliceInstanceSpawnerExternalEditor()
|
||||
test.run()
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestEmptyInstanceSpawner(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="EmptyInstanceSpawner", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Test aspects of the EmptyInstanceSpawner through the BehaviorContext and the Property Tree.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# 1) Open an empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Grab the UUID that we need for creating an Empty Spawner
|
||||
empty_spawner_uuid = azlmbr.math.Uuid_CreateString('{23C40FD4-A55F-4BD3-BE5B-DC5423F217C2}', 0)
|
||||
|
||||
# 2) Test EmptyInstanceSpawner BehaviorContext
|
||||
behavior_context_test_success = True
|
||||
empty_spawner = azlmbr.vegetation.EmptyInstanceSpawner()
|
||||
behavior_context_test_success = behavior_context_test_success and (empty_spawner is not None)
|
||||
behavior_context_test_success = behavior_context_test_success and (empty_spawner.typename == 'EmptyInstanceSpawner')
|
||||
self.test_success = self.test_success and behavior_context_test_success
|
||||
self.log(f'EmptyInstanceSpawner() BehaviorContext test: {behavior_context_test_success}')
|
||||
|
||||
# 3) Test Descriptor BehaviorContext - setting spawnerType sets spawner too
|
||||
spawner_type_test_success = True
|
||||
descriptor = azlmbr.vegetation.Descriptor()
|
||||
spawner_type_test_success = spawner_type_test_success and hydra.get_set_property_test(descriptor, 'spawnerType', empty_spawner_uuid)
|
||||
spawner_type_test_success = spawner_type_test_success and (descriptor.spawner.typename == 'EmptyInstanceSpawner')
|
||||
self.test_success = self.test_success and spawner_type_test_success
|
||||
self.log(f'Descriptor() BehaviorContext spawnerType test: {spawner_type_test_success}')
|
||||
|
||||
# 4) Test Descriptor BehaviorContext - setting spawner sets spawnerType too
|
||||
spawner_test_success = True
|
||||
descriptor = azlmbr.vegetation.Descriptor()
|
||||
descriptor.spawner = empty_spawner
|
||||
spawner_test_success = spawner_test_success and (descriptor.spawnerType.Equal(empty_spawner_uuid))
|
||||
spawner_test_success = spawner_test_success and (descriptor.spawner.typename == 'EmptyInstanceSpawner')
|
||||
self.test_success = self.test_success and spawner_test_success
|
||||
self.log(f'Descriptor() BehaviorContext spawner test: {spawner_test_success}')
|
||||
|
||||
### Setup for Property Tree set of tests
|
||||
|
||||
# Create a new entity with required vegetation area components
|
||||
spawner_entity = hydra.Entity("Veg Area")
|
||||
spawner_entity.create_entity(
|
||||
math.Vector3(512.0, 512.0, 32.0),
|
||||
["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
|
||||
)
|
||||
if spawner_entity.id.IsValid():
|
||||
self.log(f"'{spawner_entity.name}' created")
|
||||
|
||||
# Resize the Box Shape component
|
||||
new_box_dimensions = math.Vector3(16.0, 16.0, 16.0)
|
||||
box_dimensions_path = "Box Shape|Box Configuration|Dimensions"
|
||||
spawner_entity.get_set_test(1, box_dimensions_path, new_box_dimensions)
|
||||
|
||||
# Create a surface to plant on
|
||||
dynveg.create_surface_entity("Surface Entity", math.Vector3(512.0, 512.0, 32.0), 1024.0, 1024.0, 1.0)
|
||||
|
||||
# 5) Descriptor Property Tree test: spawner type can be set
|
||||
|
||||
# - Validate the empty spawner type can be set correctly.
|
||||
property_tree_success = True
|
||||
property_tree_success = property_tree_success and spawner_entity.get_set_test(2, 'Configuration|Embedded Assets|[0]|Instance Spawner', empty_spawner_uuid)
|
||||
|
||||
# This should result in 400 instances, since our box is 16 m x 16 m and by default the veg system plants
|
||||
# 20 instances per 16 meters
|
||||
general.idle_wait(2.0)
|
||||
num_expected_instances = 20 * 20
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
property_tree_success = property_tree_success and (num_found == num_expected_instances)
|
||||
self.test_success = self.test_success and property_tree_success
|
||||
self.log(f'Found {num_found} instances -- Expected {num_expected_instances} instances')
|
||||
self.log(f'Property Tree spawner type test: {property_tree_success}')
|
||||
|
||||
# 6) Validate that the "Allow Empty Assets" setting doesn't affect the EmptyInstanceSpawner
|
||||
allow_empty_assets_success = True
|
||||
spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
|
||||
general.idle_wait(2.0)
|
||||
num_found = azlmbr.areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
allow_empty_assets_success = allow_empty_assets_success and (num_found == num_expected_instances)
|
||||
self.test_success = self.test_success and allow_empty_assets_success
|
||||
self.log(f'Allow Empty Assets test: {allow_empty_assets_success}')
|
||||
|
||||
|
||||
test = TestEmptyInstanceSpawner()
|
||||
test.run()
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.vegetation as vegetation
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestInstanceSpawnerPriority(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="InstanceSpawnerPriority", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new level is created. An instance spawner area and blocker area are setup to overlap. Instance counts are
|
||||
verified with the initial setup. Layer priority on the blocker area is set to lower than the instance spawner
|
||||
area, and instance counts are re-verified.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation areas with a higher Layer Priority plant over those with a lower Layer Priority
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create overlapping instance spawner and blocker areas
|
||||
3) Create a surface to plant on
|
||||
4) Validate initial instance counts in the spawner area
|
||||
5) Reduce the Layer Priority of the blocker area
|
||||
6) Validate instance counts in the spawner area
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create overlapping areas: 1 instance spawner area, and 1 blocker area
|
||||
spawner_center_point = math.Vector3(508.0, 508.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 1.0,
|
||||
asset_path)
|
||||
blocker_center_point = math.Vector3(516.0, 516.0, 32.0)
|
||||
blocker_entity = dynveg.create_blocker_area("Instance Blocker", blocker_center_point, 16.0, 16.0, 1.0)
|
||||
|
||||
# 3) Create a surface for planting
|
||||
planting_surface_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
dynveg.create_surface_entity("Planting Surface", planting_surface_center_point, 64.0, 64.0, 1.0)
|
||||
|
||||
# Set instances to spawn on a center snap point to avoid unexpected instances around the edges of the box shape
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 4) Validate the expected instance count with initial setup. GetAreaProductCount is used as
|
||||
# GetInstanceCountInAabb does not filter out blocked instances
|
||||
num_expected = (20 * 20) - (10 * 10) # 20 instances per 16m per side minus 1 blocked quadrant
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
# 5) Change the Instance Spawner area to a higher layer priority than the Instance Blocker
|
||||
blocker_entity.get_set_test(0, 'Configuration|Layer Priority', 0)
|
||||
|
||||
# 6) Validate the expected instance count with changed area priorities
|
||||
num_expected = 20 * 20 # 20 instances per 16m per side, no instances should be blocked at this point
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
# 7) Revert Layer Priority changes so both areas are equal, and change Sub Priority to a higher value on the
|
||||
# Instance Spawner area
|
||||
blocker_entity.get_set_test(0, 'Configuration|Layer Priority', 1)
|
||||
spawner_entity.get_set_test(0, 'Configuration|Sub Priority', 100)
|
||||
blocker_entity.get_set_test(0, 'Configuration|Sub Priority', 1)
|
||||
|
||||
# 8) Validate the expected instance count with changed area priorities
|
||||
num_expected = 20 * 20 # 20 instances per 16m per side, no instances should be blocked at this point
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
|
||||
test = TestInstanceSpawnerPriority()
|
||||
test.run()
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C2627906: A simple Vegetation Layer Blender area can be created
|
||||
"""
|
||||
|
||||
import os
|
||||
from math import radians
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestVegLayerBlenderCreated(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="LayerBlender_E2E_Editor", args=["level"])
|
||||
self.screenshot_count = 0
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A temporary level is loaded. Two vegetation areas with different meshes are added and then
|
||||
pinned to a vegetation blender. Screenshots are taken in the editor normal mode and in game mode.
|
||||
|
||||
Expected Behavior:
|
||||
The specified assets plant in the specified blend area and are visible in the Viewport in
|
||||
Edit Mode, Game Mode.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create 2 vegetation areas with different meshes
|
||||
3) Create Blender entity and pin the vegetation areas
|
||||
4) Take screenshot in normal mode
|
||||
5) Create a new entity with a Camera component for testing in the launcher
|
||||
6) Save level and take screenshot in game mode
|
||||
7) Export to engine
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create/prepare a new level and set an appropriate view of blender area
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(500.49, 498.69, 46.66)
|
||||
general.set_current_view_rotation(-42.05, 0.00, -36.33)
|
||||
|
||||
# 2) Create 2 vegetation areas with different meshes
|
||||
purple_position = math.Vector3(504.0, 512.0, 32.0)
|
||||
purple_asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity_1 = dynveg.create_vegetation_area("Purple Spawner",
|
||||
purple_position,
|
||||
16.0, 16.0, 1.0,
|
||||
purple_asset_path)
|
||||
|
||||
pink_position = math.Vector3(520.0, 512.0, 32.0)
|
||||
pink_asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity_2 = dynveg.create_vegetation_area("Pink Spawner",
|
||||
pink_position,
|
||||
16.0, 16.0, 1.0,
|
||||
pink_asset_path)
|
||||
|
||||
base_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
dynveg.create_surface_entity("Surface Entity",
|
||||
base_position,
|
||||
16.0, 16.0, 1.0)
|
||||
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# 3) Create Blender entity and pin the vegetation areas. We also add and attach a Lua script to validate in the
|
||||
# launcher for the follow-up test
|
||||
blender_entity = hydra.Entity("Blender")
|
||||
blender_entity.create_entity(
|
||||
base_position,
|
||||
["Box Shape", "Vegetation Layer Blender", "Lua Script"]
|
||||
)
|
||||
if blender_entity.id.IsValid():
|
||||
print(f"'{blender_entity.name}' created")
|
||||
|
||||
blender_entity.get_set_test(0, "Box Shape|Box Configuration|Dimensions", math.Vector3(16.0, 16.0, 1.0))
|
||||
blender_entity.get_set_test(1, "Configuration|Vegetation Areas", [spawner_entity_1.id, spawner_entity_2.id])
|
||||
instance_counter_path = os.path.join("luascripts", "instance_counter_blender.lua")
|
||||
instance_counter_script = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", instance_counter_path,
|
||||
math.Uuid(), False)
|
||||
blender_entity.get_set_test(2, "Script properties|Asset", instance_counter_script)
|
||||
|
||||
# 4) Verify instances in blender area are equally represented by both descriptors
|
||||
|
||||
# Wait for instances to spawn
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
num_expected = 20 * 20
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count(base_position, 8.0, num_expected), 5.0)
|
||||
|
||||
if self.test_success:
|
||||
box = math.Aabb_CreateCenterRadius(base_position, 8.0)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
pink_count = 0
|
||||
purple_count = 0
|
||||
for instance in instances:
|
||||
purple_asset_path = purple_asset_path.replace("\\", "/").lower()
|
||||
pink_asset_path = pink_asset_path.replace("\\", "/").lower()
|
||||
if instance.descriptor.spawner.GetSliceAssetPath() == pink_asset_path:
|
||||
pink_count += 1
|
||||
elif instance.descriptor.spawner.GetSliceAssetPath() == purple_asset_path:
|
||||
purple_count += 1
|
||||
self.test_success = pink_count == purple_count and (pink_count + purple_count == num_expected) and self.test_success
|
||||
|
||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
||||
entity_position = math.Vector3(500.0, 500.0, 47.0)
|
||||
rot_degrees_vector = math.Vector3(radians(-55.0), radians(28.5), radians(-17.0))
|
||||
camera_component = ["Camera"]
|
||||
camera_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
if camera_id.IsValid():
|
||||
self.log("Camera entity created")
|
||||
camera_entity = hydra.Entity("Camera Entity", camera_id)
|
||||
camera_entity.components = []
|
||||
for component in camera_component:
|
||||
camera_entity.components.append(hydra.add_component(component, camera_id))
|
||||
azlmbr.components.TransformBus(bus.Event, "SetLocalRotation", camera_id, rot_degrees_vector)
|
||||
|
||||
# 6) Save and export level
|
||||
general.save_level()
|
||||
general.idle_wait(1.0)
|
||||
general.export_to_engine()
|
||||
general.idle_wait(1.0)
|
||||
|
||||
|
||||
test = TestVegLayerBlenderCreated()
|
||||
test.run()
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestLayerBlocker(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="LayerBlocker_InstancesBlocked", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
An empty level is created. A Vegetation Layer Spawner area is configured. A Vegetation Layer Blocker area is
|
||||
configured to block instances in the spawner area.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation is blocked by the configured Blocker area.
|
||||
|
||||
Test Steps:
|
||||
1. A new level is created
|
||||
2. Vegetation Layer Spawner area is created
|
||||
3. Planting surface is created
|
||||
4. Vegetation System Settings level component is added, and Snap Mode set to center to ensure expected instance
|
||||
counts are accurate in the configured vegetation area
|
||||
5. Initial instance counts pre-blocker are validated
|
||||
6. A Vegetation Layer Blocker area is created, overlapping the spawner area
|
||||
7. Post-blocker instance counts are validated
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new instance spawner entity
|
||||
spawner_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Create surface for planting on
|
||||
dynveg.create_surface_entity("Surface Entity", spawner_center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# 4) Add a Vegetation System Settings Level component and set Sector Point Snap Mode to Center
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 5) Verify initial instance counts
|
||||
num_expected = 20 * 20
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
# 6) Create a new Vegetation Layer Blocker area overlapping the spawner area
|
||||
blocker_entity = hydra.Entity("Blocker Area")
|
||||
blocker_entity.create_entity(
|
||||
spawner_center_point,
|
||||
["Vegetation Layer Blocker", "Box Shape"]
|
||||
)
|
||||
if blocker_entity.id.IsValid():
|
||||
print(f"'{blocker_entity.name}' created")
|
||||
blocker_entity.get_set_test(1, "Box Shape|Box Configuration|Dimensions",
|
||||
math.Vector3(3.0, 3.0, 3.0))
|
||||
|
||||
# 7) Validate instance counts post-blocker. 16 instances should now be blocked in the center of the spawner area
|
||||
num_expected = (20 * 20) - 16
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
|
||||
test = TestLayerBlocker()
|
||||
test.run()
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestLayerSpawnerFilterStageToggle(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="LayerSpawner_FilterStageToggle", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C4765973 Filter Stage toggle affects final vegetation position.
|
||||
|
||||
Expected Result:
|
||||
Vegetation instances plant differently depending on the Filter Stage setting.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
PREPROCESS_INSTANCE_COUNT = 16
|
||||
POSTPROCESS_INSTANCE_COUNT = 19
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create a vegetation area with all needed components
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
vegetation_entity = dynveg.create_vegetation_area("vegetation", position, 16.0, 16.0, 10.0, asset_path)
|
||||
vegetation_entity.add_component("Vegetation Slope Filter")
|
||||
vegetation_entity.add_component("Vegetation Position Modifier")
|
||||
|
||||
# Create a child entity under vegetation area
|
||||
child_entity = hydra.Entity("child_entity")
|
||||
components_to_add = ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"]
|
||||
child_entity.create_entity(position, components_to_add, vegetation_entity.id)
|
||||
|
||||
# Set the Gradient Id in X and Y direction
|
||||
vegetation_entity.get_set_test(4, "Configuration|Position X|Gradient|Gradient Entity Id", child_entity.id)
|
||||
vegetation_entity.get_set_test(4, "Configuration|Position Y|Gradient|Gradient Entity Id", child_entity.id)
|
||||
|
||||
# Set the min and max values for Slope Filter
|
||||
vegetation_entity.get_set_test(3, "Configuration|Slope Min", 25)
|
||||
vegetation_entity.get_set_test(3, "Configuration|Slope Max", 35)
|
||||
|
||||
# Add entity with Mesh to replicate creation of hills
|
||||
dynveg.create_mesh_surface_entity_with_slopes("hill", position, 5.0, 5.0, 5.0)
|
||||
|
||||
# Set the filter stage to preprocess and postprocess respectively and verify instance count
|
||||
vegetation_entity.get_set_test(0, "Configuration|Filter Stage", 1)
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 16.0, PREPROCESS_INSTANCE_COUNT), 3.0)
|
||||
result = dynveg.validate_instance_count(position, 16.0, PREPROCESS_INSTANCE_COUNT)
|
||||
self.log(f"Preprocess filter stage vegetation instance count is as expected: {result}")
|
||||
vegetation_entity.get_set_test(0, "Configuration|Filter Stage", 2)
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 16.0, POSTPROCESS_INSTANCE_COUNT), 3.0)
|
||||
result = dynveg.validate_instance_count(position, 16.0, POSTPROCESS_INSTANCE_COUNT)
|
||||
self.log(f"Postprocess filter vegetation instance stage count is as expected: {result}")
|
||||
|
||||
|
||||
test = TestLayerSpawnerFilterStageToggle()
|
||||
test.run()
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.math as math
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.paths
|
||||
import azlmbr.surface_data as surface_data
|
||||
import azlmbr.vegetation as vegetation
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestLayerSpawnerInheritBehavior(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="LayerSpawner_InheritBehavior", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C4762381 Verifies if Inherit Behavior Flag works as expected.
|
||||
|
||||
Expected Result:
|
||||
The spawner with Inherit Behavior toggled off no longer obeys
|
||||
Vegetation Surface Mask Filter of the Vegetation Layer Blender entity and plants on the surface.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
SURFACE_TAG = "test_tag"
|
||||
|
||||
def set_dynamic_slice_asset(entity_obj, component_index, dynamic_slice_asset_path):
|
||||
dynamic_slice_spawner = vegetation.DynamicSliceInstanceSpawner()
|
||||
dynamic_slice_spawner.SetSliceAssetPath(dynamic_slice_asset_path)
|
||||
descriptor = hydra.get_component_property_value(
|
||||
entity_obj.components[component_index], "Configuration|Embedded Assets|[0]"
|
||||
)
|
||||
descriptor.spawner = dynamic_slice_spawner
|
||||
entity_obj.get_set_test(2, "Configuration|Embedded Assets|[0]", descriptor)
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create Emitter entity and add the required components
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
emitter_entity = dynveg.create_surface_entity("emitter_entity", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# Add surface tag to the Surface Tag Emitter
|
||||
tag = surface_data.SurfaceTag()
|
||||
tag.SetTag(SURFACE_TAG)
|
||||
pte = hydra.get_property_tree(emitter_entity.components[1])
|
||||
path = "Configuration|Generated Tags"
|
||||
pte.add_container_item(path, 0, tag)
|
||||
emitter_entity.get_set_test(1, "Configuration|Generated Tags|[0]", tag)
|
||||
|
||||
# Create Blender entity and add required components
|
||||
components_to_add = ["Box Shape", "Vegetation Layer Blender"]
|
||||
blender_entity = hydra.Entity("blender_entity")
|
||||
blender_entity.create_entity(position, components_to_add)
|
||||
blender_entity.get_set_test(0, "Box Shape|Box Configuration|Dimensions", math.Vector3(16.0, 16.0, 1.0))
|
||||
|
||||
# Create Vegetation area and assign a valid asset
|
||||
veg_1 = hydra.Entity("veg_1")
|
||||
veg_1.create_entity(
|
||||
position, ["Vegetation Layer Spawner", "Vegetation Reference Shape", "Vegetation Asset List"]
|
||||
)
|
||||
set_dynamic_slice_asset(veg_1, 2, os.path.join("Slices", "PinkFlower.dynamicslice"))
|
||||
veg_1.get_set_test(1, "Configuration|Shape Entity Id", blender_entity.id)
|
||||
|
||||
# Create second vegetation area and assign a valid asset
|
||||
veg_2 = hydra.Entity("veg_2")
|
||||
veg_2.create_entity(
|
||||
position, ["Vegetation Layer Spawner", "Vegetation Reference Shape", "Vegetation Asset List"]
|
||||
)
|
||||
set_dynamic_slice_asset(veg_2, 2, os.path.join("Slices", "PurpleFlower.dynamicslice"))
|
||||
veg_2.get_set_test(1, "Configuration|Shape Entity Id", blender_entity.id)
|
||||
|
||||
# Assign the vegetation areas to the Blender entity
|
||||
pte = hydra.get_property_tree(blender_entity.components[1])
|
||||
path = "Configuration|Vegetation Areas"
|
||||
pte.update_container_item(path, 0, veg_1.id)
|
||||
pte.add_container_item(path, 1, veg_2.id)
|
||||
|
||||
# Add Vegetation Surface Mask Filter to the blender entity and add a Exclusion tag
|
||||
tag = surface_data.SurfaceTag()
|
||||
tag.SetTag(SURFACE_TAG)
|
||||
blender_entity.add_component("Vegetation Surface Mask Filter")
|
||||
pte = hydra.get_property_tree(blender_entity.components[2])
|
||||
path = "Configuration|Exclusion|Surface Tags"
|
||||
pte.add_container_item(path, 0, tag)
|
||||
blender_entity.get_set_test(2, "Configuration|Exclusion|Surface Tags|[0]", tag)
|
||||
|
||||
# Toggle Inherit Behavior flag and verify vegetation instances
|
||||
self.log(
|
||||
f"Vegetation is not planted when Inherit Behavior flag is checked: {dynveg.validate_instance_count(position, 16.0, 0)}"
|
||||
)
|
||||
veg_1.get_set_test(0, "Configuration|Inherit Behavior", False)
|
||||
self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 16.0, 400), 2.0)
|
||||
self.log(
|
||||
f"Vegetation plant when Inherit Behavior flag is unchecked: {dynveg.validate_instance_count(position, 16.0, 400)}"
|
||||
)
|
||||
|
||||
|
||||
test = TestLayerSpawnerInheritBehavior()
|
||||
test.run()
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestLayerSpawner_AllShapesPlant(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="TestLayerSpawner_AllShapesPlant", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
The level is loaded and vegetation area is created. Then the Vegetation Reference Shape
|
||||
component of vegetation area is pinned with entities of different shape components to check
|
||||
if the vegetation plants in different shaped areas.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation properly plants in areas of any shape.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create basic vegetation area entity and set the properties
|
||||
3) Box Shape Entity: create, set properties and pin to vegetation
|
||||
4) Capsule Shape Entity: create, set properties and pin to vegetation
|
||||
5) Tube Shape Entity: create, set properties and pin to vegetation
|
||||
6) Sphere Shape Entity: create, set properties and pin to vegetation
|
||||
7) Cylinder Shape Entity: create, set properties and pin to vegetation
|
||||
8) Prism Shape Entity: create, set properties and pin to vegetation
|
||||
9) Compound Shape Entity: create, set properties and pin to vegetation
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def pin_shape_and_check_count(entity_id, count):
|
||||
hydra.get_set_test(vegetation, 2, "Configuration|Shape Entity Id", entity_id)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(vegetation.id,
|
||||
count), 2.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create basic vegetation area entity and set the properties
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
vegetation = dynveg.create_vegetation_area("Instance Spawner",
|
||||
entity_position,
|
||||
10.0, 10.0, 10.0,
|
||||
asset_path)
|
||||
vegetation.remove_component("Box Shape")
|
||||
vegetation.add_component("Vegetation Reference Shape")
|
||||
|
||||
# Create surface for planting on
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 60.0, 60.0, 1.0)
|
||||
|
||||
# Adjust camera to be close to the vegetation entity
|
||||
general.set_current_view_position(135.0, 102.0, 39.0)
|
||||
general.set_current_view_rotation(-15.0, 0, 0)
|
||||
|
||||
# 3) Box Shape Entity: create, set properties and pin to vegetation
|
||||
box = hydra.Entity("box")
|
||||
box.create_entity(math.Vector3(124.0, 126.0, 32.0), ["Box Shape"])
|
||||
new_box_dimension = math.Vector3(10.0, 10.0, 1.0)
|
||||
hydra.get_set_test(box, 0, "Box Shape|Box Configuration|Dimensions", new_box_dimension)
|
||||
# This and subsequent counts are the number of "PurpleFlower" that spawn in the shape with given dimensions
|
||||
pin_shape_and_check_count(box.id, 156)
|
||||
|
||||
# 4) Capsule Shape Entity: create, set properties and pin to vegetation
|
||||
capsule = hydra.Entity("capsule")
|
||||
capsule.create_entity(math.Vector3(120.0, 142.0, 32.0), ["Capsule Shape"])
|
||||
hydra.get_set_test(capsule, 0, "Capsule Shape|Capsule Configuration|Height", 10.0)
|
||||
hydra.get_set_test(capsule, 0, "Capsule Shape|Capsule Configuration|Radius", 2.0)
|
||||
pin_shape_and_check_count(capsule.id, 20)
|
||||
|
||||
# 5) Tube Shape Entity: create, set properties and pin to vegetation
|
||||
tube = hydra.Entity("tube")
|
||||
tube.create_entity(math.Vector3(124.0, 136.0, 32.0), ["Tube Shape", "Spline"])
|
||||
pin_shape_and_check_count(tube.id, 27)
|
||||
|
||||
# 6) Sphere Shape Entity: create, set properties and pin to vegetation
|
||||
sphere = hydra.Entity("sphere")
|
||||
sphere.create_entity(math.Vector3(112.0, 143.0, 32.0), ["Sphere Shape"])
|
||||
hydra.get_set_test(sphere, 0, "Sphere Shape|Sphere Configuration|Radius", 5.0)
|
||||
pin_shape_and_check_count(sphere.id, 122)
|
||||
|
||||
# 7) Cylinder Shape Entity: create, set properties and pin to vegetation
|
||||
cylinder = hydra.Entity("cylinder")
|
||||
cylinder.create_entity(math.Vector3(136.0, 143.0, 32.0), ["Cylinder Shape"])
|
||||
hydra.get_set_test(cylinder, 0, "Cylinder Shape|Cylinder Configuration|Radius", 5.0)
|
||||
hydra.get_set_test(cylinder, 0, "Cylinder Shape|Cylinder Configuration|Height", 5.0)
|
||||
pin_shape_and_check_count(cylinder.id, 124)
|
||||
|
||||
# 8) Prism Shape Entity: create, set properties and pin to vegetation
|
||||
polygon_prism = hydra.Entity("polygonprism")
|
||||
polygon_prism.create_entity(math.Vector3(127.0, 142.0, 32.0), ["Polygon Prism Shape"])
|
||||
pin_shape_and_check_count(polygon_prism.id, 20)
|
||||
|
||||
# 9) Compound Shape Entity: create, set properties and pin to vegetation
|
||||
compound = hydra.Entity("Compound")
|
||||
compound.create_entity(math.Vector3(125.0, 136.0, 32.0), ["Compound Shape"])
|
||||
pte = hydra.get_property_tree(compound.components[0])
|
||||
shapes = [box.id, capsule.id, tube.id, sphere.id, cylinder.id, polygon_prism.id]
|
||||
for index in range(6):
|
||||
pte.add_container_item("Configuration|Child Shape Entities", index, EntityId.EntityId())
|
||||
for index, element in enumerate(shapes):
|
||||
hydra.get_set_test(compound, 0, f"Configuration|Child Shape Entities|[{index}]", element)
|
||||
pin_shape_and_check_count(compound.id, 469)
|
||||
|
||||
|
||||
test = TestLayerSpawner_AllShapesPlant()
|
||||
test.run()
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestLayerSpawnerInstanceCameraRefresh(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="LayerSpawner_InstanceCameraRefresh", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Test that the Dynamic Vegetation System is using the current Editor viewport camera as the center
|
||||
of the spawn area for vegetation. To verify this, we create two separate Editor viewports pointed
|
||||
at two different vegetation areas, and verify that as we switch between active viewports, only the
|
||||
area directly underneath that viewport's camera has vegetation.
|
||||
"""
|
||||
# Create an empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
# Set up a test environment to validate that switching viewports correctly changes which camera
|
||||
# the vegetation system uses.
|
||||
# The test environment consists of the following:
|
||||
# - two 32 x 32 x 1 box shapes located far apart that emit a surface with no tags
|
||||
# - two 32 x 32 x 32 vegetation areas that place vegetation on the boxes
|
||||
|
||||
# Initialize some constants for our test.
|
||||
# The boxes are intentionally shifted by 0.5 meters to ensure that we get a predictable number
|
||||
# of vegetation points. By default, vegetation plants on grid corners, so if our boxes are aligned
|
||||
# with grid corner points, the right/bottom edges will include more points than we might intuitively expect.
|
||||
# By shifting by 0.5 meters, the vegetation grid points don't fall on the box edges, making the total count
|
||||
# more predictable.
|
||||
first_entity_center_point = math.Vector3(0.5, 0.5, 100.0)
|
||||
# The second box needs to be far enough away from the first that the vegetation system will never spawn instances
|
||||
# in both at the same time.
|
||||
second_entity_center_point = math.Vector3(1024.5, 1024.5, 100.0)
|
||||
box_size = 32.0
|
||||
surface_height = 1.0
|
||||
# By default, vegetation spawns 20 instances per 16 meters, so for our box of 32 meters, we should have
|
||||
# ((20 instances / 16 m) * 32 m) ^ 2 instances.
|
||||
filled_vegetation_area_instance_count = (20 * 2) * (20 * 2)
|
||||
|
||||
# Change the Editor view to contain two viewports
|
||||
general.set_view_pane_layout(1)
|
||||
get_view_pane_layout_success = self.wait_for_condition(lambda: (general.get_view_pane_layout() == 1), 2)
|
||||
get_viewport_count_success = self.wait_for_condition(lambda: (general.get_viewport_count() == 2), 2)
|
||||
self.test_success = get_view_pane_layout_success and self.test_success
|
||||
self.test_success = get_viewport_count_success and self.test_success
|
||||
|
||||
# Set the view in the first viewport to point down at the first box
|
||||
general.set_active_viewport(0)
|
||||
self.wait_for_condition(lambda: general.get_active_viewport() == 0, 2)
|
||||
general.set_current_view_position(first_entity_center_point.x, first_entity_center_point.y,
|
||||
first_entity_center_point.z + 30.0)
|
||||
general.set_current_view_rotation(-85.0, 0.0, 0.0)
|
||||
|
||||
# Set the view in the second viewport to point down at the second box
|
||||
general.set_active_viewport(1)
|
||||
self.wait_for_condition(lambda: general.get_active_viewport() == 1, 2)
|
||||
general.set_current_view_position(second_entity_center_point.x, second_entity_center_point.y,
|
||||
second_entity_center_point.z + 30.0)
|
||||
general.set_current_view_rotation(-85.0, 0.0, 0.0)
|
||||
|
||||
# Create the "flat surface" entities to use as our vegetation surfaces
|
||||
first_surface_entity = dynveg.create_surface_entity("Surface 1", first_entity_center_point, box_size, box_size,
|
||||
surface_height)
|
||||
second_surface_entity = dynveg.create_surface_entity("Surface 2", second_entity_center_point, box_size, box_size,
|
||||
surface_height)
|
||||
|
||||
# Create the two vegetation areas
|
||||
test_slice_asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
first_veg_entity = dynveg.create_vegetation_area("Veg Area 1", first_entity_center_point, box_size, box_size,
|
||||
box_size, test_slice_asset_path)
|
||||
second_veg_entity = dynveg.create_vegetation_area("Veg Area 2", second_entity_center_point, box_size, box_size,
|
||||
box_size, test_slice_asset_path)
|
||||
|
||||
# When the first viewport is active, the first area should be full of instances, and the second should be empty
|
||||
general.set_active_viewport(0)
|
||||
viewport_0_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(first_entity_center_point,
|
||||
box_size / 2.0,
|
||||
filled_vegetation_area_instance_count), 5)
|
||||
self.test_success = viewport_0_success and self.test_success
|
||||
viewport_1_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(second_entity_center_point,
|
||||
box_size / 2.0, 0), 5)
|
||||
self.test_success = viewport_1_success and self.test_success
|
||||
|
||||
# When the second viewport is active, the second area should be full of instances, and the first should be empty
|
||||
general.set_active_viewport(1)
|
||||
viewport_0_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(first_entity_center_point,
|
||||
box_size / 2.0, 0), 5)
|
||||
self.test_success = viewport_0_success and self.test_success
|
||||
viewport_1_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(second_entity_center_point,
|
||||
box_size / 2.0,
|
||||
filled_vegetation_area_instance_count), 5)
|
||||
self.test_success = viewport_1_success and self.test_success
|
||||
|
||||
|
||||
test = TestLayerSpawnerInstanceCameraRefresh()
|
||||
test.run()
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class test_MeshBlocker_InstancesBlockedByMesh(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="MeshBlocker_InstancesBlockedByMesh", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Level is created. An entity with a vegetation spawner and entity with vegetation blocker (Mesh) component are
|
||||
added. Finally, the instance counts are checked to verify expected numbers after blocker is applied.
|
||||
|
||||
Expected Behavior:
|
||||
The vegetation planted in the Spawner area is blocked by the Mesh of the Vegetation Blocker Mesh component.
|
||||
|
||||
Test Steps:
|
||||
--> Create level
|
||||
--> Create Spawner Entity
|
||||
--> Create Surface Entity to spawn vegetation instances on
|
||||
--> Create Blocker Entity with cube mesh
|
||||
--> Verify spawned vegetation instance counts
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
# Create a new level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner",
|
||||
entity_position,
|
||||
10.0, 10.0, 10.0,
|
||||
asset_path)
|
||||
|
||||
# Create surface entity to plant on
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 10.0, 10.0, 1.0)
|
||||
|
||||
# Create blocker entity with cube mesh
|
||||
blocker_entity = hydra.Entity("Blocker Entity")
|
||||
blocker_entity.create_entity(entity_position,
|
||||
["Mesh", "Vegetation Layer Blocker (Mesh)"])
|
||||
if blocker_entity.id.IsValid():
|
||||
print(f"'{blocker_entity.name}' created")
|
||||
|
||||
cubeId = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "default", "primitive_cube.cgf"), math.Uuid(),
|
||||
False)
|
||||
blocker_entity.get_set_test(0, "MeshComponentRenderNode|Mesh asset", cubeId)
|
||||
|
||||
# Verify spawned instance counts are accurate after addition of Blocker Entity
|
||||
num_expected = 160 # Number of "PurpleFlower"s that plant on a 10 x 10 surface minus 1m blocker cube
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 2.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
|
||||
test = test_MeshBlocker_InstancesBlockedByMesh()
|
||||
test.run()
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.math as math
|
||||
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class test_MeshBlocker_InstancesBlockedByMeshHeightTuning(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="MeshBlocker_InstancesBlockedByMeshHeightTuning", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A temporary level is created, then a simple vegetation area is created. A blocker area is created and it is
|
||||
verified that the tuning of the height percent blocker setting works as expected.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation is blocked only around the trunk of the tree, while it still plants under the areas covered by branches.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
3) Create surface entity
|
||||
4) Create blocker entity with sphere mesh
|
||||
5) Adjust the height Min/Max percentage values of blocker
|
||||
6) Verify spawned instance counts are accurate after adjusting height Max percentage of Blocker Entity
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner",
|
||||
entity_position,
|
||||
10.0, 10.0, 10.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Create surface entity to plant on
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 10.0, 10.0, 1.0)
|
||||
|
||||
# 4) Create blocker entity with cube mesh
|
||||
entity_position = math.Vector3(512.0, 512.0, 36.0)
|
||||
blocker_entity = hydra.Entity("Blocker Entity")
|
||||
blocker_entity.create_entity(entity_position,
|
||||
["Mesh", "Vegetation Layer Blocker (Mesh)"])
|
||||
if blocker_entity.id.IsValid():
|
||||
print(f"'{blocker_entity.name}' created")
|
||||
|
||||
sphereId = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "default", "primitive_sphere.cgf"), math.Uuid(),
|
||||
False)
|
||||
blocker_entity.get_set_test(0, "MeshComponentRenderNode|Mesh asset", sphereId)
|
||||
components.TransformBus(bus.Event, "SetLocalScale", blocker_entity.id, math.Vector3(5.0, 5.0, 5.0))
|
||||
|
||||
# 5) Adjust the height Max percentage values of blocker
|
||||
blocker_entity.get_set_test(1, "Configuration|Mesh Height Percent Max", 0.8)
|
||||
|
||||
# 6) Verify spawned instance counts are accurate after adjusting height Max percentage of Blocker Entity
|
||||
# The number of "PurpleFlower" instances that plant on a 10 x 10 surface minus those blocked by the sphere at
|
||||
# 80% max height factored in.
|
||||
num_expected = 117
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 2.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
|
||||
test = test_MeshBlocker_InstancesBlockedByMeshHeightTuning()
|
||||
test.run()
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestMeshSurfaceTagEmitter(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="MeshSurfaceTagEmitter_DependentOnMeshComponent", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A New level is loaded. A New entity is created with component "Mesh Surface Tag Emitter". Adding a component
|
||||
"Mesh" to the same entity.
|
||||
|
||||
Expected Behavior:
|
||||
Mesh Surface Tag Emitter is disabled until the required Mesh component is added to the entity.
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create a new entity with component "Mesh Surface Tag Emitter"
|
||||
3) Make sure Mesh Surface Tag Emitter is disabled
|
||||
4) Add Mesh to the same entity
|
||||
5) Make sure Mesh Surface Tag Emitter is enabled after adding Mesh
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
def is_component_enabled(EntityComponentIdPair):
|
||||
return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with component "Mesh Surface Tag Emitter"
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
component_to_add = "Mesh Surface Tag Emitter"
|
||||
entity_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
meshentity = hydra.Entity("meshentity", entity_id)
|
||||
meshentity.components = []
|
||||
meshentity.components.append(hydra.add_component(component_to_add, entity_id))
|
||||
if entity_id.IsValid():
|
||||
print("New Entity Created")
|
||||
|
||||
# 3) Make sure Mesh Surface Tag Emitter is disabled
|
||||
is_enabled = is_component_enabled(meshentity.components[0])
|
||||
self.test_success = self.test_success and not is_enabled
|
||||
if not is_enabled:
|
||||
print(f"{component_to_add} is Disabled")
|
||||
elif is_enabled:
|
||||
print(f"{component_to_add} is Enabled. But It should be disabled before adding Mesh")
|
||||
|
||||
# 4) Add Mesh to the same entity
|
||||
component = "Mesh"
|
||||
meshentity.components.append(hydra.add_component(component, entity_id))
|
||||
|
||||
# 5) Make sure Mesh Surface Tag Emitter is enabled after adding Mesh
|
||||
is_enabled = is_component_enabled(meshentity.components[0])
|
||||
self.test_success = self.test_success and is_enabled
|
||||
if is_enabled:
|
||||
print(f"{component_to_add} is Enabled")
|
||||
elif not is_enabled:
|
||||
print(f"{component_to_add} is Disabled. But It should be enabled after adding Mesh")
|
||||
|
||||
|
||||
test = TestMeshSurfaceTagEmitter()
|
||||
test.run()
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestMeshSurfaceTagEmitter(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSucessfully",
|
||||
args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
An enity with Mesh Tag Emitter and a Mesh is added to the viewport to verify if we are able to
|
||||
add/remove surface tags.
|
||||
|
||||
Expected Behavior:
|
||||
A new Surface Tag can be added and removed from the component.
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create a new entity with components "Mesh Surface Tag Emitter", "Mesh"
|
||||
3) Add/ remove Surface Tags
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with components "Mesh Surface Tag Emitter", "Mesh"
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
components_to_add = ["Mesh Surface Tag Emitter", "Mesh"]
|
||||
entity = hydra.Entity("entity")
|
||||
entity.create_entity(entity_position, components_to_add)
|
||||
|
||||
# 3) Add/ remove Surface Tags
|
||||
tag = surface_data.SurfaceTag()
|
||||
tag.SetTag("water")
|
||||
pte = hydra.get_property_tree(entity.components[0])
|
||||
path = "Configuration|Generated Tags"
|
||||
pte.add_container_item(path, 0, tag)
|
||||
success = self.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 1, 5.0)
|
||||
self.test_success = self.test_success and success
|
||||
print(f"Added SurfaceTag: container count is {pte.get_container_count(path).GetValue()}")
|
||||
pte.remove_container_item(path, 0)
|
||||
success = self.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 0, 5.0)
|
||||
self.test_success = self.test_success and success
|
||||
print(f"Removed SurfaceTag: container count is {pte.get_container_count(path).GetValue()}")
|
||||
|
||||
|
||||
test = TestMeshSurfaceTagEmitter()
|
||||
test.run()
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestPhysXColliderSurfaceTagEmitter(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="PhysXColliderSurfaceTagEmitter_E2E_Editor", args=["level"])
|
||||
|
||||
def validate_behavior_context(self):
|
||||
# Verify that we can create the component through the BehaviorContext
|
||||
behavior_context_test_success = True
|
||||
test_component = azlmbr.surface_data.SurfaceDataColliderComponent()
|
||||
behavior_context_test_success = behavior_context_test_success and (test_component is not None)
|
||||
behavior_context_test_success = behavior_context_test_success and (test_component.typename ==
|
||||
'SurfaceDataColliderComponent')
|
||||
|
||||
# Verify that we can get/set the tags through the BehaviorContext
|
||||
provider_tag1 = azlmbr.surface_data.SurfaceTag('provider_tag1')
|
||||
provider_tag2 = azlmbr.surface_data.SurfaceTag('provider_tag2')
|
||||
modifier_tag1 = azlmbr.surface_data.SurfaceTag('modifier_tag1')
|
||||
modifier_tag2 = azlmbr.surface_data.SurfaceTag('modifier_tag2')
|
||||
behavior_context_test_success = behavior_context_test_success and hydra.get_set_property_test(test_component,
|
||||
'providerTags',
|
||||
[provider_tag1,
|
||||
provider_tag2])
|
||||
behavior_context_test_success = behavior_context_test_success and hydra.get_set_property_test(test_component,
|
||||
'modifierTags',
|
||||
[modifier_tag1,
|
||||
modifier_tag2])
|
||||
self.log(f'SurfaceDataColliderComponent() BehaviorContext test: {behavior_context_test_success}')
|
||||
return behavior_context_test_success
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Test aspects of the PhysX Collider Surface Tag Emitter Component through the BehaviorContext and the Property Tree.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# Create an empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Verify all of the BehaviorContext API:
|
||||
self.test_success = self.test_success and self.validate_behavior_context()
|
||||
|
||||
# Set up a test environment to validate the PhysX Collider Surface Tag Emitter Component.
|
||||
# The test environment will consist of the following:
|
||||
# - a 32 x 32 x 1 box shape that emits a surface with no tags
|
||||
# - a 32 x 32 x 32 vegetation area that will only place vegetation on surfaces with the 'test' tag
|
||||
# With this setup, no vegetation will appear until a Surface Tag Emitter either emits new points with
|
||||
# the correct tag, or modifies points on our box shape to emit the correct tag.
|
||||
|
||||
# Initialize some arbitrary constants for our test
|
||||
entity_center_point = math.Vector3(512.0, 512.0, 100.0)
|
||||
invalid_tag = azlmbr.surface_data.SurfaceTag('invalid')
|
||||
surface_tag = azlmbr.surface_data.SurfaceTag('test')
|
||||
test_box_size = 32.0
|
||||
baseline_surface_height = 1.0
|
||||
collider_radius = 4.0
|
||||
collider_diameter = collider_radius * 2.0
|
||||
|
||||
# Set viewport view of area under test, and toggle helpers back on
|
||||
general.set_current_view_position(512.0, 485.0, 110.0)
|
||||
general.set_current_view_rotation(-35.0, 0.0, 0.0)
|
||||
general.toggle_helpers()
|
||||
|
||||
# Create the "flat surface" entity to use as our baseline surface
|
||||
dynveg.create_surface_entity("Baseline Surface", entity_center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# Create a new entity with required vegetation area components
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Veg Area", entity_center_point, 32.0, 32.0, 32.0, asset_path)
|
||||
|
||||
# Add a Vegetation Surface Mask Filter component to the spawner entity and set it to include the "test" tag
|
||||
spawner_entity.add_component("Vegetation Surface Mask Filter")
|
||||
spawner_entity.get_set_test(3, "Configuration|Inclusion|Surface Tags", [surface_tag])
|
||||
|
||||
# At this point, there should be 0 instances within our entire veg area
|
||||
initial_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(entity_center_point, 16.0, 0),
|
||||
5.0)
|
||||
self.test_success = self.test_success and initial_success
|
||||
|
||||
# Create an entity with a PhysX Collider and our PhysX Collider Surface Tag Emitter
|
||||
collider_entity = hydra.Entity("Collider Surface")
|
||||
collider_entity.create_entity(
|
||||
entity_center_point,
|
||||
["PhysX Collider", "PhysX Collider Surface Tag Emitter"]
|
||||
)
|
||||
if collider_entity.id.IsValid():
|
||||
self.log(f"'{collider_entity.name}' created")
|
||||
|
||||
# Set up the PhysX Collider so that each shape type (sphere, box, capsule) has the same test height.
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Sphere|Radius", collider_radius)
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Box|Dimensions", math.Vector3(collider_diameter,
|
||||
collider_diameter,
|
||||
collider_diameter))
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Capsule|Height", collider_diameter)
|
||||
|
||||
# Run through each collider shape type (sphere, box, capsule) and verify the surface generation
|
||||
# and surface modification of the PhysX Collision Surface Tag Emitter Component.
|
||||
for collider_shape in range(0, 3):
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Shape", collider_shape)
|
||||
|
||||
# Test: Generate a new surface on the collider.
|
||||
# There should be one instance at the very top of the collider sphere, and none on the baseline surface
|
||||
# (We use a small query box to only check for one placed instance point)
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Generated Tags", [surface_tag])
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Extended Tags", [invalid_tag])
|
||||
top_point = math.Vector3(entity_center_point.x, entity_center_point.y, entity_center_point.z +
|
||||
collider_radius)
|
||||
baseline_surface_point = math.Vector3(entity_center_point.x, entity_center_point.y, entity_center_point.z +
|
||||
(baseline_surface_height / 2.0))
|
||||
top_point_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, 0.25, 1), 5.0)
|
||||
self.test_success = self.test_success and top_point_success
|
||||
baseline_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(baseline_surface_point,
|
||||
0.25, 0), 5.0)
|
||||
self.test_success = self.test_success and baseline_success
|
||||
|
||||
# Test: Modify an existing surface inside the collider.
|
||||
# There should be no instances at the very top of the collider sphere, and one on the baseline surface
|
||||
# within our query box.
|
||||
# (We use a small query box to only check for one placed instance point)
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Generated Tags", [invalid_tag])
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Extended Tags", [surface_tag])
|
||||
top_point_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, 0.25, 0), 5.0)
|
||||
self.test_success = self.test_success and top_point_success
|
||||
baseline_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(baseline_surface_point,
|
||||
0.25, 1), 5.0)
|
||||
self.test_success = self.test_success and baseline_success
|
||||
|
||||
# Setup collider entity with a PhysX Mesh
|
||||
test_physx_mesh_asset_path = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("levels", "physics",
|
||||
"c4044697_material_perfacematerialvalidation",
|
||||
"test.pxmesh"), math.Uuid(), False)
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Shape", 7)
|
||||
hydra.get_set_test(collider_entity, 0, "Shape Configuration|Asset|PhysX Mesh", test_physx_mesh_asset_path)
|
||||
|
||||
# Set the asset scale to match the test heights of the shapes tested
|
||||
asset_scale = math.Vector3(1.0, 1.0, 9.0)
|
||||
collider_entity.get_set_test(0, "Shape Configuration|Asset|Configuration|Asset Scale", asset_scale)
|
||||
|
||||
# Test: Generate a new surface on the collider.
|
||||
# There should be one instance at the very top of the collider mesh, and none on the baseline surface
|
||||
# (We use a small query box to only check for one placed instance point)
|
||||
self.log("Starting PhysX Mesh Collider Test")
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Generated Tags", [surface_tag])
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Extended Tags", [invalid_tag])
|
||||
top_point_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, 0.25, 1), 5.0)
|
||||
self.test_success = self.test_success and top_point_success
|
||||
baseline_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(baseline_surface_point,
|
||||
0.25, 0), 5.0)
|
||||
self.test_success = self.test_success and baseline_success
|
||||
|
||||
# Test: Modify an existing surface inside the collider.
|
||||
# There should be no instances at the very top of the collider mesh, and none on the baseline surface within
|
||||
# our query box as PhysX meshes are treated as hollow shells, not solid volumes.
|
||||
# (We use a small query box to only check for one placed instance point)
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Generated Tags", [invalid_tag])
|
||||
hydra.get_set_test(collider_entity, 1, "Configuration|Extended Tags", [surface_tag])
|
||||
top_point_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, 0.25, 0), 5.0)
|
||||
self.test_success = self.test_success and top_point_success
|
||||
baseline_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(baseline_surface_point,
|
||||
0.25, 0), 5.0)
|
||||
self.test_success = self.test_success and baseline_success
|
||||
|
||||
|
||||
test = TestPhysXColliderSurfaceTagEmitter()
|
||||
test.run()
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestPositionModifierAutoSnapToSurface(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="PositionModifier_AutoSnapToSurface", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Instance spawner is setup to plant on a spherical mesh. Offsets are set on the x-axis, and checks are performed
|
||||
to ensure instances plant where expected depending on the toggle setting.
|
||||
|
||||
Expected Behavior:
|
||||
Offset instances snap to the expected surface when Auto Snap to Surface is enabled, and offset away from surface
|
||||
when it is disabled.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new, temporary level
|
||||
2) Create a new entity with required vegetation area components and a Position Modifier
|
||||
3) Create a spherical planting surface
|
||||
4) Verify initial instance counts pre-filter
|
||||
5) Create a child entity of the spawner entity with a Constant Gradient component and pin to spawner
|
||||
6) Set the Position Modifier offset to 5 on the x-axis
|
||||
7) Validate instance counts on top of and inside the sphere mesh with Auto Snap to Surface enabled
|
||||
8) Validate instance counts on top of and inside the sphere mesh with Auto Snap to Surface disabled
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
position_modifier_paths = ['Configuration|Position X|Range Min', 'Configuration|Position X|Range Max',
|
||||
'Configuration|Position Y|Range Min', 'Configuration|Position Y|Range Max',
|
||||
'Configuration|Position Z|Range Min', 'Configuration|Position Z|Range Max']
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and a Position Modifier
|
||||
spawner_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
|
||||
# Add a Vegetation Position Modifier and set offset values to 0
|
||||
spawner_entity.add_component("Vegetation Position Modifier")
|
||||
for path in position_modifier_paths:
|
||||
spawner_entity.get_set_test(3, path, 0)
|
||||
|
||||
# 3) Create a spherical planting surface
|
||||
dynveg.create_mesh_surface_entity_with_slopes("Planting Surface", spawner_center_point, 5.0, 5.0, 5.0)
|
||||
|
||||
# 4) Verify initial instance counts pre-filter
|
||||
num_expected = 121 # Single instance planted
|
||||
spawner_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and spawner_success
|
||||
|
||||
# 5) Create a child entity of the spawner entity with a Constant Gradient component and pin to spawner
|
||||
components_to_add = ["Constant Gradient"]
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(spawner_center_point, components_to_add, parent_id=spawner_entity.id)
|
||||
|
||||
# Pin the Constant Gradient to the X axis of the spawner's Position Modifier component
|
||||
spawner_entity.get_set_test(3, 'Configuration|Position X|Gradient|Gradient Entity Id', gradient_entity.id)
|
||||
|
||||
# 6) Set the Position Modifier offset to 5 on the x-axis
|
||||
spawner_entity.get_set_test(3, position_modifier_paths[0], 5)
|
||||
spawner_entity.get_set_test(3, position_modifier_paths[1], 5)
|
||||
|
||||
# 7) Validate instance count at the top of the sphere mesh and inside the sphere mesh while Auto Snap to Surface
|
||||
# is enabled
|
||||
top_point = math.Vector3(512.0, 512.0, 37.0)
|
||||
inside_point = math.Vector3(512.0, 512.0, 33.0)
|
||||
radius = 0.5
|
||||
num_expected = 1
|
||||
self.log(f"Checking for instances in a {radius * 2}m area at {top_point.ToString()}")
|
||||
top_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, radius, num_expected),
|
||||
5.0)
|
||||
self.test_success = top_success and self.test_success
|
||||
num_expected = 0
|
||||
self.log(f"Checking for instances in a {radius * 2}m area at {inside_point.ToString()}")
|
||||
inside_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(inside_point, radius,
|
||||
num_expected), 5.0)
|
||||
self.test_success = inside_success and self.test_success
|
||||
|
||||
# 8) Toggle off Auto Snap to Surface. Instances should now plant inside the sphere and no longer on top
|
||||
spawner_entity.get_set_test(3, "Configuration|Auto Snap To Surface", False)
|
||||
num_expected = 0
|
||||
self.log(f"Checking for instances in a {radius * 2}m area at {top_point.ToString()}")
|
||||
top_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(top_point, radius, num_expected),
|
||||
5.0)
|
||||
self.test_success = top_success and self.test_success
|
||||
num_expected = 1
|
||||
self.log(f"Checking for instances in a {radius * 2}m area at {inside_point.ToString()}")
|
||||
inside_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(inside_point, radius,
|
||||
num_expected), 5.0)
|
||||
self.test_success = inside_success and self.test_success
|
||||
|
||||
|
||||
test = TestPositionModifierAutoSnapToSurface()
|
||||
test.run()
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestPositionModifierComponentAndOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="PositionModifierComponentAndOverrides_InstanceOffset", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary: Range Min/Max in the Vegetation Position Modifier component and component overrides can be set for all
|
||||
axes, and functions as expected when fed a gradient signal.
|
||||
|
||||
Expected Behavior: Instances are offset by the specified amount.
|
||||
|
||||
Test Steps:
|
||||
1) New test level is created
|
||||
2) Spawner area is setup with all necessary components
|
||||
3) Surface for planting is created
|
||||
4) Initial instance count validation pre-filter is performed
|
||||
5) An entity with a Constant Gradient of 1 is added as a child to the spawner entity, and pinned to the Position
|
||||
Modifier Gradient Entity Id fields
|
||||
6) Sector size is adjusted on a Vegetation System Settings component to allow for offset instances to not fall
|
||||
outside of the queried sector
|
||||
7) Random offsets are set for each axis of the Position Modifier component, and instance counts are validated
|
||||
8) Overrides are enabled on the Position Modifier component
|
||||
9) Random offsets are set for each axis of the descriptor's Position Modifier overrides, and instance counts
|
||||
are validated
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
position_modifier_paths = ['Configuration|Position X|Range Min', 'Configuration|Position X|Range Max',
|
||||
'Configuration|Position Y|Range Min', 'Configuration|Position Y|Range Max',
|
||||
'Configuration|Position Z|Range Min', 'Configuration|Position Z|Range Max']
|
||||
|
||||
override_position_modifier_paths = ['Configuration|Embedded Assets|[0]|Position Modifier|Min X',
|
||||
'Configuration|Embedded Assets|[0]|Position Modifier|Max X',
|
||||
'Configuration|Embedded Assets|[0]|Position Modifier|Min Y',
|
||||
'Configuration|Embedded Assets|[0]|Position Modifier|Max Y',
|
||||
'Configuration|Embedded Assets|[0]|Position Modifier|Min Z',
|
||||
'Configuration|Embedded Assets|[0]|Position Modifier|Max Z']
|
||||
|
||||
def generate_random_offset_list():
|
||||
offset_list = []
|
||||
while len(offset_list) < 10:
|
||||
offset = round(random.uniform(-8.0, 8.0), 2)
|
||||
if not -1.0 <= offset <= 1.0:
|
||||
offset_list.append(offset)
|
||||
print("List of values to test against = " + str(offset_list))
|
||||
return offset_list
|
||||
|
||||
def set_offset_and_verify_instance_counts(offset_to_test, center, is_override=False):
|
||||
print(f"Starting test with an offset of {offset_to_test}")
|
||||
# Set min/max values to the offset value
|
||||
if not is_override:
|
||||
for path in position_modifier_paths:
|
||||
spawner_entity.get_set_test(3, path, offset_to_test)
|
||||
else:
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Position Modifier|Override Enabled",
|
||||
True)
|
||||
for path in override_position_modifier_paths:
|
||||
spawner_entity.get_set_test(2, path, offset_to_test)
|
||||
center_point = math.Vector3(center.x + offset_to_test, center.y + offset_to_test, center.z + offset_to_test)
|
||||
radius = 0.5
|
||||
print(f"Querying for instances in a {radius * 2}m area around {center_point.ToString()}")
|
||||
offset_success = self.wait_for_condition(lambda: dynveg.validate_instance_count(center_point, radius, 1), 5.0)
|
||||
offset_success2 = self.wait_for_condition(lambda: dynveg.validate_instance_count(center, radius, 0), 5.0)
|
||||
self.test_success = offset_success and offset_success2 and self.test_success
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(16.0, -5.0, 32.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
spawner_center_point = math.Vector3(16.0, 16.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 1.0, 1.0, 1.0, asset_path)
|
||||
|
||||
# Add a Vegetation Position Modifier and set offset values to 0
|
||||
spawner_entity.add_component("Vegetation Position Modifier")
|
||||
for path in position_modifier_paths:
|
||||
spawner_entity.get_set_test(3, path, 0)
|
||||
|
||||
# 3) Add flat surface to plant on
|
||||
dynveg.create_surface_entity("Planting Surface", spawner_center_point, 32.0, 32.0, 0.0)
|
||||
|
||||
# 4) Verify initial instance counts pre-filter
|
||||
num_expected = 1 # Single instance planted
|
||||
spawner_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = self.test_success and spawner_success
|
||||
|
||||
# 5) Create a child entity of the spawner entity with a Constant Gradient component
|
||||
components_to_add = ["Constant Gradient"]
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(spawner_center_point, components_to_add, parent_id=spawner_entity.id)
|
||||
|
||||
# Pin the Constant Gradient to each axis of the Position Modifier
|
||||
position_modifier_gradient_paths = ['Configuration|Position X|Gradient|Gradient Entity Id',
|
||||
'Configuration|Position Y|Gradient|Gradient Entity Id',
|
||||
'Configuration|Position Z|Gradient|Gradient Entity Id']
|
||||
for path in position_modifier_gradient_paths:
|
||||
spawner_entity.get_set_test(3, path, gradient_entity.id)
|
||||
|
||||
# 6) Add a Vegetation System Settings Level component and change sector size to 32 sq meters so instances can
|
||||
# offset to a greater range and still be validated
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Size In Meters", 32)
|
||||
sector_size = hydra.get_component_property_value(veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Size In Meters")
|
||||
self.test_success = (sector_size == 32) and self.test_success
|
||||
|
||||
# 7) Set offsets on all axes and verify instance counts
|
||||
offsets_to_test = generate_random_offset_list()
|
||||
for offset in offsets_to_test:
|
||||
if self.test_success:
|
||||
set_offset_and_verify_instance_counts(offset, spawner_center_point)
|
||||
|
||||
# 8) Toggle on allow overrides on the Position Modifier Component
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
|
||||
# 9) Set offsets on all axes on descriptor overrides and verify instance counts
|
||||
for offset in offsets_to_test:
|
||||
if self.test_success:
|
||||
set_offset_and_verify_instance_counts(offset, spawner_center_point, is_override=True)
|
||||
|
||||
|
||||
test = TestPositionModifierComponentAndOverrides()
|
||||
test.run()
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4814460: A level with simple vegetation is created. A child entity with required components is then created,
|
||||
and pinned to the gradient entity id in Z direction for vegetation entity. The changes in vegetation area are observed.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.areasystem as areasystem
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestRotationModifierOverrides_InstancesRotateWithinRange(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="RotationModifierOverrides_InstancesRotateWithinRange", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A level with simple vegetation is created. A child entity with required components is then created,
|
||||
and pinned to the gradient entity id in Z direction for vegetation entity. The changes in vegetation
|
||||
area are observed.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation instances all rotate randomly between 0-360 degrees on the Z-axis.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create vegetation entity and add components
|
||||
3) Set properties for vegetation entity
|
||||
4) Create new child entity
|
||||
5) Pin the child entity to vegetation entity as gradient entity id
|
||||
6) Verify rotation without per-item overrides
|
||||
7) Verify rotation with per-item overrides
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def get_expected_rotation(min, max, gradient_value):
|
||||
return min + ((max - min) * gradient_value)
|
||||
|
||||
def validate_rotation(center, radius, num_expected, rot_degrees_vector):
|
||||
# Verify that every instance in the given area has the expected rotation.
|
||||
box = math.Aabb_CreateCenterRadius(center, radius)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
num_found = len(instances)
|
||||
num_validated = 0
|
||||
result = (num_found == num_expected)
|
||||
print(f'instance count validation: {result} (found={num_found}, expected={num_expected})')
|
||||
expected_rotation = math.Quaternion()
|
||||
expected_rotation.SetFromEulerDegrees(rot_degrees_vector)
|
||||
for instance in instances:
|
||||
is_close = instance.rotation.IsClose(expected_rotation)
|
||||
result = result and is_close
|
||||
if is_close:
|
||||
num_validated = num_validated + 1
|
||||
#else:
|
||||
# print(f'instance rotation validation: {is_close} (rotation={instance.rotation} expected={expected_rotation})')
|
||||
print(f'instance rotation validation: {result} (num_validated={num_validated})')
|
||||
return result
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.run_console("e_WaterOcean=0")
|
||||
|
||||
# 2) Create vegetation entity and add components
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Entity", entity_position, 16.0, 16.0, 16.0, asset_path)
|
||||
spawner_entity.add_component("Vegetation Rotation Modifier")
|
||||
# Our default vegetation settings places 20 instances per 16 meters, so we expect 20 * 20 total instances.
|
||||
num_expected = 20 * 20
|
||||
# This is technically twice as big as we need, but we want to make sure our query radius is large enough to discover every
|
||||
# instance we've created.
|
||||
area_radius = 16.0
|
||||
|
||||
# Create surface to spawn on
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 16.0, 16.0, 1.0)
|
||||
|
||||
# 3) Set properties for the rotation override on the descriptor, but don't set "allow overrides" on the rotation modifier yet.
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Rotation Modifier|Override Enabled", True)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Rotation Modifier|Min Z", -70.0)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Rotation Modifier|Max Z", 30.0)
|
||||
|
||||
# 4) Create new child entity with a constant gradient
|
||||
constant_gradient_value = 0.25
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(
|
||||
entity_position,
|
||||
["Constant Gradient"],
|
||||
parent_id=spawner_entity.id
|
||||
)
|
||||
if gradient_entity.id.IsValid():
|
||||
self.log(f"'{gradient_entity.name}' created")
|
||||
gradient_entity.get_set_test(0, "Configuration|Value", constant_gradient_value)
|
||||
|
||||
# 5) Pin the child entity to vegetation entity as gradient entity id
|
||||
spawner_entity.get_set_test(3, "Configuration|Rotation Z|Gradient|Gradient Entity Id", gradient_entity.id)
|
||||
|
||||
# 6) Verify that without per-item overrides, the rotation matches the one calculated from the default rotation range.
|
||||
general.idle_wait(1.0)
|
||||
rotation_degrees = get_expected_rotation(-180.0, 180.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(entity_position, area_radius, num_expected, math.Vector3(0.0, 0.0, rotation_degrees)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
# 7) Verify that with per-item overrides enabled, the rotation matches the one calculated from the override range.
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
rotation_degrees = get_expected_rotation(-70.0, 30.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(entity_position, area_radius, num_expected, math.Vector3(0.0, 0.0, rotation_degrees)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
|
||||
test = TestRotationModifierOverrides_InstancesRotateWithinRange()
|
||||
test.run()
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.math as math
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.areasystem as areasystem
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestRotationModifier_InstancesRotateWithinRange(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="RotationModifier_InstancesRotateWithinRange", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary: Range Min/Max in the Vegetation Rotation Modifier component can be set for all axes,
|
||||
and functions as expected when fed a gradient signal
|
||||
|
||||
Vegetation Entity: Set in the middle of the level it holds a child entity and the following components:
|
||||
Vegetation Asset List
|
||||
Box Shape (size: <10, 10, 10>)
|
||||
Vegetation Layer Spawner
|
||||
Vegetation Rotation Modifier
|
||||
Rotation X (gradient: child, Range Min: Variable, Range Max: Variable)
|
||||
Rotation Y (gradient: child, Range Min: Variable, Range Max: Variable)
|
||||
Rotation Z (gradient: child, Range Min: Variable, Range Max: Variable)
|
||||
|
||||
|
||||
Child Entity: Child to Vegetation Entity has the following components:
|
||||
Box Shape (size: <10, 10, 10>)
|
||||
Gradient Transform Modifier
|
||||
Constant Gradient
|
||||
|
||||
Expected Behavior: The vegetation area adjusts rotation based on the Constant Gradient component
|
||||
and the min and max values for each component. Min max of each axis is checked
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Set up vegetation entities
|
||||
3) X-axis Check
|
||||
4) Y-axis Check
|
||||
5) Z-axis Check
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
# Test Constants
|
||||
LEVEL_CENTER = math.Vector3(512.0, 512.0, 32.0)
|
||||
constant_gradient_value = 0.15
|
||||
|
||||
# Helper Functions
|
||||
def change_range_max(axis, value):
|
||||
spawner_entity.get_set_test(3, f"Configuration|Rotation {axis}|Range Max", value)
|
||||
|
||||
def change_range_min(axis, value):
|
||||
spawner_entity.get_set_test(3, f"Configuration|Rotation {axis}|Range Min", value)
|
||||
|
||||
def get_expected_rotation(min, max, gradient_value):
|
||||
return min + ((max - min) * gradient_value)
|
||||
|
||||
def validate_rotation(center, radius, num_expected, rot_degrees_vector):
|
||||
# Verify that every instance in the given area has the expected rotation.
|
||||
box = math.Aabb_CreateCenterRadius(center, radius)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
num_found = len(instances)
|
||||
result = (num_found == num_expected)
|
||||
print(f'instance count validation: {result} (found={num_found}, expected={num_expected})')
|
||||
expected_rotation = math.Quaternion()
|
||||
expected_rotation.SetFromEulerDegrees(rot_degrees_vector)
|
||||
for instance in instances:
|
||||
result = result and instance.rotation.IsClose(expected_rotation)
|
||||
print(f'instance rotation validation: {result} (rotation={instance.rotation} expected={expected_rotation})')
|
||||
return result
|
||||
|
||||
|
||||
# Main Script
|
||||
# 1) Create Level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.run_console("e_WaterOcean=0")
|
||||
|
||||
# 2) Set up vegetation entities
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Entity", LEVEL_CENTER, 2.0, 2.0, 2.0, asset_path)
|
||||
|
||||
additional_components = [
|
||||
"Vegetation Rotation Modifier"
|
||||
]
|
||||
for component in additional_components:
|
||||
spawner_entity.add_component(component)
|
||||
|
||||
# Create surface to spawn vegetation on
|
||||
dynveg.create_surface_entity("Surface Entity", LEVEL_CENTER, 10.0, 10.0, 1.0)
|
||||
|
||||
# Create Gradient Entity
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(
|
||||
LEVEL_CENTER,
|
||||
["Constant Gradient"],
|
||||
parent_id=spawner_entity.id
|
||||
)
|
||||
if gradient_entity.id.IsValid():
|
||||
self.log(f"'{gradient_entity.name}' created")
|
||||
gradient_entity.get_set_test(0, "Configuration|Value", constant_gradient_value)
|
||||
|
||||
# Vegetation Rotation Modifier
|
||||
for axis in ["X", "Y", "Z"]:
|
||||
spawner_entity.get_set_test(
|
||||
3, f"Configuration|Rotation {axis}|Gradient|Gradient Entity Id", gradient_entity.id
|
||||
)
|
||||
|
||||
# Set up constants used across all the rotation checks
|
||||
|
||||
# Choose an area large enough to contain all of the instances we spawned.
|
||||
area_center = LEVEL_CENTER
|
||||
area_radius = 20.0
|
||||
# We're spawning a 2x2 area, which will have 3 rows of 3 instances due to default vegetation system spacing, so
|
||||
# we should have a total of 9 instances.
|
||||
num_expected = 9
|
||||
|
||||
# 3) X-axis check
|
||||
general.idle_wait(3.0) # Allow mesh to load
|
||||
|
||||
# baseline, verify that we initially have no rotation
|
||||
change_range_min("Z", 0.0)
|
||||
change_range_max("Z", 0.0)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(0.0, 0.0, 0.0)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
# Adjust x-axis range min / max to (-180, 0).
|
||||
# Because we have a constant gradient of 0.25, our actual rotation should be (min + (max - min) * gradient),
|
||||
# or (-180 + (0 - -180) * 0.25)
|
||||
change_range_min("X", -180.0)
|
||||
rotation_degrees = get_expected_rotation(-180.0, 0.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(rotation_degrees, 0.0, 0.0)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
# Set the min / max to (0, 90), with an expected result of (0 + (90 - 0) * 0.25)
|
||||
change_range_min("X", 0.0)
|
||||
change_range_max("X", 90.0)
|
||||
rotation_degrees = get_expected_rotation(0.0, 90.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(rotation_degrees, 0.0, 0.0)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
change_range_max("X", 0.0)
|
||||
|
||||
# 4) Y-axis check
|
||||
change_range_min("Y", -180.0)
|
||||
rotation_degrees = get_expected_rotation(-180.0, 0.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(0.0, rotation_degrees, 0.0)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
change_range_min("Y", 0.0)
|
||||
change_range_max("Y", 90.0)
|
||||
rotation_degrees = get_expected_rotation(0.0, 90.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(0.0, rotation_degrees, 0.0)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
change_range_max("Y", 0.0)
|
||||
|
||||
# 5) Z-axis check
|
||||
change_range_min("Z", -180.0)
|
||||
rotation_degrees = get_expected_rotation(-180.0, 0.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(0.0, 0.0, rotation_degrees)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
change_range_min("Z", 0.0)
|
||||
change_range_max("Z", 90.0)
|
||||
rotation_degrees = get_expected_rotation(0.0, 90.0, constant_gradient_value)
|
||||
rotation_success = self.wait_for_condition(
|
||||
lambda: validate_rotation(area_center, area_radius, num_expected, math.Vector3(0.0, 0.0, rotation_degrees)),
|
||||
5.0)
|
||||
self.test_success = self.test_success and rotation_success
|
||||
|
||||
|
||||
test = TestRotationModifier_InstancesRotateWithinRange()
|
||||
test.run()
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
# Constants
|
||||
CLOSE_ENOUGH_THRESHOLD = 0.01
|
||||
|
||||
|
||||
class TestScaleModifierOverrides_InstancesProperlyScale(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ScaleModifierOverrides_InstancesProperlyScale", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A level is created, then as simple vegetation area is created. Vegetation Scale Modifier component is
|
||||
added to the vegetation area. A new child entity is created with Random Noise Gradient Generator,
|
||||
Gradient Transform Modifier, and Box Shape. Child entity is set as gradient entity id in Vegetation
|
||||
Scale Modifier, and scale of instances is validated to fall within expected range.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation instances have random scale between Range Min and Range Max applied.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a new entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
3) Set a valid mesh asset on the Vegetation Asset List
|
||||
4) Add Vegetation Scale Modifier component to the vegetation and set the values
|
||||
5) Toggle on Scale Modifier Override and verify Scale Min and Scale Max are set 0.1 and 1.0
|
||||
6) Create a new child entity and add components
|
||||
7) Add child entity as gradient entity id in Vegetation Scale Modifier
|
||||
8) Validate scale of instances with a few different min/max override values
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def set_and_validate_scale(entity, min_scale, max_scale):
|
||||
# Set Range Min/Max
|
||||
entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Scale Modifier|Min", min_scale)
|
||||
entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Scale Modifier|Max", max_scale)
|
||||
|
||||
# Clear all areas to force a refresh
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
|
||||
# Wait for instances to spawn
|
||||
num_expected = 20 * 20
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
# Validate scale values of instances
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
if len(instances) == num_expected:
|
||||
for instance in instances:
|
||||
if min_scale <= instance.scale <= max_scale:
|
||||
self.log("All instances scaled within appropriate range")
|
||||
return True
|
||||
self.log(f"Instance at {instance.position} scale is {instance.scale}. Expected between "
|
||||
f"{min_scale}/{max_scale}")
|
||||
return False
|
||||
self.log(f"Failed to find all instances! Found {len(instances)}, expected {num_expected}.")
|
||||
return False
|
||||
|
||||
# 1) Create level and set an appropriate view of spawner area
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(500.49, 498.69, 46.66)
|
||||
general.set_current_view_rotation(-42.05, 0.00, -36.33)
|
||||
|
||||
# 2) Create a new entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Entity", entity_position, 16.0, 16.0, 10.0, asset_path)
|
||||
|
||||
# Create a surface to plant on and add a Vegetation Debugger Level component to allow refreshes
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 20.0, 20.0, 1.0)
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# 4) Add Vegetation Scale Modifier component to the vegetation and set the values
|
||||
spawner_entity.add_component("Vegetation Scale Modifier")
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
|
||||
# 5) Toggle on Scale Modifier Override and verify Scale Min and Scale Max are set 0.1 and 1.0
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Scale Modifier|Override Enabled", True)
|
||||
scale_min = float(
|
||||
format(
|
||||
(
|
||||
hydra.get_component_property_value(
|
||||
spawner_entity.components[2], "Configuration|Embedded Assets|[0]|Scale Modifier|Min"
|
||||
)
|
||||
),
|
||||
".1f",
|
||||
)
|
||||
)
|
||||
scale_max = float(
|
||||
format(
|
||||
(
|
||||
hydra.get_component_property_value(
|
||||
spawner_entity.components[2], "Configuration|Embedded Assets|[0]|Scale Modifier|Max"
|
||||
)
|
||||
),
|
||||
".1f",
|
||||
)
|
||||
)
|
||||
if ((scale_max - 1.0) < CLOSE_ENOUGH_THRESHOLD) and ((scale_min - 0.1) < CLOSE_ENOUGH_THRESHOLD):
|
||||
self.log("Scale Min and Scale Max are set to 0.1 and 1.0 in Vegetation Asset List")
|
||||
else:
|
||||
self.log("Scale Min and Scale Max are not set to 0.1 and 1.0 in Vegetation Asset List")
|
||||
|
||||
# 6) Create a new child entity and add components
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(
|
||||
entity_position,
|
||||
["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"],
|
||||
parent_id=spawner_entity.id
|
||||
)
|
||||
if gradient_entity.id.IsValid():
|
||||
self.log(f"'{gradient_entity.name}' created")
|
||||
|
||||
# 7) Add child entity as gradient entity id in Vegetation Scale Modifier
|
||||
spawner_entity.get_set_test(3, "Configuration|Gradient|Gradient Entity Id", gradient_entity.id)
|
||||
|
||||
# 8) Validate instances are scaled properly via a few different Range Min/Max settings on the override
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 0.1, 1.0) and self.test_success
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 2.0, 2.5) and self.test_success
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 1.0, 5.0) and self.test_success
|
||||
|
||||
|
||||
test = TestScaleModifierOverrides_InstancesProperlyScale()
|
||||
test.run()
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestScaleModifier_InstancesProperlyScale(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ScaleModifier_InstancesProperlyScale", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A New level is created. A New entity is created with components Vegetation Layer Spawner, Vegetation Asset List,
|
||||
Box Shape and Vegetation Scale Modifier. A New child entity is created with components Random Noise Gradient,
|
||||
Gradient Transform Modifier, and Box Shape. Pin the Random Noise entity to the Gradient Entity Id field for
|
||||
the Gradient group. Range Min and Range Max are set to few values and values are validated. Range Min and Range
|
||||
Max are set to few other values and values are validated.
|
||||
|
||||
Expected Behavior:
|
||||
Vegetation instances are scaled within Range Min/Range Max.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a new entity with components Vegetation Layer Spawner, Vegetation Asset List, Box Shape and
|
||||
Vegetation Scale Modifier
|
||||
3) Create child entity with components Random Noise Gradient, Gradient Transform Modifier and Box Shape
|
||||
4) Pin the Random Noise entity to the Gradient Entity Id field for the Gradient group.
|
||||
5) Range Min/Max is set to few different values on the Vegetation Scale Modifier component and
|
||||
scale of instances is validated
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def set_and_validate_scale(entity, min_scale, max_scale):
|
||||
# Set Range Min/Max
|
||||
entity.get_set_test(3, "Configuration|Range Min", min_scale)
|
||||
entity.get_set_test(3, "Configuration|Range Max", max_scale)
|
||||
|
||||
# Clear all areas to force a refresh
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
|
||||
# Wait for instances to spawn
|
||||
num_expected = 20 * 20
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
# Validate scale values of instances
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
if len(instances) == num_expected:
|
||||
for instance in instances:
|
||||
if min_scale <= instance.scale <= max_scale:
|
||||
self.log("All instances scaled within appropriate range")
|
||||
return True
|
||||
self.log(f"Instance at {instance.position} scale is {instance.scale}. Expected between "
|
||||
f"{min_scale}/{max_scale}")
|
||||
return False
|
||||
self.log(f"Failed to find all instances! Found {len(instances)}, expected {num_expected}.")
|
||||
return False
|
||||
|
||||
# 1) Create level and set an appropriate view of spawner area
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(500.49, 498.69, 46.66)
|
||||
general.set_current_view_rotation(-42.05, 0.00, -36.33)
|
||||
|
||||
# 2) Create a new entity with components Vegetation Layer Spawner, Vegetation Asset List, Box Shape and
|
||||
# Vegetation Scale Modifier
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Entity", entity_position, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
spawner_entity.add_component("Vegetation Scale Modifier")
|
||||
|
||||
# Create a surface to plant on and add a Vegetation Debugger Level component to allow refreshes
|
||||
dynveg.create_surface_entity("Surface Entity", entity_position, 20.0, 20.0, 1.0)
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# 3) Create child entity with components Random Noise Gradient, Gradient Transform Modifier and Box Shape
|
||||
gradient_entity = hydra.Entity("Gradient Entity")
|
||||
gradient_entity.create_entity(
|
||||
entity_position,
|
||||
["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"],
|
||||
parent_id=spawner_entity.id
|
||||
)
|
||||
if gradient_entity.id.IsValid():
|
||||
self.log(f"'{gradient_entity.name}' created")
|
||||
|
||||
# 4) Pin the Random Noise entity to the Gradient Entity Id field for the Gradient group.
|
||||
spawner_entity.get_set_test(3, "Configuration|Gradient|Gradient Entity Id", gradient_entity.id)
|
||||
|
||||
# 5) Set Range Min/Max on the Vegetation Scale Modifier component to diff values, and verify instance scale is
|
||||
# within bounds
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 2.0, 4.0) and self.test_success
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 12.0, 40.0) and self.test_success
|
||||
self.test_success = set_and_validate_scale(spawner_entity, 0.5, 2.5) and self.test_success
|
||||
|
||||
|
||||
test = TestScaleModifier_InstancesProperlyScale()
|
||||
test.run()
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4874094: Shape reference can be replaced/removed
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestShapeIntersectionFilter(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ShapeIntersectionFilter_InstancePlanting", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A spawner area is created with a Vegetation Shape Intersection Filter. 2 different shape entities are created,
|
||||
pinned to the Shape Intersection Filter, and instance counts are verified.
|
||||
|
||||
Expected Behavior:
|
||||
The Shape Entity Id reference can be successfully set/updated. Instances spawn only in the specified shape area.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level, and set view for visual debugging
|
||||
2) Create an instance spawner and planting surface
|
||||
3) Create child entity with Box Shape
|
||||
4) Create child entity with Cylinder Shape
|
||||
5) Assign the Intersection Filter to the Box Shape and validate instance counts
|
||||
6) Assign the Intersection Filter to the Cylinder Shape and validate instance counts
|
||||
7) Remove the shape reference on the Intersection Filter and validate instance counts
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and Vegetation Shape Intersection Filter
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 16.0, 16.0, 1.0,
|
||||
asset_path)
|
||||
spawner_entity.add_component("Vegetation Shape Intersection Filter")
|
||||
|
||||
# Create a planting surface
|
||||
dynveg.create_surface_entity("Planting Surface", center_point, 32.0, 32.0, 1.0)
|
||||
|
||||
# 3) Create a child entity with Box Shape
|
||||
components_to_add = ["Box Shape"]
|
||||
box_id = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", spawner_entity.id)
|
||||
box = hydra.Entity("Box", box_id)
|
||||
box.components = []
|
||||
for component in components_to_add:
|
||||
box.components.append(hydra.add_component(component, box_id))
|
||||
new_box_dimension = math.Vector3(5.0, 5.0, 5.0)
|
||||
hydra.get_set_test(box, 0, "Box Shape|Box Configuration|Dimensions", new_box_dimension)
|
||||
|
||||
# 4) Create a child entity with Cylinder Shape
|
||||
components_to_add = ["Cylinder Shape"]
|
||||
cylinder_id = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", spawner_entity.id)
|
||||
cylinder = hydra.Entity("Cylinder", cylinder_id)
|
||||
cylinder.components = []
|
||||
for component in components_to_add:
|
||||
cylinder.components.append(hydra.add_component(component, cylinder_id))
|
||||
hydra.get_set_test(cylinder, 0, "Cylinder Shape|Cylinder Configuration|Radius", 5.0)
|
||||
|
||||
# 5) Set the Intersection Filter's Shape Entity Id to the Box Shape entity
|
||||
spawner_entity.get_set_test(3, "Configuration|Shape Entity Id", box_id)
|
||||
|
||||
# Validate instance counts. Instances should only plant in the Box Shape area
|
||||
num_expected = 49
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
# 6) Set the Intersection Filter's Shape Entity Id to the Cylinder Shape entity
|
||||
spawner_entity.get_set_test(3, "Configuration|Shape Entity Id", cylinder_id)
|
||||
|
||||
# Validate instance counts. Instances should only plant in the Cylinder Shape area
|
||||
num_expected = 121
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
# 7) Clear the Intersection Filter's Shape Entity Id reference
|
||||
spawner_entity.get_set_test(3, "Configuration|Shape Entity Id", None)
|
||||
|
||||
# Validate instance counts. Instances should now fill the entire spawner_entity's area
|
||||
num_expected = 20 * 20
|
||||
success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 5.0)
|
||||
self.test_success = success and self.test_success
|
||||
|
||||
|
||||
test = TestShapeIntersectionFilter()
|
||||
test.run()
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
from math import radians
|
||||
import sys
|
||||
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSlopeAlignmentModifierOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SlopeAlignmentModifierOverrides", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C4814459 Verifies instances properly align to surfaces based on configuration of descriptor overrides of the
|
||||
Vegetation Slope Alignment Modifier component.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def verify_proper_alignment(instance, rot_degrees_vec):
|
||||
expected_rotation = math.Quaternion()
|
||||
expected_rotation.SetFromEulerDegrees(rot_degrees_vec)
|
||||
if instance.alignment.IsClose(expected_rotation):
|
||||
return True
|
||||
self.log(f"Expected rotation of {expected_rotation}, Found {instance.alignment}")
|
||||
return False
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create a spawner entity setup with all needed components
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 16.0, 16.0, 32.0, asset_path)
|
||||
|
||||
# Create a sloped mesh surface for the instances to plant on
|
||||
mesh_asset_path = os.path.join("Objects", "default", "primitive_plane.cgf")
|
||||
mesh_asset = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", mesh_asset_path, math.Uuid(),
|
||||
False)
|
||||
rotation = math.Vector3(0.0, radians(45.0), 0.0)
|
||||
scale = math.Vector3(30.0, 30.0, 30.0)
|
||||
surface_entity = hydra.Entity("Surface Entity")
|
||||
surface_entity.create_entity(
|
||||
center_point,
|
||||
["Mesh", "Mesh Surface Tag Emitter"]
|
||||
)
|
||||
if surface_entity.id.IsValid():
|
||||
print(f"'{surface_entity.name}' created")
|
||||
hydra.get_set_test(surface_entity, 0, "MeshComponentRenderNode|Mesh asset", mesh_asset)
|
||||
components.TransformBus(bus.Event, "SetLocalRotation", surface_entity.id, rotation)
|
||||
components.TransformBus(bus.Event, "SetLocalScale", surface_entity.id, scale)
|
||||
|
||||
# Add a Vegetation Debugger component to allow refreshing instances
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# Add Vegetation Slope Alignment Modifier to the spawner entity and toggle on Allow Per-Item Overrides
|
||||
spawner_entity.add_component("Vegetation Slope Alignment Modifier")
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
|
||||
# Toggle on Surface Slope Alignment Override Enabled on the Vegetation Asset List component
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Surface Slope Alignment|Override Enabled",
|
||||
True)
|
||||
|
||||
# Set Surface Slope Alignment Override Min and Max to 0 and validate instance alignment
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Surface Slope Alignment|Max", 0.0)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Surface Slope Alignment|Max", 0.0)
|
||||
|
||||
# Verify instances are have planted and are aligned to slope as expected
|
||||
num_expected = 20 * 20
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
|
||||
if self.test_success and num_expected == len(instances):
|
||||
for instance in instances:
|
||||
self.test_success = verify_proper_alignment(instance,
|
||||
math.Vector3(0.0, 0.0, 0.0)) and self.test_success
|
||||
|
||||
# Set Surface Slope Alignment Min and Max to 1 and validate instance alignment
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Surface Slope Alignment|Min", 1.0)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Surface Slope Alignment|Max", 1.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
|
||||
if self.test_success and num_expected == len(instances):
|
||||
for instance in instances:
|
||||
self.test_success = verify_proper_alignment(instance, math.Vector3(0.0, 45.0, 0.0)) and \
|
||||
self.test_success
|
||||
|
||||
|
||||
test = TestSlopeAlignmentModifierOverrides()
|
||||
test.run()
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
from math import radians
|
||||
import sys
|
||||
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSlopeAlignmentModifier(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SlopeAlignmentModifier", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
C4896941 Verifies instances properly align to surfaces based on configuration of the Vegetation Slope Alignment
|
||||
Modifier.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def verify_proper_alignment(instance, rot_degrees_vec):
|
||||
expected_rotation = math.Quaternion()
|
||||
expected_rotation.SetFromEulerDegrees(rot_degrees_vec)
|
||||
if instance.alignment.IsClose(expected_rotation):
|
||||
return True
|
||||
self.log(f"Expected rotation of {expected_rotation}, Found {instance.alignment}")
|
||||
return False
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create a spawner entity setup with all needed components
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 16.0, 16.0, 32.0, asset_path)
|
||||
|
||||
# Create a sloped mesh surface for the instances to plant on
|
||||
mesh_asset_path = os.path.join("Objects", "default", "primitive_plane.cgf")
|
||||
mesh_asset = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", mesh_asset_path, math.Uuid(),
|
||||
False)
|
||||
rotation = math.Vector3(0.0, radians(45.0), 0.0)
|
||||
scale = math.Vector3(30.0, 30.0, 30.0)
|
||||
surface_entity = hydra.Entity("Surface Entity")
|
||||
surface_entity.create_entity(
|
||||
center_point,
|
||||
["Mesh", "Mesh Surface Tag Emitter"]
|
||||
)
|
||||
if surface_entity.id.IsValid():
|
||||
print(f"'{surface_entity.name}' created")
|
||||
hydra.get_set_test(surface_entity, 0, "MeshComponentRenderNode|Mesh asset", mesh_asset)
|
||||
components.TransformBus(bus.Event, "SetLocalRotation", surface_entity.id, rotation)
|
||||
components.TransformBus(bus.Event, "SetLocalScale", surface_entity.id, scale)
|
||||
|
||||
# Add a Vegetation Debugger component to allow refreshing instances
|
||||
hydra.add_level_component("Vegetation Debugger")
|
||||
|
||||
# Add Vegetation Slope Alignment Modifier to the spawner entity
|
||||
spawner_entity.add_component("Vegetation Slope Alignment Modifier")
|
||||
|
||||
# Set Alignment Coefficient Min/Max to 1 on the Slope Alignment Modifier
|
||||
spawner_entity.get_set_test(3, "Configuration|Alignment Coefficient Min", 1.0)
|
||||
spawner_entity.get_set_test(3, "Configuration|Alignment Coefficient Max", 1.0)
|
||||
|
||||
# Create new child entity with a Constant Gradient
|
||||
child_vegetation_id = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", spawner_entity.id)
|
||||
child_vegetation = hydra.Entity("Child Vegetation Entity", child_vegetation_id)
|
||||
components_to_add = ["Constant Gradient"]
|
||||
child_vegetation.components = []
|
||||
for component in components_to_add:
|
||||
child_vegetation.components.append(hydra.add_component(component, child_vegetation_id))
|
||||
|
||||
# Reference the Constant Gradient on the Slope Alignment Modifier component
|
||||
spawner_entity.get_set_test(3, "Configuration|Gradient|Gradient Entity Id", child_vegetation_id)
|
||||
|
||||
# Verify instances are have planted and are aligned to slope as expected
|
||||
num_expected = 20 * 20
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
|
||||
if self.test_success and num_expected == len(instances):
|
||||
for instance in instances:
|
||||
self.test_success = verify_proper_alignment(instance, math.Vector3(0.0, 45.0, 0.0)) and \
|
||||
self.test_success
|
||||
|
||||
# Change Min/Max to 0.0 and verify proper alignment
|
||||
spawner_entity.get_set_test(3, "Configuration|Alignment Coefficient Min", 0.0)
|
||||
spawner_entity.get_set_test(3, "Configuration|Alignment Coefficient Max", 0.0)
|
||||
general.run_console('veg_debugClearAllAreas')
|
||||
self.test_success = self.test_success and self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
|
||||
box = azlmbr.shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
instances = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstancesInAabb', box)
|
||||
|
||||
if self.test_success and num_expected == len(instances):
|
||||
for instance in instances:
|
||||
self.test_success = verify_proper_alignment(instance, math.Vector3(0.0, 0.0, 0.0)) and self.test_success
|
||||
|
||||
|
||||
test = TestSlopeAlignmentModifier()
|
||||
test.run()
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4874096 - Slope Min/Max properties can be set, and properly affect planted vegetation
|
||||
C4814464 - Slope Filter overrides function as expected
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSlopeFilterComponentAndOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SlopeFilter_InstancesPlantOnValidSlope", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new level is created. A spawner entity is added, along with a flat planting surface at 32 on Z, and sphere
|
||||
mesh at 38 on Z to provide a sloped surface. A Slope Filter is added to the spawner entity, and Slope Min/Max
|
||||
values are set. Instance counts are validated. The same test is then performed for Slope Filter overrides.
|
||||
|
||||
Expected Behavior:
|
||||
Instances plant only on surfaces that fall between the Slope Filter Min/Max settings
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create an instance spawner entity
|
||||
3) Create surfaces to plant on, one at 32 on Z and another sloped surface at 38 on Z.
|
||||
4) Initial instance counts pre-filter are verified.
|
||||
5) Slope Min/Max values are set on the Slope Filter component
|
||||
6) Instance counts are validated
|
||||
7) Setup for overrides tests
|
||||
8) Slope Min/Max values are set on the descriptor overrides
|
||||
9) Instance counts are validated
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 475.0, 38.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", center_point, 32.0, 32.0, 32.0, asset_path)
|
||||
|
||||
# Add a Vegetation Slope Filter
|
||||
spawner_entity.add_component("Vegetation Slope Filter")
|
||||
|
||||
# 3) Add surfaces to plant on. This will include a flat surface and a sphere mesh to provide a sloped surface
|
||||
dynveg.create_surface_entity("Planting Surface", center_point, 32.0, 32.0, 1.0)
|
||||
sloped_surface_center = math.Vector3(512.0, 512.0, 38.0)
|
||||
dynveg.create_mesh_surface_entity_with_slopes("Sloped Planting Surface", sloped_surface_center, 5.0, 5.0, 5.0)
|
||||
|
||||
# Set instances to spawn on a center snap point to avoid unexpected instances around the edges of the box shape
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", veg_system_settings_component,
|
||||
'Configuration|Area System Settings|Sector Point Snap Mode', 1)
|
||||
|
||||
# 4) Validate instance counts pre-filter
|
||||
num_expected_flat_surface = 40 * 40 # 20x20 instances per 16m
|
||||
num_expected_slopes_pre_filter = 120 # Unfiltered planting on the top of the sphere mesh
|
||||
num_expected = num_expected_flat_surface + num_expected_slopes_pre_filter
|
||||
initial_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(
|
||||
spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = initial_success and self.test_success
|
||||
|
||||
# 5) Change Slope Min/Max on the Vegetation Slope Filter component
|
||||
spawner_entity.get_set_test(3, "Configuration|Slope Min", 20)
|
||||
spawner_entity.get_set_test(3, "Configuration|Slope Max", 45)
|
||||
|
||||
# 6) Validate instance counts post-filter: instances should only plant on slopes between 20-45 degrees
|
||||
num_expected_slopes_post_filter = 44
|
||||
slope_min_max_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(
|
||||
spawner_entity.id, num_expected_slopes_post_filter), 5.0)
|
||||
self.test_success = slope_min_max_success and self.test_success
|
||||
|
||||
# 7) Setup for overrides on the Slope Filter component and the spawner entity's descriptor
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Slope Filter|Override Enabled", True)
|
||||
|
||||
# 8) Set Slope Filter Min/Max overrides on the spawner entity's descriptor
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Slope Filter|Min", 5)
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]|Slope Filter|Max", 20)
|
||||
|
||||
# 9) Validate instance counts post-filter: instances should only plant on slopes between 5-20 degrees
|
||||
num_expected_slopes_post_filter_overrides = 16
|
||||
overrides_min_max_success = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(
|
||||
spawner_entity.id, num_expected_slopes_post_filter_overrides), 5.0)
|
||||
self.test_success = overrides_min_max_success and self.test_success
|
||||
|
||||
|
||||
test = TestSlopeFilterComponentAndOverrides()
|
||||
test.run()
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.math as math
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.components as components
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
class TestSlopeFilterFilterStageToggle(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SlopeFilter_FilterStageToggle", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Filter Stage toggle affects final vegetation position
|
||||
|
||||
Expected Result:
|
||||
Vegetation instances plant differently depending on the Filter Stage setting. With PreProcess, some vegetation instances can
|
||||
appear on slopes outside the filtered values. With PostProcess, vegetation instances only appear on the correct slope values.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
vegetation = dynveg.create_vegetation_area("vegetation", position, 16.0, 16.0, 16.0, asset_path)
|
||||
|
||||
# Create Surface for instances to plant on
|
||||
dynveg.create_surface_entity("Surface_Entity_Parent", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# Add a Vegetation Shape Intersection Filter to the vegetation area entity
|
||||
vegetation.add_component("Vegetation Shape Intersection Filter")
|
||||
|
||||
# Create a new entity as a child of the vegetation area entity with Box Shape
|
||||
box = hydra.Entity("box")
|
||||
box.create_entity(position, ["Box Shape"])
|
||||
box.get_set_test(0, "Box Shape|Box Configuration|Dimensions", math.Vector3(8.0, 8.0, 1.0))
|
||||
|
||||
# Create a new entity as a child of the vegetation area entity with Cylinder Shape.
|
||||
cylinder = hydra.Entity("cylinder")
|
||||
cylinder.create_entity(position, ["Cylinder Shape"])
|
||||
cylinder.get_set_test(0, "Cylinder Shape|Cylinder Configuration|Radius", 5.0)
|
||||
cylinder.get_set_test(0, "Cylinder Shape|Cylinder Configuration|Height", 5.0)
|
||||
box.set_test_parent_entity(vegetation)
|
||||
cylinder.set_test_parent_entity(vegetation)
|
||||
|
||||
# # On the Vegetation Shape Intersection Filter component, click the crosshair button, and add child entities one by one
|
||||
vegetation.get_set_test(3, "Configuration|Shape Entity Id", box.id)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 8.0, 100), 2.0)
|
||||
self.log(f"Vegetation plant only in the areas where the Box overlaps with the vegetation area's boundaries: {result}")
|
||||
vegetation.get_set_test(3, "Configuration|Shape Entity Id", cylinder.id)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 5.0, 100), 2.0)
|
||||
self.log(f"Vegetation plant only in the areas where the Cylinder overlaps with the vegetation area's boundaries: {result}")
|
||||
|
||||
# Create a new entity as a child of the vegetation area entity with Random Noise Gradient Generator, Gradient Transform Modifier,
|
||||
# and Box Shape component
|
||||
random_noise = hydra.Entity("random_noise")
|
||||
random_noise.create_entity(position, ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"])
|
||||
random_noise.set_test_parent_entity(vegetation)
|
||||
|
||||
# Add a Vegetation Position Modifier to the vegetation area entity
|
||||
vegetation.add_component("Vegetation Position Modifier")
|
||||
|
||||
# Pin the Random Noise entity to the Gradient Entity Id field of the Position Modifier's Gradient X
|
||||
vegetation.get_set_test(4, "Configuration|Position X|Gradient|Gradient Entity Id", random_noise.id)
|
||||
|
||||
# Toggle between PreProcess and PostProcess
|
||||
vegetation.get_set_test(3, "Configuration|Filter Stage", 1)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 5.0, 117), 2.0)
|
||||
self.log(f"Vegetation instances count equal to expected value for PREPROCESS filter stage: {result}")
|
||||
vegetation.get_set_test(3, "Configuration|Filter Stage", 2)
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count(position, 5.0, 122), 2.0)
|
||||
self.log(f"Vegetation instances count equal to expected value for POSTPROCESS filter stage: {result}")
|
||||
|
||||
test = TestSlopeFilterFilterStageToggle()
|
||||
test.run()
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSurfaceDataRefreshes_RemainsStable(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SurfaceDataRefreshes_RemainsStable", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
The Vegetation Area System can intermittently crash when updating surface data and moving the camera
|
||||
around rapidly. The situation occurs across multiple frames - the surface data updates, which triggers a bunch
|
||||
of sector updates getting added to the update queue. Then in a subsequent frame, there is no active vegetation
|
||||
area or surface data updates, which triggers "delete all sectors". The "delete all" wasn't deleting entries from
|
||||
the update queue, so any unprocessed updates would continue to get processed. If any of those updates referenced
|
||||
a sector that no longer exists, because the camera changed position, then it would assert and crash.
|
||||
|
||||
To repro this bug, this test creates an empty level with a large box shape emitting a surface, and then runs a tight
|
||||
loop of camera movements and "surface changed" events that invalidate all surface points. Because this is a timing
|
||||
issue, there's no guarantee that the test below will successfully cause the condition to occur, but it successfully
|
||||
crashed every time it was tested locally prior to the bugfix.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# 1) Create a test level with the needed test setup
|
||||
self.test_success = self.create_level(
|
||||
self.get_arg('level'),
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False)
|
||||
|
||||
world_center = math.Vector3(512.0, 512.0, 32.0)
|
||||
|
||||
# Add an entity with a 1024 x 1024 box centered at 512,512.
|
||||
surface_entity = dynveg.create_surface_entity("Surface Data", world_center, 1024.0, 1024.0, 1.0)
|
||||
|
||||
# Move the camera to the world center
|
||||
general.set_current_view_position(world_center.x, world_center.y, world_center.z)
|
||||
|
||||
# 2) Perform the test. Since the conditions are extremely timing related, and every machine
|
||||
# running the test can have different timing conditions, we run through a set of different
|
||||
# combinations to try and cause the crash under as many scenarios as possible
|
||||
|
||||
loops_per_surface_changed = [3, 5, 5]
|
||||
loops_per_camera_reset = [20, 20, 20]
|
||||
camera_speed_per_loop = [10.0, 10.0, 15.0]
|
||||
|
||||
# Setting test success to false to make sure the toggle at the end accurately conveys the loop being successful
|
||||
self.test_success = False
|
||||
|
||||
# Loop through all our attempted timing test cases to cause the crash pretty consistently.
|
||||
for test_case in range(0,3):
|
||||
self.log(f'Starting test case {test_case}')
|
||||
self.log(f'Loops per surface changed: {loops_per_surface_changed[test_case]}')
|
||||
self.log(f'Loops per camera reset: {loops_per_camera_reset[test_case]}')
|
||||
self.log(f'Camera speed per loop: {camera_speed_per_loop[test_case]}')
|
||||
for test_counter in range (0,100):
|
||||
|
||||
# Every N loops, invalidate the entire set of surface data. It's mostly just important for this
|
||||
# not to happen *every* iteration, since we need the vegetation system to bounce between having
|
||||
# dirty surface points that cause sectors to be refreshed, and having no dirty surface points or
|
||||
# active surface areas to trigger a "delete all sectors" condition.
|
||||
if (test_counter % loops_per_surface_changed[test_case]) == 0:
|
||||
azlmbr.surface_data.SurfaceDataSystemNotificationBus(azlmbr.bus.Broadcast,
|
||||
'OnSurfaceChanged',
|
||||
surface_entity.id,
|
||||
azlmbr.math.Aabb(),
|
||||
azlmbr.math.Aabb())
|
||||
|
||||
# Move the camera back and forth along the X axis at just the right speed to invalidate sectors that are
|
||||
# queued for updating but haven't updated yet, so that when they try to update they crash.
|
||||
x_pos = world_center.x + ((test_counter % loops_per_camera_reset[test_case]) * camera_speed_per_loop[test_case])
|
||||
general.set_current_view_position(x_pos, world_center.y, world_center.z)
|
||||
|
||||
self.log(f'{test_counter}: {x_pos}')
|
||||
|
||||
# Give a little processing time each iteration.
|
||||
general.idle_wait(0.01)
|
||||
|
||||
# If we haven't crashed, then we've succeeded.
|
||||
self.test_success = True
|
||||
|
||||
|
||||
test = TestSurfaceDataRefreshes_RemainsStable()
|
||||
test.run()
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C3711666: Multiple Descriptors with different Surface Mask Filter overrides plant as expected.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSurfaceMaskFilterMultipleOverrides(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SurfaceMaskFilter_MultipleDescriptorOverrides", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A new level is created. An instance spawner with 3 descriptors is created. 3 planting surfaces of different
|
||||
sizes are created and different surface tags are applied to each. Descriptor surface mask filter overrides are
|
||||
set and instance counts are validated.
|
||||
|
||||
Expected Behavior:
|
||||
Instances plant on surfaces based on surface mask filter overrides.
|
||||
|
||||
Test Steps:
|
||||
1) A new level is created
|
||||
2) An instance spawner with 3 descriptors is created, and a Surface Mask Filter is added to the entity
|
||||
3) 3 surfaces of different sizes are created, and set to emit different tags
|
||||
4) Pre-test validation of instances
|
||||
5) Test 1 setup and validation: Inclusion tag matching surface a is set on a single descriptor
|
||||
6) Test 2 setup and validation: Inclusion tag matching surface b is set on a single descriptor
|
||||
7) Test 3 setup and validation: Inclusion tag matching surface c is set on a single descriptor
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
surface_tag_list = [surface_data.SurfaceTag("test_tag"), surface_data.SurfaceTag("test_tag2"),
|
||||
surface_data.SurfaceTag("test_tag3")]
|
||||
|
||||
# 1) Create a new, temporary level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Set view of planting area for visual debugging
|
||||
general.set_current_view_position(512.0, 500.0, 38.0)
|
||||
general.set_current_view_rotation(-20.0, 0.0, 0.0)
|
||||
|
||||
# 2) Create a new instance spawner entity with multiple Dynamic Slice Instance Spawner descriptors
|
||||
spawner_center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner", spawner_center_point, 16.0, 16.0, 16.0,
|
||||
asset_path)
|
||||
asset_list_component = spawner_entity.components[2]
|
||||
desc_asset = hydra.get_component_property_value(asset_list_component,
|
||||
"Configuration|Embedded Assets")[0]
|
||||
desc_list = [desc_asset, desc_asset, desc_asset]
|
||||
spawner_entity.get_set_test(2, "Configuration|Embedded Assets", desc_list)
|
||||
|
||||
# Add a Surface Mask Filter component to the spawner entity and toggle on Allow Overrides
|
||||
spawner_entity.add_component("Vegetation Surface Mask Filter")
|
||||
spawner_entity.get_set_test(3, "Configuration|Allow Per-Item Overrides", True)
|
||||
|
||||
# 3) Create 3 surfaces for planting, spaced out vertically, and set expected instance counts for each surface
|
||||
surface_entity_a = dynveg.create_surface_entity("Surface Entity A", math.Vector3(512.0, 512.0, 32.0),
|
||||
16.0, 16.0, 1.0)
|
||||
num_expected_surface_a = 20 * 20 # 20x20 instances on a 16x16 meter surface
|
||||
surface_entity_b = dynveg.create_surface_entity("Surface Entity B", math.Vector3(512.0, 512.0, 35.0),
|
||||
12.0, 12.0, 1.0)
|
||||
num_expected_surface_b = 15 * 15 # 15x15 instances on a 12x12 meter surface
|
||||
surface_entity_c = dynveg.create_surface_entity("Surface Entity C", math.Vector3(512.0, 512.0, 38.0),
|
||||
8.0, 8.0, 1.0)
|
||||
num_expected_surface_c = 10 * 10 # 10x10 instances on a 8x8 meter surface
|
||||
|
||||
# Set each surface to emit a different tag
|
||||
surface_entity_a.get_set_test(1, "Configuration|Generated Tags", [surface_tag_list[0]])
|
||||
surface_entity_b.get_set_test(1, "Configuration|Generated Tags", [surface_tag_list[1]])
|
||||
surface_entity_c.get_set_test(1, "Configuration|Generated Tags", [surface_tag_list[2]])
|
||||
|
||||
# 4) Initial Validation: Validate instance count in the spawner area. Instances should plant on all surfaces
|
||||
num_expected = num_expected_surface_a + num_expected_surface_b + num_expected_surface_c
|
||||
initial_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected), 5.0)
|
||||
self.test_success = initial_success and self.test_success
|
||||
|
||||
# 5)
|
||||
# Test #1 Setup: Set test_tag to inclusion list for descriptor 1. Set other descriptors to exclude all surfaces
|
||||
|
||||
# Toggle on Display Per-Item Overrides and Surface Mask Filter Override for each descriptor
|
||||
for index in range(3):
|
||||
spawner_entity.get_set_test(2, f"Configuration|Embedded Assets|[{index}]|Display Per-Item Overrides", True)
|
||||
spawner_entity.get_set_test(2,
|
||||
f"Configuration|Embedded Assets|[{index}]|Surface Mask Filter|Override Mode", 1)
|
||||
|
||||
spawner_entity.get_set_test(2,
|
||||
"Configuration|Embedded Assets|[0]|Surface Mask Filter|Inclusion Tags",
|
||||
[surface_tag_list[0]])
|
||||
spawner_entity.get_set_test(2,
|
||||
"Configuration|Embedded Assets|[1]|Surface Mask Filter|Exclusion Tags",
|
||||
surface_tag_list)
|
||||
spawner_entity.get_set_test(2,
|
||||
"Configuration|Embedded Assets|[2]|Surface Mask Filter|Exclusion Tags",
|
||||
surface_tag_list)
|
||||
|
||||
# Test #1 Validation: Validate instance count. Should only plant on a single surface for 400 instances
|
||||
test_1_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_surface_a), 5.0)
|
||||
self.test_success = test_1_success and self.test_success
|
||||
|
||||
# 6)
|
||||
# Test #2 Setup: Set test_tag2 to inclusion for descriptor 1.
|
||||
spawner_entity.get_set_test(2,
|
||||
"Configuration|Embedded Assets|[0]|Surface Mask Filter|Inclusion Tags",
|
||||
[surface_tag_list[1]])
|
||||
|
||||
# Test #2 Validation: Validate instance count. Should only plant on a single surface for 225 instances
|
||||
test_2_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_surface_b), 5.0)
|
||||
self.test_success = test_2_success and self.test_success
|
||||
|
||||
# 7)
|
||||
# Test #3 Setup: Set test_tag3 to inclusion for descriptor 1.
|
||||
spawner_entity.get_set_test(2,
|
||||
"Configuration|Embedded Assets|[0]|Surface Mask Filter|Inclusion Tags",
|
||||
[surface_tag_list[2]])
|
||||
|
||||
# Test #3 Validation: Validate instance count. Should only plant on a single surface for 100 instances
|
||||
test_3_success = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_surface_c), 5.0)
|
||||
self.test_success = test_3_success and self.test_success
|
||||
|
||||
|
||||
test = TestSurfaceMaskFilterMultipleOverrides()
|
||||
test.run()
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestSurfaceMaskFilter_BasicSurfaceTagCreation(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="TestSurfaceMaskFilter_BasicSurfaceTagCreation", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
self.log("SurfaceTag test started")
|
||||
|
||||
# Create a level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
tag1 = surface_data.SurfaceTag()
|
||||
tag2 = surface_data.SurfaceTag()
|
||||
|
||||
# Test 1: Verify that two tags with the same value are equal
|
||||
tag1.SetTag('equal_test')
|
||||
tag2.SetTag('equal_test')
|
||||
self.log("SurfaceTag equal tag comparison is {} expected True".format(tag1.Equal(tag2)))
|
||||
self.test_success = self.test_success and tag1.Equal(tag2)
|
||||
|
||||
# Test 2: Verify that two tags with different values are not equal
|
||||
tag2.SetTag('not_equal_test')
|
||||
self.log("SurfaceTag not equal tag comparison is {} expected False".format(tag1.Equal(tag2)))
|
||||
self.test_success = self.test_success and not tag1.Equal(tag2)
|
||||
|
||||
self.log("SurfaceTag test finished")
|
||||
|
||||
|
||||
test = TestSurfaceMaskFilter_BasicSurfaceTagCreation()
|
||||
test.run()
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
"""
|
||||
C2561342: Exclusive Surface Masks tags function
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.shape as shape
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestExclusiveSurfaceMasksTag(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SurfaceMaskFilter_ExclusionList", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
New level is created and set up with surface shapes with varying surface tags. A simple vegetation area has been
|
||||
created and Vegetation Surface Mask Filter component is added to entity with terrain hole exclusion tag.
|
||||
|
||||
Expected Behavior:
|
||||
With default Exclusion settings, vegetation does not plant over the terrain holes.
|
||||
With Exclusion Weight Max below 1.0, vegetation plants over the terrain holes.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level.
|
||||
2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
3) Add a Vegetation Surface Mask Filter component to the entity.
|
||||
4) Create 2 surface entities to represent terrain and terrain hole surfaces
|
||||
5) Add an Exclusion List tag to the component, and set it to terrainHole.
|
||||
6) Check spawn count with default Exclusion Weights
|
||||
7) Check spawn count with Exclusion Weight Max set below 1.0
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def update_surface_tag_exclusion_list(Entity, component_index, surface_tag):
|
||||
tag_list = [surface_data.SurfaceTag()]
|
||||
|
||||
# assign list with one surface tag to exclusion list
|
||||
hydra.get_set_test(Entity, component_index, "Configuration|Exclusion|Surface Tags", tag_list)
|
||||
|
||||
# set that one surface tag element to required surface tag
|
||||
component = Entity.components[component_index]
|
||||
path = "Configuration|Exclusion|Surface Tags|[0]|Surface Tag"
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", component, path, surface_tag)
|
||||
new_value = hydra.get_component_property_value(component, path)
|
||||
|
||||
if new_value == surface_tag:
|
||||
self.log(f"Exclusive surface mask filter of {surface_tag} is added successfully")
|
||||
else:
|
||||
self.log(f"Failed to add an Exclusive surface mask filter of {surface_tag}")
|
||||
|
||||
def update_generated_surface_tag(Entity, component_index, surface_tag):
|
||||
tag_list = [surface_data.SurfaceTag()]
|
||||
|
||||
# assign list with one surface tag to Generated Tags list
|
||||
hydra.get_set_test(Entity, component_index, "Configuration|Generated Tags", tag_list)
|
||||
|
||||
# set that one surface tag element to required surface tag
|
||||
component = Entity.components[component_index]
|
||||
path = "Configuration|Generated Tags|[0]|Surface Tag"
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", component, path, surface_tag)
|
||||
new_value = hydra.get_component_property_value(component, path)
|
||||
|
||||
if new_value == surface_tag:
|
||||
self.log(f"Generated surface tag of {surface_tag} is added successfully")
|
||||
else:
|
||||
self.log(f"Failed to add Generated surface tag of {surface_tag}")
|
||||
|
||||
# 1) Create a new level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner",
|
||||
entity_position,
|
||||
10.0, 10.0, 10.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Add a Vegetation Surface Mask Filter component to the entity.
|
||||
spawner_entity.add_component("Vegetation Surface Mask Filter")
|
||||
|
||||
# 4) Create 2 surface entities to represent terrain and terrain hole surfaces
|
||||
surface_tags: dict = {"terrainHole": 1327698037, "terrain": 3363197873}
|
||||
entity_position = math.Vector3(510.0, 512.0, 32.0)
|
||||
surface_entity_1 = dynveg.create_surface_entity("Surface Entity 1",
|
||||
entity_position,
|
||||
10.0, 10.0, 1.0)
|
||||
update_generated_surface_tag(surface_entity_1, 1, surface_tags["terrainHole"])
|
||||
|
||||
entity_position = math.Vector3(520.0, 512.0, 32.0)
|
||||
surface_entity_2 = dynveg.create_surface_entity("Surface Entity 2",
|
||||
entity_position,
|
||||
10.0, 10.0, 1.0)
|
||||
update_generated_surface_tag(surface_entity_2, 1, surface_tags["terrain"])
|
||||
|
||||
# 5) Add an Exclusion List tag to the component, and set it to "terrainHole".
|
||||
update_surface_tag_exclusion_list(spawner_entity, 3, surface_tags["terrainHole"])
|
||||
|
||||
# 6) Check spawn count with default Exclusion Weights
|
||||
general.idle_wait(2.0) # Allow a few seconds for instances to spawn
|
||||
num_expected_instances = 39
|
||||
box = shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
# 7) Check spawn count with Exclusion Weight Max set below 1.0
|
||||
hydra.get_set_test(spawner_entity, 3, "Configuration|Exclusion|Weight Max", 0.9)
|
||||
general.idle_wait(2.0) # Allow a few seconds for instances to spawn
|
||||
num_expected_instances = 169
|
||||
num_found = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
|
||||
test = TestExclusiveSurfaceMasksTag()
|
||||
test.run()
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
"""
|
||||
C2561341: Inclusive Surface Masks tags function
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.shape as shape
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestInclusiveSurfaceMasksTag(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SurfaceMaskFilter_InclusionList", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
New level is created and set up with surface shapes with varying surface tags. A simple vegetation area has been
|
||||
created and Vegetation Surface Mask Filter component is added to entity with terrain hole inclusion tag.
|
||||
|
||||
Expected Behavior:
|
||||
With default Inclusion Weights, vegetation draws over the terrain holes.
|
||||
With Inclusion Weight Max set below 1.0, vegetation stops drawing over the terrain holes.
|
||||
|
||||
Test Steps:
|
||||
1) Create a new level
|
||||
2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
3) Add a Vegetation Surface Mask Filter component to the entity.
|
||||
4) Create 2 surface entities to represent terrain and terrain hole surfaces
|
||||
5) Add an Inclusion List tag to the component, and set it to "terrainHole".
|
||||
6) Check spawn count with default Inclusion Weights
|
||||
7) Check spawn count with Inclusion Weight Max set below 1.0
|
||||
|
||||
Note:
|
||||
- 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
|
||||
"""
|
||||
|
||||
def update_surface_tag_inclusion_list(Entity, component_index, surface_tag):
|
||||
tag_list = [surface_data.SurfaceTag()]
|
||||
|
||||
# assign list with one surface tag to inclusion list
|
||||
hydra.get_set_test(Entity, component_index, "Configuration|Inclusion|Surface Tags", tag_list)
|
||||
|
||||
# set that one surface tag element to required surface tag
|
||||
component = Entity.components[component_index]
|
||||
path = "Configuration|Inclusion|Surface Tags|[0]|Surface Tag"
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", component, path, surface_tag)
|
||||
new_value = hydra.get_component_property_value(component, path)
|
||||
|
||||
if new_value == surface_tag:
|
||||
print("Inclusive surface mask filter of terrainHole is added successfully")
|
||||
else:
|
||||
print("Failed to add an Inclusive surface mask filter of terrainHole")
|
||||
general.idle_wait(2.0)
|
||||
|
||||
def update_generated_surface_tag(Entity, component_index, surface_tag):
|
||||
tag_list = [surface_data.SurfaceTag()]
|
||||
|
||||
# assign list with one surface tag to Generated Tags list
|
||||
hydra.get_set_test(Entity, component_index, "Configuration|Generated Tags", tag_list)
|
||||
|
||||
# set that one surface tag element to required surface tag
|
||||
component = Entity.components[component_index]
|
||||
path = "Configuration|Generated Tags|[0]|Surface Tag"
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "SetComponentProperty", component, path, surface_tag)
|
||||
new_value = hydra.get_component_property_value(component, path)
|
||||
|
||||
if new_value == surface_tag:
|
||||
self.log(f"Generated surface tag of {surface_tag} is added successfully")
|
||||
else:
|
||||
self.log(f"Failed to add Generated surface tag of {surface_tag}")
|
||||
|
||||
# 1) Create a new level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Instance Spawner",
|
||||
entity_position,
|
||||
10.0, 10.0, 10.0,
|
||||
asset_path)
|
||||
|
||||
# 3) Add a Vegetation Surface Mask Filter component to the entity.
|
||||
spawner_entity.add_component("Vegetation Surface Mask Filter")
|
||||
|
||||
# 4) Create 2 surface entities to represent terrain and terrain hole surfaces
|
||||
surface_tags: dict = {"terrainHole": 1327698037, "terrain": 3363197873}
|
||||
entity_position = math.Vector3(510.0, 512.0, 32.0)
|
||||
surface_entity_1 = dynveg.create_surface_entity("Surface Entity 1",
|
||||
entity_position,
|
||||
10.0, 10.0, 1.0)
|
||||
update_generated_surface_tag(surface_entity_1, 1, surface_tags["terrainHole"])
|
||||
|
||||
entity_position = math.Vector3(520.0, 512.0, 32.0)
|
||||
surface_entity_2 = dynveg.create_surface_entity("Surface Entity 2",
|
||||
entity_position,
|
||||
10.0, 10.0, 1.0)
|
||||
update_generated_surface_tag(surface_entity_2, 1, surface_tags["terrain"])
|
||||
|
||||
# 5) Add an Inclusion List tag to the component, and set it to "terrainHole".
|
||||
update_surface_tag_inclusion_list(spawner_entity, 3, surface_tags["terrainHole"])
|
||||
|
||||
# 6) Check spawn count with default Inclusion Weights
|
||||
general.idle_wait(2.0) # Allow a few seconds for instances to spawn
|
||||
num_expected_instances = 130
|
||||
box = shape.ShapeComponentRequestsBus(bus.Event, 'GetEncompassingAabb', spawner_entity.id)
|
||||
num_found = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
# 7) Check spawn count with Inclusion Weight Max set below 1.0
|
||||
hydra.get_set_test(spawner_entity, 3, "Configuration|Inclusion|Weight Max", 0.9)
|
||||
general.idle_wait(2.0) # Allow a few seconds for instances to update
|
||||
num_expected_instances = 0
|
||||
num_found = areasystem.AreaSystemRequestBus(bus.Broadcast, 'GetInstanceCountInAabb', box)
|
||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||
self.test_success = self.test_success and num_found == num_expected_instances
|
||||
|
||||
|
||||
test = TestInclusiveSurfaceMasksTag()
|
||||
test.run()
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.bus as bus
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSystemSettingsSectorPointDensity(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SystemSettings_SectorPointDensity", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Sector Point Density increases/reduces the number of vegetation points within a sector
|
||||
|
||||
Expected Result:
|
||||
Default value for Sector Point Density is 20.
|
||||
20 vegetation meshes appear on each side of the established vegetation area with the default value.
|
||||
When altered, the specified number of vegetation meshes along a side of a vegetation area matches the value set
|
||||
in Sector Point Density.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
INSTANCE_COUNT_BEFORE_DENSITY_CHANGE = 400
|
||||
INSTANCE_COUNT_AFTER_DENSITY_CHANGE = 100
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
dynveg.create_vegetation_area("vegetation", position, 16.0, 16.0, 1.0, asset_path)
|
||||
dynveg.create_surface_entity("Surface_Entity", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# Count the number of vegetation meshes along one side of the new vegetation area. #
|
||||
result = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count(position, 8.0, INSTANCE_COUNT_BEFORE_DENSITY_CHANGE), 2.0
|
||||
)
|
||||
self.log(f"Vegetation instances count equal to expected value before changing sector point density: {result}")
|
||||
|
||||
# Add the Vegetation Debugger component to the Level Inspector
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
|
||||
# Change Sector Point Density to 10
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast,
|
||||
"SetComponentProperty",
|
||||
veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Point Snap Mode",
|
||||
1,
|
||||
)
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast,
|
||||
"SetComponentProperty",
|
||||
veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Point Density",
|
||||
10,
|
||||
)
|
||||
|
||||
# Count the number of vegetation meshes along one side of the new vegetation area.
|
||||
result = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count(position, 8.0, INSTANCE_COUNT_AFTER_DENSITY_CHANGE), 2.0
|
||||
)
|
||||
self.log(f"Vegetation instances count equal to expected value after changing sector point density: {result}")
|
||||
|
||||
|
||||
test = TestSystemSettingsSectorPointDensity()
|
||||
test.run()
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.bus as bus
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestSystemSettingsSectorSize(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="SystemSettings_SectorSize", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Sector Size In Meters increases/reduces the size of a sector
|
||||
|
||||
Expected Result:
|
||||
The number of spawned vegetation meshes inside the vegetation area is identical after updating the Sector Size
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
VEGETATION_INSTANCE_COUNT = 400
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
vegetation = dynveg.create_vegetation_area("vegetation", position, 16.0, 16.0, 1.0, asset_path)
|
||||
dynveg.create_surface_entity("Surface_Entity", position, 16.0, 16.0, 1.0)
|
||||
|
||||
# Add the Vegetation Debugger component to the Level Inspector
|
||||
veg_system_settings_component = hydra.add_level_component("Vegetation System Settings")
|
||||
|
||||
# Count the number of vegetation meshes along one side of the new vegetation area.
|
||||
result = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count(position, 8.0, VEGETATION_INSTANCE_COUNT), 2.0
|
||||
)
|
||||
self.log(f"Vegetation instances count equal to expected value before changing sector size: {result}")
|
||||
|
||||
# Change Sector Size in Meters to 10.
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast,
|
||||
"SetComponentProperty",
|
||||
veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Point Snap Mode",
|
||||
1,
|
||||
)
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast,
|
||||
"SetComponentProperty",
|
||||
veg_system_settings_component,
|
||||
"Configuration|Area System Settings|Sector Size In Meters",
|
||||
10,
|
||||
)
|
||||
|
||||
# Alter the Box Shape to be 10,10,1
|
||||
vegetation.get_set_test(1, "Box Shape|Box Configuration|Dimensions", math.Vector3(10.0, 10.0, 1.0))
|
||||
|
||||
# Count the number of vegetation meshes along one side of the new vegetation area.
|
||||
result = self.wait_for_condition(
|
||||
lambda: dynveg.validate_instance_count(position, 5.0, VEGETATION_INSTANCE_COUNT), 2.0
|
||||
)
|
||||
self.log(f"Vegetation instances count equal to expected value after changing sector size: {result}")
|
||||
|
||||
|
||||
test = TestSystemSettingsSectorSize()
|
||||
test.run()
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
This script tests for regressions of "vegetation instances don't despawn correctly
|
||||
when the camera moves beyond the range of all active vegetation areas".
|
||||
|
||||
This creates a new level and a vegetation area with 400 instances.
|
||||
The expectation is that we will have 400 instances in that area when the camera is centered on it,
|
||||
and 0 instances when the camera is moved sufficiently far away.
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
|
||||
|
||||
class TestVegetationInstances_DespawnWhenOutOfRange(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix='VegetationInstances_DespawnWhenOutOfRange', args=['level'])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
# Create a new level
|
||||
self.test_success = self.create_level(
|
||||
self.get_arg('level'),
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False)
|
||||
|
||||
# Create vegetation layer spawner
|
||||
world_center = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
spawner_entity = dynveg.create_vegetation_area("Spawner Instance", world_center, 16.0, 16.0, 16.0, asset_path)
|
||||
|
||||
# Create a surface to spawn on
|
||||
dynveg.create_surface_entity("Spawner Entity", world_center, 16.0, 16.0, 1.0)
|
||||
|
||||
# Get the root position of our veg area and use it to position our camera.
|
||||
# This is useful both to ensure that vegetation is spawned where we're querying and to
|
||||
# visually verify the number of instances in each box
|
||||
position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", spawner_entity.id)
|
||||
general.set_current_view_position(position.x, position.y, position.z + 30.0)
|
||||
general.set_current_view_rotation(-90.0, 0.0, 0.0)
|
||||
|
||||
# When centered over the veg area, we expect to find 400 instances.
|
||||
# (16x16 area, 20 points per 16 meters)
|
||||
num_expected = 400
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 2.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
# Move sufficiently far away from the veg area that it should all despawn.
|
||||
general.set_current_view_position(position.x - 1000.0, position.y - 1000.0, position.z + 30.0)
|
||||
|
||||
# We now expect to find 0 instances. If the bug exists, we will find 400 still.
|
||||
num_expected = 0
|
||||
result = self.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id,
|
||||
num_expected), 2.0)
|
||||
self.test_success = self.test_success and result
|
||||
|
||||
|
||||
test = TestVegetationInstances_DespawnWhenOutOfRange()
|
||||
test.run()
|
||||
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestAltitudeFilter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id('C4814463', 'C4847477')
|
||||
@pytest.mark.SUITE_main
|
||||
def test_AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"'Planting Surface Elevated' created",
|
||||
"instance count validation: True (found=3200, expected=3200)",
|
||||
"instance count validation: True (found=1600, expected=1600)",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"AltitudeFilterComponentAndOverrides: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4847476")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"'Planting Surface Elevated' created",
|
||||
"instance count validation: True (found=800, expected=800)",
|
||||
"'Shape Sampler' created",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"AltitudeFilterShapeSample: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4847478")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_AltitudeFilterFilterStageToggle(self, request, editor, level, workspace, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"AltitudeFilter_FilterStageToggle: test started",
|
||||
"AltitudeFilter_FilterStageToggle: Vegetation instances count equal to expected value for PREPROCESS filter stage: True",
|
||||
"AltitudeFilter_FilterStageToggle: Vegetation instances count equal to expected value for POSTPROCESS filter stage: True",
|
||||
"AltitudeFilter_FilterStageToggle: result=SUCCESS",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"AltitudeFilter_FilterStageToggle: Vegetation instances count equal to expected value for PREPROCESS filter stage: False",
|
||||
"AltitudeFilter_FilterStageToggle: Vegetation instances count equal to expected value for POSTPROCESS filter stage: False",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AltitudeFilter_FilterStageToggle.py",
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=cfg_args
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestAreaComponents(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Cleanup the test slices
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "slices", "TestSlice_1.slice")], True, True)
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "slices", "TestSlice_2.slice")], True, True)
|
||||
|
||||
def teardown():
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Cleanup the test slices
|
||||
file_system.delete(
|
||||
[os.path.join(workspace.paths.dev(), project, "slices", "TestSlice_1.slice")], True, True
|
||||
)
|
||||
file_system.delete(
|
||||
[os.path.join(workspace.paths.dev(), project, "slices", "TestSlice_2.slice")], True, True
|
||||
)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id("C2627900", "C2627905", "C2627904")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_AreaComponents_SliceCreationVisibilityToggleWorks(self, request, editor, level, workspace,
|
||||
launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: test started",
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: Slice has been created successfully (entity with spawner component): True",
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: Vegetation plants initially when slice is shown: True",
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: Vegetation is cleared when slice is hidden: True",
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: Slice has been created successfully (entity with blender component): True",
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AreaComponentSlices_SliceCreationAndVisibilityToggle.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=cfg_args
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestAssetListCombiner(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4762374", "C4762373")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Asset List 1' created",
|
||||
"'Asset List 2' created",
|
||||
"'Asset List 3' created",
|
||||
"'Surface Entity' created",
|
||||
"'Spawner Entity' created",
|
||||
"Spawner Entity Configuration|Descriptor Providers: SUCCESS",
|
||||
"Spawner Entity Configuration|Gradient|Gradient Entity Id: SUCCESS",
|
||||
"instance count validation: True (found=200, expected=200.0)",
|
||||
"Spawner Entity Configuration|Descriptor Providers|[1]: SUCCESS",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"instance count validation: True (found=0, expected=0)",
|
||||
"AssetListCombiner_CombinedDescriptors: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C6269654: Vegetation areas using weight selectors properly distribute instances according to Sort By Weight setting
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestAssetWeightSelector(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C6269654", "C4762368")
|
||||
@pytest.mark.SUITE_sandbox
|
||||
def test_AssetWeightSelector_InstancesExpressBasedOnWeight(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"Instance Spawner Configuration|Embedded Assets|[1]|Instance|Slice Asset: SUCCESS",
|
||||
"'Planting Surface' created",
|
||||
"Configuration|Embedded Assets|[0]|Weight set to 50.0",
|
||||
"Instance Spawner Configuration|Allow Empty Assets: SUCCESS",
|
||||
"AssetWeightSelector_SortByWeight: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"AssetWeightSelector_InstancesExpressBasedOnWeight.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestDebugger(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
def teardown():
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id("C2789148")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_Debugger_DebugCVarsWork(self, request, editor, level, workspace, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"Debugger_DebugCVarsWorks: test started",
|
||||
"[Warning] Unknown command: veg_debugDumpReport",
|
||||
"[CONSOLE] Executing console command 'veg_debugRefreshAllAreas'",
|
||||
"Debugger_DebugCVarsWorks: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"Debugger_DebugCVarsWorks.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=cfg_args
|
||||
)
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestDistanceBetweenFilter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4851066")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Configuration|Radius Min set to 1.0",
|
||||
"Configuration|Radius Min set to 2.0",
|
||||
"Configuration|Radius Min set to 16.0",
|
||||
"DistanceBetweenFilterComponent: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4814458")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min set to 1.0",
|
||||
"Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min set to 2.0",
|
||||
"Configuration|Embedded Assets|[0]|Distance Between Filter (Radius)|Radius Min set to 16.0",
|
||||
"DistanceBetweenFilterComponentOverrides: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class Test_DynVeg_Regressions(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
# delete temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Setup - add the teardown finalizer
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
# Make sure the temp level doesn't already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C29470845")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_SurfaceDataRefreshes_RemainsStable(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"SurfaceDataRefreshes_RemainsStable: test started",
|
||||
"SurfaceDataRefreshes_RemainsStable: test finished",
|
||||
"SurfaceDataRefreshes_RemainsStable: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"Sector update mode is 'RebuildSurfaceCache' but sector doesn't exist"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
'SurfaceDataRefreshes_RemainsStable.py',
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_VegetationInstances_DespawnWhenOutOfRange(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"VegetationInstances_DespawnWhenOutOfRange: test started",
|
||||
"VegetationInstances_DespawnWhenOutOfRange: test finished",
|
||||
"VegetationInstances_DespawnWhenOutOfRange: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
'VegetationInstances_DespawnWhenOutOfRange.py',
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
class TestDynamicSliceInstanceSpawner(object):
|
||||
|
||||
@pytest.fixture
|
||||
def remote_console_instance(self, request):
|
||||
console = RemoteConsole()
|
||||
|
||||
def teardown():
|
||||
if console.connected:
|
||||
console.stop()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return console
|
||||
|
||||
@pytest.mark.test_case_id("C28851763")
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
def test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(self, request, editor, level, workspace, project,
|
||||
launcher_platform):
|
||||
# Ensure temp level does not already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"DynamicSliceInstanceSpawner: test started",
|
||||
"DynamicSliceInstanceSpawner: test finished",
|
||||
"DynamicSliceInstanceSpawner: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(request, test_directory, editor,
|
||||
'DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py',
|
||||
expected_lines=expected_lines, cfg_args=cfg_args)
|
||||
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id('C2574330')
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
def test_DynamicSliceInstanceSpawner_Embedded_E2E_Editor(self, workspace, request, editor, level, project,
|
||||
launcher_platform):
|
||||
# Ensure temp level does not already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"DynamicSliceInstanceSpawnerEmbeddedEditor: Expected 400 instances - Found 400 instances",
|
||||
"DynamicSliceInstanceSpawnerEmbeddedEditor: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(request, test_directory, editor, "DynamicSliceInstanceSpawner_Embedded_E2E.py",
|
||||
expected_lines, cfg_args=[level])
|
||||
|
||||
@pytest.mark.test_case_id('C2574330')
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||
def test_DynamicSliceInstanceSpawner_Embedded_E2E_Launcher(self, workspace, launcher, level,
|
||||
remote_console_instance, project, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Instances found in area = 400"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines)
|
||||
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id('C4762367')
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
def test_DynamicSliceInstanceSpawner_External_E2E_Editor(self, workspace, request, editor, level, project,
|
||||
launcher_platform):
|
||||
# Ensure temp level does not already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
expected_lines = [
|
||||
"Spawner entity created",
|
||||
"'Planting Surface' created",
|
||||
"DynamicSliceInstanceSpawnerExternalEditor: Expected 400 instances - Found 400 instances",
|
||||
"DynamicSliceInstanceSpawnerExternalEditor: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(request, test_directory, editor, "DynamicSliceInstanceSpawner_External_E2E.py",
|
||||
expected_lines, cfg_args=[level])
|
||||
|
||||
@pytest.mark.test_case_id('C4762367')
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||
def test_DynamicSliceInstanceSpawner_External_E2E_Launcher(self, workspace, launcher, level,
|
||||
remote_console_instance, project, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Instances found in area = 400"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines)
|
||||
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestEmptyInstanceSpawner(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C28851762")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_EmptyInstanceSpawner_EmptySpawnerWorks(self, request, editor, level, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"EmptyInstanceSpawner: test started",
|
||||
"EmptyInstanceSpawner: test finished",
|
||||
"EmptyInstanceSpawner: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(request, test_directory, editor, 'EmptyInstanceSpawner_EmptySpawnerWorks.py',
|
||||
expected_lines=expected_lines, cfg_args=cfg_args)
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C5747383: Vegetation areas with a higher Layer Priority plant over those with a lower Layer Priority
|
||||
C4762382: Vegetation areas with a higher Sub Priority plant over those with a lower Sub Priority
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestInstanceSpawnerPriority(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C5747383", "C4762382")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_InstanceSpawnerPriority_LayerAndSubPriority_HigherValuesPlantOverLower(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Instance Blocker' created",
|
||||
"'Planting Surface' created",
|
||||
"Instance Blocker Configuration|Layer Priority: SUCCESS",
|
||||
"Instance Spawner Configuration|Sub Priority: SUCCESS",
|
||||
"Instance Blocker Configuration|Sub Priority: SUCCESS",
|
||||
"InstanceSpawnerPriority: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"InstanceSpawnerPriority_LayerAndSubPriority.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C2627906: A simple Vegetation Layer Blender area can be created.
|
||||
The specified assets plant in the specified blend area and are visible in the Viewport in
|
||||
Edit Mode, Game Mode.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("ly_test_tools")
|
||||
|
||||
import time as time
|
||||
|
||||
import ly_test_tools.launchers.launcher_helper as launcher_helper
|
||||
import ly_remote_console.remote_console_commands as remote_console_commands
|
||||
from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response
|
||||
import ly_test_tools.environment.waiter as waiter
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import automatedtesting_shared.screenshot_utils as screenshot_utils
|
||||
|
||||
from automatedtesting_shared.network_utils import check_for_listening_port
|
||||
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
remote_console_port = 4600
|
||||
listener_timeout = 120
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
class TestLayerBlender(object):
|
||||
|
||||
@pytest.fixture
|
||||
def remote_console_instance(self, request):
|
||||
console = remote_console_commands.RemoteConsole()
|
||||
|
||||
def teardown():
|
||||
if console.connected:
|
||||
console.stop()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return console
|
||||
|
||||
@pytest.mark.test_case_id("C2627906")
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
def test_LayerBlender_E2E_Editor(self, workspace, request, editor, project, level, launcher_platform):
|
||||
# Make sure temp level doesn't already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
expected_lines = [
|
||||
"'Purple Spawner' created",
|
||||
"'Pink Spawner' created",
|
||||
"'Surface Entity' created",
|
||||
"Entity has a Vegetation Layer Spawner component",
|
||||
"Entity has a Vegetation Asset List component",
|
||||
"Entity has a Box Shape component",
|
||||
"Purple Spawner Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Pink Spawner Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Purple Spawner Configuration|Embedded Assets|[0]: SUCCESS",
|
||||
"Pink Spawner Configuration|Embedded Assets|[0]: SUCCESS",
|
||||
"'Blender' created",
|
||||
"Entity has a Vegetation Layer Blender component",
|
||||
"Entity has a Box Shape component",
|
||||
"Blender Configuration|Vegetation Areas: SUCCESS",
|
||||
"Blender Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Camera entity created",
|
||||
"LayerBlender_E2E_Editor: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerBlender_E2E_Editor.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2627906")
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||
def test_LayerBlender_E2E_Launcher(self, workspace, project, launcher, level, remote_console_instance,
|
||||
launcher_platform):
|
||||
|
||||
launcher.args.extend(["-NullRenderer"])
|
||||
launcher.start()
|
||||
assert launcher.is_alive(), "Launcher failed to start"
|
||||
|
||||
# Wait for test script to quit the launcher. If wait_for returns exc, test was not successful
|
||||
waiter.wait_for(lambda: not launcher.is_alive(), timeout=300)
|
||||
|
||||
# Verify launcher quit successfully and did not crash
|
||||
ret_code = launcher.get_returncode()
|
||||
assert ret_code == 0, "Test failed. See Game.log for details"
|
||||
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestLayerBlocker(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C2793772")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_LayerBlocker_InstancesBlockedInConfiguredArea(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Surface Entity' created",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"'Blocker Area' created",
|
||||
"instance count validation: True (found=384, expected=384)",
|
||||
"LayerBlocker_InstancesBlocked: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerBlocker_InstancesBlockedInConfiguredArea.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestLayerSpawner(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
def teardown():
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id("C4762381")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_LayerSpawner_InheritBehaviorFlag(self, request, editor, level, workspace, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"LayerSpawner_InheritBehavior: test started",
|
||||
"LayerSpawner_InheritBehavior: Vegetation is not planted when Inherit Behavior flag is checked: True",
|
||||
"LayerSpawner_InheritBehavior: Vegetation plant when Inherit Behavior flag is unchecked: True",
|
||||
"LayerSpawner_InheritBehavior: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerSpawner_InheritBehaviorFlag.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2802020")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_LayerSpawner_InstancesPlantInAllSupportedShapes(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Surface Entity' created",
|
||||
"Entity has a Vegetation Reference Shape component",
|
||||
"Entity has a Box Shape component",
|
||||
"box Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Entity has a Capsule Shape component",
|
||||
"capsule Capsule Shape|Capsule Configuration|Height: SUCCESS",
|
||||
"capsule Capsule Shape|Capsule Configuration|Radius: SUCCESS",
|
||||
"Entity has a Tube Shape component",
|
||||
"Entity has a Spline component",
|
||||
"Entity has a Sphere Shape component",
|
||||
"sphere Sphere Shape|Sphere Configuration|Radius: SUCCESS",
|
||||
"Entity has a Cylinder Shape component",
|
||||
"cylinder Cylinder Shape|Cylinder Configuration|Radius: SUCCESS",
|
||||
"cylinder Cylinder Shape|Cylinder Configuration|Height: SUCCESS",
|
||||
"Entity has a Polygon Prism Shape component",
|
||||
"Entity has a Compound Shape component",
|
||||
"Compound Configuration|Child Shape Entities|[0]: SUCCESS",
|
||||
"Compound Configuration|Child Shape Entities|[1]: SUCCESS",
|
||||
"Compound Configuration|Child Shape Entities|[2]: SUCCESS",
|
||||
"Compound Configuration|Child Shape Entities|[3]: SUCCESS",
|
||||
"Compound Configuration|Child Shape Entities|[4]: SUCCESS",
|
||||
"Compound Configuration|Child Shape Entities|[5]: SUCCESS",
|
||||
"Instance Spawner Configuration|Shape Entity Id: SUCCESS",
|
||||
"TestLayerSpawner_AllShapesPlant: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerSpawner_InstancesPlantInAllSupportedShapes.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4765973")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_LayerSpawner_FilterStageToggle(self, request, editor, level, workspace, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"LayerSpawner_FilterStageToggle: test started",
|
||||
"LayerSpawner_FilterStageToggle: Preprocess filter stage vegetation instance count is as expected: True",
|
||||
"LayerSpawner_FilterStageToggle: Postprocess filter vegetation instance stage count is as expected: True",
|
||||
"LayerSpawner_FilterStageToggle: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerSpawner_FilterStageToggle.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C30000751")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_LayerSpawner_InstancesRefreshUsingCorrectViewportCamera(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"LayerSpawner_InstanceCameraRefresh: test started",
|
||||
"LayerSpawner_InstanceCameraRefresh: test finished",
|
||||
"LayerSpawner_InstanceCameraRefresh: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"LayerSpawner_InstancesRefreshUsingCorrectViewportCamera.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
import os
|
||||
import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestMeshBlocker(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, editor, project, level):
|
||||
pass
|
||||
|
||||
def teardown():
|
||||
# delete temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Setup - add the teardown finalizer
|
||||
request.addfinalizer(teardown)
|
||||
# Make sure the temp level doesn't already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
"""
|
||||
C3980834: A simple Vegetation Blocker Mesh can be created
|
||||
"""
|
||||
@pytest.mark.test_case_id("C3980834")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_MeshBlocker_InstancesBlockedByMesh(self, request, editor, level, launcher_platform):
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Surface Entity' created",
|
||||
"'Blocker Entity' created",
|
||||
"instance count validation: True (found=160, expected=160)",
|
||||
"MeshBlocker_InstancesBlockedByMesh: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"MeshBlocker_InstancesBlockedByMesh.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
"""
|
||||
C4766030: Mesh Height Percent Min/Max values can be set to fine tune the blocked area
|
||||
"""
|
||||
@pytest.mark.test_case_id("C4766030")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_MeshBlocker_InstancesBlockedByMeshHeightTuning(self, request, editor, level, launcher_platform):
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Surface Entity' created",
|
||||
"'Blocker Entity' created",
|
||||
"Blocker Entity Configuration|Mesh Height Percent Max: SUCCESS",
|
||||
"instance count validation: True (found=117, expected=117)",
|
||||
"MeshBlocker_InstancesBlockedByMeshHeightTuning: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"MeshBlocker_InstancesBlockedByMeshHeightTuning.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestMeshSurfaceTagEmitter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C2908172")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_MeshSurfaceTagEmitter_DependentOnMeshComponent(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Entity has a Mesh Surface Tag Emitter component",
|
||||
"New Entity Created",
|
||||
"Mesh Surface Tag Emitter is Disabled",
|
||||
"Entity has a Mesh component",
|
||||
"Mesh Surface Tag Emitter is Enabled",
|
||||
"MeshSurfaceTagEmitter_DependentOnMeshComponent: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"Mesh Surface Tag Emitter is Enabled. But It should be disabled before adding Mesh",
|
||||
"Mesh Surface Tag Emitter is Disabled. But It should be enabled after adding Mesh",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"MeshSurfaceTagEmitter_DependentOnMeshComponent.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2908174")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Added SurfaceTag: container count is 1",
|
||||
"Removed SurfaceTag: container count is 0",
|
||||
"MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSucessfully: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestPhysXColliderSurfaceTagEmitter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C29053640")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_PhysXColliderSurfaceTagEmitter_E2E_Editor(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"PhysXColliderSurfaceTagEmitter_E2E_Editor: test started",
|
||||
"PhysXColliderSurfaceTagEmitter_E2E_Editor: test finished",
|
||||
"PhysXColliderSurfaceTagEmitter_E2E_Editor: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"PhysXColliderSurfaceTagEmitter_E2E_Editor.py",
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestPositionModifier(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4874099", "C4814461")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"Vegetation Position Modifier component was added to entity",
|
||||
"'Planting Surface' created",
|
||||
"Entity has a Constant Gradient component",
|
||||
"PositionModifierComponentAndOverrides_InstanceOffset: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4874100")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_PositionModifier_AutoSnapToSurfaceWorks(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"instance count validation: True (found=121, expected=121)",
|
||||
"Instance Spawner Configuration|Position X|Range Min: SUCCESS",
|
||||
"Instance Spawner Configuration|Position X|Range Max: SUCCESS",
|
||||
"PositionModifier_AutoSnapToSurface: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"PositionModifier_AutoSnapToSurfaceWorks.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import pytest
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestRotationModifier(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
# delete temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Setup - add the teardown finalizer
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4896922")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_RotationModifier_InstancesRotateWithinRange(self, request, editor, level, launcher_platform) -> None:
|
||||
"""
|
||||
Launches editor and run test script to test that rotation modifier works for all axis.
|
||||
Manual test case: C4896922
|
||||
"""
|
||||
|
||||
expected_lines = [
|
||||
"'Spawner Entity' created",
|
||||
"'Surface Entity' created",
|
||||
"'Gradient Entity' created",
|
||||
"Entity has a Vegetation Asset List component",
|
||||
"Entity has a Vegetation Layer Spawner component",
|
||||
"Entity has a Vegetation Rotation Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"Entity has a Constant Gradient component",
|
||||
"RotationModifier_InstancesRotateWithinRange: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"RotationModifier_InstancesRotateWithinRange.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4814460")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_RotationModifierOverrides_InstancesRotateWithinRange(self, request, editor, level, launcher_platform) -> None:
|
||||
|
||||
expected_lines = [
|
||||
"'Spawner Entity' created",
|
||||
"'Surface Entity' created",
|
||||
"'Gradient Entity' created",
|
||||
"Entity has a Vegetation Layer Spawner component",
|
||||
"Entity has a Vegetation Asset List component",
|
||||
"Spawner Entity Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Entity has a Vegetation Rotation Modifier component",
|
||||
"Spawner Entity Configuration|Embedded Assets|[0]|Rotation Modifier|Override Enabled: SUCCESS",
|
||||
"Spawner Entity Configuration|Allow Per-Item Overrides: SUCCESS",
|
||||
"Entity has a Constant Gradient component",
|
||||
"Entity has a Box Shape component",
|
||||
"Spawner Entity Configuration|Rotation Z|Gradient|Gradient Entity Id: SUCCESS",
|
||||
"RotationModifierOverrides_InstancesRotateWithinRange: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"RotationModifierOverrides_InstancesRotateWithinRange.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4814462: Vegetation instances have random scale between 0.1 and 1.0 applied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestScaleOverrideWorksSuccessfully(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4814462")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_ScaleModifierOverrides_InstancesProperlyScale(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Spawner Entity' created",
|
||||
"'Surface Entity' created",
|
||||
"Entity has a Vegetation Scale Modifier component",
|
||||
"'Gradient Entity' created",
|
||||
"Scale Min and Scale Max are set to 0.1 and 1.0 in Vegetation Asset List",
|
||||
"Entity has a Random Noise Gradient component",
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"Spawner Entity Configuration|Gradient|Gradient Entity Id: SUCCESS",
|
||||
"ScaleModifierOverrides_InstancesProperlyScale: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = ["Scale Min and Scale Max are not set to 0.1 and 1.0 in Vegetation Asset List"]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"ScaleModifierOverrides_InstancesProperlyScale.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4896937")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_ScaleModifier_InstancesProperlyScale(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Spawner Entity' created",
|
||||
"Entity has a Vegetation Scale Modifier component",
|
||||
"'Surface Entity' created",
|
||||
"'Gradient Entity' created",
|
||||
"Spawner Entity Configuration|Gradient|Gradient Entity Id: SUCCESS",
|
||||
"Spawner Entity Configuration|Range Min: SUCCESS",
|
||||
"Spawner Entity Configuration|Range Max: SUCCESS",
|
||||
"ScaleModifier_InstancesProperlyScale: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"ScaleModifier_InstancesProperlyScale.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestShapeIntersectionFilter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4874094")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_ShapeIntersectionFilter_InstancesPlantInAssignedShape(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"instance count validation: True (found=49, expected=49)",
|
||||
"instance count validation: True (found=121, expected=121)",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"ShapeIntersectionFilter_InstancePlanting: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"ShapeIntersectionFilter_InstancesPlantInAssignedShape.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C4896941 - Surface Alignment functions as expected
|
||||
C4814459 - Surface Alignment overrides function as expected
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestSlopeAlignmentModifier(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C4896941")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SlopeAlignmentModifier_InstanceSurfaceAlignment(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Vegetation Slope Alignment Modifier component was added to entity",
|
||||
"Instance Spawner Configuration|Alignment Coefficient Min: SUCCESS",
|
||||
"Constant Gradient component was added to entity",
|
||||
"Instance Spawner Configuration|Gradient|Gradient Entity Id: SUCCESS",
|
||||
"SlopeAlignmentModifier: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SlopeAlignmentModifier_InstanceSurfaceAlignment.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4814459")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Instance Spawner Configuration|Allow Per-Item Overrides: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]|Surface Slope Alignment|Override Enabled: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]|Surface Slope Alignment|Max: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]|Surface Slope Alignment|Min: SUCCESS",
|
||||
"SlopeAlignmentModifierOverrides: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestSlopeFilter(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
def teardown():
|
||||
# Cleanup our temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id("C4874097")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SlopeFilter_FilterStageToggle(self, request, editor, level, workspace, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"SlopeFilter_FilterStageToggle: test started",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation plant only in the areas where the Box overlaps with the vegetation area's boundaries: True",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation plant only in the areas where the Cylinder overlaps with the vegetation area's boundaries: True",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation instances count equal to expected value for PREPROCESS filter stage: True",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation instances count equal to expected value for POSTPROCESS filter stage: True",
|
||||
"SlopeFilter_FilterStageToggle: result=SUCCESS",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"SlopeFilter_FilterStageToggle: Vegetation plant only in the areas where the Box overlaps with the vegetation area's boundaries: False",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation plant only in the areas where the Cylinder overlaps with the vegetation area's boundaries: False",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation instances count equal to expected value for PREPROCESS filter stage: False",
|
||||
"SlopeFilter_FilterStageToggle: Vegetation instances count equal to expected value for POSTPROCESS filter stage: False",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SlopeFilter_FilterStageToggle.py",
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=cfg_args
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4814464", "C4874096")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlopes(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Planting Surface' created",
|
||||
"'Sloped Planting Surface' created",
|
||||
"instance count validation: True (found=1720, expected=1720)",
|
||||
"Instance Spawner Configuration|Slope Min: SUCCESS",
|
||||
"Instance Spawner Configuration|Slope Max: SUCCESS",
|
||||
"instance count validation: True (found=44, expected=44)",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]|Slope Filter|Min: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]|Slope Filter|Max: SUCCESS",
|
||||
"instance count validation: True (found=16, expected=16)",
|
||||
"SlopeFilter_InstancesPlantOnValidSlope: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestSurfaceMaskFilter(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
# delete temp level
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Setup - add the teardown finalizer
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
# Make sure the temp level doesn't already exist
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
# Simple validation test to ensure that SurfaceTag can be created, set to a value, and compared to another SurfaceTag.
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_SurfaceMaskFilter_BasicSurfaceTagCreation(self, request, level, editor, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"SurfaceTag test started",
|
||||
"SurfaceTag equal tag comparison is True expected True",
|
||||
"SurfaceTag not equal tag comparison is False expected False",
|
||||
"SurfaceTag test finished",
|
||||
"TestSurfaceMaskFilter_BasicSurfaceTagCreation: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
'SurfaceMaskFilter_BasicSurfaceTagCreation.py',
|
||||
expected_lines=expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2561342")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SurfaceMaskFilter_ExclusiveSurfaceTags_Function(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"Instance Spawner Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]: SUCCESS",
|
||||
"'Surface Entity 1' created",
|
||||
"Surface Entity 1 Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Surface Entity 1 Configuration|Generated Tags: SUCCESS",
|
||||
"'Surface Entity 2' created",
|
||||
"Surface Entity 2 Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Surface Entity 2 Configuration|Generated Tags: SUCCESS",
|
||||
"SurfaceMaskFilter_ExclusionList: Expected 39 instances - Found 39 instances",
|
||||
"Instance Spawner Configuration|Exclusion|Weight Max: SUCCESS",
|
||||
"SurfaceMaskFilter_ExclusionList: Expected 169 instances - Found 169 instances",
|
||||
"SurfaceMaskFilter_ExclusionList: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = ["Failed to add an Exclusive surface mask filter of terrainHole"]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SurfaceMaskFilter_ExclusionList.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2561341")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SurfaceMaskFilter_InclusiveSurfaceTags_Function(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"Instance Spawner Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Instance Spawner Configuration|Embedded Assets|[0]: SUCCESS",
|
||||
"'Surface Entity 1' created",
|
||||
"Surface Entity 1 Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Surface Entity 1 Configuration|Generated Tags: SUCCESS",
|
||||
"'Surface Entity 2' created",
|
||||
"Surface Entity 2 Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||
"Surface Entity 2 Configuration|Generated Tags: SUCCESS",
|
||||
"SurfaceMaskFilter_InclusionList: Expected 130 instances - Found 130 instances",
|
||||
"Instance Spawner Configuration|Inclusion|Weight Max: SUCCESS",
|
||||
"SurfaceMaskFilter_InclusionList: Expected 0 instances - Found 0 instances",
|
||||
"SurfaceMaskFilter_InclusionList: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = ["Failed to add an Inclusive surface mask filter of terrainHole"]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SurfaceMaskFilter_InclusionList.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C3711666")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"'Instance Spawner' created",
|
||||
"'Surface Entity A' created",
|
||||
"'Surface Entity B' created",
|
||||
"'Surface Entity C' created",
|
||||
"instance count validation: True (found=725, expected=725)",
|
||||
"instance count validation: True (found=400, expected=400)",
|
||||
"instance count validation: True (found=225, expected=225)",
|
||||
"instance count validation: True (found=100, expected=100)",
|
||||
"SurfaceMaskFilter_MultipleDescriptorOverrides: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestSystemSettings(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C2646869")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SystemSettings_SectorPointDensity(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"SystemSettings_SectorPointDensity: test started",
|
||||
"SystemSettings_SectorPointDensity: Vegetation instances count equal to expected value before changing sector point density: True",
|
||||
"SystemSettings_SectorPointDensity: Vegetation instances count equal to expected value after changing sector point density: True",
|
||||
"SystemSettings_SectorPointDensity: result=SUCCESS",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"SystemSettings_SectorPointDensity: Vegetation instances count equal to expected value before changing sector point density: False",
|
||||
"SystemSettings_SectorPointDensity: Vegetation instances count equal to expected value after changing sector point density: False",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SystemSettings_SectorPointDensity.py",
|
||||
expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2646870")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_SystemSettings_SectorSize(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"SystemSettings_SectorSize: test started",
|
||||
"SystemSettings_SectorSize: Vegetation instances count equal to expected value before changing sector size: True",
|
||||
"SystemSettings_SectorSize: Vegetation instances count equal to expected value after changing sector size: True",
|
||||
"SystemSettings_SectorSize: result=SUCCESS",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"SystemSettings_SectorSize: Vegetation instances count equal to expected value before changing sector size: False",
|
||||
"SystemSettings_SectorSize: Vegetation instances count equal to expected value after changing sector size: False",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"SystemSettings_SectorSize.py",
|
||||
expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientGeneratorIncompatibilities(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientGeneratorIncompatibilities", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Verify that Entities are not active when a Gradient Generator and incompatible component are both present
|
||||
on the same Entity.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
gradient_generators = [
|
||||
'Altitude Gradient',
|
||||
'Constant Gradient',
|
||||
'FastNoise Gradient',
|
||||
'Image Gradient',
|
||||
'Perlin Noise Gradient',
|
||||
'Random Noise Gradient',
|
||||
'Shape Falloff Gradient',
|
||||
'Slope Gradient',
|
||||
'Surface Mask Gradient'
|
||||
]
|
||||
require_transform_modifiers = [
|
||||
'FastNoise Gradient',
|
||||
'Image Gradient',
|
||||
'Perlin Noise Gradient',
|
||||
'Random Noise Gradient'
|
||||
]
|
||||
vegetation_areas = [
|
||||
'Vegetation Layer Spawner',
|
||||
'Vegetation Layer Blender',
|
||||
'Vegetation Layer Blocker',
|
||||
'Vegetation Layer Blocker (Mesh)'
|
||||
]
|
||||
area_dependencies = {
|
||||
'Vegetation Layer Spawner': 'Vegetation Asset List',
|
||||
'Vegetation Layer Blocker (Mesh)': 'Mesh'
|
||||
}
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# For every gradient generator component, verify that they are incompatible
|
||||
# which each vegetation area component
|
||||
for component_name in gradient_generators:
|
||||
for vegetation_area_name in vegetation_areas:
|
||||
# Create a new Entity in the level
|
||||
entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
# Most of these need a shape, so use a Box Shape
|
||||
hydra.add_component('Box Shape', entity_id)
|
||||
|
||||
# Add the specific vegetation area dependencies (if necessary)
|
||||
if vegetation_area_name in area_dependencies:
|
||||
hydra.add_component(area_dependencies[vegetation_area_name], entity_id)
|
||||
|
||||
# Add the vegetation area component we are validating against, then add the
|
||||
# gradient generator afterwards, so that the gradient generator will actually
|
||||
# be disabled (if it was present before, it would only get deactivated instead of disabled
|
||||
# by the vegetation area)
|
||||
area_component = hydra.add_component(vegetation_area_name, entity_id)
|
||||
gradient_component = hydra.add_component(component_name, entity_id)
|
||||
|
||||
# Verify the gradient generator component is disabled since the vegetation area is incompatible
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and not active
|
||||
if not active:
|
||||
self.log(f"{component_name} is disabled before removing {vegetation_area_name} component")
|
||||
|
||||
# Remove the vegetation area component
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
|
||||
|
||||
# Add required dependencies for our gradient generators after the vegetation
|
||||
# area has been removed, because the transform modifier is also incompatible
|
||||
# with the vegetation areas
|
||||
if component_name in require_transform_modifiers:
|
||||
hydra.add_component('Gradient Transform Modifier', entity_id)
|
||||
|
||||
# Verify the gradient generator component is enabled now that the vegetation area is gone
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and active
|
||||
if active:
|
||||
self.log(f"{component_name} is enabled after removing {vegetation_area_name} component")
|
||||
|
||||
|
||||
test = TestGradientGeneratorIncompatibilities()
|
||||
test.run()
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientModifiersIncompatibilities(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientModifiersIncompatibilities", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Verify that Entities are not active when a Gradient Modifier and incompatible component are both present
|
||||
on the same Entity.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
gradient_generators = [
|
||||
'Altitude Gradient',
|
||||
'Constant Gradient',
|
||||
'FastNoise Gradient',
|
||||
'Image Gradient',
|
||||
'Perlin Noise Gradient',
|
||||
'Random Noise Gradient',
|
||||
'Shape Falloff Gradient',
|
||||
'Slope Gradient',
|
||||
'Surface Mask Gradient'
|
||||
]
|
||||
require_transform_modifiers = [
|
||||
'FastNoise Gradient',
|
||||
'Image Gradient',
|
||||
'Perlin Noise Gradient',
|
||||
'Random Noise Gradient'
|
||||
]
|
||||
gradient_modifiers = [
|
||||
'Dither Gradient Modifier',
|
||||
'Gradient Mixer',
|
||||
'Invert Gradient Modifier',
|
||||
'Levels Gradient Modifier',
|
||||
'Posterize Gradient Modifier',
|
||||
'Smooth-Step Gradient Modifier',
|
||||
'Threshold Gradient Modifier'
|
||||
]
|
||||
vegetation_areas = [
|
||||
'Vegetation Layer Spawner',
|
||||
'Vegetation Layer Blender',
|
||||
'Vegetation Layer Blocker',
|
||||
'Vegetation Layer Blocker (Mesh)'
|
||||
]
|
||||
area_dependencies = {
|
||||
'Vegetation Layer Spawner': 'Vegetation Asset List',
|
||||
'Vegetation Layer Blocker (Mesh)': 'Mesh'
|
||||
}
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# For every gradient modifier component, verify that they are incompatible
|
||||
# which each vegetation area and gradient generator/modifier component
|
||||
all_gradients = gradient_modifiers + gradient_generators
|
||||
for component_name in gradient_modifiers:
|
||||
for vegetation_area_name in vegetation_areas:
|
||||
# Create a new Entity in the level
|
||||
entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
# Most of these need a shape, so use a Box Shape
|
||||
hydra.add_component('Box Shape', entity_id)
|
||||
|
||||
# Add the specific vegetation area dependencies (if necessary)
|
||||
if vegetation_area_name in area_dependencies:
|
||||
hydra.add_component(area_dependencies[vegetation_area_name], entity_id)
|
||||
|
||||
# Add the vegetation area component we are validating against, then add the
|
||||
# gradient modifier afterwards, so that the gradient modifier will actually
|
||||
# be disabled (if it was present before, it would only get deactivated instead of disabled
|
||||
# by the vegetation area)
|
||||
area_component = hydra.add_component(vegetation_area_name, entity_id)
|
||||
gradient_component = hydra.add_component(component_name, entity_id)
|
||||
|
||||
# Verify the gradient modifier component is disabled since the vegetation area is incompatible
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and not active
|
||||
if not active:
|
||||
self.log("{gradient} is disabled before removing {vegetation_area} component".format(gradient=component_name, vegetation_area=vegetation_area_name))
|
||||
|
||||
# Remove the vegetation area component
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
|
||||
|
||||
# Verify the gradient modifier component is enabled now that the vegetation area is gone
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and active
|
||||
if active:
|
||||
self.log("{gradient} is enabled after removing {vegetation_area} component".format(gradient=component_name, vegetation_area=vegetation_area_name))
|
||||
|
||||
for gradient_name in all_gradients:
|
||||
# Create a new Entity in the level
|
||||
entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
# Most of these need a shape, so use a Box Shape
|
||||
hydra.add_component('Box Shape', entity_id)
|
||||
|
||||
# Add the specific gradient generator dependencies (if necessary)
|
||||
conflicting_components = []
|
||||
if gradient_name in require_transform_modifiers:
|
||||
component = hydra.add_component('Gradient Transform Modifier', entity_id)
|
||||
conflicting_components.append(component)
|
||||
|
||||
# Add the gradient component we are validating against, then add the
|
||||
# gradient modifier afterwards, so that the gradient modifier will actually
|
||||
# be disabled (if it was present before, it would only get deactivated instead of disabled
|
||||
# by the other gradient)
|
||||
component = hydra.add_component(gradient_name, entity_id)
|
||||
conflicting_components.append(component)
|
||||
gradient_component = hydra.add_component(component_name, entity_id)
|
||||
|
||||
# Verify the gradient modifier component is disabled since the other gradient is incompatible
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and not active
|
||||
if not active:
|
||||
self.log("{gradient} is disabled before removing {conflicting_gradient} component".format(gradient=component_name, conflicting_gradient=gradient_name))
|
||||
|
||||
# Remove the conflicting gradient component (and transform modifier if it was added)
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', conflicting_components)
|
||||
|
||||
# Verify the gradient modifier component is enabled now that the other gradient is gone
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
|
||||
self.test_success = self.test_success and active
|
||||
if active:
|
||||
self.log("{gradient} is enabled after removing {conflicting_gradient} component".format(gradient=component_name, conflicting_gradient=gradient_name))
|
||||
|
||||
|
||||
test = TestGradientModifiersIncompatibilities()
|
||||
test.run()
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
The below cases are combined in this script
|
||||
C2676829
|
||||
C3961326
|
||||
C3980659
|
||||
C3980664
|
||||
C3980669
|
||||
C3416548
|
||||
C2676823
|
||||
C3961321
|
||||
C2676826
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.entity as EntityId
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientPreviewSettings(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientPreviewSettings_ClearPinnedEntity", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A temporary level is created. An entity for each test case is created and added with the corresponding
|
||||
components to verify if the gradient transform is set to the world origin.
|
||||
|
||||
Expected Behavior:
|
||||
1) Preview image updates to reflect change in transform of the gradient sampler.
|
||||
2) New Preview Position property is exposed, and set to 0,0,0 (world origin).
|
||||
3) Preview Size is set to 1,1,1 by default.
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create entity with Random Noise gradient and verify gradient position after clearing pinned entity
|
||||
3) Create entity with Levels Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
4) Create entity with Posterize Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
5) Create entity with Smooth-Step Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
6) Create entity with Threshold Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
7) Create entity with FastNoise Gradient and verify gradient position after clearing pinned entity
|
||||
8) Create entity with Dither Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
9) Create entity with Invert Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
10) Create entity with Perlin Noise Gradient and verify gradient position after clearing pinned entity
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
WORLD_ORIGIN = math.Vector3(0.0, 0.0, 0.0)
|
||||
EXPECTED_SIZE = math.Vector3(1.0, 1.0, 1.0)
|
||||
CLOSE_THRESHOLD = sys.float_info.min
|
||||
|
||||
def create_entity(enity_name, components_to_add):
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
entity_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
entity = hydra.Entity(enity_name, entity_id)
|
||||
if entity_id.IsValid():
|
||||
print(f"{enity_name} entity Created")
|
||||
entity.components = []
|
||||
for component in components_to_add:
|
||||
entity.components.append(hydra.add_component(component, entity_id))
|
||||
return entity
|
||||
|
||||
def clear_entityid_check_position(entity_name, components_to_add, check_preview_size=False):
|
||||
entity = create_entity(entity_name, components_to_add)
|
||||
hydra.get_set_test(entity, 0, "Preview Settings|Pin Preview to Shape", EntityId.EntityId())
|
||||
preview_position = hydra.get_component_property_value(
|
||||
entity.components[0], "Preview Settings|Preview Position"
|
||||
)
|
||||
if preview_position.IsClose(WORLD_ORIGIN, CLOSE_THRESHOLD):
|
||||
print(f"{entity_name} --- Preview Position set to world origin")
|
||||
if check_preview_size:
|
||||
preview_size = hydra.get_component_property_value(entity.components[0], "Preview Settings|Preview Size")
|
||||
if preview_size.IsClose(EXPECTED_SIZE, CLOSE_THRESHOLD):
|
||||
print(f"{entity_name} --- Preview Size set to (1, 1, 1)")
|
||||
return entity
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create entity with Random Noise gradient and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position(
|
||||
"Random Noise Gradient", ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"], True
|
||||
)
|
||||
|
||||
# 3) Create entity with Levels Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Levels Gradient Modifier", ["Levels Gradient Modifier"])
|
||||
|
||||
# 4) Create entity with Posterize Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Posterize Gradient Modifier", ["Posterize Gradient Modifier"])
|
||||
|
||||
# 5) Create entity with Smooth-Step Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Smooth-Step Gradient Modifier", ["Smooth-Step Gradient Modifier"])
|
||||
|
||||
# 6) Create entity with Threshold Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Threshold Gradient Modifier", ["Threshold Gradient Modifier"])
|
||||
|
||||
# 7) Create entity with FastNoise Gradient and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position(
|
||||
"FastNoise Gradient", ["FastNoise Gradient", "Gradient Transform Modifier", "Box Shape"], True
|
||||
)
|
||||
|
||||
# 8) Create entity with Dither Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Dither Gradient Modifier", ["Dither Gradient Modifier"], True)
|
||||
|
||||
# 9) Create entity with Invert Gradient Modifier and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position("Invert Gradient Modifier", ["Invert Gradient Modifier"])
|
||||
|
||||
# 10) Create entity with Perlin Noise Gradient and verify gradient position after clearing pinned entity
|
||||
clear_entityid_check_position(
|
||||
"Perlin Noise Gradient", ["Perlin Noise Gradient", "Gradient Transform Modifier", "Box Shape"], True
|
||||
)
|
||||
|
||||
|
||||
test = TestGradientPreviewSettings()
|
||||
test.run()
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class Scoped:
|
||||
def __init__(self, constructor, destructor, *args):
|
||||
self.data = constructor(*args)
|
||||
self.destructor = destructor
|
||||
|
||||
def __del__(self):
|
||||
self.destructor(self.data)
|
||||
|
||||
|
||||
class TestParams:
|
||||
def __init__(self, required_components, accessed_component):
|
||||
self.required_components = required_components
|
||||
self.accessed_component = accessed_component
|
||||
|
||||
|
||||
class TestGradientPreviewSettings(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientPreviewSettings_DefaultPinnedEntity", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Verify if the current entity is set to the pin preview to shape entity by default for several components.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def execute_test(test_id, function, *args):
|
||||
if function(*args):
|
||||
self.log(test_id + ' has Preview pinned to own Entity result: SUCCESS')
|
||||
|
||||
def create_entity():
|
||||
return editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
def delete_entity(entity_id):
|
||||
editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityAndAllDescendants', entity_id)
|
||||
|
||||
def attach_components(component_list, entity_id):
|
||||
components = []
|
||||
for i in component_list:
|
||||
components.append(hydra.add_component(i, entity_id))
|
||||
return components
|
||||
|
||||
def validate_id_is_current(param):
|
||||
entity_ptr = Scoped(create_entity, delete_entity)
|
||||
added_components = attach_components(param.required_components, entity_ptr.data)
|
||||
value = hydra.get_component_property_value(added_components[param.accessed_component],
|
||||
'Preview Settings|Pin Preview to Shape')
|
||||
self.test_success = self.test_success and entity_ptr.data.Equal(value)
|
||||
return entity_ptr.data.Equal(value)
|
||||
|
||||
param_list = [
|
||||
TestParams(['Gradient Transform Modifier', 'Box Shape', 'Perlin Noise Gradient'], 2),
|
||||
TestParams(['Random Noise Gradient', 'Gradient Transform Modifier', 'Box Shape'], 0),
|
||||
TestParams(['FastNoise Gradient', 'Gradient Transform Modifier', 'Box Shape'], 0),
|
||||
TestParams(['Dither Gradient Modifier'], 0),
|
||||
TestParams(['Invert Gradient Modifier'], 0),
|
||||
TestParams(['Levels Gradient Modifier'], 0),
|
||||
TestParams(['Posterize Gradient Modifier'], 0),
|
||||
TestParams(['Smooth-Step Gradient Modifier'], 0),
|
||||
TestParams(['Threshold Gradient Modifier'], 0)
|
||||
]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
for param in param_list:
|
||||
execute_test(param.required_components[param.accessed_component],
|
||||
validate_id_is_current, param)
|
||||
|
||||
|
||||
test = TestGradientPreviewSettings()
|
||||
test.run()
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.entity as EntityId
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientSampling(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientSampling_GradientReferences", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
An existing gradient generator can be pinned and cleared to/from the Gradient Entity Id field
|
||||
|
||||
Expected Behavior:
|
||||
Gradient generator is assigned to the Gradient Entity Id field.
|
||||
Gradient generator is removed from the field.
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create a new entity with components "Random Noise Gradient", "Gradient Transform Modifier" and "Box Shape"
|
||||
3) Create a new entity with Gradient Modifier's, pin and clear the random noise entity id to the Gradient Id
|
||||
field in Gradient Modifier
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
def modifier_pin_clear_to_gradiententityid(modifier):
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
component_to_add = [modifier]
|
||||
gradient_modifier = hydra.Entity(modifier)
|
||||
gradient_modifier.create_entity(entity_position, component_to_add)
|
||||
gradient_modifier.get_set_test(0, "Configuration|Gradient|Gradient Entity Id", random_noise.id)
|
||||
entity = hydra.get_component_property_value(
|
||||
gradient_modifier.components[0], "Configuration|Gradient|Gradient Entity Id"
|
||||
)
|
||||
if entity.Equal(random_noise.id):
|
||||
print(f"Gradient Generator is pinned to the {modifier} successfully")
|
||||
else:
|
||||
print(f"Failed to pin Gradient Generator to the {modifier}")
|
||||
hydra.get_set_test(gradient_modifier, 0, "Configuration|Gradient|Gradient Entity Id", EntityId.EntityId())
|
||||
entity = hydra.get_component_property_value(
|
||||
gradient_modifier.components[0], "Configuration|Gradient|Gradient Entity Id"
|
||||
)
|
||||
if entity.Equal(EntityId.EntityId()):
|
||||
print(f"Gradient Generator is cleared from the {modifier} successfully")
|
||||
else:
|
||||
print(f"Failed to clear Gradient Generator from the {modifier}")
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with components "Random Noise Gradient", "Gradient Transform Modifier" and "Box Shape"
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
components_to_add = ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"]
|
||||
random_noise = hydra.Entity("Random_Noise")
|
||||
random_noise.create_entity(entity_position, components_to_add)
|
||||
|
||||
# 3) Create a new entity with Gradient Modifier's, pin and clear the random noise entity id to the Gradient Id
|
||||
# field in Gradient Modifier
|
||||
modifier_pin_clear_to_gradiententityid("Dither Gradient Modifier")
|
||||
modifier_pin_clear_to_gradiententityid("Invert Gradient Modifier")
|
||||
modifier_pin_clear_to_gradiententityid("Levels Gradient Modifier")
|
||||
modifier_pin_clear_to_gradiententityid("Posterize Gradient Modifier")
|
||||
modifier_pin_clear_to_gradiententityid("Smooth-Step Gradient Modifier")
|
||||
modifier_pin_clear_to_gradiententityid("Threshold Gradient Modifier")
|
||||
|
||||
|
||||
test = TestGradientSampling()
|
||||
test.run()
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.math as math
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(
|
||||
self, log_prefix="GradientSurfaceTagEmitter_ComponentDependencies", args=["level"]
|
||||
)
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Component has a dependency on a Gradient component
|
||||
|
||||
Expected Result:
|
||||
Component is disabled until a Gradient Generator, Modifier or Gradient Reference component
|
||||
(and any sub-dependencies) is added to the entity.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def is_enabled(EntityComponentIdPair):
|
||||
return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
|
||||
|
||||
# Create empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create an entity with Gradient Surface Tag Emitter component
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
gradient = hydra.Entity("gradient")
|
||||
gradient.create_entity(position, ["Gradient Surface Tag Emitter"])
|
||||
|
||||
# Make sure Gradient Surface Tag Emitter is disabled
|
||||
is_enable = is_enabled(gradient.components[0])
|
||||
if not is_enable:
|
||||
self.log("Gradient Surface Tag Emitter is Disabled")
|
||||
elif not is_enable:
|
||||
self.log("Gradient Surface Tag Emitter is Enabled, but should be Disabled without dependencies met")
|
||||
|
||||
# Verify Gradient Surface Tag Emitter component is enabled after adding Gradient, Generator, Modifier
|
||||
# or Reference component
|
||||
new_components_to_add = [
|
||||
"Dither Gradient Modifier",
|
||||
"Gradient Mixer",
|
||||
"Invert Gradient Modifier",
|
||||
"Levels Gradient Modifier",
|
||||
"Posterize Gradient Modifier",
|
||||
"Smooth-Step Gradient Modifier",
|
||||
"Threshold Gradient Modifier",
|
||||
"Altitude Gradient",
|
||||
"Constant Gradient",
|
||||
"FastNoise Gradient",
|
||||
"Image Gradient",
|
||||
"Perlin Noise Gradient",
|
||||
"Random Noise Gradient",
|
||||
"Reference Gradient",
|
||||
"Shape Falloff Gradient",
|
||||
"Slope Gradient",
|
||||
"Surface Mask Gradient",
|
||||
]
|
||||
for component in new_components_to_add:
|
||||
component_list = ["FastNoise Gradient", "Image Gradient", "Perlin Noise Gradient", "Random Noise Gradient"]
|
||||
if component in component_list:
|
||||
for Component in ["Gradient Transform Modifier", "Box Shape"]:
|
||||
hydra.add_component(Component, gradient.id)
|
||||
typeIdsList = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', [component],
|
||||
entity.EntityType().Game)
|
||||
ComponentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', gradient.id, [typeIdsList[0]])
|
||||
Components = ComponentOutcome.GetValue()
|
||||
ComponentIdPair = Components[0]
|
||||
gradient_enabled = new_components_enabled = False
|
||||
gradient_enabled = is_enabled(gradient.components[0])
|
||||
new_components_enabled = is_enabled(ComponentIdPair)
|
||||
if new_components_enabled and gradient_enabled:
|
||||
self.log(f"{component} and Gradient Surface Tag Emitter are enabled")
|
||||
else:
|
||||
self.log(f"{component} and Gradient Surface Tag Emitter are disabled")
|
||||
if component in component_list:
|
||||
hydra.remove_component("Gradient Transform Modifier", gradient.id)
|
||||
hydra.remove_component("Box Shape", gradient.id)
|
||||
hydra.remove_component(component, gradient.id)
|
||||
|
||||
|
||||
test = TestGradientSurfaceTagEmitterDependencies()
|
||||
test.run()
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.surface_data as surface_data
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientSurfaceTagEmitter(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSucessfully",
|
||||
args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Entity with Gradient Surface Tag Emitter and Reference Gradient components is created.
|
||||
And new surface tag has been added and removed.
|
||||
|
||||
Expected Behavior:
|
||||
A new Surface Tag can be added and removed from the component
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create an entity with Gradient Surface Tag Emitter and Reference Gradient components.
|
||||
3) Add/ remove Surface Tags
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create an entity with Gradient Surface Tag Emitter and Reference Gradient components.
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
components_to_add = ["Gradient Surface Tag Emitter", "Reference Gradient"]
|
||||
entity = hydra.Entity("entity")
|
||||
entity.create_entity(entity_position, components_to_add)
|
||||
|
||||
# 3) Add/ remove Surface Tags
|
||||
tag = surface_data.SurfaceTag()
|
||||
tag.SetTag("water")
|
||||
pte = hydra.get_property_tree(entity.components[0])
|
||||
path = "Configuration|Extended Tags"
|
||||
pte.add_container_item(path, 0, tag)
|
||||
success = self.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 1)
|
||||
self.test_success = self.test_success and success
|
||||
print(f"Added SurfaceTag: container count is {pte.get_container_count(path).GetValue()}")
|
||||
pte.remove_container_item(path, 0)
|
||||
success = self.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 0)
|
||||
self.test_success = self.test_success and success
|
||||
print(f"Removed SurfaceTag: container count is {pte.get_container_count(path).GetValue()}")
|
||||
|
||||
|
||||
test = TestGradientSurfaceTagEmitter()
|
||||
test.run()
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.entity as EntityId
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientTransform_ComponentIncompatibleWithExpectedGradients(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientTransform_ComponentIncompatibleWithExpectedGradients",
|
||||
args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A New level is created. A New entity is created with components Gradient Transform Modifier and Box Shape.
|
||||
Adding components Constant Gradient, Altitude Gradient, Gradient Mixer, Reference Gradient, Shape
|
||||
Falloff Gradient, Slope Gradient and Surface Mask Gradient to the same entity.
|
||||
|
||||
Expected Behavior:
|
||||
All added components are disabled and inform the user that they are incompatible with the Gradient Transform
|
||||
Modifier
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a new entity with components Gradient Transform Modifier and Box Shape
|
||||
3) Make sure all components are enabled in Entity
|
||||
4) Add Constant Gradient, Altitude Gradient, Gradient Mixer, Reference Gradient, Shape
|
||||
Falloff Gradient, Slope Gradient and Surface Mask Gradient to the same entity
|
||||
5) Make sure all newly added components are disabled
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
def is_enabled(EntityComponentIdPair):
|
||||
return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with components Gradient Transform Modifier and Box Shape
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
components_to_add = ["Gradient Transform Modifier", "Box Shape"]
|
||||
gradient_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
gradient = hydra.Entity("gradient", gradient_id)
|
||||
|
||||
gradient.components = []
|
||||
|
||||
for component in components_to_add:
|
||||
gradient.components.append(hydra.add_component(component, gradient_id))
|
||||
if gradient_id.isValid():
|
||||
self.log("New Entity Created")
|
||||
|
||||
# 3) Make sure all components are enabled in Entity
|
||||
index = 0
|
||||
for component in components_to_add:
|
||||
is_enable = is_enabled(gradient.components[index])
|
||||
if is_enable:
|
||||
self.log(f"{component} is Enabled")
|
||||
self.test_success = self.test_success and is_enable
|
||||
elif not is_enable:
|
||||
self.log(f"{component} is disabled, but it should be enabled")
|
||||
self.test_success = self.test_success and is_enable
|
||||
break
|
||||
index += 1
|
||||
|
||||
# 4) Add Constant Gradient, Altitude Gradient, Gradient Mixer, Reference Gradient, Shape
|
||||
# Falloff Gradient, Slope Gradient and Surface Mask Gradient to the same entity
|
||||
new_components_to_add = [
|
||||
"Constant Gradient",
|
||||
"Altitude Gradient",
|
||||
"Gradient Mixer",
|
||||
"Reference Gradient",
|
||||
"Shape Falloff Gradient",
|
||||
"Slope Gradient",
|
||||
"Surface Mask Gradient",
|
||||
]
|
||||
index = 2
|
||||
new_components_enabled = False
|
||||
for component in new_components_to_add:
|
||||
gradient.components.append(hydra.add_component(component, gradient_id))
|
||||
new_components_enabled = is_enabled(gradient.components[index])
|
||||
if new_components_enabled:
|
||||
self.log(f"{component} is enabled, but should be disabled")
|
||||
break
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", component)
|
||||
|
||||
# 5) Make sure all newly added components are disabled
|
||||
if not new_components_enabled:
|
||||
self.log("All newly added components are incompatible and disabled")
|
||||
self.test_success = self.test_success and not new_components_enabled
|
||||
|
||||
|
||||
test = TestGradientTransform_ComponentIncompatibleWithExpectedGradients()
|
||||
test.run()
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.entity as EntityId
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientTransform_ComponentIncompatibleWithSpawners(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientTransform_ComponentIncompatibleWithSpawners",
|
||||
args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
A New level is created. A New entity is created with components Gradient Transform Modifier and Box Shape.
|
||||
Adding a component Vegetation Layer Spawner to the same entity.
|
||||
|
||||
Expected Behavior:
|
||||
The Vegetation Layer Spawner is deactivated and it is communicated that it is incompatible with Gradient
|
||||
Transform Modifier
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create a new entity with components Gradient Transform Modifier and Box Shape
|
||||
3) Make sure all components are enabled in Entity
|
||||
4) Add Vegetation Layer Spawner to the same entity
|
||||
5) Make sure newly added component is disabled
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
def is_enabled(EntityComponentIdPair):
|
||||
return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create a new entity with components Gradient Transform Modifier and Box Shape
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
components_to_add = ["Gradient Transform Modifier", "Box Shape"]
|
||||
gradient_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
gradient = hydra.Entity("gradient", gradient_id)
|
||||
|
||||
gradient.components = []
|
||||
|
||||
for component in components_to_add:
|
||||
gradient.components.append(hydra.add_component(component, gradient_id))
|
||||
if gradient_id.isValid():
|
||||
self.log("New Entity Created")
|
||||
|
||||
# 3) Make sure all components are enabled in Entity
|
||||
index = 0
|
||||
for component in components_to_add:
|
||||
is_enable = is_enabled(gradient.components[index])
|
||||
if is_enable:
|
||||
self.log(f"{component} is Enabled")
|
||||
self.test_success = self.test_success and is_enable
|
||||
elif not is_enable:
|
||||
self.log(f"{component} is Disabled. But It should be Enabled in an Entity")
|
||||
self.test_success = self.test_success and is_enable
|
||||
break
|
||||
index += 1
|
||||
|
||||
# 4) Add Vegetation Layer Spawner to the same entity
|
||||
new_component_to_add = "Vegetation Layer Spawner"
|
||||
index = 2
|
||||
gradient.components.append(hydra.add_component(new_component_to_add, gradient_id))
|
||||
new_component_enabled = is_enabled(gradient.components[index])
|
||||
|
||||
# 5) Make sure newly added component is disabled
|
||||
if not new_component_enabled:
|
||||
self.log(f"{new_component_to_add} is incompatible and disabled")
|
||||
self.test_success = self.test_success and not new_component_enabled
|
||||
elif new_component_enabled:
|
||||
self.log(f"{new_component_to_add} is compatible and enabled. But It should be Incompatible and disabled")
|
||||
self.test_success = self.test_success and new_component_enabled
|
||||
|
||||
|
||||
test = TestGradientTransform_ComponentIncompatibleWithSpawners()
|
||||
test.run()
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C3430292: Frequency Zoom can manually be set higher than 8.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.entity as EntityId
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientTransformFrequencyZoom(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientTransform_FrequencyZoomBeyondSliders", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Frequency Zoom can manually be set higher than 8 in a random noise gradient
|
||||
|
||||
Expected Behavior:
|
||||
The value properly changes, despite the value being outside of the slider limit
|
||||
|
||||
Test Steps:
|
||||
1) Open level
|
||||
2) Create entity
|
||||
3) Add components to the entity
|
||||
4) Set the frequency value of the component
|
||||
5) Verify if the frequency value is set to higher value
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Open level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create entity
|
||||
entity_position = math.Vector3(125.0, 136.0, 32.0)
|
||||
entity_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
if entity_id.IsValid():
|
||||
print("Entity Created")
|
||||
|
||||
# 3) Add components to the entity
|
||||
components_to_add = ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"]
|
||||
entity = hydra.Entity("entity", entity_id)
|
||||
entity.components = []
|
||||
for component in components_to_add:
|
||||
entity.components.append(hydra.add_component(component, entity_id))
|
||||
print("Components added to the entity")
|
||||
|
||||
# 4) Set the frequency value of the component
|
||||
hydra.get_set_test(entity, 1, "Configuration|Frequency Zoom", 10)
|
||||
|
||||
# 5) Verify if the frequency value is set to higher value
|
||||
curr_value = hydra.get_component_property_value(entity.components[1], "Configuration|Frequency Zoom")
|
||||
if curr_value == 10.0:
|
||||
print("Frequency Zoom is equal to expected value")
|
||||
else:
|
||||
print("Frequency Zoom is not equal to expected value")
|
||||
|
||||
|
||||
test = TestGradientTransformFrequencyZoom()
|
||||
test.run()
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestGradientTransformRequiresShape(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientTransformRequiresShape", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Verify that Gradient Transform Modifier component requires a
|
||||
Shape component before the Entity can become active.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create a new Entity in the level
|
||||
entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
# Add a Gradient Transform Component (that will be disabled since there is no shape on the Entity)
|
||||
gradient_transform_component = hydra.add_component('Gradient Transform Modifier', entity_id)
|
||||
|
||||
# Verify the Gradient Transform Component is not active before adding the Shape
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_transform_component)
|
||||
self.test_success = self.test_success and not active
|
||||
if not active:
|
||||
self.log("Gradient Transform component is not active without a Shape component on the Entity")
|
||||
|
||||
# Add a Shape component to the same Entity
|
||||
hydra.add_component('Box Shape', entity_id)
|
||||
|
||||
# Check if the Gradient Transform Component is active now after adding the Shape
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_transform_component)
|
||||
self.test_success = self.test_success and active
|
||||
if active:
|
||||
self.log("Gradient Transform Modifier component is active now that the Entity has a Shape")
|
||||
|
||||
|
||||
test = TestGradientTransformRequiresShape()
|
||||
test.run()
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestImageGradient(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ImageGradient_ProcessedImageAssignedSucessfully",
|
||||
args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Level created with Entity having Image Gradient and Gradient Transform Modifier components.
|
||||
Save any new image to your workspace with the suffix "_gsi" and assign as image asset.
|
||||
|
||||
Expected Behavior:
|
||||
Image can be assigned as the Image Asset for the Image as Gradient component.
|
||||
|
||||
Test Steps:
|
||||
1) Create level
|
||||
2) Create an entity with Image Gradient and Gradient Transform Modifier components.
|
||||
3) Assign the newly processed gradient image as Image asset.
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Lumberyard 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
|
||||
"""
|
||||
|
||||
# 1) Create level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# 2) Create an entity with Image Gradient and Gradient Transform Modifier components
|
||||
components_to_add = ["Image Gradient", "Gradient Transform Modifier", "Box Shape"]
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
new_entity_id = editor.ToolsApplicationRequestBus(
|
||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
||||
)
|
||||
if new_entity_id.IsValid():
|
||||
print("Image Gradient Entity created")
|
||||
image_gradient_entity = hydra.Entity("Image Gradient Entity", new_entity_id)
|
||||
image_gradient_entity.components = []
|
||||
for component in components_to_add:
|
||||
image_gradient_entity.add_component(component)
|
||||
|
||||
# 3) Assign the processed gradient signal image as the Image Gradient's image asset and verify success
|
||||
|
||||
# First, check for the base image in the workspace
|
||||
base_image = "lumberyard_gsi.png"
|
||||
base_image_path = os.path.join("AutomatedTesting", "Assets", "ImageGradients", base_image)
|
||||
if os.path.isfile(base_image_path):
|
||||
print(f"{base_image} was found in the workspace")
|
||||
|
||||
# Next, assign the processed image to the Image Gradient's Image Asset property
|
||||
processed_image_path = os.path.join("Assets", "ImageGradients", "lumberyard_gsi.gradimage")
|
||||
asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", processed_image_path, math.Uuid(),
|
||||
False)
|
||||
hydra.get_set_test(image_gradient_entity, 0, "Configuration|Image Asset", asset_id)
|
||||
|
||||
# Finally, verify if the gradient image is assigned as the Image Asset
|
||||
success = hydra.get_component_property_value(image_gradient_entity.components[0], "Configuration|Image Asset") == asset_id
|
||||
self.test_success = self.test_success and success
|
||||
|
||||
|
||||
test = TestImageGradient()
|
||||
test.run()
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestImageGradientRequiresShape(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ImageGradientRequiresShape", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
Summary:
|
||||
Verify that Image Gradient component requires a
|
||||
Shape component before the Entity can become active.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Create a new Entity in the level
|
||||
entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
|
||||
|
||||
# Add an Image Gradient and Gradient Transform Component (should be disabled until a Shape exists on the Entity)
|
||||
image_gradient_component = hydra.add_component('Image Gradient', entity_id)
|
||||
hydra.add_component('Gradient Transform Modifier', entity_id)
|
||||
|
||||
# Verify the Image Gradient Component is not active before adding the Shape
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', image_gradient_component)
|
||||
self.test_success = self.test_success and not active
|
||||
if not active:
|
||||
self.log("Image Gradient component is not active without a Shape component on the Entity")
|
||||
|
||||
# Add a Shape component to the same Entity
|
||||
hydra.add_component('Box Shape', entity_id)
|
||||
|
||||
# Check if the Image Gradient Component is active now after adding the Shape
|
||||
active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', image_gradient_component)
|
||||
self.test_success = self.test_success and active
|
||||
if active:
|
||||
self.log("Image Gradient component is active now that the Entity has a Shape")
|
||||
|
||||
|
||||
test = TestImageGradientRequiresShape()
|
||||
test.run()
|
||||
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
Tests that the Gradient Generator components are incompatible with Vegetation Area components
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
pytest.importorskip('ly_test_tools')
|
||||
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
gradient_generators = [
|
||||
'Altitude Gradient',
|
||||
'Constant Gradient',
|
||||
'FastNoise Gradient',
|
||||
'Image Gradient',
|
||||
'Perlin Noise Gradient',
|
||||
'Random Noise Gradient',
|
||||
'Shape Falloff Gradient',
|
||||
'Slope Gradient',
|
||||
'Surface Mask Gradient'
|
||||
]
|
||||
|
||||
gradient_modifiers = [
|
||||
'Dither Gradient Modifier',
|
||||
'Gradient Mixer',
|
||||
'Invert Gradient Modifier',
|
||||
'Levels Gradient Modifier',
|
||||
'Posterize Gradient Modifier',
|
||||
'Smooth-Step Gradient Modifier',
|
||||
'Threshold Gradient Modifier'
|
||||
]
|
||||
|
||||
vegetation_areas = [
|
||||
'Vegetation Layer Spawner',
|
||||
'Vegetation Layer Blender',
|
||||
'Vegetation Layer Blocker',
|
||||
'Vegetation Layer Blocker (Mesh)'
|
||||
]
|
||||
|
||||
all_gradients = gradient_modifiers + gradient_generators
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestGradientIncompatibilities(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id('C2691648', 'C2691649', 'C2691650', 'C2691651',
|
||||
'C2691653', 'C2691656', 'C2691657', 'C2691658',
|
||||
'C2691647', 'C2691655')
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientGenerators_Incompatibilities(self, request, editor, level, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = []
|
||||
for gradient_generator in gradient_generators:
|
||||
for vegetation_area in vegetation_areas:
|
||||
expected_lines.append(f"{gradient_generator} is disabled before removing {vegetation_area} component")
|
||||
expected_lines.append(f"{gradient_generator} is enabled after removing {vegetation_area} component")
|
||||
expected_lines.append("GradientGeneratorIncompatibilities: result=SUCCESS")
|
||||
hydra.launch_and_validate_results(request, test_directory, editor,
|
||||
'GradientGenerators_Incompatibilities.py',
|
||||
expected_lines=expected_lines, cfg_args=cfg_args)
|
||||
|
||||
@pytest.mark.test_case_id('C3416464', 'C3416546', 'C3961318', 'C3961319',
|
||||
'C3961323', 'C3961324', 'C3980656', 'C3980657',
|
||||
'C3980661', 'C3980662', 'C3980666', 'C3980667',
|
||||
'C2691652')
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientModifiers_Incompatibilities(self, request, editor, level, launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = []
|
||||
for gradient_modifier in gradient_modifiers:
|
||||
for vegetation_area in vegetation_areas:
|
||||
expected_lines.append(f"{gradient_modifier} is disabled before removing {vegetation_area} component")
|
||||
expected_lines.append(f"{gradient_modifier} is enabled after removing {vegetation_area} component")
|
||||
|
||||
for conflicting_gradient in all_gradients:
|
||||
expected_lines.append(f"{gradient_modifier} is disabled before removing {conflicting_gradient} component")
|
||||
expected_lines.append(f"{gradient_modifier} is enabled after removing {conflicting_gradient} component")
|
||||
expected_lines.append("GradientModifiersIncompatibilities: result=SUCCESS")
|
||||
hydra.launch_and_validate_results(request, test_directory, editor,
|
||||
'GradientModifiers_Incompatibilities.py',
|
||||
expected_lines=expected_lines, cfg_args=cfg_args)
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestGradientPreviewSettings(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id('C3980668', 'C2676825', 'C2676828', 'C2676822', 'C3416547', 'C3961320', 'C3961325',
|
||||
'C3980658', 'C3980663')
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientPreviewSettings_DefaultPinnedEntityIsSelf(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Perlin Noise Gradient has Preview pinned to own Entity result: SUCCESS",
|
||||
"Random Noise Gradient has Preview pinned to own Entity result: SUCCESS",
|
||||
"FastNoise Gradient has Preview pinned to own Entity result: SUCCESS",
|
||||
"Dither Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"Invert Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"Levels Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"Posterize Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"Smooth-Step Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"Threshold Gradient Modifier has Preview pinned to own Entity result: SUCCESS",
|
||||
"GradientPreviewSettings_DefaultPinnedEntity: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientPreviewSettings_DefaultPinnedEntityIsSelf.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C2676829", "C3961326", "C3980659", "C3980664", "C3980669", "C3416548", "C2676823",
|
||||
"C3961321", "C2676826")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Random Noise Gradient entity Created",
|
||||
"Entity has a Random Noise Gradient component",
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"Random Noise Gradient Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Random Noise Gradient --- Preview Position set to world origin",
|
||||
"Random Noise Gradient --- Preview Size set to (1, 1, 1)",
|
||||
"Levels Gradient Modifier entity Created",
|
||||
"Entity has a Levels Gradient Modifier component",
|
||||
"Levels Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Levels Gradient Modifier --- Preview Position set to world origin",
|
||||
"Posterize Gradient Modifier entity Created",
|
||||
"Entity has a Posterize Gradient Modifier component",
|
||||
"Posterize Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Posterize Gradient Modifier --- Preview Position set to world origin",
|
||||
"Smooth-Step Gradient Modifier entity Created",
|
||||
"Entity has a Smooth-Step Gradient Modifier component",
|
||||
"Smooth-Step Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Smooth-Step Gradient Modifier --- Preview Position set to world origin",
|
||||
"Threshold Gradient Modifier entity Created",
|
||||
"Entity has a Threshold Gradient Modifier component",
|
||||
"Threshold Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Threshold Gradient Modifier --- Preview Position set to world origin",
|
||||
"FastNoise Gradient entity Created",
|
||||
"Entity has a FastNoise Gradient component",
|
||||
"FastNoise Gradient Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"FastNoise Gradient --- Preview Position set to world origin",
|
||||
"FastNoise Gradient --- Preview Size set to (1, 1, 1)",
|
||||
"Dither Gradient Modifier entity Created",
|
||||
"Entity has a Dither Gradient Modifier component",
|
||||
"Dither Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Dither Gradient Modifier --- Preview Position set to world origin",
|
||||
"Dither Gradient Modifier --- Preview Size set to (1, 1, 1)",
|
||||
"Invert Gradient Modifier entity Created",
|
||||
"Entity has a Invert Gradient Modifier component",
|
||||
"Invert Gradient Modifier Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Invert Gradient Modifier --- Preview Position set to world origin",
|
||||
"Perlin Noise Gradient entity Created",
|
||||
"Entity has a Perlin Noise Gradient component",
|
||||
"Perlin Noise Gradient Preview Settings|Pin Preview to Shape: SUCCESS",
|
||||
"Perlin Noise Gradient --- Preview Position set to world origin",
|
||||
"Perlin Noise Gradient --- Preview Size set to (1, 1, 1)",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,90 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestGradientSampling(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C3526311")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientSampling_GradientReferencesAddRemoveSuccessfully(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Entity has a Random Noise Gradient component",
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"Entity has a Dither Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Dither Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Dither Gradient Modifier successfully",
|
||||
"Entity has a Invert Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Invert Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Invert Gradient Modifier successfully",
|
||||
"Entity has a Levels Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Levels Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Levels Gradient Modifier successfully",
|
||||
"Entity has a Posterize Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Posterize Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Posterize Gradient Modifier successfully",
|
||||
"Entity has a Smooth-Step Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Smooth-Step Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Smooth-Step Gradient Modifier successfully",
|
||||
"Entity has a Threshold Gradient Modifier component",
|
||||
"Gradient Generator is pinned to the Threshold Gradient Modifier successfully",
|
||||
"Gradient Generator is cleared from the Threshold Gradient Modifier successfully",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"Failed to pin Gradient Generator to the Dither Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Dither Gradient Modifier",
|
||||
"Failed to pin Gradient Generator to the Invert Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Invert Gradient Modifier",
|
||||
"Failed to pin Gradient Generator to the Levels Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Levels Gradient Modifier",
|
||||
"Failed to pin Gradient Generator to the Posterize Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Posterize Gradient Modifier",
|
||||
"Failed to pin Gradient Generator to the Smooth-Step Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Smooth-Step Gradient Modifier",
|
||||
"Failed to pin Gradient Generator to the Threshold Gradient Modifier",
|
||||
"Failed to clear Gradient Generator from the Threshold Gradient Modifier",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientSampling_GradientReferencesAddRemoveSuccessfully.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip("ly_test_tools")
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["tmp_level"])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestGradientSurfaceTagEmitter(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
# Cleanup temp level before and after test runs
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id("C3297302")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_GradientSurfaceTagEmitter_ComponentDependencies(self, request, editor, level, workspace,
|
||||
launcher_platform):
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: test started",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Gradient Surface Tag Emitter is Disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Dither Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Gradient Mixer and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Invert Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Levels Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Posterize Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Smooth-Step Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Threshold Gradient Modifier and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Altitude Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Constant Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: FastNoise Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Image Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Perlin Noise Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Random Noise Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Reference Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Shape Falloff Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Slope Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Surface Mask Gradient and Gradient Surface Tag Emitter are enabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: result=SUCCESS",
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Gradient Surface Tag Emitter is Enabled, but should be Disabled without dependencies met",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Dither Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Gradient Mixer and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Invert Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Levels Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Posterize Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Smooth-Step Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Threshold Gradient Modifier and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Altitude Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Constant Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: FastNoise Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Image Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Perlin Noise Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Random Noise Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Reference Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Shape Falloff Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Slope Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies: Surface Mask Gradient and Gradient Surface Tag Emitter are disabled",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientSurfaceTagEmitter_ComponentDependencies.py",
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=cfg_args
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C3297303")
|
||||
@pytest.mark.SUITE_main
|
||||
def test_GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(self, request, editor, level,
|
||||
launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Entity has a Gradient Surface Tag Emitter component",
|
||||
"Entity has a Reference Gradient component",
|
||||
"Added SurfaceTag: container count is 1",
|
||||
"Removed SurfaceTag: container count is 0",
|
||||
"GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSucessfully: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
Tests that the Gradient Transform Modifier component isn't enabled unless it has a component on
|
||||
the same Entity that provides the ShapeService (e.g. box shape, or reference shape)
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestGradientTransformRequiresShape(object):
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
@pytest.mark.test_case_id('C3430289')
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientTransform_RequiresShape(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Gradient Transform Modifier component was added to entity, but the component is disabled",
|
||||
"Gradient Transform component is not active without a Shape component on the Entity",
|
||||
"Box Shape component was added to entity",
|
||||
"Gradient Transform Modifier component is active now that the Entity has a Shape",
|
||||
"GradientTransformRequiresShape: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientTransform_RequiresShape.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C3430292")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Entity Created",
|
||||
"Entity has a Random Noise Gradient component",
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"Components added to the entity",
|
||||
"entity Configuration|Frequency Zoom: SUCCESS",
|
||||
"Frequency Zoom is equal to expected value",
|
||||
]
|
||||
|
||||
unexpected_lines = ["Frequency Zoom is not equal to expected value"]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py",
|
||||
expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C3430297")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientTransform_ComponentIncompatibleWithSpawners(self, request, editor, launcher_platform, level):
|
||||
# C3430297: Component cannot be active on the same Entity as an active Vegetation Layer Spawner
|
||||
expected_lines = [
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"New Entity Created",
|
||||
"Gradient Transform Modifier is Enabled",
|
||||
"Box Shape is Enabled",
|
||||
"Entity has a Vegetation Layer Spawner component",
|
||||
"Vegetation Layer Spawner is incompatible and disabled",
|
||||
"GradientTransform_ComponentIncompatibleWithSpawners: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"Gradient Transform Modifier is Disabled. But It should be Enabled in an Entity",
|
||||
"Box Shape is Disabled. But It should be Enabled in an Entity",
|
||||
"Vegetation Layer Spawner is compatible and enabled. But It should be Incompatible and disabled",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientTransform_ComponentIncompatibleWithSpawners.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C4753767")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_GradientTransform_ComponentIncompatibleWithExpectedGradients(self, request, editor, launcher_platform, level):
|
||||
expected_lines = [
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"New Entity Created",
|
||||
"Gradient Transform Modifier is Enabled",
|
||||
"Box Shape is Enabled",
|
||||
"Entity has a Constant Gradient component",
|
||||
"Entity has a Altitude Gradient component",
|
||||
"Entity has a Gradient Mixer component",
|
||||
"Entity has a Reference Gradient component",
|
||||
"Entity has a Shape Falloff Gradient component",
|
||||
"Entity has a Slope Gradient component",
|
||||
"Entity has a Surface Mask Gradient component",
|
||||
"All newly added components are incompatible and disabled",
|
||||
"GradientTransform_ComponentIncompatibleWithExpectedGradients: result=SUCCESS"
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
"Gradient Transform Modifier is disabled, but it should be enabled",
|
||||
"Box Shape is disabled, but it should be enabled",
|
||||
"Constant Gradient is enabled, but should be disabled",
|
||||
"Altitude Gradient is enabled, but should be disabled",
|
||||
"Gradient Mixer is enabled, but should be disabled",
|
||||
"Reference Gradient is enabled, but should be disabled",
|
||||
"Shape Falloff Gradient is enabled, but should be disabled",
|
||||
"Slope Gradient is enabled, but should be disabled",
|
||||
"Surface Mask Gradient component is enabled, but should be disabled",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"GradientTransform_ComponentIncompatibleWithExpectedGradients.py",
|
||||
expected_lines,
|
||||
unexpected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import automatedtesting_shared.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['tmp_level'])
|
||||
@pytest.mark.usefixtures("automatic_process_killer")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestImageGradientRequiresShape(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.dev(), project, "Levels", level)], True, True)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.test_case_id('C2707570')
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_ImageGradient_RequiresShape(self, request, editor, level, launcher_platform):
|
||||
cfg_args = [level]
|
||||
expected_lines = [
|
||||
"Image Gradient component was added to entity, but the component is disabled",
|
||||
"Gradient Transform Modifier component was added to entity, but the component is disabled",
|
||||
"Image Gradient component is not active without a Shape component on the Entity",
|
||||
"Box Shape component was added to entity",
|
||||
"Image Gradient component is active now that the Entity has a Shape",
|
||||
"ImageGradientRequiresShape: result=SUCCESS"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(request, test_directory, editor,
|
||||
'ImageGradient_RequiresShape.py',
|
||||
expected_lines=expected_lines, cfg_args=cfg_args)
|
||||
|
||||
@pytest.mark.test_case_id("C3829430")
|
||||
@pytest.mark.SUITE_periodic
|
||||
def test_ImageGradient_ProcessedImageAssignedSuccessfully(self, request, editor, level, launcher_platform):
|
||||
|
||||
expected_lines = [
|
||||
"Image Gradient Entity created",
|
||||
"Entity has a Image Gradient component",
|
||||
"Entity has a Gradient Transform Modifier component",
|
||||
"Entity has a Box Shape component",
|
||||
"lumberyard_gsi.png was found in the workspace",
|
||||
"Entity Configuration|Image Asset: SUCCESS",
|
||||
"ImageGradient_ProcessedImageAssignedSucessfully: result=SUCCESS",
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
test_directory,
|
||||
editor,
|
||||
"ImageGradient_ProcessedImageAssignedSuccessfully.py",
|
||||
expected_lines,
|
||||
cfg_args=[level]
|
||||
)
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
newEntityId = None
|
||||
|
||||
|
||||
class TestAreaNodeComponentDependency(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AreaNodeComponentDependency", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global newEntityId
|
||||
newEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Listen for entity creation notifications so we can check if the entity created
|
||||
# from adding these vegetation area nodes has the main target Vegetation Layer Component
|
||||
# as well as automatically adding all required dependency components
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
|
||||
# Vegetation area mapping with the key being the node name and the value is the
|
||||
# expected Components that should be added to the Entity created for the node
|
||||
areas = {
|
||||
'SpawnerAreaNode': [
|
||||
'Vegetation Layer Spawner',
|
||||
'Vegetation Asset List',
|
||||
'Vegetation Reference Shape'
|
||||
],
|
||||
'MeshBlockerAreaNode': [
|
||||
'Vegetation Layer Blocker (Mesh)',
|
||||
'Mesh'
|
||||
],
|
||||
'BlockerAreaNode': [
|
||||
'Vegetation Layer Blocker',
|
||||
'Vegetation Reference Shape'
|
||||
]
|
||||
}
|
||||
|
||||
# Retrieve a mapping of the TypeIds for all the components
|
||||
# we will be checking for
|
||||
componentNames = []
|
||||
for name in areas:
|
||||
componentNames.extend(areas[name])
|
||||
componentTypeIds = hydra.get_component_type_id_map(componentNames)
|
||||
|
||||
# Create nodes for the vegetation areas that have additional required dependencies and check if
|
||||
# the Entity created by adding the node has the appropriate component and required
|
||||
# additional components added automatically to it
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
x = 10.0
|
||||
y = 10.0
|
||||
for nodeName in areas:
|
||||
nodePosition = math.Vector2(x, y)
|
||||
node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
|
||||
newGraph, nodeName)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
|
||||
|
||||
components = areas[nodeName]
|
||||
success = False
|
||||
for component in components:
|
||||
componentTypeId = componentTypeIds[component]
|
||||
success = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
|
||||
componentTypeId)
|
||||
if not success:
|
||||
break
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("{node} created new Entity with all required components".format(node=nodeName))
|
||||
|
||||
x += 40.0
|
||||
y += 40.0
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestAreaNodeComponentDependency()
|
||||
test.run()
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
newEntityId = None
|
||||
|
||||
|
||||
class TestGradientNodeEntityCreate(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityCreate", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global newEntityId
|
||||
newEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Listen for entity creation notifications so we can check if the entity created
|
||||
# from adding vegetation area nodes has the appropriate Vegetation Layer Component
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
|
||||
# Vegetation Area mapping with the key being the node name and the value is the
|
||||
# expected Component that should be added to the Entity created for the node
|
||||
areas = {
|
||||
'AreaBlenderNode': 'Vegetation Layer Blender',
|
||||
'BlockerAreaNode': 'Vegetation Layer Blocker',
|
||||
'MeshBlockerAreaNode': 'Vegetation Layer Blocker (Mesh)',
|
||||
'SpawnerAreaNode': 'Vegetation Layer Spawner'
|
||||
}
|
||||
|
||||
# Retrieve a mapping of the TypeIds for all the components
|
||||
# we will be checking for
|
||||
componentNames = []
|
||||
for name in areas:
|
||||
componentNames.append(areas[name])
|
||||
componentTypeIds = hydra.get_component_type_id_map(componentNames)
|
||||
|
||||
# Create nodes for all the vegetation areas we support and check if the Entity created by
|
||||
# adding the node has the appropriate Component added automatically to it
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
x = 10.0
|
||||
y = 10.0
|
||||
for nodeName in areas:
|
||||
nodePosition = math.Vector2(x, y)
|
||||
node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
|
||||
|
||||
areaComponent = areas[nodeName]
|
||||
componentTypeId = componentTypeIds[areaComponent]
|
||||
hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, componentTypeId)
|
||||
self.test_success = self.test_success and hasComponent
|
||||
if hasComponent:
|
||||
self.log("{node} created new Entity with {component} Component".format(node=nodeName, component=areaComponent))
|
||||
|
||||
x += 40.0
|
||||
y += 40.0
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestGradientNodeEntityCreate()
|
||||
test.run()
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
createdEntityId = None
|
||||
deletedEntityId = None
|
||||
|
||||
|
||||
class TestAreaNodeEntityDelete(EditorTestHelper):
|
||||
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityDelete", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global createdEntityId
|
||||
createdEntityId = parameters[0]
|
||||
|
||||
def onEntityDeleted(parameters):
|
||||
global deletedEntityId
|
||||
deletedEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Listen for entity creation notifications so we can check if the entity created
|
||||
# from adding gradient nodes has the appropriate Gradient Component
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
handler.add_callback('OnEditorEntityDeleted', onEntityDeleted)
|
||||
|
||||
# Vegetation Area mapping with the key being the node name and the value is the
|
||||
# expected Component that should be added to the Entity created for the node
|
||||
areas = [
|
||||
'AreaBlenderNode',
|
||||
'BlockerAreaNode',
|
||||
'MeshBlockerAreaNode',
|
||||
'SpawnerAreaNode',
|
||||
]
|
||||
|
||||
# Create nodes for all the gradients we support and check if the Entity created by
|
||||
# adding the node has the appropriate Component added automatically to it
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
x = 10.0
|
||||
y = 10.0
|
||||
for nodeName in areas:
|
||||
nodePosition = math.Vector2(x, y)
|
||||
node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
|
||||
|
||||
removed = graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, node)
|
||||
|
||||
# Verify that the created Entity for this node matches the Entity that gets
|
||||
# deleted when the node is removed
|
||||
self.test_success = self.test_success and removed and createdEntityId.invoke("Equal", deletedEntityId)
|
||||
if removed and createdEntityId.invoke("Equal", deletedEntityId):
|
||||
self.log("{node} corresponding Entity was deleted when node is removed".format(node=nodeName))
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestAreaNodeEntityDelete()
|
||||
test.run()
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
C22602072 - Graph is updated when underlying components are added/removed
|
||||
|
||||
1. Open Level.
|
||||
2. Find LandscapeCanvas named entity.
|
||||
3. Ensure Vegetation Distribution Component is present on the BushSpawner entity.
|
||||
4. Open graph and ensure Distribution Filter wrapped node is present.
|
||||
5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector.
|
||||
6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is no longer
|
||||
present in the graph.
|
||||
7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector.
|
||||
8. Ensure Altitude Filter was added to the BushSpawner node in the open graph.
|
||||
9. Add a new entity with unique name as a child of the Landscape Canvas entity.
|
||||
10. Add a Box Shape component to the new child entity.
|
||||
11. Ensure Box Shape node is present on the open graph.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.math as math
|
||||
import azlmbr.slice as slice
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestComponentUpdatesUpdateGraph(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="ComponentUpdatesUpdateGraph", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
transform = math.Transform_CreateIdentity()
|
||||
position = math.Vector3(64.0, 64.0, 32.0)
|
||||
transform.invoke('SetPosition', position)
|
||||
test_slice_path = os.path.join("Slices", "LC_BushFlowerBlender.slice")
|
||||
test_slice_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", test_slice_path, math.Uuid(),
|
||||
False)
|
||||
test_slice = slice.SliceRequestBus(bus.Broadcast, 'InstantiateSliceFromAssetId', test_slice_id, transform)
|
||||
self.test_success = self.test_success and test_slice.IsValid()
|
||||
if test_slice.IsValid():
|
||||
self.log("Slice spawned!")
|
||||
|
||||
# Find root entity in the loaded level
|
||||
search_filter = entity.SearchFilter()
|
||||
search_filter.names = ["LandscapeCanvas"]
|
||||
|
||||
# Allow a few seconds for matching entity to be found
|
||||
self.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0, 5.0)
|
||||
lc_matching_entities = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||
slice_root_id = lc_matching_entities[0] #Entity with Landscape Canvas component
|
||||
self.test_success = self.test_success and slice_root_id.IsValid()
|
||||
if slice_root_id.IsValid():
|
||||
self.log("LandscapeCanvas entity found")
|
||||
|
||||
# Find the BushSpawner entity
|
||||
search_filter.names = ["BushSpawner"]
|
||||
spawner_matching_entities = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||
spawner_id = spawner_matching_entities[0] #Entity with Vegetation Layer Spawner component
|
||||
self.test_success = self.test_success and spawner_id.IsValid()
|
||||
if spawner_id.IsValid():
|
||||
self.log("BushSpawner entity found")
|
||||
|
||||
# Get needed component type ids
|
||||
distribution_filter_type_id = hydra.get_component_type_id("Vegetation Distribution Filter")
|
||||
altitude_filter_type_id = hydra.get_component_type_id("Vegetation Altitude Filter")
|
||||
box_shape_type_id = hydra.get_component_type_id("Box Shape")
|
||||
|
||||
# Verify the BushSpawner entity has a Distribution Filter
|
||||
has_distribution_filter = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', spawner_id,
|
||||
distribution_filter_type_id)
|
||||
self.test_success = self.test_success and has_distribution_filter
|
||||
if has_distribution_filter:
|
||||
self.log("Vegetation Distribution Filter on BushSpawner entity found")
|
||||
|
||||
# Open Landscape Canvas and the existing graph
|
||||
general.open_pane('Landscape Canvas')
|
||||
open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
|
||||
self.test_success = self.test_success and open_graph.IsValid()
|
||||
if open_graph.IsValid():
|
||||
self.log("Graph opened")
|
||||
|
||||
# Verify that Distribution Filter node is present on the graph
|
||||
spawner_distribution_filter_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', spawner_id,
|
||||
distribution_filter_type_id)
|
||||
spawner_distribution_filter_component_id = spawner_distribution_filter_component.GetValue()
|
||||
distribution_filter_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast,
|
||||
'GetNodeMatchingEntityComponentInGraph',
|
||||
open_graph,
|
||||
spawner_distribution_filter_component_id)
|
||||
self.test_success = self.test_success and distribution_filter_node is not None
|
||||
if distribution_filter_node is not None:
|
||||
self.log("Distribution Filter node found on graph")
|
||||
else:
|
||||
self.log("Distribution Filter node not found on graph")
|
||||
|
||||
# Add a Vegetation Altitude Filter component to the BushSpawner entity, and verify the node is added to the graph
|
||||
spawner_altitude_filter_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', spawner_id,
|
||||
altitude_filter_type_id)
|
||||
spawner_altitude_filter_component_id = spawner_altitude_filter_component.GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentOfType', spawner_id, altitude_filter_type_id)
|
||||
has_altitude_filter = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', spawner_id,
|
||||
altitude_filter_type_id)
|
||||
altitude_filter_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'GetNodeMatchingEntityComponentInGraph',
|
||||
open_graph, spawner_altitude_filter_component_id)
|
||||
self.test_success = self.test_success and has_altitude_filter and altitude_filter_node is not None
|
||||
if has_altitude_filter:
|
||||
self.log("Vegetation Altitude Filter on BushSpawner entity found")
|
||||
|
||||
if altitude_filter_node is not None:
|
||||
self.log("Altitude Filter node found on graph")
|
||||
else:
|
||||
self.log("Altitude Filter node not found on graph")
|
||||
|
||||
# Remove the Distribution Filter
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [spawner_distribution_filter_component_id])
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Verify the Distribution Filter was successfully removed from entity and the node was likewise removed
|
||||
has_distribution_filter = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', spawner_id,
|
||||
distribution_filter_type_id)
|
||||
self.test_success = self.test_success and not has_distribution_filter
|
||||
if not has_distribution_filter:
|
||||
self.log("Vegetation Distribution Filter removed from BushSpawner entity")
|
||||
|
||||
distribution_filter_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast,
|
||||
'GetAllNodesMatchingEntityComponent',
|
||||
spawner_distribution_filter_component_id)
|
||||
self.test_success = self.test_success and not distribution_filter_node
|
||||
if distribution_filter_node:
|
||||
self.log("Distribution Filter node is still present on the graph")
|
||||
else:
|
||||
self.log("Distribution Filter node was removed from the graph")
|
||||
|
||||
# Add a new child entity of BushSpawner entity
|
||||
box_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', spawner_id)
|
||||
if editor.EditorEntityInfoRequestBus(bus.Event, 'GetParent', box_id) == spawner_id:
|
||||
self.log("New entity successfully added as a child of the BushSpawner entity")
|
||||
else:
|
||||
self.log("New entity added with an unexpected parent")
|
||||
|
||||
# Add a Box Shape component to the new entity and verify it was properly added
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentOfType', box_id, box_shape_type_id)
|
||||
has_box_shape = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', box_id,
|
||||
box_shape_type_id)
|
||||
self.test_success = self.test_success and has_box_shape
|
||||
if has_box_shape:
|
||||
self.log("Box Shape on Box entity found")
|
||||
|
||||
# Verify the Box Shape node appear on the graph
|
||||
box_shape_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', box_id,
|
||||
box_shape_type_id)
|
||||
|
||||
box_shape_component_id = box_shape_component.GetValue()
|
||||
box_shape_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'GetAllNodesMatchingEntityComponent',
|
||||
box_shape_component_id)
|
||||
self.test_success = self.test_success and box_shape_node is not None
|
||||
if box_shape_node is not None:
|
||||
self.log("Box Shape node found on graph")
|
||||
else:
|
||||
self.log("Box Shape node not found on graph")
|
||||
|
||||
|
||||
test = TestComponentUpdatesUpdateGraph()
|
||||
test.run()
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
new_root_entity_id = None
|
||||
|
||||
|
||||
class TestCreateNewGraph(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="CreateNewGraph", args=["level"])
|
||||
|
||||
def on_entity_created(self, parameters):
|
||||
global new_root_entity_id
|
||||
new_root_entity_id = parameters[0]
|
||||
|
||||
print("New root entity created")
|
||||
|
||||
def run_test(self):
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane("Landscape Canvas")
|
||||
self.test_success = self.test_success and general.is_pane_visible("Landscape Canvas")
|
||||
if general.is_pane_visible("Landscape Canvas"):
|
||||
self.log("Landscape Canvas pane is open")
|
||||
|
||||
# Listen for entity creation notifications so we can check if the entity created
|
||||
# with the new graph has our Landscape Canvas component automatically added
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback("OnEditorEntityCreated", self.on_entity_created)
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, "CreateNewGraph", editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, "ContainsGraph", editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Check if the entity created when we create a new graph has the
|
||||
# Landscape Canvas component already added to it
|
||||
landscape_canvas_type_id = hydra.get_component_type_id("Landscape Canvas")
|
||||
success = editor.EditorComponentAPIBus(bus.Broadcast, "HasComponentOfType", new_root_entity_id,
|
||||
landscape_canvas_type_id)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Root entity has Landscape Canvas component")
|
||||
|
||||
# Close Landscape Canvas tool and verify
|
||||
general.close_pane("Landscape Canvas")
|
||||
self.test_success = self.test_success and not general.is_pane_visible("Landscape Canvas")
|
||||
if not general.is_pane_visible("Landscape Canvas"):
|
||||
self.log("Landscape Canvas pane is closed")
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestCreateNewGraph()
|
||||
test.run()
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
newEntityId = None
|
||||
|
||||
|
||||
class TestDisabledNodeDuplication(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="DisabledNodeDuplication", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global newEntityId
|
||||
newEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Listen for entity creation notifications so when we add a new node
|
||||
# we can access the corresponding Entity that was created so that we
|
||||
# can disable/remove components on that Entity
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
|
||||
# Mapping of our Landscape Canvas nodes with corresponding dependent components
|
||||
# that we can disable/remove to reproduce the crash
|
||||
nodes = {
|
||||
'SpawnerAreaNode': 'Vegetation Asset List',
|
||||
'MeshBlockerAreaNode': 'Mesh',
|
||||
'BlockerAreaNode': 'Vegetation Reference Shape',
|
||||
'FastNoiseGradientNode': 'Gradient Transform Modifier',
|
||||
'ImageGradientNode': 'Gradient Transform Modifier',
|
||||
'PerlinNoiseGradientNode': 'Gradient Transform Modifier',
|
||||
'RandomNoiseGradientNode': 'Gradient Transform Modifier'
|
||||
}
|
||||
|
||||
# Retrieve a mapping of the TypeIds for all the components
|
||||
# we will be checking for
|
||||
componentNames = list(set(nodes.values())) # Convert to set then back to list to remove any duplicates
|
||||
componentTypeIds = hydra.get_component_type_id_map(componentNames)
|
||||
|
||||
# Iterate through creating our nodes and then disabling/deleting required components
|
||||
# and then duplicating the node to reproduce the crash
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
x = 10.0
|
||||
y = 10.0
|
||||
for nodeName in nodes:
|
||||
nodePosition = math.Vector2(x, y)
|
||||
node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
|
||||
|
||||
dependentComponentName = nodes[nodeName]
|
||||
componentTypeId = componentTypeIds[dependentComponentName]
|
||||
componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', newEntityId, componentTypeId)
|
||||
component = componentOutcome.GetValue()
|
||||
|
||||
# First make sure we can duplicate a node with a dependent component that is disabled
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [component])
|
||||
general.idle_wait(1.0)
|
||||
graph.SceneRequestBus(bus.Event, 'DuplicateSelection', newGraphId) # This duplication would cause a crash without the fix
|
||||
self.log("{node} duplicated with disabled component".format(node=nodeName))
|
||||
|
||||
# Then, make sure we can duplicate the node with a dependent component that is deleted
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [component])
|
||||
general.idle_wait(1.0)
|
||||
graph.SceneRequestBus(bus.Event, 'DuplicateSelection', newGraphId) # This duplication would cause a crash without the fix
|
||||
self.log("{node} duplicated with deleted component".format(node=nodeName))
|
||||
|
||||
x += 40.0
|
||||
y += 40.0
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestDisabledNodeDuplication()
|
||||
test.run()
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
C30813586 - Editor remains stable after Undoing deletion of a node on a slice entity
|
||||
|
||||
1. Open level with instantiated slice.
|
||||
2. Open the graph.
|
||||
3. Find the BushSpawner's Vegetation Layer Spawner node.
|
||||
4. Delete the node.
|
||||
5. Undo to restore the node.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.math as math
|
||||
import azlmbr.slice as slice
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
class TestUndoNodeDeleteSlice(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="UndoNodeDeleteSlice", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
transform = math.Transform_CreateIdentity()
|
||||
position = math.Vector3(64.0, 64.0, 32.0)
|
||||
transform.invoke('SetPosition', position)
|
||||
test_slice_path = os.path.join("Slices", "LC_BushFlowerBlender.slice")
|
||||
test_slice_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", test_slice_path, math.Uuid(),
|
||||
False)
|
||||
test_slice = slice.SliceRequestBus(bus.Broadcast, 'InstantiateSliceFromAssetId', test_slice_id, transform)
|
||||
self.test_success = self.test_success and test_slice.IsValid()
|
||||
if test_slice.IsValid():
|
||||
self.log("Slice spawned!")
|
||||
|
||||
# Find root entity in the loaded level
|
||||
search_filter = entity.SearchFilter()
|
||||
search_filter.names = ["LandscapeCanvas"]
|
||||
|
||||
# Allow a few seconds for matching entity to be found
|
||||
self.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0,
|
||||
5.0)
|
||||
lc_matching_entities = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||
slice_root_id = lc_matching_entities[0] # Entity with Landscape Canvas component
|
||||
self.test_success = self.test_success and slice_root_id.IsValid()
|
||||
if slice_root_id.IsValid():
|
||||
self.log("LandscapeCanvas entity found")
|
||||
|
||||
# Find the BushSpawner entity
|
||||
search_filter.names = ["BushSpawner"]
|
||||
spawner_matching_entities = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||
spawner_id = spawner_matching_entities[0] # Entity with Vegetation Layer Spawner component
|
||||
self.test_success = self.test_success and spawner_id.IsValid()
|
||||
if spawner_id.IsValid():
|
||||
self.log("BushSpawner entity found")
|
||||
|
||||
# Open Landscape Canvas and the existing graph
|
||||
general.open_pane('Landscape Canvas')
|
||||
open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
|
||||
self.test_success = self.test_success and open_graph.IsValid()
|
||||
if open_graph.IsValid():
|
||||
self.log("Graph opened")
|
||||
|
||||
# Get needed component type ids
|
||||
layer_spawner_type_id = hydra.get_component_type_id("Vegetation Layer Spawner")
|
||||
|
||||
# Find the Vegetation Layer Spawner node on the BushSpawner entity
|
||||
layer_spawner_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', spawner_id,
|
||||
layer_spawner_type_id)
|
||||
layer_spawner_component_component_id = layer_spawner_component.GetValue()
|
||||
layer_spawner_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'GetAllNodesMatchingEntityComponent',
|
||||
layer_spawner_component_component_id)
|
||||
|
||||
self.test_success = self.test_success and layer_spawner_node
|
||||
if layer_spawner_node:
|
||||
self.log("Vegetation Layer Spawner node found on graph")
|
||||
else:
|
||||
self.log("Vegetation Layer Spawner node not found")
|
||||
|
||||
# Remove the Layer Spawner node
|
||||
graph.GraphControllerRequestBus(bus.Event, "RemoveNode", open_graph, layer_spawner_node[0])
|
||||
|
||||
# Verify node was removed
|
||||
layer_spawner_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'GetAllNodesMatchingEntityComponent',
|
||||
layer_spawner_component_component_id)
|
||||
|
||||
self.test_success = self.test_success and not layer_spawner_node
|
||||
if not layer_spawner_node:
|
||||
self.log("Vegetation Layer Spawner node was removed")
|
||||
else:
|
||||
self.log("Vegetation Layer Spawner node was not removed")
|
||||
|
||||
# Undo the Node deletion. This is required to be executed twice to hit the node removal.
|
||||
general.undo()
|
||||
general.undo()
|
||||
|
||||
# self.log a line to the Console to verify the Editor is still active
|
||||
self.log("Editor is still responsive")
|
||||
|
||||
|
||||
test = TestUndoNodeDeleteSlice()
|
||||
test.run()
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
newEntityId = None
|
||||
|
||||
|
||||
class TestGradientMixerNodeConstruction(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientMixerNodeConstruction", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global newEntityId
|
||||
newEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=1024,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Listen for entity creation notifications so we can verify the component EntityId
|
||||
# references are set correctly when connecting slots on the nodes
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
|
||||
positionX = 10.0
|
||||
positionY = 10.0
|
||||
offsetX = 340.0
|
||||
offsetY = 100.0
|
||||
|
||||
# Add a Box Shape node to the graph
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
boxShapeNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph,
|
||||
'BoxShapeNode')
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, boxShapeNode, math.Vector2(positionX, positionY))
|
||||
boxShapeEntityId = newEntityId
|
||||
|
||||
positionX += offsetX
|
||||
positionY += offsetY
|
||||
|
||||
# Add a Random Noise Gradient node to the graph
|
||||
perlinNoiseNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph,
|
||||
'PerlinNoiseGradientNode')
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, perlinNoiseNode, math.Vector2(positionX, positionY))
|
||||
perlinNoiseEntityId = newEntityId
|
||||
|
||||
positionX += offsetX
|
||||
positionY += offsetY
|
||||
|
||||
# Add a FastNoise Gradient node to the graph
|
||||
fastNoiseNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph,
|
||||
'FastNoiseGradientNode')
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, fastNoiseNode, math.Vector2(positionX, positionY))
|
||||
fastNoiseEntityId = newEntityId
|
||||
|
||||
positionX += offsetX
|
||||
positionY += offsetY
|
||||
|
||||
# Add a Gradient Mixer node to the graph
|
||||
gradientMixerNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph,
|
||||
'GradientMixerNode')
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, gradientMixerNode, math.Vector2(positionX, positionY))
|
||||
gradientMixerEntityId = newEntityId
|
||||
|
||||
boundsSlotId = graph.GraphModelSlotId('Bounds')
|
||||
previewBoundsSlotId = graph.GraphModelSlotId('PreviewBounds')
|
||||
inboundGradientSlotId = graph.GraphModelSlotId('InboundGradient')
|
||||
outboundGradientSlotId = graph.GraphModelSlotId('OutboundGradient')
|
||||
inboundGradientSlotId2 = graph.GraphControllerRequestBus(bus.Event, 'ExtendSlot', newGraphId, gradientMixerNode,
|
||||
'InboundGradient')
|
||||
|
||||
# Connect slots on our nodes to construct a Gradient Mixer hierarchy
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, boxShapeNode, boundsSlotId,
|
||||
perlinNoiseNode, previewBoundsSlotId)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, boxShapeNode, boundsSlotId,
|
||||
fastNoiseNode, previewBoundsSlotId)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, boxShapeNode, boundsSlotId,
|
||||
gradientMixerNode, previewBoundsSlotId)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, perlinNoiseNode, outboundGradientSlotId,
|
||||
gradientMixerNode, inboundGradientSlotId)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, fastNoiseNode, outboundGradientSlotId,
|
||||
gradientMixerNode, inboundGradientSlotId2)
|
||||
|
||||
# Delay to allow all the underlying component properties to be updated after the slot connections are made
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Get component info
|
||||
gradientMixerTypeId = hydra.get_component_type_id("Gradient Mixer")
|
||||
perlinNoiseTypeId = hydra.get_component_type_id("Perlin Noise Gradient")
|
||||
gradientMixerOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', gradientMixerEntityId,
|
||||
gradientMixerTypeId)
|
||||
gradientMixerComponent = gradientMixerOutcome.GetValue()
|
||||
perlinNoiseOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', perlinNoiseEntityId,
|
||||
perlinNoiseTypeId)
|
||||
perlinNoiseComponent = perlinNoiseOutcome.GetValue()
|
||||
|
||||
# Verify the Preview EntityId property on our Perlin Noise Gradient component has been set to our Box Shape's EntityId
|
||||
previewEntityId = hydra.get_component_property_value(perlinNoiseComponent, 'Preview Settings|Pin Preview to Shape')
|
||||
self.test_success = self.test_success and previewEntityId and boxShapeEntityId.invoke("Equal", previewEntityId)
|
||||
if previewEntityId and boxShapeEntityId.invoke("Equal", previewEntityId):
|
||||
self.log("Perlin Noise Gradient component Preview Entity property set to Box Shape EntityId")
|
||||
|
||||
# Verify the 1st Inbound Gradient EntityId property on our Gradient Mixer component has been set to our Perlin Noise
|
||||
# Gradient's EntityId
|
||||
inboundGradientEntityId = hydra.get_component_property_value(gradientMixerComponent,
|
||||
'Configuration|Layers|[0]|Gradient|Gradient Entity Id')
|
||||
self.test_success = self.test_success and inboundGradientEntityId and perlinNoiseEntityId.invoke("Equal", inboundGradientEntityId)
|
||||
if inboundGradientEntityId and perlinNoiseEntityId.invoke("Equal", inboundGradientEntityId):
|
||||
self.log("Gradient Mixer component Inbound Gradient extendable property set to Perlin Noise Gradient EntityId")
|
||||
|
||||
# Verify the 2nd Inbound Gradient EntityId property on our Gradient Mixer component has been set to our FastNoise
|
||||
# Gradient Modifier's EntityId
|
||||
inboundGradientEntityId2 = hydra.get_component_property_value(gradientMixerComponent,
|
||||
'Configuration|Layers|[1]|Gradient|Gradient Entity Id')
|
||||
self.test_success = self.test_success and inboundGradientEntityId2 and fastNoiseEntityId.invoke("Equal", inboundGradientEntityId2)
|
||||
if inboundGradientEntityId2 and fastNoiseEntityId.invoke("Equal", inboundGradientEntityId2):
|
||||
self.log("Gradient Mixer component Inbound Gradient extendable property set to FastNoise Gradient EntityId")
|
||||
|
||||
# Verify that Gradient Mixer Layer Operations are properly set
|
||||
hydra.get_component_property_value(gradientMixerComponent, 'Configuration|Layers|[0]|Operation')
|
||||
hydra.get_component_property_value(gradientMixerComponent, 'Configuration|Layers|[1]|Operation')
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestGradientMixerNodeConstruction()
|
||||
test.run()
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.editor.graph as graph
|
||||
import azlmbr.landscapecanvas as landscapecanvas
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
|
||||
newEntityId = None
|
||||
|
||||
|
||||
class TestGradientModifierNodeEntityCreate(EditorTestHelper):
|
||||
def __init__(self):
|
||||
EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityCreate", args=["level"])
|
||||
|
||||
def run_test(self):
|
||||
|
||||
def onEntityCreated(parameters):
|
||||
global newEntityId
|
||||
newEntityId = parameters[0]
|
||||
|
||||
# Create a new empty level
|
||||
self.test_success = self.create_level(
|
||||
self.args["level"],
|
||||
heightmap_resolution=128,
|
||||
heightmap_meters_per_pixel=1,
|
||||
terrain_texture_resolution=128,
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
# Open Landscape Canvas tool and verify
|
||||
general.open_pane('Landscape Canvas')
|
||||
self.test_success = self.test_success and general.is_pane_visible('Landscape Canvas')
|
||||
if general.is_pane_visible('Landscape Canvas'):
|
||||
self.log('Landscape Canvas pane is open')
|
||||
|
||||
# Create a new graph in Landscape Canvas
|
||||
newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
|
||||
self.test_success = self.test_success and newGraphId
|
||||
if newGraphId:
|
||||
self.log("New graph created")
|
||||
|
||||
# Make sure the graph we created is in Landscape Canvas
|
||||
success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
|
||||
self.test_success = self.test_success and success
|
||||
if success:
|
||||
self.log("Graph registered with Landscape Canvas")
|
||||
|
||||
# Listen for entity creation notifications so we can check if the entity created
|
||||
# from adding gradient modifier nodes has the appropriate Gradient Modifier Component
|
||||
handler = editor.EditorEntityContextNotificationBusHandler()
|
||||
handler.connect()
|
||||
handler.add_callback('OnEditorEntityCreated', onEntityCreated)
|
||||
|
||||
# Gradient modifier mapping with the key being the node name and the value is the
|
||||
# expected Component that should be added to the Entity created for the node
|
||||
gradientModifiers = {
|
||||
'DitherGradientModifierNode': 'Dither Gradient Modifier',
|
||||
'GradientMixerNode': 'Gradient Mixer',
|
||||
'InvertGradientModifierNode': 'Invert Gradient Modifier',
|
||||
'LevelsGradientModifierNode': 'Levels Gradient Modifier',
|
||||
'PosterizeGradientModifierNode': 'Posterize Gradient Modifier',
|
||||
'SmoothStepGradientModifierNode': 'Smooth-Step Gradient Modifier',
|
||||
'ThresholdGradientModifierNode': 'Threshold Gradient Modifier'
|
||||
}
|
||||
|
||||
# Retrieve a mapping of the TypeIds for all the components
|
||||
# we will be checking for
|
||||
componentNames = []
|
||||
for name in gradientModifiers:
|
||||
componentNames.append(gradientModifiers[name])
|
||||
componentTypeIds = hydra.get_component_type_id_map(componentNames)
|
||||
|
||||
# Create nodes for all the gradients modifiers we support and check if the Entity created by
|
||||
# adding the node has the appropriate Component added automatically to it
|
||||
newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
|
||||
x = 10.0
|
||||
y = 10.0
|
||||
for nodeName in gradientModifiers:
|
||||
nodePosition = math.Vector2(x, y)
|
||||
node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
|
||||
newGraph, nodeName)
|
||||
graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
|
||||
|
||||
gradientComponent = gradientModifiers[nodeName]
|
||||
componentTypeId = componentTypeIds[gradientComponent]
|
||||
hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
|
||||
componentTypeId)
|
||||
self.test_success = self.test_success and hasComponent
|
||||
if hasComponent:
|
||||
self.log("{node} created new Entity with {component} Component".format(node=nodeName,
|
||||
component=gradientComponent))
|
||||
|
||||
x += 40.0
|
||||
y += 40.0
|
||||
|
||||
# Stop listening for entity creation notifications
|
||||
handler.disconnect()
|
||||
|
||||
|
||||
test = TestGradientModifierNodeEntityCreate()
|
||||
test.run()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user