diff --git a/.gitignore b/.gitignore
index 1b63c7698a..b73c89b1d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ TestResults/**
*.swatches
/imgui.ini
/scripts/project_manager/logs/
+/AutomatedTesting/Gem/PythonTests/scripting/TestResults
diff --git a/Assets/Editor/Icons/Components/Viewport/Non Uniform Scale.svg b/Assets/Editor/Icons/Components/Viewport/NonUniformScale.svg
similarity index 100%
rename from Assets/Editor/Icons/Components/Viewport/Non Uniform Scale.svg
rename to Assets/Editor/Icons/Components/Viewport/NonUniformScale.svg
diff --git a/Assets/Editor/Prefabs/Default_Level.prefab b/Assets/Editor/Prefabs/Default_Level.prefab
index 64656e1e2f..d02d669f53 100644
--- a/Assets/Editor/Prefabs/Default_Level.prefab
+++ b/Assets/Editor/Prefabs/Default_Level.prefab
@@ -212,10 +212,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
- "guid": "{935F694A-8639-515B-8133-81CDC7948E5B}",
- "subId": 277333723
+ "guid": "{0CD745C0-6AA8-569A-A68A-73A3270986C4}",
+ "subId": 277889906
},
- "assetHint": "objects/groudplane/groundplane_521x521m.azmodel"
+ "assetHint": "objects/groudplane/groundplane_512x512m.azmodel"
}
}
}
diff --git a/Assets/Editor/Translation/scriptcanvas_en_us.ts b/Assets/Editor/Translation/scriptcanvas_en_us.ts
index f057ba2f30..937f6a4d96 100644
--- a/Assets/Editor/Translation/scriptcanvas_en_us.ts
+++ b/Assets/Editor/Translation/scriptcanvas_en_us.ts
@@ -2771,6 +2771,80 @@
VECTOR2_CREATEONE_OUTPUT0_TOOLTIP
+
+ VECTOR2_DIRECTIONTO_NAME
+ Class/Bus: Vector2 Event/Method: DirectionTo
+ Get Direction Vector
+
+
+ VECTOR2_DIRECTIONTO_TOOLTIP
+ Returns a direction vector between two points and the distance between them, by default the direction will be normalized, it may be optionally scaled using the Scale parameter if different from 1.0
+
+
+ VECTOR2_DIRECTIONTO_CATEGORY
+
+
+
+ VECTOR2_DIRECTIONTO_OUT_NAME
+
+
+
+ VECTOR2_DIRECTIONTO_OUT_TOOLTIP
+
+
+
+ VECTOR2_DIRECTIONTOL_IN_NAME
+
+
+
+ VECTOR2_DIRECTIONTO_IN_TOOLTIP
+
+
+
+ VECTOR2_DIRECTIONTO_OUTPUT0_NAME
+ C++ Type: const Vector2
+ Direction
+
+
+ VECTOR2_DIRECTIONTO_OUTPUT0_TOOLTIP
+ The direction between To and From normalized and optionally scaled
+
+
+ VECTOR2_DIRECTIONTO_OUTPUT1_NAME
+ C++ Type: float
+ Distance
+
+
+ VECTOR2_DIRECTIONTO_OUTPUT1_TOOLTIP
+ The distance between To and From
+
+
+ VECTOR2_DIRECTIONTO_PARAM0_NAME
+ Simple Type: Vector2 C++ Type: Vector2*
+ From
+
+
+ VECTOR2_DIRECTIONTO_PARAM0_TOOLTIP
+
+
+
+ VECTOR2_DIRECTIONTO_PARAM1_NAME
+ Simple Type: Vector2 C++ Type: Vector2*
+ To
+
+
+ VECTOR2_DIRECTIONTO_PARAM1_TOOLTIP
+
+
+
+ VECTOR2_DIRECTIONTO_PARAM2_NAME
+ Simple Type: Vector2 C++ Type: Vector2*
+ Scale
+
+
+ VECTOR2_DIRECTIONTO_PARAM2_TOOLTIP
+
+
VECTOR2_GETPROJECTED_NAME
Class/Bus: Vector2 Event/Method: GetProjected
@@ -32262,6 +32336,80 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
VECTOR4_GETRECIPROCAL_PARAM0_TOOLTIP
+
+ VECTOR4_DIRECTIONTO_NAME
+ Class/Bus: Vector4 Event/Method: DirectionTo
+ Get Direction Vector
+
+
+ VECTOR4_DIRECTIONTO_TOOLTIP
+ Returns a direction vector between two points and the distance between them, by default the direction will be normalized, it may be optionally scaled using the Scale parameter if different from 1.0
+
+
+ VECTOR4_DIRECTIONTO_CATEGORY
+
+
+
+ VECTOR4_DIRECTIONTO_OUT_NAME
+
+
+
+ VECTOR4_DIRECTIONTO_OUT_TOOLTIP
+
+
+
+ VECTOR4_DIRECTIONTOL_IN_NAME
+
+
+
+ VECTOR4_DIRECTIONTO_IN_TOOLTIP
+
+
+
+ VECTOR4_DIRECTIONTO_OUTPUT0_NAME
+ C++ Type: const Vector4
+ Direction
+
+
+ VECTOR4_DIRECTIONTO_OUTPUT0_TOOLTIP
+ The direction between To and From normalized and optionally scaled
+
+
+ VECTOR4_DIRECTIONTO_OUTPUT1_NAME
+ C++ Type: float
+ Distance
+
+
+ VECTOR4_DIRECTIONTO_OUTPUT1_TOOLTIP
+ The distance between To and From
+
+
+ VECTOR4_DIRECTIONTO_PARAM0_NAME
+ Simple Type: Vector4 C++ Type: Vector4*
+ From
+
+
+ VECTOR4_DIRECTIONTO_PARAM0_TOOLTIP
+
+
+
+ VECTOR4_DIRECTIONTO_PARAM1_NAME
+ Simple Type: Vector4 C++ Type: Vector4*
+ To
+
+
+ VECTOR4_DIRECTIONTO_PARAM1_TOOLTIP
+
+
+
+ VECTOR4_DIRECTIONTO_PARAM2_NAME
+ Simple Type: Vector4 C++ Type: Vector4*
+ Scale
+
+
+ VECTOR4_DIRECTIONTO_PARAM2_TOOLTIP
+
+
VECTOR4_AXISX_NAME
Class/Bus: Vector4 Event/Method: CreateAxisX
@@ -37469,6 +37617,80 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
VECTOR3_GETRECIPROCAL_PARAM0_TOOLTIP
+
+ VECTOR3_DIRECTIONTO_NAME
+ Class/Bus: Vector3 Event/Method: DirectionTo
+ Get Direction Vector
+
+
+ VECTOR3_DIRECTIONTO_TOOLTIP
+ Returns a direction vector between two points and the distance between them, by default the direction will be normalized, it may be optionally scaled using the Scale parameter if different from 1.0
+
+
+ VECTOR3_DIRECTIONTO_CATEGORY
+
+
+
+ VECTOR3_DIRECTIONTO_OUT_NAME
+
+
+
+ VECTOR3_DIRECTIONTO_OUT_TOOLTIP
+
+
+
+ VECTOR3_DIRECTIONTOL_IN_NAME
+
+
+
+ VECTOR3_DIRECTIONTO_IN_TOOLTIP
+
+
+
+ VECTOR3_DIRECTIONTO_OUTPUT0_NAME
+ C++ Type: const Vector3
+ Direction
+
+
+ VECTOR3_DIRECTIONTO_OUTPUT0_TOOLTIP
+ The direction between To and From normalized and optionally scaled
+
+
+ VECTOR3_DIRECTIONTO_OUTPUT1_NAME
+ C++ Type: float
+ Distance
+
+
+ VECTOR3_DIRECTIONTO_OUTPUT1_TOOLTIP
+ The distance between To and From
+
+
+ VECTOR3_DIRECTIONTO_PARAM0_NAME
+ Simple Type: Vector3 C++ Type: Vector3*
+ From
+
+
+ VECTOR3_DIRECTIONTO_PARAM0_TOOLTIP
+
+
+
+ VECTOR3_DIRECTIONTO_PARAM1_NAME
+ Simple Type: Vector3 C++ Type: Vector3*
+ To
+
+
+ VECTOR3_DIRECTIONTO_PARAM1_TOOLTIP
+
+
+
+ VECTOR3_DIRECTIONTO_PARAM2_NAME
+ Simple Type: Vector3 C++ Type: Vector3*
+ Scale
+
+
+ VECTOR3_DIRECTIONTO_PARAM2_TOOLTIP
+
+
VECTOR3_PROJECT_NAME
Class/Bus: Vector3 Event/Method: Project
diff --git a/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg
new file mode 100644
index 0000000000..5457b3f1ca
--- /dev/null
+++ b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg
@@ -0,0 +1,19 @@
+{
+ "Amazon": {
+ "AssetProcessor": {
+ "Settings": {
+ "RC cgf": {
+ "ignore": true
+ },
+ "RC fbx": {
+ "ignore": true
+ },
+ "ScanFolder AtomTestData": {
+ "watch": "@ENGINEROOT@/Gems/Atom/TestData",
+ "recursive": 1,
+ "order": 1000
+ }
+ }
+ }
+ }
+}
diff --git a/AutomatedTesting/surfacetypemateriallibrary.physmaterial b/AutomatedTesting/Assets/Physics/SurfaceTypeMaterialLibrary.physmaterial
similarity index 100%
rename from AutomatedTesting/surfacetypemateriallibrary.physmaterial
rename to AutomatedTesting/Assets/Physics/SurfaceTypeMaterialLibrary.physmaterial
diff --git a/AutomatedTesting/Gem/Code/CMakeLists.txt b/AutomatedTesting/Gem/Code/CMakeLists.txt
index 76c0db3f5c..58ffd957d6 100644
--- a/AutomatedTesting/Gem/Code/CMakeLists.txt
+++ b/AutomatedTesting/Gem/Code/CMakeLists.txt
@@ -57,6 +57,12 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
TARGETS Editor
VARIANTS Tools)
+ # The Material Editor needs the Lyshine "Tools" gem variant for the custom LyShine pass
+ ly_enable_gems(
+ PROJECT_NAME AutomatedTesting GEMS LyShine
+ TARGETS MaterialEditor
+ VARIANTS Tools)
+
# The pipeline tools use "Builders" gem variants:
ly_enable_gems(
PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt
index 1c555c1e17..a589a395c1 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt
@@ -12,6 +12,11 @@
################################################################################
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
+ # Only enable AWS automated tests on Windows
+ if(NOT "${PAL_PLATFORM_NAME}" STREQUAL "Windows")
+ return()
+ endif()
+
# Enable after installing NodeJS and CDK on jenkins Windows AMI.
ly_add_pytest(
NAME AutomatedTesting::AWSTests
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/README.md b/AutomatedTesting/Gem/PythonTests/AWS/README.md
new file mode 100644
index 0000000000..8b5e65d6d7
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/AWS/README.md
@@ -0,0 +1,26 @@
+# AWS Gem Automation Tests
+
+## Prerequisites
+1. Build the O3DE Editor and AutomatedTesting.GameLauncher in Profile.
+2. AWS CLI is installed and configured following [Configuration and Credential File Settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html).
+3. [AWS Cloud Development Kit (CDK)](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html#getting_started_install) is installed.
+
+## Deploy CDK Applications
+1. Go to the AWS IAM console and create an IAM role called o3de-automation-tests which adds your own account as as a trusted entity and uses the "AdministratorAccess" permissions policy.
+2. Copy {engine_root}\scripts\build\Platform\Windows\deploy_cdk_applications.cmd to your engine root folder.
+3. Open a Command Prompt window at the engine root and set the following environment variables:
+ Set O3DE_AWS_PROJECT_NAME=AWSAUTO
+ Set O3DE_AWS_DEPLOY_REGION=us-east-1
+ Set ASSUME_ROLE_ARN="arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests"
+ Set COMMIT_ID=HEAD
+4. Deploy the CDK applications for AWS gems by running deploy_cdk_applications.cmd in the same Command Prompt window.
+5. Edit AWS\common\constants.py to replace the assume role ARN with your own:
+ arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests
+
+## Run Automation Tests
+### CLI
+Open a Command Prompt window at the engine root and run the following CLI command:
+python\python.cmd -m pytest {path_to_the_test_file} --build-directory {directory_to_the_profile_build}
+
+### Pycharm
+You can also run any specific automation test directly from Pycharm by providing the "--build-directory" argument in the Run Configuration.
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
index cd8858e7f2..061db991cf 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
@@ -9,18 +9,18 @@ import logging
import os
import pytest
import typing
-
from datetime import datetime
+
import ly_test_tools.log.log_monitor
+from AWS.common import constants
+from .aws_metrics_custom_thread import AWSMetricsThread
+
# fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
from .aws_metrics_utils import aws_metrics_utils
-from .aws_metrics_custom_thread import AWSMetricsThread
AWS_METRICS_FEATURE_NAME = 'AWSMetrics'
-GAME_LOG_NAME = 'Game.log'
-CONTEXT_VARIABLE = ['-c', 'batch_processing=true']
logger = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ def setup(launcher: pytest.fixture,
asset_processor.start()
asset_processor.wait_for_idle()
- file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), GAME_LOG_NAME)
+ file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
# Initialize the log monitor.
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
@@ -73,23 +73,26 @@ def monitor_metrics_submission(log_monitor: pytest.fixture) -> None:
f'unexpected_lines values: {unexpected_lines}')
-def query_metrics_from_s3(aws_metrics_utils: pytest.fixture, stack_name: str) -> None:
+def query_metrics_from_s3(aws_metrics_utils: pytest.fixture, resource_mappings: pytest.fixture, stack_name: str) -> None:
"""
Verify that the metrics events are delivered to the S3 bucket and can be queried.
- aws_metrics_utils: aws_metrics_utils fixture.
- stack_name: name of the CloudFormation stack.
+ :param aws_metrics_utils: aws_metrics_utils fixture.
+ :param resource_mappings: resource_mappings fixture.
+ :param stack_name: name of the CloudFormation stack.
"""
- analytics_bucket_name = aws_metrics_utils.get_analytics_bucket_name(stack_name)
- aws_metrics_utils.verify_s3_delivery(analytics_bucket_name)
+ aws_metrics_utils.verify_s3_delivery(
+ resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName')
+ )
logger.info('Metrics are sent to S3.')
- aws_metrics_utils.run_glue_crawler(f'{stack_name}-EventsCrawler')
+ aws_metrics_utils.run_glue_crawler(
+ resource_mappings.get_resource_name_id('AWSMetrics.EventsCrawlerName'))
+
+ # Remove the events_json table if exists so that the sample query can create a table with the same name.
+ aws_metrics_utils.delete_table(f'{stack_name}-eventsdatabase', 'events_json')
aws_metrics_utils.run_named_queries(f'{stack_name}-AthenaWorkGroup')
logger.info('Query metrics from S3 successfully.')
- # Empty the S3 bucket. S3 buckets can only be deleted successfully when it doesn't contain any object.
- aws_metrics_utils.empty_batch_analytics_bucket(analytics_bucket_name)
-
def verify_operational_metrics(aws_metrics_utils: pytest.fixture, stack_name: str, start_time: datetime) -> None:
"""
@@ -102,7 +105,7 @@ def verify_operational_metrics(aws_metrics_utils: pytest.fixture, stack_name: st
'AWS/Lambda',
'Invocations',
[{'Name': 'FunctionName',
- 'Value': f'{stack_name}-AnalyticsProcessingLambdaName'}],
+ 'Value': f'{stack_name}-AnalyticsProcessingLambda'}],
start_time)
logger.info('AnalyticsProcessingLambda metrics are sent to CloudWatch.')
@@ -115,50 +118,59 @@ def verify_operational_metrics(aws_metrics_utils: pytest.fixture, stack_name: st
logger.info('EventsProcessingLambda metrics are sent to CloudWatch.')
-def start_kinesis_analytics_application(aws_metrics_utils: pytest.fixture, stack_name: str) -> None:
+def update_kinesis_analytics_application_status(aws_metrics_utils: pytest.fixture,
+ resource_mappings: pytest.fixture, start_application: bool) -> None:
"""
- Start the Kinesis analytics application for real-time analytics.
- aws_metrics_utils: aws_metrics_utils fixture.
- stack_name: name of the CloudFormation stack.
+ Update the Kinesis analytics application to start or stop it.
+ :param aws_metrics_utils: aws_metrics_utils fixture.
+ :param resource_mappings: resource_mappings fixture.
+ :param start_application: whether to start or stop the application.
"""
- analytics_application_name = f'{stack_name}-AnalyticsApplication'
- aws_metrics_utils.start_kinesis_data_analytics_application(analytics_application_name)
+ if start_application:
+ aws_metrics_utils.start_kinesis_data_analytics_application(
+ resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsApplicationName'))
+ else:
+ aws_metrics_utils.stop_kinesis_data_analytics_application(
+ resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsApplicationName'))
@pytest.mark.SUITE_periodic
@pytest.mark.usefixtures('automatic_process_killer')
-@pytest.mark.parametrize('project', ['AutomatedTesting'])
-@pytest.mark.parametrize('level', ['AWS/Metrics'])
-@pytest.mark.parametrize('feature_name', [AWS_METRICS_FEATURE_NAME])
-@pytest.mark.usefixtures('resource_mappings')
-@pytest.mark.parametrize('resource_mappings_filename', ['default_aws_resource_mappings.json'])
@pytest.mark.usefixtures('aws_credentials')
+@pytest.mark.usefixtures('resource_mappings')
+@pytest.mark.parametrize('assume_role_arn', [constants.ASSUME_ROLE_ARN])
+@pytest.mark.parametrize('feature_name', [AWS_METRICS_FEATURE_NAME])
+@pytest.mark.parametrize('level', ['AWS/Metrics'])
@pytest.mark.parametrize('profile_name', ['AWSAutomationTest'])
-@pytest.mark.parametrize('region_name', ['us-west-2'])
-@pytest.mark.parametrize('assume_role_arn', ['arn:aws:iam::645075835648:role/o3de-automation-tests'])
-@pytest.mark.usefixtures('cdk')
-@pytest.mark.parametrize('session_name', ['o3de-Automation-session'])
-@pytest.mark.parametrize('deployment_params', [CONTEXT_VARIABLE])
+@pytest.mark.parametrize('project', ['AutomatedTesting'])
+@pytest.mark.parametrize('region_name', [constants.AWS_REGION])
+@pytest.mark.parametrize('resource_mappings_filename', [constants.AWS_RESOURCE_MAPPING_FILE_NAME])
+@pytest.mark.parametrize('session_name', [constants.SESSION_NAME])
+@pytest.mark.parametrize('stacks', [[f'{constants.AWS_PROJECT_NAME}-{AWS_METRICS_FEATURE_NAME}-{constants.AWS_REGION}']])
class TestAWSMetricsWindows(object):
"""
Test class to verify the real-time and batch analytics for metrics.
"""
-
- @pytest.mark.parametrize('destroy_stacks_on_teardown', [False])
def test_realtime_and_batch_analytics(self,
level: str,
launcher: pytest.fixture,
asset_processor: pytest.fixture,
workspace: pytest.fixture,
aws_utils: pytest.fixture,
- cdk: pytest.fixture,
+ resource_mappings: pytest.fixture,
+ stacks: typing.List,
aws_metrics_utils: pytest.fixture):
"""
Verify that the metrics events are sent to CloudWatch and S3 for analytics.
"""
# Start Kinesis analytics application on a separate thread to avoid blocking the test.
- kinesis_analytics_application_thread = AWSMetricsThread(target=start_kinesis_analytics_application,
- args=(aws_metrics_utils, cdk.stacks[0]))
+ kinesis_analytics_application_thread = AWSMetricsThread(target=update_kinesis_analytics_application_status,
+ args=(aws_metrics_utils, resource_mappings, True))
kinesis_analytics_application_thread.start()
+
+ # Clear the analytics bucket objects before sending new metrics.
+ aws_metrics_utils.empty_bucket(
+ resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName'))
+
log_monitor = setup(launcher, asset_processor)
# Kinesis analytics application needs to be in the running state before we start the game launcher.
@@ -177,18 +189,22 @@ class TestAWSMetricsWindows(object):
start_time)
logger.info('Real-time metrics are sent to CloudWatch.')
- # Run time-consuming verifications on separate threads to avoid blocking the test.
- verification_threads = list()
- verification_threads.append(
- AWSMetricsThread(target=query_metrics_from_s3, args=(aws_metrics_utils, cdk.stacks[0])))
- verification_threads.append(
- AWSMetricsThread(target=verify_operational_metrics, args=(aws_metrics_utils, cdk.stacks[0], start_time)))
- for thread in verification_threads:
+ # Run time-consuming operations on separate threads to avoid blocking the test.
+ operational_threads = list()
+ operational_threads.append(
+ AWSMetricsThread(target=query_metrics_from_s3,
+ args=(aws_metrics_utils, resource_mappings, stacks[0])))
+ operational_threads.append(
+ AWSMetricsThread(target=verify_operational_metrics,
+ args=(aws_metrics_utils, stacks[0], start_time)))
+ operational_threads.append(
+ AWSMetricsThread(target=update_kinesis_analytics_application_status,
+ args=(aws_metrics_utils, resource_mappings, False)))
+ for thread in operational_threads:
thread.start()
- for thread in verification_threads:
+ for thread in operational_threads:
thread.join()
- @pytest.mark.parametrize('destroy_stacks_on_teardown', [True])
def test_unauthorized_user_request_rejected(self,
level: str,
launcher: pytest.fixture,
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_utils.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_utils.py
index 97cd563651..e7eb486d02 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_utils.py
@@ -198,7 +198,7 @@ class AWSMetricsUtils:
assert state == 'SUCCEEDED', f'Failed to run the named query {named_query.get("Name", {})}'
- def empty_batch_analytics_bucket(self, bucket_name: str) -> None:
+ def empty_bucket(self, bucket_name: str) -> None:
"""
Empty the S3 bucket following:
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/migrations3.html
@@ -211,25 +211,18 @@ class AWSMetricsUtils:
for key in bucket.objects.all():
key.delete()
- def get_analytics_bucket_name(self, stack_name: str) -> str:
+ def delete_table(self, database_name: str, table_name: str) -> None:
"""
- Get the name of the deployed S3 bucket.
- :param stack_name: Name of the CloudFormation stack.
- :return: Name of the deployed S3 bucket.
+ Delete an existing Glue table.
+
+ :param database_name: Name of the Glue database.
+ :param table_name: Name of the table to delete.
"""
-
- client = self._aws_util.client('cloudformation')
-
- response = client.describe_stack_resources(
- StackName=stack_name
+ client = self._aws_util.client('glue')
+ client.delete_table(
+ DatabaseName=database_name,
+ Name=table_name
)
- resources = response.get('StackResources', [])
-
- for resource in resources:
- if resource.get('ResourceType') == 'AWS::S3::Bucket':
- return resource.get('PhysicalResourceId', '')
-
- return ''
@pytest.fixture(scope='function')
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_waiters.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_waiters.py
index abfeaec076..46070a3a64 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_waiters.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_waiters.py
@@ -45,7 +45,8 @@ class KinesisAnalyticsApplicationUpdatedWaiter(CustomWaiter):
class GlueCrawlerReadyWaiter(CustomWaiter):
"""
Subclass of the base custom waiter class.
- Wait for the Glue crawler to finish its processing.
+ Wait for the Glue crawler to finish its processing. Return when the crawler is in the "Stopping" status
+ to avoid wasting too much time in the automation tests on its shutdown process.
"""
def __init__(self, client: botocore.client):
"""
@@ -57,7 +58,7 @@ class GlueCrawlerReadyWaiter(CustomWaiter):
'GlueCrawlerReady',
'GetCrawler',
'Crawler.State',
- {'READY': WaitState.SUCCESS},
+ {'STOPPING': WaitState.SUCCESS},
client)
def wait(self, crawler_name):
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/__init__.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/__init__.py
deleted file mode 100644
index bbcbcf1807..0000000000
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/cdk_utils.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/cdk_utils.py
deleted file mode 100644
index 3643c3bb36..0000000000
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/cdk/cdk_utils.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-import os
-import pytest
-import boto3
-import uuid
-import logging
-import subprocess
-import botocore
-
-import ly_test_tools.environment.process_utils as process_utils
-from typing import List
-
-BOOTSTRAP_STACK_NAME = 'CDKToolkit'
-BOOTSTRAP_STAGING_BUCKET_LOGIC_ID = 'StagingBucket'
-
-logger = logging.getLogger(__name__)
-
-
-class Cdk:
- """
- Cdk class that provides methods to run cdk application commands.
- Expects system to have NodeJS, AWS CLI and CDK installed globally and have their paths setup as env variables.
- """
-
- def __init__(self):
- self._cdk_env = ''
- self._stacks = []
- self._cdk_path = os.path.dirname(os.path.realpath(__file__))
- self._session = ''
-
- cdk_npm_latest_version_cmd = ['npm', 'view', 'aws-cdk', 'version']
-
- output = process_utils.check_output(
- cdk_npm_latest_version_cmd,
- cwd=self._cdk_path,
- shell=True)
- cdk_npm_latest_version = output.split()[0]
-
- cdk_version_cmd = ['cdk', 'version']
- output = process_utils.check_output(
- cdk_version_cmd,
- cwd=self._cdk_path,
- shell=True)
- cdk_version = output.split()[0]
- logger.info(f'Current CDK version {cdk_version}')
-
- if cdk_version != cdk_npm_latest_version:
- try:
- logger.info(f'Updating CDK to latest')
- # uninstall and reinstall cdk in case npm has been updated.
- output = process_utils.check_output(
- 'npm uninstall -g aws-cdk',
- cwd=self._cdk_path,
- shell=True)
-
- logger.info(f'Uninstall CDK output: {output}')
-
- output = process_utils.check_output(
- 'npm install -g aws-cdk@latest',
- cwd=self._cdk_path,
- shell=True)
-
- logger.info(f'Install CDK output: {output}')
- except subprocess.CalledProcessError as error:
- logger.warning(f'Failed reinstalling latest CDK on npm'
- f'\nError:{error.stderr}')
-
- def setup(self, cdk_path: str, project: str, account_id: str,
- workspace: pytest.fixture, session: boto3.session.Session):
- """
- :param cdk_path: Path where cdk app.py is stored.
- :param project: Project name used for cdk project name env variable.
- :param account_id: AWS account id to use with cdk application.
- :param workspace: ly_test_tools workspace fixture.
- :param session: Current boto3 session, provides credentials and region.
- """
- self._cdk_env = os.environ.copy()
- unique_id = uuid.uuid4().hex[-4:]
- self._cdk_env['O3DE_AWS_PROJECT_NAME'] = project[:4] + unique_id if len(project) > 4 else project + unique_id
- self._cdk_env['O3DE_AWS_DEPLOY_REGION'] = session.region_name
- self._cdk_env['O3DE_AWS_DEPLOY_ACCOUNT'] = account_id
- self._cdk_env['PATH'] = f'{workspace.paths.engine_root()}\\python;' + self._cdk_env['PATH']
-
- credentials = session.get_credentials().get_frozen_credentials()
- self._cdk_env['AWS_ACCESS_KEY_ID'] = credentials.access_key
- self._cdk_env['AWS_SECRET_ACCESS_KEY'] = credentials.secret_key
- self._cdk_env['AWS_SESSION_TOKEN'] = credentials.token
- self._cdk_path = cdk_path
-
- self._session = session
-
- output = process_utils.check_output(
- 'python -m pip install -r requirements.txt',
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
-
- logger.info(f'Installing cdk python dependencies: {output}')
-
- self.bootstrap()
-
- def bootstrap(self) -> None:
- """
- Deploy the bootstrap stack.
- """
- try:
- bootstrap_cmd = ['cdk', 'bootstrap',
- f'aws://{self._cdk_env["O3DE_AWS_DEPLOY_ACCOUNT"]}/{self._cdk_env["O3DE_AWS_DEPLOY_REGION"]}']
-
- process_utils.check_call(
- bootstrap_cmd,
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
- except botocore.exceptions.ClientError as clientError:
- logger.warning(f'Failed creating Bootstrap stack {BOOTSTRAP_STACK_NAME} not found. '
- f'\nError:{clientError["Error"]["Message"]}')
-
- def list(self, deployment_params: List[str] = None) -> List[str]:
- """
- lists cdk stack names.
- :param deployment_params: Deployment parameters like --all can be passed in this way.
- :return List of cdk stack names.
- """
- if not self._cdk_path:
- return []
-
- list_cdk_application_cmd = ['cdk', 'list']
- if deployment_params:
- list_cdk_application_cmd.extend(deployment_params)
-
- output = process_utils.check_output(
- list_cdk_application_cmd,
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
-
- return output.splitlines()
-
- def synthesize(self, deployment_params: List[str] = None) -> None:
- """
- Synthesizes all cdk stacks.
- :param deployment_params: Deployment parameters like --all can be passed in this way.
- """
- if not self._cdk_path:
- return
-
- synth_cdk_application_cmd = ['cdk', 'synth']
- if deployment_params:
- synth_cdk_application_cmd.extend(deployment_params)
-
- process_utils.check_output(
- synth_cdk_application_cmd,
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
-
- def deploy(self, deployment_params: List[str] = None) -> List[str]:
- """
- Deploys all the CDK stacks.
- :param deployment_params: Deployment parameters like --all can be passed in this way.
- :return List of deployed stack arns.
- """
- if not self._cdk_path:
- return []
-
- deploy_cdk_application_cmd = ['cdk', 'deploy', '--require-approval', 'never']
- if deployment_params:
- deploy_cdk_application_cmd.extend(deployment_params)
-
- output = process_utils.check_output(
- deploy_cdk_application_cmd,
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
-
- for line in output.splitlines():
- line_sections = line.split('/')
- assert len(line_sections), 3
- self._stacks.append(line.split('/')[-2])
-
- return self._stacks
-
- def destroy(self, deployment_params: List[str] = None) -> None:
- """
- Destroys the cdk application.
- :param deployment_params: Deployment parameters like --all can be passed in this way.
- """
-
- logger.info(f'CDK Path {self._cdk_path}')
- destroy_cdk_application_cmd = ['cdk', 'destroy', '-f']
- if deployment_params:
- destroy_cdk_application_cmd.extend(deployment_params)
-
- try:
- process_utils.check_output(
- destroy_cdk_application_cmd,
- cwd=self._cdk_path,
- env=self._cdk_env,
- shell=True)
-
- except subprocess.CalledProcessError as e:
- logger.error(e.output)
- raise e
-
- self._stacks = []
-
- def remove_bootstrap_stack(self) -> None:
- """
- Remove the CDK bootstrap stack.
- :param aws_utils: aws_utils fixture.
- """
- # Check if the bootstrap stack exists.
- response = self._session.client('cloudformation').describe_stacks(
- StackName=BOOTSTRAP_STACK_NAME
- )
- stacks = response.get('Stacks', [])
- if not stacks or len(stacks) is 0:
- return
-
- # Clear the bootstrap staging bucket before deleting the bootstrap stack.
- response = self._session.client('cloudformation').describe_stack_resource(
- StackName=BOOTSTRAP_STACK_NAME,
- LogicalResourceId=BOOTSTRAP_STAGING_BUCKET_LOGIC_ID
- )
-
- staging_bucket_name = response.get('StackResourceDetail', {}).get('PhysicalResourceId', '')
- if staging_bucket_name:
- s3 = self._session.resource('s3')
- bucket = s3.Bucket(staging_bucket_name)
- for key in bucket.objects.all():
- key.delete()
-
- # Delete the bootstrap stack.
- # Should not need to delete the stack if S3 bucket can be cleaned.
- # self._session.client('cloudformation').delete_stack(
- # StackName=BOOTSTRAP_STACK_NAME
- # )
-
- @property
- def stacks(self):
- return self._stacks
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/client_auth/aws_client_auth_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/client_auth/aws_client_auth_automation_test.py
index bdd1eea469..b56d3f88f5 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/client_auth/aws_client_auth_automation_test.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/client_auth/aws_client_auth_automation_test.py
@@ -4,45 +4,42 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-import pytest
-import os
+
import logging
+import os
+import pytest
+
import ly_test_tools.log.log_monitor
+from AWS.common import constants
+
# fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
-AWS_PROJECT_NAME = 'AWS-AutomationTest'
AWS_CLIENT_AUTH_FEATURE_NAME = 'AWSClientAuth'
-AWS_CLIENT_AUTH_DEFAULT_PROFILE_NAME = 'default'
-
-GAME_LOG_NAME = 'Game.log'
logger = logging.getLogger(__name__)
@pytest.mark.SUITE_periodic
-@pytest.mark.usefixtures('automatic_process_killer')
@pytest.mark.usefixtures('asset_processor')
-@pytest.mark.usefixtures('workspace')
-@pytest.mark.parametrize('project', ['AutomatedTesting'])
-@pytest.mark.usefixtures('cdk')
-@pytest.mark.parametrize('feature_name', [AWS_CLIENT_AUTH_FEATURE_NAME])
-@pytest.mark.usefixtures('resource_mappings')
-@pytest.mark.parametrize('resource_mappings_filename', ['default_aws_resource_mappings.json'])
+@pytest.mark.usefixtures('automatic_process_killer')
@pytest.mark.usefixtures('aws_utils')
-@pytest.mark.parametrize('region_name', ['us-west-2'])
-@pytest.mark.parametrize('assume_role_arn', ['arn:aws:iam::645075835648:role/o3de-automation-tests'])
-@pytest.mark.parametrize('session_name', ['o3de-Automation-session'])
-@pytest.mark.usefixtures('cdk')
-@pytest.mark.parametrize('deployment_params', [[]])
+@pytest.mark.usefixtures('workspace')
+@pytest.mark.parametrize('assume_role_arn', [constants.ASSUME_ROLE_ARN])
+@pytest.mark.parametrize('feature_name', [AWS_CLIENT_AUTH_FEATURE_NAME])
+@pytest.mark.parametrize('project', ['AutomatedTesting'])
+@pytest.mark.usefixtures('resource_mappings')
+@pytest.mark.parametrize('resource_mappings_filename', [constants.AWS_RESOURCE_MAPPING_FILE_NAME])
+@pytest.mark.parametrize('region_name', [constants.AWS_REGION])
+@pytest.mark.parametrize('session_name', [constants.SESSION_NAME])
+@pytest.mark.parametrize('stacks', [[f'{constants.AWS_PROJECT_NAME}-{AWS_CLIENT_AUTH_FEATURE_NAME}-Stack-{constants.AWS_REGION}']])
class TestAWSClientAuthWindows(object):
"""
Test class to verify AWS Client Auth gem features on Windows.
"""
@pytest.mark.parametrize('level', ['AWS/ClientAuth'])
- @pytest.mark.parametrize('destroy_stacks_on_teardown', [False])
def test_anonymous_credentials(self,
level: str,
launcher: pytest.fixture,
@@ -53,14 +50,14 @@ class TestAWSClientAuthWindows(object):
"""
Test to verify AWS Cognito Identity pool anonymous authorization.
- Setup: Deploys cdk and updates resource mapping file.
+ Setup: Updates resource mapping file using existing CloudFormation stacks.
Tests: Getting credentials when no credentials are configured
Verification: Log monitor looks for success credentials log.
"""
asset_processor.start()
asset_processor.wait_for_idle()
- file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), GAME_LOG_NAME)
+ file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', level]
@@ -74,10 +71,8 @@ class TestAWSClientAuthWindows(object):
)
assert result, 'Anonymous credentials fetched successfully.'
- @pytest.mark.parametrize('destroy_stacks_on_teardown', [True])
def test_password_signin_credentials(self,
launcher: pytest.fixture,
- cdk: pytest.fixture,
resource_mappings: pytest.fixture,
workspace: pytest.fixture,
asset_processor: pytest.fixture,
@@ -86,16 +81,29 @@ class TestAWSClientAuthWindows(object):
"""
Test to verify AWS Cognito IDP Password sign in and Cognito Identity pool authenticated authorization.
- Setup: Deploys cdk and updates resource mapping file.
+ Setup: Updates resource mapping file using existing CloudFormation stacks.
Tests: Sign up new test user, admin confirm the user, sign in and get aws credentials.
Verification: Log monitor looks for success credentials log.
"""
asset_processor.start()
asset_processor.wait_for_idle()
- file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), GAME_LOG_NAME)
+ file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
+ cognito_idp = aws_utils.client('cognito-idp')
+ user_pool_id = resource_mappings.get_resource_name_id(f'{AWS_CLIENT_AUTH_FEATURE_NAME}.CognitoUserPoolId')
+ logger.info(f'UserPoolId:{user_pool_id}')
+
+ # Remove the user if already exists
+ try:
+ cognito_idp.admin_delete_user(
+ UserPoolId=user_pool_id,
+ Username='test1'
+ )
+ except cognito_idp.exceptions.UserNotFoundException:
+ pass
+
launcher.args = ['+LoadLevel', 'AWS/ClientAuthPasswordSignUp']
launcher.args.extend(['-rhi=null'])
@@ -109,9 +117,6 @@ class TestAWSClientAuthWindows(object):
launcher.stop()
- cognito_idp = aws_utils.client('cognito-idp')
- user_pool_id = resource_mappings.get_resource_name_id(f'{AWS_CLIENT_AUTH_FEATURE_NAME}.CognitoUserPoolId')
- print(f'UserPoolId:{user_pool_id}')
cognito_idp.admin_confirm_sign_up(
UserPoolId=user_pool_id,
Username='test1'
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
index 55f06660e8..529151f3f6 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
@@ -5,10 +5,11 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-import os
import logging
-import typing
+import os
import shutil
+import typing
+from botocore.exceptions import ClientError
import pytest
import ly_test_tools
@@ -16,16 +17,15 @@ import ly_test_tools.log.log_monitor
import ly_test_tools.environment.process_utils as process_utils
import ly_test_tools.o3de.asset_processor_utils as asset_processor_utils
-from botocore.exceptions import ClientError
+from AWS.common import constants
+
+# fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
AWS_CORE_FEATURE_NAME = 'AWSCore'
-AWS_RESOURCE_MAPPING_FILE_NAME = 'default_aws_resource_mappings.json'
process_utils.kill_processes_named("o3de", ignore_extensions=True) # Kill ProjectManager windows
-GAME_LOG_NAME = 'Game.log'
-
logger = logging.getLogger(__name__)
@@ -46,7 +46,7 @@ def setup(launcher: pytest.fixture, asset_processor: pytest.fixture) -> typing.T
asset_processor.start()
asset_processor.wait_for_idle()
- file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), GAME_LOG_NAME)
+ file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
return log_monitor, s3_download_dir
@@ -58,7 +58,7 @@ def write_test_data_to_dynamodb_table(resource_mappings: pytest.fixture, aws_uti
:param resource_mappings: resource_mappings fixture.
:param aws_utils: aws_utils fixture.
"""
- table_name = resource_mappings.get_resource_name_id("AWSCore.ExampleDynamoTableOutput")
+ table_name = resource_mappings.get_resource_name_id(f'{AWS_CORE_FEATURE_NAME}.ExampleDynamoTableOutput')
try:
aws_utils.client('dynamodb').put_item(
TableName=table_name,
@@ -77,21 +77,19 @@ def write_test_data_to_dynamodb_table(resource_mappings: pytest.fixture, aws_uti
@pytest.mark.SUITE_periodic
@pytest.mark.usefixtures('automatic_process_killer')
@pytest.mark.usefixtures('asset_processor')
-@pytest.mark.usefixtures('cdk')
@pytest.mark.parametrize('feature_name', [AWS_CORE_FEATURE_NAME])
-@pytest.mark.parametrize('region_name', ['us-west-2'])
-@pytest.mark.parametrize('assume_role_arn', ['arn:aws:iam::645075835648:role/o3de-automation-tests'])
-@pytest.mark.parametrize('session_name', ['o3de-Automation-session'])
+@pytest.mark.parametrize('region_name', [constants.AWS_REGION])
+@pytest.mark.parametrize('assume_role_arn', [constants.ASSUME_ROLE_ARN])
+@pytest.mark.parametrize('session_name', [constants.SESSION_NAME])
@pytest.mark.usefixtures('workspace')
@pytest.mark.parametrize('project', ['AutomatedTesting'])
@pytest.mark.parametrize('level', ['AWS/Core'])
@pytest.mark.usefixtures('resource_mappings')
-@pytest.mark.parametrize('resource_mappings_filename', [AWS_RESOURCE_MAPPING_FILE_NAME])
+@pytest.mark.parametrize('resource_mappings_filename', [constants.AWS_RESOURCE_MAPPING_FILE_NAME])
+@pytest.mark.parametrize('stacks', [[f'{constants.AWS_PROJECT_NAME}-{AWS_CORE_FEATURE_NAME}',
+ f'{constants.AWS_PROJECT_NAME}-{AWS_CORE_FEATURE_NAME}-Example-{constants.AWS_REGION}']])
@pytest.mark.usefixtures('aws_credentials')
@pytest.mark.parametrize('profile_name', ['AWSAutomationTest'])
-@pytest.mark.usefixtures('cdk')
-@pytest.mark.parametrize('deployment_params', [['--all']])
-@pytest.mark.parametrize('destroy_stacks_on_teardown', [True])
class TestAWSCoreAWSResourceInteraction(object):
"""
Test class to verify the scripting behavior for the AWSCore gem.
@@ -119,7 +117,7 @@ class TestAWSCoreAWSResourceInteraction(object):
expected_lines: typing.List[str],
unexpected_lines: typing.List[str]):
"""
- Setup: Deploys cdk and updates resource mapping file.
+ Setup: Updates resource mapping file using existing CloudFormation stacks.
Tests: Interact with AWS S3, DynamoDB and Lambda services.
Verification: Script canvas nodes can communicate with AWS services successfully.
"""
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/__init__.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/__init__.py
deleted file mode 100644
index e01850f919..0000000000
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/common/constants.py b/AutomatedTesting/Gem/PythonTests/AWS/common/constants.py
new file mode 100644
index 0000000000..be143547a7
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/AWS/common/constants.py
@@ -0,0 +1,19 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+# ARN of the IAM role to assume for retrieving temporary AWS credentials
+ASSUME_ROLE_ARN = 'arn:aws:iam::645075835648:role/o3de-automation-tests'
+# Name of the AWS project deployed by the CDK applications
+AWS_PROJECT_NAME = 'AWSAUTO'
+# Region for the existing CloudFormation stacks used by the automation tests
+AWS_REGION = 'us-east-1'
+# Name of the default resource mapping config file used by the automation tests
+AWS_RESOURCE_MAPPING_FILE_NAME = 'default_aws_resource_mappings.json'
+# Name of the game launcher log
+GAME_LOG_NAME = 'Game.log'
+# Name of the IAM role session for retrieving temporary AWS credentials
+SESSION_NAME = 'o3de-Automation-session'
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/resource_mappings.py b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
similarity index 90%
rename from AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/resource_mappings.py
rename to AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
index fd679de99d..5f01ecdbf8 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/resource_mappings/resource_mappings.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
@@ -6,9 +6,9 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import os
-import pytest
import json
import logging
+from AWS.common import constants
logger = logging.getLogger(__name__)
@@ -22,18 +22,14 @@ class ResourceMappings:
ResourceMappings class that handles writing Cloud formation outputs to resource mappings json file in a project.
"""
- def __init__(self, file_path: str, region: str, feature_name: str, account_id: str, workspace: pytest.fixture,
- cloud_formation_client):
+ def __init__(self, file_path: str, region: str, feature_name: str, account_id: str, cloud_formation_client):
"""
:param file_path: Path for the resource mapping file.
:param region: Region value for the resource mapping file.
:param feature_name: Feature gem name to use to append name to mappings key.
:param account_id: AWS account id value for the resource mapping file.
- :param workspace: ly_test_tools workspace fixture.
:param cloud_formation_client: AWS cloud formation client.
"""
- self._cdk_env = os.environ.copy()
- self._cdk_env['PATH'] = f'{workspace.paths.engine_root()}\\python;' + self._cdk_env['PATH']
self._resource_mapping_file_path = file_path
self._region = region
self._feature_name = feature_name
@@ -44,7 +40,7 @@ class ResourceMappings:
f'Invalid resource mapping file path {self._resource_mapping_file_path}'
self._client = cloud_formation_client
- def populate_output_keys(self, stacks=[]) -> None:
+ def populate_output_keys(self, stacks=None) -> None:
"""
Calls describe stacks on cloud formation service and persists outputs to resource mappings file.
:param stacks List of stack arns to describe and populate resource mappings with.
@@ -58,7 +54,7 @@ class ResourceMappings:
self._write_resource_mappings(stacks[0].get('Outputs', []))
- def _write_resource_mappings(self, outputs, append_feature_name = True) -> None:
+ def _write_resource_mappings(self, outputs, append_feature_name=True) -> None:
with open(self._resource_mapping_file_path) as file_content:
resource_mappings = json.load(file_content)
@@ -91,7 +87,7 @@ class ResourceMappings:
resource_mappings = json.load(file_content)
resource_mappings[AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY] = ''
- resource_mappings[AWS_RESOURCE_MAPPINGS_REGION_KEY] = 'us-west-2'
+ resource_mappings[AWS_RESOURCE_MAPPINGS_REGION_KEY] = constants.AWS_REGION
# Append new mappings.
resource_mappings[AWS_RESOURCE_MAPPINGS_KEY] = resource_mappings.get(AWS_RESOURCE_MAPPINGS_KEY, {})
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/conftest.py b/AutomatedTesting/Gem/PythonTests/AWS/conftest.py
index 6ad495ab66..df65aa7a5c 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/conftest.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/conftest.py
@@ -11,8 +11,7 @@ import typing
from AWS.common.aws_utils import AwsUtils
from AWS.common.aws_credentials import AwsCredentials
-from AWS.Windows.cdk.cdk_utils import Cdk
-from AWS.Windows.resource_mappings.resource_mappings import ResourceMappings
+from AWS.common.resource_mappings import ResourceMappings
logger = logging.getLogger(__name__)
@@ -52,6 +51,7 @@ def resource_mappings(
project: str,
feature_name: str,
resource_mappings_filename: str,
+ stacks: typing.List,
workspace: pytest.fixture,
aws_utils: pytest.fixture) -> ResourceMappings:
"""
@@ -61,6 +61,7 @@ def resource_mappings(
:param project: Project to find resource mapping file.
:param feature_name: AWS Gem name that is prepended to resource mapping keys.
:param resource_mappings_filename: Name of resource mapping file.
+ :param stacks: List of stack names to describe and populate resource mappings with.
:param workspace: ly_test_tools workspace fixture.
:param aws_utils: AWS utils fixture.
:return: ResourceMappings class object.
@@ -70,8 +71,8 @@ def resource_mappings(
logger.info(f'Resource mapping path : {path}')
logger.info(f'Resource mapping resolved path : {abspath(path)}')
resource_mappings_obj = ResourceMappings(abspath(path), aws_utils.assume_session().region_name, feature_name,
- aws_utils.assume_account_id(), workspace,
- aws_utils.client('cloudformation'))
+ aws_utils.assume_account_id(), aws_utils.client('cloudformation'))
+ resource_mappings_obj.populate_output_keys(stacks)
def teardown():
resource_mappings_obj.clear_output_keys()
@@ -81,56 +82,6 @@ def resource_mappings(
return resource_mappings_obj
-@pytest.fixture(scope='function')
-def cdk(
- request: pytest.fixture,
- project: str,
- feature_name: str,
- workspace: pytest.fixture,
- aws_utils: pytest.fixture,
- resource_mappings: pytest.fixture,
- deployment_params: typing.List[str],
- destroy_stacks_on_teardown: bool) -> Cdk:
- """
- Fixture for setting up a Cdk
- :param request: _pytest.fixtures.SubRequest class that handles getting
- a pytest fixture from a pytest function/fixture.
- :param project: Project name used for cdk project name env variable.
- :param feature_name: Feature gem name to expect cdk folder in.
- :param workspace: ly_test_tools workspace fixture.
- :param aws_utils: aws_utils fixture.
- :param resource_mappings: resource_mappings fixture.
- :param deployment_params: Parameters for the CDK application deployment.
- :param destroy_stacks_on_teardown: option to control calling destroy ot the end of test.
- :return Cdk class object.
- """
-
- cdk_path = f'{workspace.paths.engine_root()}/Gems/{feature_name}/cdk'
- logger.info(f'CDK Path {cdk_path}')
-
- if pytest.cdk_obj is None:
- pytest.cdk_obj = Cdk()
- pytest.cdk_obj.setup(cdk_path, project, aws_utils.assume_account_id(), workspace, aws_utils.assume_session())
-
- stacks = pytest.cdk_obj.deploy(deployment_params=deployment_params)
-
- logger.info(f'Cdk stack names:\n{stacks}')
- resource_mappings.populate_output_keys(stacks)
-
- def teardown():
- if destroy_stacks_on_teardown:
- pytest.cdk_obj.destroy(deployment_params=deployment_params)
- # Enable after https://github.com/aws/aws-cdk/issues/986 is fixed.
- # Until then clean the bootstrap bucket manually.
- # pytest.cdk_obj.remove_bootstrap_stack()
-
- pytest.cdk_obj = None
-
- request.addfinalizer(teardown)
-
- return pytest.cdk_obj
-
-
@pytest.fixture(scope='function')
def aws_credentials(request: pytest.fixture, aws_utils: pytest.fixture, profile_name: str):
"""
diff --git a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt
index 7048a6bd46..172eded09a 100644
--- a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE main
TEST_SERIAL TRUE
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt
index 0405dacbf4..90afee39bc 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt
@@ -8,7 +8,7 @@ INTRODUCTION
------------
EditorPythonBindings is a Python project that contains a collection of editor testing tools
-developed by the Lumberyard feature teams. The project contains tools for system level
+developed by the O3DE feature teams. The project contains tools for system level
editor tests.
@@ -23,7 +23,7 @@ installed on your system.
INSTALL
-----------
-It is recommended to set up these these tools with Lumberyard's CMake build commands.
+It is recommended to set up these these tools with O3DE's CMake build commands.
Assuming CMake is already setup on your operating system, below are some sample build commands:
cd /path/to/od3e/
mkdir windows_vs2019
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py
index cec1b6456b..985e32ede5 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py
@@ -8,6 +8,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
import azlmbr.bus as bus
import azlmbr.editor as editor
import azlmbr.entity as entity
+import azlmbr.legacy.general as general
import azlmbr.object
from typing import List
@@ -428,3 +429,32 @@ def get_component_type_id_map(component_name_list):
type_ids_by_component[component_names[i]] = typeId
return type_ids_by_component
+
+
+def attach_component_to_entity(entity_id, component_name):
+ # type: (azlmbr.entity.EntityId, str) -> azlmbr.entity.EntityComponentIdPair
+ """
+ Adds the component if not added already.
+ :param entity_id: EntityId of the entity to attach the component to
+ :param component_name: name of the component
+ :return: If successful, returns the EntityComponentIdPair, otherwise returns None.
+ """
+ type_ids_list = editor.EditorComponentAPIBus(
+ bus.Broadcast, 'FindComponentTypeIdsByEntityType', [component_name], 0)
+ general.log(f"Components found = {len(type_ids_list)}")
+ if len(type_ids_list) < 1:
+ general.log(f"ERROR: A component class with name {component_name} doesn't exist")
+ return None
+ elif len(type_ids_list) > 1:
+ general.log(f"ERROR: Found more than one component classes with same name: {component_name}")
+ return None
+ # Before adding the component let's check if it is already attached to the entity.
+ component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', entity_id, type_ids_list[0])
+ if component_outcome.IsSuccess():
+ return component_outcome.GetValue() # In this case the value is not a list.
+ component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', entity_id, type_ids_list)
+ if component_outcome.IsSuccess():
+ general.log(f"{component_name} Component added to entity.")
+ return component_outcome.GetValue()[0]
+ general.log(f"ERROR: Failed to add component [{component_name}] to entity")
+ return None
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py
index 3004b9ec7d..3d4d9ea419 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py
@@ -29,7 +29,7 @@ def teardown_editor(editor):
def launch_and_validate_results(request, test_directory, editor, editor_script, expected_lines, unexpected_lines=[],
halt_on_unexpected=False, run_python="--runpythontest", auto_test_mode=True, null_renderer=True, cfg_args=[],
- timeout=300):
+ timeout=300, log_file_name="Editor.log"):
"""
Runs the Editor with the specified script, and monitors for expected log lines.
:param request: Special fixture providing information of the requesting test function.
@@ -44,6 +44,7 @@ def launch_and_validate_results(request, test_directory, editor, editor_script,
:param null_renderer: Specifies the test does not require the renderer. Defaults to True.
:param cfg_args: Additional arguments for CFG, such as LevelName.
:param timeout: Length of time for test to run. Default is 60.
+ :param log_file_name: Name of the log file created by the editor. Defaults to 'Editor.log'
"""
test_case = os.path.join(test_directory, editor_script)
request.addfinalizer(lambda: teardown_editor(editor))
@@ -58,7 +59,17 @@ def launch_and_validate_results(request, test_directory, editor, editor_script,
with editor.start():
- editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log')
+ editorlog_file = os.path.join(editor.workspace.paths.project_log(), log_file_name)
+
+ # Log monitor requires the file to exist.
+ logger.debug(f"Waiting until log file <{editorlog_file}> exists...")
+ waiter.wait_for(
+ lambda: os.path.exists(editorlog_file),
+ timeout=60,
+ exc=f"Log file '{editorlog_file}' was never created by another process.",
+ interval=1,
+ )
+ logger.debug(f"Done! log file <{editorlog_file}> exists.")
# Initialize the log monitor and set time to wait for log creation
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=editor, log_file_path=editorlog_file)
diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt
index a39cdf04cf..3913041f88 100644
--- a/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_REQUIRES gpu
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py
index 1fe60e3707..45e633a979 100644
--- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py
+++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py
@@ -27,19 +27,19 @@ class TestPythonAssetProcessing(object):
unexpected_lines = []
expected_lines = [
'Mock asset exists',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel) found',
- 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found'
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found',
+ 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found'
]
timeout = 180
halt_on_unexpected = False
test_directory = os.path.join(os.path.dirname(__file__))
testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py')
- editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile])
+ editor.args.extend(['-NullRenderer', '-rhi=Null', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile])
with editor.start():
editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log')
diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py
index c1519a6fdb..8d418222ce 100644
--- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py
+++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py
@@ -29,21 +29,21 @@ if (assetIdString.endswith(':528cca58') is False):
print ('Mock asset exists')
# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets
-def test_azmodel_product(generatedModelAssetPath, expectedSubId):
+def test_azmodel_product(generatedModelAssetPath):
azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0)
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False)
assetIdString = assetId.to_string()
- if (assetIdString.endswith(':' + expectedSubId) is False):
- raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath}), expected {expectedSubId}!')
+ if (assetId.is_valid()):
+ print(f'AssetId found for asset ({generatedModelAssetPath}) found')
else:
- print(f'Expected subId for asset ({generatedModelAssetPath}) found')
+ raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel', '1024be55')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel', '1052c94e')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel', '10130556')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel', '1065724d')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel', '10d16e68')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel', '10a71973')
-test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel')
+test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel')
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt
index 9b6542b3e3..905470e08f 100644
--- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt
index b5fcfcc44c..1c7a02862d 100644
--- a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE main
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt
index 0170d73af0..3d7a9204e2 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt
@@ -92,17 +92,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AZ::AssetProcessor
)
- ly_add_pytest(
- NAME AssetPipelineTests.AssetBundler
- PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
- EXCLUDE_TEST_RUN_TARGET_FROM_IDE
- TEST_SERIAL
- TIMEOUT 2400
- TEST_SUITE periodic
- RUNTIME_DEPENDENCIES
- AZ::AssetProcessor
- AZ::AssetBundlerBatch
- )
+ # Issue #3017
+ #ly_add_pytest(
+ # NAME AssetPipelineTests.AssetBundler
+ # PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
+ # EXCLUDE_TEST_RUN_TARGET_FROM_IDE
+ # TEST_SERIAL
+ # TEST_SUITE periodic
+ # RUNTIME_DEPENDENCIES
+ # AZ::AssetProcessor
+ # AZ::AssetBundlerBatch
+ #)
ly_add_pytest(
NAME AssetPipelineTests.AssetBundler_SandBox
@@ -111,7 +111,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
PYTEST_MARKS "SUITE_sandbox" # run only sandbox tests in this file
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
TEST_SERIAL
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
AZ::AssetBundlerBatch
@@ -133,7 +132,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
TEST_SERIAL
- TIMEOUT 1500
TEST_SUITE periodic
RUNTIME_DEPENDENCIES
AZ::AssetProcessorBatch
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt
index d4f036faeb..f056623ecd 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt
@@ -39,7 +39,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
TEST_SUITE main
TEST_REQUIRES gpu
TEST_SERIAL
- TIMEOUT 800
+ TIMEOUT 1200
PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_GPUTests.py
RUNTIME_DEPENDENCIES
AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py
index b4031d2ffa..cd10caf57b 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py
@@ -206,8 +206,8 @@ def run():
# PostFX Layer Component
ComponentTests("PostFX Layer")
- # Radius Weight Modifier Component
- ComponentTests("Radius Weight Modifier")
+ # PostFX Radius Weight Modifier Component
+ ComponentTests("PostFX Radius Weight Modifier")
# Light Component
ComponentTests("Light")
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py
index ec8dc199ae..24866f3b19 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py
@@ -19,7 +19,7 @@ import azlmbr.legacy.general as general
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
-from atom_renderer.atom_utils.atom_component_helper import LIGHT_TYPES
+from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES
LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type'
SPHERE_AND_SPOT_DISK_LIGHT_PROPERTIES = [
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py
new file mode 100644
index 0000000000..b3c51ca912
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py
@@ -0,0 +1,183 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe
+This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe
+You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear.
+"""
+
+import os
+import sys
+import time
+
+import azlmbr.math as math
+import azlmbr.paths
+
+sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
+
+import atom_renderer.atom_utils.material_editor_utils as material_editor
+
+NEW_MATERIAL = "test_material.material"
+NEW_MATERIAL_1 = "test_material_1.material"
+NEW_MATERIAL_2 = "test_material_2.material"
+TEST_MATERIAL_1 = "001_DefaultWhite.material"
+TEST_MATERIAL_2 = "002_BaseColorLerp.material"
+TEST_MATERIAL_3 = "003_MetalMatte.material"
+TEST_DATA_PATH = os.path.join(
+ azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
+)
+MATERIAL_TYPE_PATH = os.path.join(
+ azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets",
+ "Materials", "Types", "StandardPBR.materialtype",
+)
+
+
+def run():
+ """
+ Summary:
+ Material Editor basic tests including the below
+ 1. Opening an Existing Asset
+ 2. Creating a New Asset
+ 3. Closing Selected Material
+ 4. Closing All Materials
+ 5. Closing all but Selected Material
+ 6. Saving Material
+ 7. Saving as a New Material
+ 8. Saving as a Child Material
+ 9. Saving all Open Materials
+
+ Expected Result:
+ All the above functions work as expected in Material Editor.
+
+ :return: None
+ """
+
+ # 1) Test Case: Opening an Existing Asset
+ document_id = material_editor.open_material(MATERIAL_TYPE_PATH)
+ print(f"Material opened: {material_editor.is_open(document_id)}")
+
+ # Verify if the test material exists initially
+ target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL)
+ print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}")
+
+ # 2) Test Case: Creating a New Material Using Existing One
+ material_editor.save_document_as_child(document_id, target_path)
+ material_editor.wait_for_condition(lambda: os.path.exists(target_path), 2.0)
+ print(f"New asset created: {os.path.exists(target_path)}")
+
+ # Verify if the newly created document is open
+ new_document_id = material_editor.open_material(target_path)
+ material_editor.wait_for_condition(lambda: material_editor.is_open(new_document_id))
+ print(f"New Material opened: {material_editor.is_open(new_document_id)}")
+
+ # 3) Test Case: Closing Selected Material
+ print(f"Material closed: {material_editor.close_document(new_document_id)}")
+
+ # Open materials initially
+ document1_id, document2_id, document3_id = (
+ material_editor.open_material(os.path.join(TEST_DATA_PATH, material))
+ for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3]
+ )
+
+ # 4) Test Case: Closing All Materials
+ print(f"All documents closed: {material_editor.close_all_documents()}")
+
+ # 5) Test Case: Closing all but Selected Material
+ document1_id, document2_id, document3_id = (
+ material_editor.open_material(os.path.join(TEST_DATA_PATH, material))
+ for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3]
+ )
+ result = material_editor.close_all_except_selected(document1_id)
+ print(f"Close All Except Selected worked as expected: {result and material_editor.is_open(document1_id)}")
+
+ # 6) Test Case: Saving Material
+ document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
+ property_name = azlmbr.name.Name("baseColor.color")
+ initial_color = material_editor.get_property(document_id, property_name)
+ # Assign new color to the material file and save the actual material
+ expected_color = math.Color(0.25, 0.25, 0.25, 1.0)
+ material_editor.set_property(document_id, property_name, expected_color)
+ material_editor.save_document(document_id)
+
+ # 7) Test Case: Saving as a New Material
+ # Assign new color to the material file and save the document as copy
+ expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0)
+ material_editor.set_property(document_id, property_name, expected_color_1)
+ target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1)
+ material_editor.save_document_as_copy(document_id, target_path_1)
+ time.sleep(2.0)
+
+ # 8) Test Case: Saving as a Child Material
+ # Assign new color to the material file save the document as child
+ expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0)
+ material_editor.set_property(document_id, property_name, expected_color_2)
+ target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2)
+ material_editor.save_document_as_child(document_id, target_path_2)
+ time.sleep(2.0)
+
+ # Close/Reopen documents
+ material_editor.close_all_documents()
+ document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
+ document1_id = material_editor.open_material(target_path_1)
+ document2_id = material_editor.open_material(target_path_2)
+
+ # Verify if the changes are saved in the actual document
+ actual_color = material_editor.get_property(document_id, property_name)
+ print(f"Actual Document saved with changes: {material_editor.compare_colors(actual_color, expected_color)}")
+
+ # Verify if the changes are saved in the document saved as copy
+ actual_color = material_editor.get_property(document1_id, property_name)
+ result_copy = material_editor.compare_colors(actual_color, expected_color_1)
+ print(f"Document saved as copy is saved with changes: {result_copy}")
+
+ # Verify if the changes are saved in the document saved as child
+ actual_color = material_editor.get_property(document2_id, property_name)
+ result_child = material_editor.compare_colors(actual_color, expected_color_2)
+ print(f"Document saved as child is saved with changes: {result_child}")
+
+ # Revert back the changes in the actual document
+ material_editor.set_property(document_id, property_name, initial_color)
+ material_editor.save_document(document_id)
+ material_editor.close_all_documents()
+
+ # 9) Test Case: Saving all Open Materials
+ # Open first material and make change to the values
+ document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
+ property1_name = azlmbr.name.Name("metallic.factor")
+ initial_metallic_factor = material_editor.get_property(document1_id, property1_name)
+ expected_metallic_factor = 0.444
+ material_editor.set_property(document1_id, property1_name, expected_metallic_factor)
+
+ # Open second material and make change to the values
+ document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2))
+ property2_name = azlmbr.name.Name("baseColor.color")
+ initial_color = material_editor.get_property(document2_id, property2_name)
+ expected_color = math.Color(0.4156, 0.0196, 0.6862, 1.0)
+ material_editor.set_property(document2_id, property2_name, expected_color)
+
+ # Save all and close all documents
+ material_editor.save_all()
+ material_editor.close_all_documents()
+
+ # Reopen materials and verify values
+ document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1))
+ result = material_editor.is_close(
+ material_editor.get_property(document1_id, property1_name), expected_metallic_factor, 0.00001
+ )
+ document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2))
+ result = result and material_editor.compare_colors(
+ expected_color, material_editor.get_property(document2_id, property2_name))
+ print(f"Save All worked as expected: {result}")
+
+ # Revert the changes made
+ material_editor.set_property(document1_id, property1_name, initial_metallic_factor)
+ material_editor.set_property(document2_id, property2_name, initial_color)
+ material_editor.save_all()
+ material_editor.close_all_documents()
+
+
+if __name__ == "__main__":
+ run()
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
index b899d7dcde..3aa9fe660c 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
@@ -93,6 +93,7 @@ def run():
general.idle_wait_frames(100)
for i in range(1, 101):
benchmarker.capture_pass_timestamp(i)
+ benchmarker.capture_cpu_frame_time(i)
general.exit_game_mode()
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0)
general.log("Capturing complete.")
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py
new file mode 100644
index 0000000000..8063445608
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py
@@ -0,0 +1,267 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+Hydra script that is used to create an entity with a Light component attached.
+It then updates the property values of the Light component and takes a screenshot.
+The screenshot is compared against an expected golden image for test verification.
+
+See the run() function for more in-depth test info.
+"""
+import os
+import sys
+
+import azlmbr.asset as asset
+import azlmbr.bus as bus
+import azlmbr.editor as editor
+import azlmbr.math as math
+import azlmbr.paths
+import azlmbr.legacy.general as general
+
+sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
+
+import editor_python_test_tools.hydra_editor_utils as hydra
+from atom_renderer.atom_utils import atom_component_helper, atom_constants, screenshot_utils
+from editor_python_test_tools.editor_test_helper import EditorTestHelper
+
+helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
+
+LEVEL_NAME = "auto_test"
+LIGHT_COMPONENT = "Light"
+LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type'
+DEGREE_RADIAN_FACTOR = 0.0174533
+
+
+def run():
+ """
+ Sets up the tests by making sure the required level is created & setup correctly.
+ It then executes 2 test cases - see each associated test function's docstring for more info.
+
+ Finally prints the string "Light component tests completed" after completion
+
+ Tests will fail immediately if any of these log lines are found:
+ 1. Trace::Assert
+ 2. Trace::Error
+ 3. Traceback (most recent call last):
+
+ :return: None
+ """
+ atom_component_helper.create_basic_atom_level(level_name=LEVEL_NAME)
+
+ # Run tests.
+ area_light_test()
+ spot_light_test()
+ general.log("Light component tests completed.")
+
+
+def area_light_test():
+ """
+ Basic test for the "Light" component attached to an "area_light" entity.
+
+ Test Case - Light Component: Capsule, Spot (disk), and Point (sphere):
+ 1. Creates "area_light" entity w/ a Light component that has a Capsule Light type w/ the color set to 255, 0, 0
+ 2. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 3. Sets the Light component Intensity Mode to Lumens (default).
+ 4. Ensures the Light component Mode is Automatic (default).
+ 5. Sets the Intensity value of the Light component to 0.0
+ 6. Enters game mode again, takes another screenshot for comparison, then exits game mode.
+ 7. Updates the Intensity value of the Light component to 1000.0
+ 8. Enters game mode again, takes another screenshot for comparison, then exits game mode.
+ 9. Swaps the Capsule light type option to Spot (disk) light type on the Light component
+ 10. Updates "area_light" entity Transform rotate value to x: 90.0, y:0.0, z:0.0
+ 11. Enters game mode again, takes another screenshot for comparison, then exits game mode.
+ 12. Swaps the Spot (disk) light type for the Point (sphere) light type in the Light component.
+ 13. Enters game mode again, takes another screenshot for comparison, then exits game mode.
+ 14. Deletes the Light component from the "area_light" entity and verifies its successful.
+ """
+ # Create an "area_light" entity with "Light" component using Light type of "Capsule"
+ area_light_entity_name = "area_light"
+ area_light = hydra.Entity(area_light_entity_name)
+ area_light.create_entity(math.Vector3(-1.0, -2.0, 3.0), [LIGHT_COMPONENT])
+ general.log(
+ f"{area_light_entity_name}_test: Component added to the entity: "
+ f"{hydra.has_components(area_light.id, [LIGHT_COMPONENT])}")
+ light_component_id_pair = hydra.attach_component_to_entity(area_light.id, LIGHT_COMPONENT)
+
+ # Select the "Capsule" light type option.
+ azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast,
+ 'SetComponentProperty',
+ light_component_id_pair,
+ LIGHT_TYPE_PROPERTY,
+ atom_constants.LIGHT_TYPES['capsule']
+ )
+
+ # Update color and take screenshot in game mode
+ color = math.Color(255.0, 0.0, 0.0, 0.0)
+ area_light.get_set_test(0, "Controller|Configuration|Color", color)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("AreaLight_1", area_light_entity_name)
+
+ # Update intensity value to 0.0 and take screenshot in game mode
+ area_light.get_set_test(0, "Controller|Configuration|Attenuation Radius|Mode", 1)
+ area_light.get_set_test(0, "Controller|Configuration|Intensity", 0.0)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("AreaLight_2", area_light_entity_name)
+
+ # Update intensity value to 1000.0 and take screenshot in game mode
+ area_light.get_set_test(0, "Controller|Configuration|Intensity", 1000.0)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("AreaLight_3", area_light_entity_name)
+
+ # Swap the "Capsule" light type option to "Spot (disk)" light type
+ azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast,
+ 'SetComponentProperty',
+ light_component_id_pair,
+ LIGHT_TYPE_PROPERTY,
+ atom_constants.LIGHT_TYPES['spot_disk']
+ )
+ area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0)
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("AreaLight_4", area_light_entity_name)
+
+ # Swap the "Spot (disk)" light type to the "Point (sphere)" light type and take screenshot.
+ azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast,
+ 'SetComponentProperty',
+ light_component_id_pair,
+ LIGHT_TYPE_PROPERTY,
+ atom_constants.LIGHT_TYPES['sphere']
+ )
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name)
+
+ editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntityById", area_light.id)
+
+
+def spot_light_test():
+ """
+ Basic test for the Light component attached to a "spot_light" entity.
+
+ Test Case - Light Component: Spot (disk) with shadows & colors:
+ 1. Creates "spot_light" entity w/ a Light component attached to it.
+ 2. Selects the "directional_light" entity already present in the level and disables it.
+ 3. Selects the "global_skylight" entity already present in the level and disables the HDRi Skybox component,
+ as well as the Global Skylight (IBL) component.
+ 4. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 5. Selects the "ground_plane" entity and changes updates the material to a new material.
+ 6. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 7. Selects the "spot_light" entity and increases the Light component Intensity to 800 lm
+ 8. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 9. Selects the "spot_light" entity and sets the Light component Color to 47, 75, 37
+ 10. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 11. Selects the "spot_light" entity and modifies the Shutter controls to the following values:
+ - Enable shutters: True
+ - Inner Angle: 60.0
+ - Outer Angle: 75.0
+ 12. Enters game mode to take a screenshot for comparison, then exits game mode.
+ 13. Selects the "spot_light" entity and modifies the Shadow controls to the following values:
+ - Enable Shadow: True
+ - ShadowmapSize: 256
+ 14. Modifies the world translate position of the "spot_light" entity to 0.7, -2.0, 1.9 (for casting shadows better)
+ 15. Enters game mode to take a screenshot for comparison, then exits game mode.
+ """
+ # Disable "Directional Light" component for the "directional_light" entity
+ # "directional_light" entity is created by the create_basic_atom_level() function by default.
+ directional_light_entity_id = hydra.find_entity_by_name("directional_light")
+ directional_light = hydra.Entity(name='directional_light', id=directional_light_entity_id)
+ directional_light_component_type = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Directional Light"], 0)[0]
+ directional_light_component = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'GetComponentOfType', directional_light.id, directional_light_component_type
+ ).GetValue()
+ editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [directional_light_component])
+ general.idle_wait(0.5)
+
+ # Disable "Global Skylight (IBL)" and "HDRi Skybox" components for the "global_skylight" entity
+ global_skylight_entity_id = hydra.find_entity_by_name("global_skylight")
+ global_skylight = hydra.Entity(name='global_skylight', id=global_skylight_entity_id)
+ global_skylight_component_type = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Global Skylight (IBL)"], 0)[0]
+ global_skylight_component = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, global_skylight_component_type
+ ).GetValue()
+ editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [global_skylight_component])
+ hdri_skybox_component_type = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDRi Skybox"], 0)[0]
+ hdri_skybox_component = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, hdri_skybox_component_type
+ ).GetValue()
+ editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [hdri_skybox_component])
+ general.idle_wait(0.5)
+
+ # Create a "spot_light" entity with "Light" component using Light Type of "Spot (disk)"
+ spot_light_entity_name = "spot_light"
+ spot_light = hydra.Entity(spot_light_entity_name)
+ spot_light.create_entity(math.Vector3(0.7, -2.0, 1.0), [LIGHT_COMPONENT])
+ general.log(
+ f"{spot_light_entity_name}_test: Component added to the entity: "
+ f"{hydra.has_components(spot_light.id, [LIGHT_COMPONENT])}")
+ rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 300.0, 0.0, 0.0)
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", spot_light.id, rotation)
+ light_component_type = hydra.attach_component_to_entity(spot_light.id, LIGHT_COMPONENT)
+ editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast,
+ 'SetComponentProperty',
+ light_component_type,
+ LIGHT_TYPE_PROPERTY,
+ atom_constants.LIGHT_TYPES['spot_disk']
+ )
+
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_1", spot_light_entity_name)
+
+ # Change default material of ground plane entity and take screenshot
+ ground_plane_entity_id = hydra.find_entity_by_name("ground_plane")
+ ground_plane = hydra.Entity(name='ground_plane', id=ground_plane_entity_id)
+ ground_plane_asset_path = os.path.join("Materials", "Presets", "MacBeth", "22_neutral_5-0_0-70d.azmaterial")
+ ground_plane_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", ground_plane_asset_path, math.Uuid(), False)
+ material_property_path = "Default Material|Material Asset"
+ material_component_type = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Material"], 0)[0]
+ material_component = azlmbr.editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast, 'GetComponentOfType', ground_plane.id, material_component_type).GetValue()
+ editor.EditorComponentAPIBus(
+ azlmbr.bus.Broadcast,
+ 'SetComponentProperty',
+ material_component,
+ material_property_path,
+ ground_plane_asset_value
+ )
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_2", spot_light_entity_name)
+
+ # Increase intensity value of the Spot light and take screenshot in game mode
+ spot_light.get_set_test(0, "Controller|Configuration|Intensity", 800.0)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_3", spot_light_entity_name)
+
+ # Update the Spot light color and take screenshot in game mode
+ color_value = math.Color(47.0 / 255.0, 75.0 / 255.0, 37.0 / 255.0, 255.0 / 255.0)
+ spot_light.get_set_test(0, "Controller|Configuration|Color", color_value)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_4", spot_light_entity_name)
+
+ # Update the Shutter controls of the Light component and take screenshot
+ spot_light.get_set_test(0, "Controller|Configuration|Shutters|Enable shutters", True)
+ spot_light.get_set_test(0, "Controller|Configuration|Shutters|Inner angle", 60.0)
+ spot_light.get_set_test(0, "Controller|Configuration|Shutters|Outer angle", 75.0)
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_5", spot_light_entity_name)
+
+ # Update the Shadow controls, move the spot_light entity world translate position and take screenshot
+ spot_light.get_set_test(0, "Controller|Configuration|Shadows|Enable shadow", True)
+ spot_light.get_set_test(0, "Controller|Configuration|Shadows|Shadowmap size", 256.0)
+ azlmbr.components.TransformBus(
+ azlmbr.bus.Event, "SetWorldTranslation", spot_light.id, math.Vector3(0.7, -2.0, 1.9))
+ general.idle_wait(1.0)
+ screenshot_utils.take_screenshot_game_mode("SpotLight_6", spot_light_entity_name)
+
+
+if __name__ == "__main__":
+ run()
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py
index de4e28bb36..58b72ef01a 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py
@@ -3,17 +3,184 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright
SPDX-License-Identifier: Apache-2.0 OR MIT
-File to assist with common hydra component functions or constants used across various Atom tests.
+File to assist with common hydra component functions used across various Atom tests.
"""
+import os
-# Light type options for the Light component.
-LIGHT_TYPES = {
- 'unknown': 0,
- 'sphere': 1,
- 'spot_disk': 2,
- 'capsule': 3,
- 'quad': 4,
- 'polygon': 5,
- 'simple_point': 6,
- 'simple_spot': 7,
-}
+from editor_python_test_tools.editor_test_helper import EditorTestHelper
+
+helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
+
+
+def create_basic_atom_level(level_name):
+ """
+ Creates a new level inside the Editor matching level_name & adds the following:
+ 1. "default_level" entity to hold all other entities.
+ 2. Adds Grid, Global Skylight (IBL), ground Mesh, Directional Light, Sphere w/ material+mesh, & Camera components.
+ 3. Each of these components has its settings tweaked slightly to match the ideal scene to test Atom rendering.
+ :param level_name: name of the level to create and apply this basic setup to.
+ :return: None
+ """
+ import azlmbr.asset as asset
+ import azlmbr.bus as bus
+ import azlmbr.camera as camera
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
+ import azlmbr.legacy.general as general
+ import azlmbr.math as math
+ import azlmbr.object
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+
+ # Create a new level.
+ new_level_name = level_name
+ heightmap_resolution = 512
+ heightmap_meters_per_pixel = 1
+ terrain_texture_resolution = 412
+ use_terrain = False
+
+ # Return codes are ECreateLevelResult defined in CryEdit.h
+ return_code = general.create_level_no_prompt(
+ new_level_name, heightmap_resolution, heightmap_meters_per_pixel, terrain_texture_resolution, use_terrain)
+ if return_code == 1:
+ general.log(f"{new_level_name} level already exists")
+ elif return_code == 2:
+ general.log("Failed to create directory")
+ elif return_code == 3:
+ general.log("Directory length is too long")
+ elif return_code != 0:
+ general.log("Unknown error, failed to create level")
+ else:
+ general.log(f"{new_level_name} level created successfully")
+
+ # Enable idle and update viewport.
+ general.idle_enable(True)
+ general.idle_wait(1.0)
+ general.update_viewport()
+ general.idle_wait(0.5) # half a second is more than enough for updating the viewport.
+
+ # Close out problematic windows, FPS meters, and anti-aliasing.
+ if general.is_helpers_shown(): # Turn off the helper gizmos if visible
+ general.toggle_helpers()
+ general.idle_wait(1.0)
+ if general.is_pane_visible("Error Report"): # Close Error Report windows that block focus.
+ general.close_pane("Error Report")
+ if general.is_pane_visible("Error Log"): # Close Error Log windows that block focus.
+ general.close_pane("Error Log")
+ general.idle_wait(1.0)
+ general.run_console("r_displayInfo=0")
+ general.run_console("r_antialiasingmode=0")
+ general.idle_wait(1.0)
+
+ # Delete all existing entities & create default_level entity
+ search_filter = azlmbr.entity.SearchFilter()
+ all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
+ editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities)
+ default_level = hydra.Entity("default_level")
+ default_position = math.Vector3(0.0, 0.0, 0.0)
+ default_level.create_entity(default_position, ["Grid"])
+ default_level.get_set_test(0, "Controller|Configuration|Secondary Grid Spacing", 1.0)
+
+ # Set the viewport up correctly after adding the parent default_level entity.
+ screen_width = 1280
+ screen_height = 720
+ degree_radian_factor = 0.0174533 # Used by "Rotation" property for the Transform component.
+ general.set_viewport_size(screen_width, screen_height)
+ general.update_viewport()
+ helper.wait_for_condition(
+ function=lambda: helper.isclose(a=general.get_viewport_size().x, b=screen_width, rel_tol=0.1)
+ and helper.isclose(a=general.get_viewport_size().y, b=screen_height, rel_tol=0.1),
+ timeout_in_seconds=4.0
+ )
+ result = helper.isclose(a=general.get_viewport_size().x, b=screen_width, rel_tol=0.1) and helper.isclose(
+ a=general.get_viewport_size().y, b=screen_height, rel_tol=0.1)
+ general.log(general.get_viewport_size().x)
+ general.log(general.get_viewport_size().y)
+ general.log(general.get_viewport_size().z)
+ general.log(f"Viewport is set to the expected size: {result}")
+ general.log("Basic level created")
+ general.run_console("r_DisplayInfo = 0")
+
+ # Create global_skylight entity and set the properties
+ global_skylight = hydra.Entity("global_skylight")
+ global_skylight.create_entity(
+ entity_position=default_position,
+ components=["HDRi Skybox", "Global Skylight (IBL)"],
+ parent_id=default_level.id)
+ global_skylight_asset_path = os.path.join(
+ "LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage")
+ global_skylight_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", global_skylight_asset_path, math.Uuid(), False)
+ global_skylight.get_set_test(0, "Controller|Configuration|Cubemap Texture", global_skylight_asset_value)
+ global_skylight.get_set_test(1, "Controller|Configuration|Diffuse Image", global_skylight_asset_value)
+ global_skylight.get_set_test(1, "Controller|Configuration|Specular Image", global_skylight_asset_value)
+
+ # Create ground_plane entity and set the properties
+ ground_plane = hydra.Entity("ground_plane")
+ ground_plane.create_entity(
+ entity_position=default_position,
+ components=["Material"],
+ parent_id=default_level.id)
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", ground_plane.id, 32.0)
+ ground_plane_material_asset_path = os.path.join(
+ "Materials", "Presets", "PBR", "metal_chrome.azmaterial")
+ ground_plane_material_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False)
+ ground_plane.get_set_test(0, "Default Material|Material Asset", ground_plane_material_asset_value)
+
+ # Work around to add the correct Atom Mesh component
+ mesh_type_id = azlmbr.globals.property.EditorMeshComponentTypeId
+ ground_plane.components.append(
+ editor.EditorComponentAPIBus(
+ bus.Broadcast, "AddComponentsOfType", ground_plane.id, [mesh_type_id]
+ ).GetValue()[0]
+ )
+ ground_plane_mesh_asset_path = os.path.join("Models", "plane.azmodel")
+ ground_plane_mesh_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False)
+ ground_plane.get_set_test(1, "Controller|Configuration|Mesh Asset", ground_plane_mesh_asset_value)
+
+ # Create directional_light entity and set the properties
+ directional_light = hydra.Entity("directional_light")
+ directional_light.create_entity(
+ entity_position=math.Vector3(0.0, 0.0, 10.0),
+ components=["Directional Light"],
+ parent_id=default_level.id)
+ directional_light_rotation = math.Vector3(degree_radian_factor * -90.0, 0.0, 0.0)
+ azlmbr.components.TransformBus(
+ azlmbr.bus.Event, "SetLocalRotation", directional_light.id, directional_light_rotation)
+
+ # Create sphere entity and set the properties
+ sphere_entity = hydra.Entity("sphere")
+ sphere_entity.create_entity(
+ entity_position=math.Vector3(0.0, 0.0, 1.0),
+ components=["Material"],
+ parent_id=default_level.id)
+ sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial")
+ sphere_material_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False)
+ sphere_entity.get_set_test(0, "Default Material|Material Asset", sphere_material_asset_value)
+
+ # Work around to add the correct Atom Mesh component
+ sphere_entity.components.append(
+ editor.EditorComponentAPIBus(
+ bus.Broadcast, "AddComponentsOfType", sphere_entity.id, [mesh_type_id]
+ ).GetValue()[0]
+ )
+ sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel")
+ sphere_mesh_asset_value = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False)
+ sphere_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", sphere_mesh_asset_value)
+
+ # Create camera component and set the properties
+ camera_entity = hydra.Entity("camera")
+ camera_entity.create_entity(
+ entity_position=math.Vector3(5.5, -12.0, 9.0),
+ components=["Camera"],
+ parent_id=default_level.id)
+ rotation = math.Vector3(
+ degree_radian_factor * -27.0, degree_radian_factor * -12.0, degree_radian_factor * 25.0
+ )
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", camera_entity.id, rotation)
+ camera_entity.get_set_test(0, "Controller|Configuration|Field of view", 60.0)
+ camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id)
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py
new file mode 100644
index 0000000000..88a959f198
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py
@@ -0,0 +1,19 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+Hold constants used across both hydra and non-hydra scripts.
+"""
+
+# Light type options for the Light component.
+LIGHT_TYPES = {
+ 'unknown': 0,
+ 'sphere': 1,
+ 'spot_disk': 2,
+ 'capsule': 3,
+ 'quad': 4,
+ 'polygon': 5,
+ 'simple_point': 6,
+ 'simple_spot': 7,
+}
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py
index 21c7489ed3..b4fdfcb8a0 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py
@@ -61,6 +61,25 @@ class BenchmarkHelper(object):
general.log('Failed to capture pass timestamps.')
return self.capturedData
+ def capture_cpu_frame_time(self, frame_number):
+ """
+ Capture CPU frame times and block further execution until it has been written to the disk.
+ """
+ self.handler = azlmbr.atom.ProfilingCaptureNotificationBusHandler()
+ self.handler.connect()
+ self.handler.add_callback('OnCaptureCpuFrameTimeFinished', self.on_data_captured)
+
+ self.done = False
+ self.capturedData = False
+ success = azlmbr.atom.ProfilingCaptureRequestBus(
+ azlmbr.bus.Broadcast, "CaptureCpuFrameTime", f'{self.output_path}/cpu_frame{frame_number}_time.json')
+ if success:
+ self.wait_until_data()
+ general.log('CPU frame time captured.')
+ else:
+ general.log('Failed to capture CPU frame time.')
+ return self.capturedData
+
def on_data_captured(self, parameters):
# the parameters come in as a tuple
if parameters[0]:
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py
new file mode 100644
index 0000000000..ef0a592df0
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py
@@ -0,0 +1,274 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe
+This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe
+You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear.
+"""
+
+import os
+import sys
+import time
+import azlmbr.atom
+import azlmbr.atomtools as atomtools
+import azlmbr.materialeditor as materialeditor
+import azlmbr.bus as bus
+
+
+def is_close(actual, expected, buffer=sys.float_info.min):
+ """
+ :param actual: actual value
+ :param expected: expected value
+ :param buffer: acceptable variation from expected
+ :return: bool
+ """
+ return abs(actual - expected) < buffer
+
+
+def compare_colors(color1, color2, buffer=0.00001):
+ """
+ Compares the red, green and blue properties of a color allowing a slight variance of buffer
+ :param color1: first color to compare
+ :param color2: second color
+ :param buffer: allowed variance in individual color value
+ :return: bool
+ """
+ return (
+ is_close(color1.r, color2.r, buffer)
+ and is_close(color1.g, color2.g, buffer)
+ and is_close(color1.b, color2.b, buffer)
+ )
+
+
+def open_material(file_path):
+ """
+ :return: uuid of material document opened
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path)
+
+
+def is_open(document_id):
+ """
+ :return: bool
+ """
+ return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "IsOpen", document_id)
+
+
+def save_document(document_id):
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id)
+
+
+def save_document_as_copy(document_id, target_path):
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
+ bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path
+ )
+
+
+def save_document_as_child(document_id, target_path):
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
+ bus.Broadcast, "SaveDocumentAsChild", document_id, target_path
+ )
+
+
+def save_all():
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments")
+
+
+def close_document(document_id):
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id)
+
+
+def close_all_documents():
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments")
+
+
+def close_all_except_selected(document_id):
+ """
+ :return: bool success
+ """
+ return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id)
+
+
+def get_property(document_id, property_name):
+ """
+ :return: property value or invalid value if the document is not open or the property_name can't be found
+ """
+ return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name)
+
+
+def set_property(document_id, property_name, value):
+ azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value)
+
+
+def is_pane_visible(pane_name):
+ """
+ :return: bool
+ """
+ return atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name)
+
+
+def set_pane_visibility(pane_name, value):
+ atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value)
+
+
+def select_lighting_config(config_name):
+ azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectLightingPresetByName", config_name)
+
+
+def set_grid_enable_disable(value):
+ azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetGridEnabled", value)
+
+
+def get_grid_enable_disable():
+ """
+ :return: bool
+ """
+ return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetGridEnabled")
+
+
+def set_shadowcatcher_enable_disable(value):
+ azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetShadowCatcherEnabled", value)
+
+
+def get_shadowcatcher_enable_disable():
+ """
+ :return: bool
+ """
+ return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetShadowCatcherEnabled")
+
+
+def select_model_config(configname):
+ azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname)
+
+
+def wait_for_condition(function, timeout_in_seconds=1.0):
+ # type: (function, float) -> bool
+ """
+ Function to run until it returns True or timeout is reached
+ the function can have no parameters and
+ waiting idle__wait_* is handled here not in the function
+
+ :param function: a function that returns a boolean indicating a desired condition is achieved
+ :param timeout_in_seconds: when reached, function execution is abandoned and False is returned
+ """
+ with Timeout(timeout_in_seconds) as t:
+ while True:
+ try:
+ azlmbr.atomtools.general.idle_wait_frames(1)
+ except Exception:
+ print("WARNING: Couldn't wait for frame")
+
+ if t.timed_out:
+ return False
+
+ ret = function()
+ if not isinstance(ret, bool):
+ raise TypeError("return value for wait_for_condition function must be a bool")
+ if ret:
+ return True
+
+
+class Timeout:
+ # type: (float) -> None
+ """
+ contextual timeout
+ :param seconds: float seconds to allow before timed_out is True
+ """
+
+ def __init__(self, seconds):
+ self.seconds = seconds
+
+ def __enter__(self):
+ self.die_after = time.time() + self.seconds
+ return self
+
+ def __exit__(self, type, value, traceback):
+ pass
+
+ @property
+ def timed_out(self):
+ return time.time() > self.die_after
+
+
+screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots")
+
+
+class ScreenshotHelper:
+ """
+ A helper to capture screenshots and wait for them.
+ """
+
+ def __init__(self, idle_wait_frames_callback):
+ super().__init__()
+ self.done = False
+ self.capturedScreenshot = False
+ self.max_frames_to_wait = 60
+
+ self.idle_wait_frames_callback = idle_wait_frames_callback
+
+ def capture_screenshot_blocking(self, filename):
+ """
+ Capture a screenshot and block the execution until the screenshot has been written to the disk.
+ """
+ self.handler = azlmbr.atom.FrameCaptureNotificationBusHandler()
+ self.handler.connect()
+ self.handler.add_callback("OnCaptureFinished", self.on_screenshot_captured)
+
+ self.done = False
+ self.capturedScreenshot = False
+ success = azlmbr.atom.FrameCaptureRequestBus(azlmbr.bus.Broadcast, "CaptureScreenshot", filename)
+ if success:
+ self.wait_until_screenshot()
+ print("Screenshot taken.")
+ else:
+ print("screenshot failed")
+ return self.capturedScreenshot
+
+ def on_screenshot_captured(self, parameters):
+ # the parameters come in as a tuple
+ if parameters[0]:
+ print("screenshot saved: {}".format(parameters[1]))
+ self.capturedScreenshot = True
+ else:
+ print("screenshot failed: {}".format(parameters[1]))
+ self.done = True
+ self.handler.disconnect()
+
+ def wait_until_screenshot(self):
+ frames_waited = 0
+ while self.done == False:
+ self.idle_wait_frames_callback(1)
+ if frames_waited > self.max_frames_to_wait:
+ print("timeout while waiting for the screenshot to be written")
+ self.handler.disconnect()
+ break
+ else:
+ frames_waited = frames_waited + 1
+ print("(waited {} frames)".format(frames_waited))
+
+
+def capture_screenshot(file_path):
+ return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking(
+ os.path.join(file_path)
+ )
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py
index 28a4037dcc..a7a02816ac 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py
@@ -91,3 +91,20 @@ class ScreenshotHelper(object):
else:
frames_waited = frames_waited + 1
general.log(f"(waited {frames_waited} frames)")
+
+
+def take_screenshot_game_mode(screenshot_name, entity_name=None):
+ """
+ Enters game mode & takes a screenshot, then exits game mode after.
+ :param screenshot_name: name to give the captured screenshot .ppm file.
+ :param entity_name: name of the entity being tested (for generating unique log lines).
+ :return: None
+ """
+ general.enter_game_mode()
+ helper.wait_for_condition(lambda: general.is_in_game_mode(), 2.0)
+ general.log(f"{entity_name}_test: Entered game mode: {general.is_in_game_mode()}")
+ ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{screenshot_name}.ppm")
+ general.idle_wait(1.0)
+ general.exit_game_mode()
+ helper.wait_for_condition(lambda: not general.is_in_game_mode(), 2.0)
+ general.log(f"{entity_name}_test: Exit game mode: {not general.is_in_game_mode()}")
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm
new file mode 100644
index 0000000000..0725999dcf
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:954d7d0df47c840a24e313893800eb3126d0c0d47c3380926776b51833778db7
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm
new file mode 100644
index 0000000000..3a45bd31e3
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e81c19128f42ba362a2d5f3ccf159dfbc942d67ceeb1ac8c21f295a6fd9d2ce5
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm
new file mode 100644
index 0000000000..15d679b784
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e20801213e065b6ea8c95ede81c23faa9b6dc70a2002dc5bced293e1bed989f
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm
new file mode 100644
index 0000000000..85c083a386
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e250f812e594e5152bf2d6f23caa8b53b78276bfdf344d7a8d355dd96cb995c0
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm
new file mode 100644
index 0000000000..d575de761e
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:95be359041f8291c74b335297a4dfe9902a180510f24a181b15e1a5ba4d3b024
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm
new file mode 100644
index 0000000000..bbbd127929
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:118e43e4b915e262726183467cc4b82f244565213fea5b6bfe02be07f0851ab1
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm
new file mode 100644
index 0000000000..8e716fabcc
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dc2ce3256a6552975962c9e113c52c1a22bf3817d417151f6f60640dd568e0fa
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm
new file mode 100644
index 0000000000..6b6a5a5d6e
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:287d98890b35427688999760f9d066bcbff1a3bc9001534241dc212b32edabd8
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm
new file mode 100644
index 0000000000..eb05228cc2
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:66e91c92c868167c850078cd91714db47e10a96e23cc30191994486bd79c353f
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm
new file mode 100644
index 0000000000..5e12edc46d
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d950d173f5101820c5e18205401ca08ce5feeff2302ac2920b292750d86a8fa4
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm
new file mode 100644
index 0000000000..d442d90287
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:72eddb7126eae0c839b933886e0fb69d78229f72d49ef13199de28df2b7879db
+size 6220817
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py
index ede140c075..7be1ed1b12 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py
@@ -15,11 +15,11 @@ import pytest
import ly_test_tools.environment.file_system as file_system
from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots
from ly_test_tools.benchmark.data_aggregator import BenchmarkDataAggregator
+
import editor_python_test_tools.hydra_test_utils as hydra
logger = logging.getLogger(__name__)
DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots'
-EDITOR_TIMEOUT = 600
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
@@ -67,6 +67,7 @@ class TestAllComponentsIndepthTests(object):
"Trace::Assert",
"Trace::Error",
"Traceback (most recent call last):",
+ "Screenshot failed"
]
hydra.launch_and_validate_results(
@@ -74,7 +75,7 @@ class TestAllComponentsIndepthTests(object):
TEST_DIRECTORY,
editor,
"hydra_GPUTest_BasicLevelSetup.py",
- timeout=EDITOR_TIMEOUT,
+ timeout=180,
expected_lines=level_creation_expected_lines,
unexpected_lines=unexpected_lines,
halt_on_unexpected=True,
@@ -85,6 +86,60 @@ class TestAllComponentsIndepthTests(object):
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
compare_screenshots(test_screenshot, golden_screenshot)
+ def test_LightComponent_ScreenshotMatchesGoldenImage(
+ self, request, editor, workspace, project, launcher_platform, level):
+ """
+ Please review the hydra script run by this test for more specific test info.
+ Tests that the Light component screenshots in a rendered level appear the same as the golden images.
+ """
+ screenshot_names = [
+ "AreaLight_1.ppm",
+ "AreaLight_2.ppm",
+ "AreaLight_3.ppm",
+ "AreaLight_4.ppm",
+ "AreaLight_5.ppm",
+ "SpotLight_1.ppm",
+ "SpotLight_2.ppm",
+ "SpotLight_3.ppm",
+ "SpotLight_4.ppm",
+ "SpotLight_5.ppm",
+ "SpotLight_6.ppm",
+ ]
+ test_screenshots = []
+ for screenshot in screenshot_names:
+ screenshot_path = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot)
+ test_screenshots.append(screenshot_path)
+ file_system.delete(test_screenshots, True, True)
+
+ golden_images = []
+ for golden_image in screenshot_names:
+ golden_image_path = os.path.join(golden_images_directory(), golden_image)
+ golden_images.append(golden_image_path)
+
+ expected_lines = ["Light component tests completed."]
+ unexpected_lines = [
+ "Trace::Assert",
+ "Trace::Error",
+ "Traceback (most recent call last):",
+ "Screenshot failed",
+ ]
+ hydra.launch_and_validate_results(
+ request,
+ TEST_DIRECTORY,
+ editor,
+ "hydra_GPUTest_LightComponent.py",
+ timeout=180,
+ expected_lines=expected_lines,
+ unexpected_lines=unexpected_lines,
+ halt_on_unexpected=True,
+ cfg_args=[level],
+ null_renderer=False,
+ )
+
+ for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
+ compare_screenshots(test_screenshot, golden_screenshot)
+
+
@pytest.mark.parametrize('rhi', ['dx12', 'vulkan'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ["windows_editor"])
@@ -99,6 +154,7 @@ class TestPerformanceBenchmarkSuite(object):
expected_lines = [
"Benchmark metadata captured.",
"Pass timestamps captured.",
+ "CPU frame time captured.",
"Capturing complete.",
"Captured data successfully."
]
@@ -106,6 +162,7 @@ class TestPerformanceBenchmarkSuite(object):
unexpected_lines = [
"Failed to capture data.",
"Failed to capture pass timestamps.",
+ "Failed to capture CPU frame time.",
"Failed to capture benchmark metadata."
]
@@ -114,7 +171,7 @@ class TestPerformanceBenchmarkSuite(object):
TEST_DIRECTORY,
editor,
"hydra_GPUTest_AtomFeatureIntegrationBenchmark.py",
- timeout=EDITOR_TIMEOUT,
+ timeout=600,
expected_lines=expected_lines,
unexpected_lines=unexpected_lines,
halt_on_unexpected=True,
diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
index 98d2ba0632..55c049b929 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
@@ -11,8 +11,9 @@ import os
import pytest
+import ly_test_tools.environment.file_system as file_system
import editor_python_test_tools.hydra_test_utils as hydra
-from atom_renderer.atom_utils.atom_component_helper import LIGHT_TYPES
+from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES
logger = logging.getLogger(__name__)
EDITOR_TIMEOUT = 120
@@ -31,7 +32,7 @@ class TestAtomEditorComponentsMain(object):
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
1. Display Mapper
2. Light
- 3. Radius Weight Modifier
+ 3. PostFX Radius Weight Modifier
4. PostFX Layer
5. Physical Sky
6. Global Skylight (IBL)
@@ -125,18 +126,18 @@ class TestAtomEditorComponentsMain(object):
"PostFX Layer_test: Entity deleted: True",
"PostFX Layer_test: UNDO entity deletion works: True",
"PostFX Layer_test: REDO entity deletion works: True",
- # Radius Weight Modifier Component
- "Radius Weight Modifier Entity successfully created",
- "Radius Weight Modifier_test: Component added to the entity: True",
- "Radius Weight Modifier_test: Component removed after UNDO: True",
- "Radius Weight Modifier_test: Component added after REDO: True",
- "Radius Weight Modifier_test: Entered game mode: True",
- "Radius Weight Modifier_test: Exit game mode: True",
- "Radius Weight Modifier_test: Entity is hidden: True",
- "Radius Weight Modifier_test: Entity is shown: True",
- "Radius Weight Modifier_test: Entity deleted: True",
- "Radius Weight Modifier_test: UNDO entity deletion works: True",
- "Radius Weight Modifier_test: REDO entity deletion works: True",
+ # PostFX Radius Weight Modifier Component
+ "PostFX Radius Weight Modifier Entity successfully created",
+ "PostFX Radius Weight Modifier_test: Component added to the entity: True",
+ "PostFX Radius Weight Modifier_test: Component removed after UNDO: True",
+ "PostFX Radius Weight Modifier_test: Component added after REDO: True",
+ "PostFX Radius Weight Modifier_test: Entered game mode: True",
+ "PostFX Radius Weight Modifier_test: Exit game mode: True",
+ "PostFX Radius Weight Modifier_test: Entity is hidden: True",
+ "PostFX Radius Weight Modifier_test: Entity is shown: True",
+ "PostFX Radius Weight Modifier_test: Entity deleted: True",
+ "PostFX Radius Weight Modifier_test: UNDO entity deletion works: True",
+ "PostFX Radius Weight Modifier_test: REDO entity deletion works: True",
# Light Component
"Light Entity successfully created",
"Light_test: Component added to the entity: True",
@@ -242,3 +243,65 @@ class TestAtomEditorComponentsMain(object):
null_renderer=True,
cfg_args=cfg_args,
)
+
+
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+@pytest.mark.parametrize("launcher_platform", ['windows_generic'])
+@pytest.mark.system
+class TestMaterialEditorBasicTests(object):
+ @pytest.fixture(autouse=True)
+ def setup_teardown(self, request, workspace, project):
+ def delete_files():
+ file_system.delete(
+ [
+ os.path.join(workspace.paths.project(), "Materials", "test_material.material"),
+ os.path.join(workspace.paths.project(), "Materials", "test_material_1.material"),
+ os.path.join(workspace.paths.project(), "Materials", "test_material_2.material"),
+ ],
+ True,
+ True,
+ )
+ # Cleanup our newly created materials
+ delete_files()
+
+ def teardown():
+ # Cleanup our newly created materials
+ delete_files()
+
+ request.addfinalizer(teardown)
+
+ @pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
+ def test_MaterialEditorBasicTests(
+ self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name):
+
+ expected_lines = [
+ "Material opened: True",
+ "Test asset doesn't exist initially: True",
+ "New asset created: True",
+ "New Material opened: True",
+ "Material closed: True",
+ "All documents closed: True",
+ "Close All Except Selected worked as expected: True",
+ "Actual Document saved with changes: True",
+ "Document saved as copy is saved with changes: True",
+ "Document saved as child is saved with changes: True",
+ "Save All worked as expected: True",
+ ]
+ unexpected_lines = [
+ # "Trace::Assert",
+ # "Trace::Error",
+ "Traceback (most recent call last):"
+ ]
+
+ hydra.launch_and_validate_results(
+ request,
+ TEST_DIRECTORY,
+ generic_launcher,
+ "hydra_AtomMaterialEditor_BasicTests.py",
+ run_python="--runpython",
+ timeout=80,
+ expected_lines=expected_lines,
+ unexpected_lines=unexpected_lines,
+ halt_on_unexpected=True,
+ log_file_name="MaterialEditor.log",
+ )
diff --git a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt
index afde0a0d94..fa35bb25c6 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_main and not REQUIRES_gpu"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -28,7 +27,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_periodic and not REQUIRES_gpu"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -44,7 +42,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_REQUIRES gpu
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_main and REQUIRES_gpu"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -59,7 +56,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_sandbox"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py
index f728714125..068f25fb1e 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py
@@ -61,7 +61,7 @@ class AssetPickerUIUXTest(EditorTestHelper):
5) Verify if Mesh Asset is assigned via both OK/Enter options
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py
index 32d20ea2b4..994fc661ed 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py
@@ -37,7 +37,7 @@ class TestBasicEditorWorkflows(EditorTestHelper):
async def run_test(self):
"""
Summary:
- Open Lumberyard editor and check if basic Editor workflows are completable.
+ Open O3DE editor and check if basic Editor workflows are completable.
Expected Behavior:
- A new level can be created
@@ -48,7 +48,7 @@ class TestBasicEditorWorkflows(EditorTestHelper):
- Level can be exported
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py
index 6b861894c0..53a8da4116 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py
@@ -36,7 +36,7 @@ class TestEditMenuOptions(EditorTestHelper):
2) Interact with Edit Menu options
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
index ab9aa1d326..77ee9ac61d 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
@@ -32,7 +32,7 @@ class TestFileMenuOptions(EditorTestHelper):
2) Interact with File Menu options
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py
index d1233e9815..d2db4210ce 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py
@@ -36,7 +36,7 @@ class TestViewMenuOptions(EditorTestHelper):
2) Interact with View Menu options
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
index 351ca19031..f133780fbc 100644
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
@@ -16,7 +16,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE main
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -33,7 +32,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE sandbox
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_sandbox"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -49,7 +47,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_filter"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -64,7 +61,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_modifier"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -79,7 +75,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_regression"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -94,7 +89,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_area"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -109,7 +103,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_misc"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -124,7 +117,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "SUITE_periodic and dynveg_surfacetagemitter"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -138,9 +130,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
NAME AutomatedTesting::LandscapeCanvasTests_Main
TEST_SERIAL
TEST_SUITE main
- PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas
- PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
- TIMEOUT 1500
+ PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/test_LandscapeCanvas_Main.py
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -153,9 +143,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
NAME AutomatedTesting::LandscapeCanvasTests_Periodic
TEST_SERIAL
TEST_SUITE periodic
- PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas
- PYTEST_MARKS "SUITE_periodic"
- TIMEOUT 1500
+ PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/test_LandscapeCanvas_Periodic.py
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -169,8 +157,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
NAME AutomatedTesting::GradientSignalTests_Periodic
TEST_SERIAL
TEST_SUITE periodic
- PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal
- TIMEOUT 1500
+ PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal/test_GradientSignal_Periodic.py
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py
index beb5c2af72..2052c59a94 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py
@@ -10,6 +10,7 @@ import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
import azlmbr.asset as asset
+import azlmbr.editor as editor
import azlmbr.legacy.general as general
import azlmbr.bus as bus
import azlmbr.math as math
@@ -107,7 +108,7 @@ class TestPhysXColliderSurfaceTagEmitter(EditorTestHelper):
# 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,
+ entity_center_point,
["PhysX Collider", "PhysX Collider Surface Tag Emitter"]
)
if collider_entity.id.IsValid():
@@ -153,23 +154,29 @@ class TestPhysXColliderSurfaceTagEmitter(EditorTestHelper):
self.test_success = self.test_success and baseline_success
# Setup collider entity with a PhysX Mesh
- test_physx_mesh_asset_path = asset.AssetCatalogRequestBus(
+ test_physx_mesh_asset_id = 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)
+
+ # Remove/re-add component due to LYN-5496
+ collider_entity.remove_component("PhysX Collider")
+ collider_entity.add_component("PhysX Collider")
+ self.wait_for_condition(lambda: editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled',
+ collider_entity.components[1]), 5.0)
+ hydra.get_set_test(collider_entity, 1, "Shape Configuration|Shape", 7)
+ hydra.get_set_test(collider_entity, 1, "Shape Configuration|Asset|PhysX Mesh", test_physx_mesh_asset_id)
# 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)
+ collider_entity.get_set_test(1, "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])
+ hydra.get_set_test(collider_entity, 0, "Configuration|Generated Tags", [surface_tag])
+ hydra.get_set_test(collider_entity, 0, "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,
@@ -180,8 +187,8 @@ class TestPhysXColliderSurfaceTagEmitter(EditorTestHelper):
# 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])
+ hydra.get_set_test(collider_entity, 0, "Configuration|Generated Tags", [invalid_tag])
+ hydra.get_set_test(collider_entity, 0, "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,
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
index 37679d34ef..09cd760647 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
@@ -4,124 +4,118 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-class TestGradientGeneratorIncompatibilities(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientGeneratorIncompatibilities", args=["level"])
+def GradientGenerators_Incompatibilities():
+ """
+ Summary:
+ This test verifies that components are disabled when conflicting components are present on the same entity.
- def run_test(self):
- """
- Summary:
- This test verifies that components are disabled when conflicting components are present on the same entity.
+ Expected Behavior:
+ Gradient Generator components are incompatible with Vegetation area components.
- Expected Behavior:
- Gradient Generator components are incompatible with Vegetation area components.
+ Test Steps:
+ 1) Open a simple level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Generator component to an entity, and add a Vegetation Area component to the same entity
+ 4) Verify that components are only enabled when entity is free of a conflicting component
- Test Steps:
- 1) Create a new level
- 2) Create a new entity in the level
- 3) Add each Gradient Generator component to an entity, and add a Vegetation Area component to the same entity
- 4) Verify that components are only enabled when entity is free of a conflicting component
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
- 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'
- }
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ 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'
+ }
- # 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())
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Most of these need a shape, so use a Box Shape
- hydra.add_component('Box Shape', entity_id)
+ # 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())
- # 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)
+ # Most of these need a shape, so use a Box Shape
+ hydra.add_component('Box Shape', 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)
+ # 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)
- # 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")
+ # 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)
- # Remove the vegetation area component
- editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
+ # Verify the gradient generator component is disabled since the vegetation area is incompatible
+ active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
+ component_is_disabled = (
+ f"{component_name} is disabled before removing {vegetation_area_name} component",
+ f"{component_name} is unexpectedly enabled before removing {vegetation_area_name} component"
+ )
+ Report.result(component_is_disabled, not active)
- # 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)
+ # Remove the vegetation area component
+ editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
- # 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")
+ # 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)
+ component_is_enabled = (
+ f"{component_name} is enabled after removing {vegetation_area_name} component",
+ f"{component_name} is unexpectedly disabled after removing {vegetation_area_name} component"
+ )
+ Report.result(component_is_enabled, active)
-test = TestGradientGeneratorIncompatibilities()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientGenerators_Incompatibilities)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
index 8908493187..a4d9181744 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
@@ -4,164 +4,162 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-class TestGradientModifiersIncompatibilities(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientModifiersIncompatibilities", args=["level"])
+def GradientModifiers_Incompatibilities():
+ """
+ Summary:
+ This test verifies that components are disabled when conflicting components are present on the same entity.
- def run_test(self):
- """
- Summary:
- This test verifies that components are disabled when conflicting components are present on the same entity.
+ Expected Behavior:
+ Gradient Modifier components are incompatible with Vegetation area components.
- Expected Behavior:
- Gradient Modifier components are incompatible with Vegetation area components.
+ Test Steps:
+ 1) Open a simple level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Modifier component to an entity, and add a Vegetation Area component to the same entity
+ 4) Verify that components are only enabled when entity is free of a conflicting component
- Test Steps:
- 1) Create a new level
- 2) Create a new entity in the level
- 3) Add each Gradient Modifier component to an entity, and add a Vegetation Area component to the same entity
- 4) Verify that components are only enabled when entity is free of a conflicting component
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
- 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'
- }
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ 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'
+ }
- # 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())
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Most of these need a shape, so use a Box Shape
- hydra.add_component('Box Shape', entity_id)
+ # 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())
- # 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)
+ # Most of these need a shape, so use a Box Shape
+ hydra.add_component('Box Shape', 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)
+ # 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)
- # 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))
+ # 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)
- # Remove the vegetation area component
- editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
+ # Verify the gradient modifier component is disabled since the vegetation area is incompatible
+ active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
+ component_is_disabled = (
+ f"{component_name} is disabled before removing {vegetation_area_name} component",
+ f"{component_name} is unexpectedly enabled before removing {vegetation_area_name} component"
+ )
+ Report.result(component_is_disabled, not active)
- # 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))
+ # Remove the vegetation area component
+ editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [area_component])
- for gradient_name in all_gradients:
- # Create a new Entity in the level
- entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
+ # Verify the gradient modifier component is enabled now that the vegetation area is gone
+ active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
+ component_is_enabled = (
+ f"{component_name} is enabled after removing {vegetation_area_name} component",
+ f"{component_name} is unexpectedly disabled after removing {vegetation_area_name} component"
+ )
+ Report.result(component_is_enabled, active)
- # Most of these need a shape, so use a Box Shape
- hydra.add_component('Box Shape', entity_id)
+ for gradient_name in all_gradients:
+ # Create a new Entity in the level
+ entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
- # 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)
+ # Most of these need a shape, so use a Box Shape
+ hydra.add_component('Box Shape', entity_id)
- # 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)
+ # 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)
- 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))
+ # 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)
- # 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 disabled since the other gradient is incompatible
+ active = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', gradient_component)
+ component_is_disabled = (
+ f"{component_name} is disabled before removing {gradient_name} component",
+ f"{component_name} is unexpectedly enabled before removing {gradient_name} component"
+ )
+ Report.result(component_is_disabled, not active)
- # 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))
+ # 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)
+ component_is_enabled = (
+ f"{component_name} is enabled after removing {gradient_name} component",
+ f"{component_name} is unexpectedly disabled after removing {gradient_name} component"
+ )
+ Report.result(component_is_enabled, active)
-test = TestGradientModifiersIncompatibilities()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientModifiers_Incompatibilities)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
index 73e8b95823..3749f93bf5 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
@@ -5,129 +5,125 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+def GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin():
+ """
+ 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.
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ 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
-class TestGradientPreviewSettings(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientPreviewSettings_ClearPinnedEntity", args=["level"])
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- 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.
+ :return: None
+ """
- 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.
+ import sys
- 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
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.math as math
+ import azlmbr.entity as EntityId
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- :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
- 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(entity_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(entity_name, entity_id)
+ if entity_id.IsValid():
+ print(f"{entity_name} entity Created")
+ entity.components = []
+ for component in components_to_add:
+ entity.components.append(hydra.add_component(component, entity_id))
+ return entity
- 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()
+ 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"
+ )
+ preview_set_to_origin = (
+ f"{entity_name}: Preview Position set to world origin",
+ f"{entity_name}: Preview Position set to unexpected coords"
+ )
+ Report.result(preview_set_to_origin, preview_position.IsClose(WORLD_ORIGIN, CLOSE_THRESHOLD))
+ if check_preview_size:
+ preview_size = hydra.get_component_property_value(entity.components[0], "Preview Settings|Preview Size")
+ preview_size_default_set = (
+ f"{entity_name}: Preview Size set as expected",
+ f"{entity_name}: Preview Size set to unexpected value. Expected {EXPECTED_SIZE}, Found {preview_size}"
)
- 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
+ Report.result(preview_size_default_set, preview_size.IsClose(EXPECTED_SIZE, CLOSE_THRESHOLD))
+ 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 an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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
+ )
- # 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"])
- # 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"])
- # 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"])
- # 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"])
- # 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
+ )
- # 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)
- # 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"])
- # 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
- )
+ # 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()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
index 99a54f614a..3756452710 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
@@ -5,18 +5,6 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
class Scoped:
def __init__(self, constructor, destructor, *args):
@@ -33,81 +21,84 @@ class TestParams:
self.accessed_component = accessed_component
-class TestGradientPreviewSettings(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientPreviewSettings_DefaultPinnedEntity", args=["level"])
+def GradientPreviewSettings_DefaultPinnedEntityIsSelf():
+ """
+ Summary:
+ This test verifies default values for the pinned entity for Gradient Preview settings.
- def run_test(self):
- """
- Summary:
- This test verifies default values for the pinned entity for Gradient Preview settings.
+ Expected Behavior:
+ Pinned entity is self for all gradient generator/modifiers.
- Expected Behavior:
- Pinned entity is self for all gradient generator/modifiers.
+ Test Steps:
+ 1) Open a simple level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Generator component to an entity, and verify the Pin Preview to Shape property is set to
+ self
- Test Steps:
- 1) Create a new level
- 2) Create a new entity in the level
- 3) Add each Gradient Generator component to an entity, and verify the Pin Preview to Shape property is set to
- self
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
- def execute_test(test_id, function, *args):
- if function(*args):
- self.log(test_id + ' has Preview pinned to own Entity result: SUCCESS')
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- 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,
+ def execute_test(test_id, function, *args):
+ pinned_to_self = (
+ f"{test_id} has Preview pinned to self",
+ f"{test_id} has Preview pinned to a different entity"
)
+ Report.result(pinned_to_self, function(*args))
- for param in param_list:
- execute_test(param.required_components[param.accessed_component],
- validate_id_is_current, param)
+ 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')
+ 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)
+ ]
+
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ for param in param_list:
+ execute_test(param.required_components[param.accessed_component],
+ validate_id_is_current, param)
-test = TestGradientPreviewSettings()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientPreviewSettings_DefaultPinnedEntityIsSelf)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py
index 6d88f43d5a..8e85345a6f 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py
@@ -5,92 +5,82 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+def GradientSampling_GradientReferencesAddRemoveSuccessfully():
+ """
+ Summary:
+ An existing gradient generator can be pinned and cleared to/from the Gradient Entity Id field
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ 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
-class TestGradientSampling(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientSampling_GradientReferences", args=["level"])
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- def run_test(self):
- """
- Summary:
- An existing gradient generator can be pinned and cleared to/from the Gradient Entity Id field
+ :return: None
+ """
- Expected Behavior:
- Gradient generator is assigned to the Gradient Entity Id field.
- Gradient generator is removed from the field.
+ import azlmbr.math as math
+ import azlmbr.entity as EntityId
- 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
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
-
- 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"
+ def modifier_pin_clear_to_gradiententityid(modifier):
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)
+ 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"
+ )
+ gradient_pinned_to_modifier = (
+ f"Gradient Generator is pinned to the {modifier} successfully",
+ f"Failed to pin Gradient Generator to the {modifier}"
+ )
+ Report.result(gradient_pinned_to_modifier, entity.Equal(random_noise.id))
+ 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"
+ )
+ gradient_cleared_from_modifier = (
+ f"Gradient Generator is cleared from the {modifier} successfully",
+ f"Failed to clear Gradient Generator from the {modifier}"
+ )
+ Report.result(gradient_cleared_from_modifier, entity.Equal(EntityId.EntityId()))
- # 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")
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientSampling_GradientReferencesAddRemoveSuccessfully)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
index 26d791495a..f653515a39 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
@@ -5,114 +5,104 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(
- self, log_prefix="GradientSurfaceTagEmitter_ComponentDependencies", args=["level"]
+def GradientSurfaceTagEmitter_ComponentDependencies():
+ """
+ Summary:
+ This test verifies that the Gradient Surface Tag Emitter component is dependent on a gradient component.
+
+ Expected Result:
+ Gradient Surface Tag Emitter component is disabled until a Gradient Generator, Modifier or Gradient Reference
+ component (and any sub-dependencies) is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Gradient Surface Tag Emitter component
+ 3) Verify the component is disabled until a dependent component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.math as math
+ import azlmbr.bus as bus
+ import azlmbr.entity as entity
+ import azlmbr.editor as editor
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ def is_enabled(EntityComponentIdPair):
+ return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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
+ gradient_surface_tag_disabled = (
+ "Gradient Surface Tag Emitter is Disabled",
+ "Gradient Surface Tag Emitter is Enabled, but should be Disabled without dependencies met"
+ )
+ Report.result(gradient_surface_tag_disabled, not is_enabled(gradient.components[0]))
+
+ # 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 = is_enabled(gradient.components[0])
+ new_components_enabled = is_enabled(ComponentIdPair)
+ dependencies_met = (
+ f"{component} and Gradient Surface Tag Emitter are enabled",
+ f"{component} and Gradient Surface Tag Emitter are disabled"
)
+ Report.result(dependencies_met, new_components_enabled and gradient_enabled)
- def run_test(self):
- """
- Summary:
- This test verifies that the Gradient Surface Tag Emitter component is dependent on a gradient component.
-
- Expected Result:
- Gradient Surface Tag Emitter component is disabled until a Gradient Generator, Modifier or Gradient Reference
- component (and any sub-dependencies) is added to the entity.
-
- Test Steps:
- 1) Open level
- 2) Create a new entity with a Gradient Surface Tag Emitter component
- 3) Verify the component is disabled until a dependent component is also added to the entity
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
-
- 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)
+ 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()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientSurfaceTagEmitter_ComponentDependencies)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py
index 44c9792296..90840a135d 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py
@@ -5,75 +5,69 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+def GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully():
+ """
+ Summary:
+ Entity with Gradient Surface Tag Emitter and Reference Gradient components is created.
+ And new surface tag has been added and removed.
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ 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 Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.math as math
+ import azlmbr.surface_data as surface_data
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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 = helper.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 1, 1.0)
+ tag_added_to_container = (
+ "Successfully added surface tag",
+ "Failed to add surface tag"
+ )
+ Report.result(tag_added_to_container, success)
+ pte.remove_container_item(path, 0)
+ success = helper.wait_for_condition(lambda: pte.get_container_count(path).GetValue() == 0, 1.0)
+ tag_removed_from_container = (
+ "Successfully removed surface tag",
+ "Failed to remove surface tag"
+ )
+ Report.result(tag_removed_from_container, success)
-class TestGradientSurfaceTagEmitter(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSucessfully",
- args=["level"])
+if __name__ == "__main__":
- 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
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully)
- 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 Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
-
- # 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()
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py
index b5f342a15f..5e6df4d52f 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py
@@ -5,118 +5,102 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+def GradientTransform_ComponentIncompatibleWithExpectedGradients():
+ """
+ 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.
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ 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
-class TestGradientTransform_ComponentIncompatibleWithExpectedGradients(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientTransform_ComponentIncompatibleWithExpectedGradients",
- args=["level"])
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- 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.
+ :return: None
+ """
- Expected Behavior:
- All added components are disabled and inform the user that they are incompatible with the Gradient Transform
- Modifier
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.math as math
+ import azlmbr.entity as EntityId
- 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
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ def is_enabled(EntityComponentIdPair):
+ return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
- :return: None
- """
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- def is_enabled(EntityComponentIdPair):
- return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
+ # 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)
- # 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,
+ gradient.components = []
+
+ for component in components_to_add:
+ gradient.components.append(hydra.add_component(component, gradient_id))
+ entity_created = (
+ "Entity created successfully",
+ "Failed to create entity"
+ )
+ Report.critical_result(entity_created, gradient_id.isValid())
+
+ # 3) Make sure all components are enabled in Entity
+ index = 0
+ for component in components_to_add:
+ components_enabled = (
+ f"{component} is enabled",
+ f"{component} is unexpectedly disabled"
)
+ Report.critical_result(components_enabled, is_enabled(gradient.components[index]))
+ index += 1
- # 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()
+ # 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",
+ ]
+ new_components_enabled = False
+ for component in new_components_to_add:
+ gradient.components.append(hydra.add_component(component, gradient_id))
+ gradient_components_disabled = (
+ f"{component} is disabled",
+ f"{component} is enabled, but should be disabled"
)
- 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
+ Report.result(gradient_components_disabled, not is_enabled(gradient.components[2]))
+ if not is_enabled(gradient.components[2]):
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
+if __name__ == "__main__":
-test = TestGradientTransform_ComponentIncompatibleWithExpectedGradients()
-test.run()
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientTransform_ComponentIncompatibleWithExpectedGradients)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py
index 54270c5ee5..fd65996fdd 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py
@@ -5,104 +5,88 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+def GradientTransform_ComponentIncompatibleWithSpawners():
+ """
+ Summary:
+ A simple level is opened. A New entity is created with components Gradient Transform Modifier and Box Shape.
+ Adding a component Vegetation Layer Spawner to the same entity.
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ Expected Behavior:
+ The Vegetation Layer Spawner is deactivated and it is communicated that it is incompatible with Gradient
+ Transform Modifier
+ Test Steps:
+ 1) Open a simple 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
-class TestGradientTransform_ComponentIncompatibleWithSpawners(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientTransform_ComponentIncompatibleWithSpawners",
- args=["level"])
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- 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.
+ :return: None
+ """
- Expected Behavior:
- The Vegetation Layer Spawner is deactivated and it is communicated that it is incompatible with Gradient
- Transform Modifier
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.math as math
+ import azlmbr.entity as EntityId
- 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
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ def is_enabled(EntityComponentIdPair):
+ return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
- :return: None
- """
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- def is_enabled(EntityComponentIdPair):
- return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", EntityComponentIdPair)
+ # 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)
- # 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,
+ gradient.components = []
+
+ for component in components_to_add:
+ gradient.components.append(hydra.add_component(component, gradient_id))
+ entity_created = (
+ "Entity created successfully",
+ "Failed to create entity"
+ )
+ Report.critical_result(entity_created, gradient_id.isValid())
+
+ # 3) Make sure all components are enabled in Entity
+ index = 0
+ for component in components_to_add:
+ components_enabled = (
+ f"{component} is enabled",
+ f"{component} is unexpectedly disabled"
)
+ Report.critical_result(components_enabled, is_enabled(gradient.components[index]))
+ index += 1
- # 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)
+ # 4) Add Vegetation Layer Spawner to the same entity
+ gradient.components.append(hydra.add_component("Vegetation Layer Spawner", 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
+ # 5) Make sure newly added component is disabled
+ spawner_component_disabled = (
+ "Spawner component is disabled",
+ "Spawner component is unexpectedly enabled"
+ )
+ Report.result(spawner_component_disabled, not is_enabled(gradient.components[2]))
-test = TestGradientTransform_ComponentIncompatibleWithSpawners()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientTransform_ComponentIncompatibleWithSpawners)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py
index 94647a0b6f..530503db86 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py
@@ -5,87 +5,82 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+class Tests:
+ entity_created = (
+ "Entity created successfully",
+ "Failed to create entity"
+ )
+ components_added = (
+ "All expected components added to entity",
+ "Failed to add expected components to entity"
+ )
+ higher_zoom_value_set = (
+ "Frequency Zoom is equal to expected value",
+ "Frequency Zoom is not equal to expected value"
+ )
-class TestGradientTransformFrequencyZoom(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientTransform_FrequencyZoomBeyondSliders", args=["level"])
+def GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange():
+ """
+ Summary:
+ Frequency Zoom can manually be set higher than 8 in a random noise gradient
- 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
- 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
- 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 Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.math as math
+ import azlmbr.entity as EntityId
- # 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,
- )
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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")
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # 2) Create entity
+ entity_position = math.Vector3(125.0, 136.0, 32.0)
+ entity_id = editor.ToolsApplicationRequestBus(
+ bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
+ )
+ Report.critical_result(Tests.entity_created, entity_id.IsValid())
- # 4) Set the frequency value of the component
- hydra.get_set_test(entity, 1, "Configuration|Frequency Zoom", 10)
+ # 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))
+ Report.critical_result(Tests.components_added, len(entity.components) == 3)
- # 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")
+ # 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")
+ Report.result(Tests.higher_zoom_value_set, curr_value == 10.0)
-test = TestGradientTransformFrequencyZoom()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
index c9cfc225d1..09cce359d5 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
@@ -4,73 +4,71 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-class TestGradientTransformRequiresShape(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientTransformRequiresShape", args=["level"])
-
- def run_test(self):
- """
- Summary:
- This test verifies that the Gradient Transform Modifier component is dependent on a shape component.
-
- Expected Result:
- Gradient Transform Modifier component is disabled until a shape component is added to the entity.
-
- Test Steps:
- 1) Open level
- 2) Create a new entity with a Gradient Transform Modifier component
- 3) Verify the component is disabled until a shape component is also added to the entity
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
- # 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")
+class Tests:
+ disabled_without_shape = (
+ "Gradient Transform Modifier component is disabled without a Shape component on the Entity",
+ "Gradient Transform Modifier component is unexpectedly enabled without a Shape component on the Entity",
+ )
+ enabled_with_shape = (
+ "Gradient Transform Modifier component is enabled now that the Entity has a Shape",
+ "Gradient Transform Modifier component is still disabled alongside a Shape component",
+ )
-test = TestGradientTransformRequiresShape()
-test.run()
+def GradientTransform_RequiresShape():
+ """
+ Summary:
+ This test verifies that the Gradient Transform Modifier component is dependent on a shape component.
+
+ Expected Result:
+ Gradient Transform Modifier component is disabled until a shape component is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Gradient Transform Modifier component
+ 3) Verify the component is disabled until a shape component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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)
+ Report.result(Tests.disabled_without_shape, not active)
+
+ # 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)
+ Report.result(Tests.enabled_with_shape, active)
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientTransform_RequiresShape)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py
index 1063260550..42458665e1 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py
@@ -5,89 +5,91 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+class Tests:
+ image_gradient_entity_created = (
+ "Image Gradient entity created",
+ "Failed to create Image Gradient entity",
+ )
+ image_gradient_asset_found = (
+ "image_grad_test_gsi.png was found in the workspace",
+ "image_grad_test_gsi.png was not found in the workspace"
+ )
+ image_gradient_assigned = (
+ "Successfully assigned image gradient asset",
+ "Failed to assign image gradient asset"
+ )
-class TestImageGradient(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="ImageGradient_ProcessedImageAssignedSucessfully",
- args=["level"])
+def ImageGradient_ProcessedImageAssignedSuccessfully():
+ """
+ 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.
- 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.
+ 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.
+ Test Steps:
+ 1) Open a 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 Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- :return: None
- """
+ :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,
- )
+ import os
- # 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)
+ 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
- # 3) Assign the processed gradient signal image as the Image Gradient's image asset and verify success
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # First, check for the base image in the workspace
- base_image = "image_grad_test_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")
+ # 1) Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Next, assign the processed image to the Image Gradient's Image Asset property
- processed_image_path = os.path.join("Assets", "ImageGradients", "image_grad_test_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)
+ # 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()
+ )
+ Report.critical_result(Tests.image_gradient_entity_created, new_entity_id.IsValid())
+ 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)
- # 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
+ # 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 = "image_grad_test_gsi.png"
+ base_image_path = os.path.join("AutomatedTesting", "Assets", "ImageGradients", base_image)
+ Report.critical_result(Tests.image_gradient_asset_found, os.path.isfile(base_image_path))
+
+ # Next, assign the processed image to the Image Gradient's Image Asset property
+ processed_image_path = os.path.join("Assets", "ImageGradients", "image_grad_test_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
+ Report.result(Tests.image_gradient_assigned, success)
-test = TestImageGradient()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(ImageGradient_ProcessedImageAssignedSuccessfully)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
index 2c6ac8d15b..3b832d160a 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
@@ -4,74 +4,72 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-class TestImageGradientRequiresShape(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="ImageGradientRequiresShape", args=["level"])
-
- def run_test(self):
- """
- Summary:
- This test verifies that the Image Gradient component is dependent on a shape component.
-
- Expected Result:
- Gradient Transform Modifier component is disabled until a shape component is added to the entity.
-
- Test Steps:
- 1) Open level
- 2) Create a new entity with a Image Gradient component
- 3) Verify the component is disabled until a shape component is also added to the entity
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
- # 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")
+class Tests:
+ disabled_without_shape = (
+ "Image Gradient component is disabled without a Shape component on the Entity",
+ "Image Gradient component is unexpectedly enabled without a Shape component on the Entity",
+ )
+ enabled_with_shape = (
+ "Image Gradient component is enabled now that the Entity has a Shape",
+ "Image Gradient component is still disabled alongside a Shape component",
+ )
-test = TestImageGradientRequiresShape()
-test.run()
+def ImageGradient_RequiresShape():
+ """
+ Summary:
+ This test verifies that the Image Gradient component is dependent on a shape component.
+
+ Expected Result:
+ Gradient Transform Modifier component is disabled until a shape component is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Image Gradient component
+ 3) Verify the component is disabled until a shape component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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)
+ Report.result(Tests.disabled_without_shape, not active)
+
+ # 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)
+ Report.result(Tests.enabled_with_shape, active)
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(ImageGradient_RequiresShape)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic.py
new file mode 100644
index 0000000000..21eecf642c
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic.py
@@ -0,0 +1,71 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import os
+import pytest
+import sys
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../automatedtesting_shared')
+from base import TestAutomationBase
+
+
+@pytest.mark.SUITE_periodic
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(TestAutomationBase):
+
+ def test_GradientGenerators_Incompatibilities(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientGenerators_Incompatibilities as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientModifiers_Incompatibilities(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientModifiers_Incompatibilities as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientPreviewSettings_DefaultPinnedEntityIsSelf(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientPreviewSettings_DefaultPinnedEntityIsSelf as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientSampling_GradientReferencesAddRemoveSuccessfully(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientSampling_GradientReferencesAddRemoveSuccessfully as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientSurfaceTagEmitter_ComponentDependencies(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientSurfaceTagEmitter_ComponentDependencies as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientTransform_RequiresShape(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientTransform_RequiresShape as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientTransform_ComponentIncompatibleWithSpawners(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientTransform_ComponentIncompatibleWithSpawners as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_GradientTransform_ComponentIncompatibleWithExpectedGradients(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientTransform_ComponentIncompatibleWithExpectedGradients as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_ImageGradient_RequiresShape(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import ImageGradient_RequiresShape as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_ImageGradient_ProcessedImageAssignedSuccessfully(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import ImageGradient_ProcessedImageAssignedSuccessfully as test_module
+ self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic_Optimized.py
new file mode 100644
index 0000000000..514504d324
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSignal_Periodic_Optimized.py
@@ -0,0 +1,55 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import pytest
+
+from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
+
+
+@pytest.mark.SUITE_periodic
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(EditorTestSuite):
+
+ class test_GradientGenerators_Incompatibilities(EditorSharedTest):
+ from .EditorScripts import GradientGenerators_Incompatibilities as test_module
+
+ class test_GradientModifiers_Incompatibilities(EditorSharedTest):
+ from .EditorScripts import GradientModifiers_Incompatibilities as test_module
+
+ class test_GradientPreviewSettings_DefaultPinnedEntityIsSelf(EditorSharedTest):
+ from .EditorScripts import GradientPreviewSettings_DefaultPinnedEntityIsSelf as test_module
+
+ class test_GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin(EditorSharedTest):
+ from .EditorScripts import GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin as test_module
+
+ class test_GradientSampling_GradientReferencesAddRemoveSuccessfully(EditorSharedTest):
+ from .EditorScripts import GradientSampling_GradientReferencesAddRemoveSuccessfully as test_module
+
+ class test_GradientSurfaceTagEmitter_ComponentDependencies(EditorSharedTest):
+ from .EditorScripts import GradientSurfaceTagEmitter_ComponentDependencies as test_module
+
+ class test_GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(EditorSharedTest):
+ from .EditorScripts import GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully as test_module
+
+ class test_GradientTransform_RequiresShape(EditorSharedTest):
+ from .EditorScripts import GradientTransform_RequiresShape as test_module
+
+ class test_GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange(EditorSharedTest):
+ from .EditorScripts import GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange as test_module
+
+ class test_GradientTransform_ComponentIncompatibleWithSpawners(EditorSharedTest):
+ from .EditorScripts import GradientTransform_ComponentIncompatibleWithSpawners as test_module
+
+ class test_GradientTransform_ComponentIncompatibleWithExpectedGradients(EditorSharedTest):
+ from .EditorScripts import GradientTransform_ComponentIncompatibleWithExpectedGradients as test_module
+
+ class test_ImageGradient_RequiresShape(EditorSharedTest):
+ from .EditorScripts import ImageGradient_RequiresShape as test_module
+
+ class test_ImageGradient_ProcessedImageAssignedSuccessfully(EditorSharedTest):
+ from .EditorScripts import ImageGradient_ProcessedImageAssignedSuccessfully as test_module
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
index 913dc46fa5..9703423901 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
@@ -5,144 +5,147 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ dependencies_added = (
+ "Node created new Entity with all required components",
+ "Failed to create node with all required components"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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 AreaNodes_DependentComponentsAdded():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
+ proper dependent components.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
- proper dependent components.
+ Expected Behavior:
+ All expected component dependencies are met when adding an area node to a graph.
- Expected Behavior:
- All expected component dependencies are met when adding an area node to a graph.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure the proper dependent components are added
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the area nodes to the graph area, and ensure the proper dependent components are added
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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'
- ]
- }
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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)
+ # 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)
- # 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)
+ # 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'
+ ]
+ }
- 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))
+ # 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)
- x += 40.0
- y += 40.0
+ # 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)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ components = areas[nodeName]
+ success = False
+ for component in components:
+ componentTypeId = componentTypeIds[component]
+ success = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
+ componentTypeId)
+ if not success:
+ break
+ Report.info(nodeName)
+ Report.result(Tests.dependencies_added, success)
+
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestAreaNodeComponentDependency()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AreaNodes_DependentComponentsAdded)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
index 2ee0c60a7d..f3f4a1862d 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
@@ -5,125 +5,129 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ component_added = (
+ "New entity created with the expected component",
+ "Expected component was not found on entity"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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 AreaNodes_EntityCreatedOnNodeAdd():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+ Expected Behavior:
+ New entities are created when dragging area nodes to graph area.
- Expected Behavior:
- New entities are created when dragging area nodes to graph area.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ 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
- # 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,
- )
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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')
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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")
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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)
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # 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'
- }
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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)
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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)
+ # 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)
- 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))
+ # 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'
+ }
- x += 40.0
- y += 40.0
+ # 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)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # 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)
+ Report.info(f"Node: {nodeName} | Component: {areaComponent}")
+ Report.result(Tests.component_added, hasComponent)
+
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientNodeEntityCreate()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AreaNodes_EntityCreatedOnNodeAdd)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
index b9960447c6..f8b0539759 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
@@ -5,123 +5,128 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ entity_deleted = (
+ "Entity was deleted when node was removed",
+ "Entity was not deleted as expected when node was removed"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
createdEntityId = None
deletedEntityId = None
-class TestAreaNodeEntityDelete(EditorTestHelper):
+def AreaNodes_EntityRemovedOnNodeDelete():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityDelete", args=["level"])
+ Expected Behavior:
+ Entities are removed when area nodes are deleted from a graph.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
- Expected Behavior:
- Entities are removed when area nodes are deleted from a graph.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
- 4) Delete the nodes, and ensure the newly created entities are removed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ 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
- :return: None
- """
- def onEntityCreated(parameters):
- global createdEntityId
- createdEntityId = parameters[0]
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityDeleted(parameters):
- global deletedEntityId
- deletedEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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,
- )
+ def onEntityCreated(parameters):
+ global createdEntityId
+ createdEntityId = parameters[0]
- # 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')
+ def onEntityDeleted(parameters):
+ global deletedEntityId
+ deletedEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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',
- ]
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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)
+ # 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)
- removed = graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, node)
+ # 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',
+ ]
- # 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))
+ # 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)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ 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
+ Report.info(f"Node: {nodeName}")
+ Report.result(Tests.entity_deleted, removed and createdEntityId.invoke("Equal", deletedEntityId))
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestAreaNodeEntityDelete()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AreaNodes_EntityRemovedOnNodeDelete)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
index a704cc9dab..cc40d8b861 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
@@ -5,197 +5,209 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+class Tests:
+ slice_instantiated = (
+ "Slice instantiated successfully",
+ "Failed to instantiate slice"
+ )
+ lc_entity_found = (
+ "LandscapeCanvas entity found",
+ "Failed to find LandscapeCanvas entity"
+ )
+ spawner_entity_found = (
+ "BushSpawner entity found",
+ "Failed to find BushSpawner entity"
+ )
+ dist_filter_component_found = (
+ "Vegetation Distribution Filter component on BushSpawner entity found",
+ "Failed to find Distribution Filter component on BushSpawner entity"
+ )
+ existing_graph_opened = (
+ "Opened existing graph from slice",
+ "Failed to open existing graph"
+ )
+ dist_filter_node_found = (
+ "Vegetation Distribution Filter node found on graph",
+ "Failed to find Distribution Filter node on graph"
+ )
+ alt_filter_component_found = (
+ "Vegetation Altitude Filter component on BushSpawner entity found",
+ "Failed to find Altitude Filter component on BushSpawner entity"
+ )
+ alt_filter_node_found = (
+ "Vegetation Altitude Filter node found on graph",
+ "Failed to find Altitude Filter node on graph"
+ )
+ dist_filter_component_removed = (
+ "Vegetation Distribution Filter component removed from BushSpawner entity",
+ "Failed to remove Distribution Filter component from BushSpawner entity"
+ )
+ dist_filter_node_removed = (
+ "Vegetation Distribution Filter node removed from graph",
+ "Failed to remove Distribution Filter node from graph"
+ )
+ child_entity_added = (
+ "New entity successfully added as a child of the BushSpawner entity",
+ "New entity added with an unexpected parent"
+ )
+ box_shape_component_found = (
+ "Box Shape component on Box entity found",
+ "Failed to find Box Shape component on Box entity"
+ )
+ box_shape_node_found = (
+ "Box Shape node found on graph",
+ "Failed to find Box Shape node on graph"
+ )
-class TestComponentUpdatesUpdateGraph(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="ComponentUpdatesUpdateGraph", args=["level"])
+def ComponentUpdates_UpdateGraph():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of
+ Landscape Canvas.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of
- Landscape Canvas.
+ Expected Behavior:
+ Graphs properly reflect component changes made to entities outside of Landscape Canvas.
- Expected Behavior:
- Graphs properly reflect component changes made to entities outside of Landscape Canvas.
+ Test Steps:
+ 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
- Test Steps:
- 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
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ import os
- # 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!")
+ 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
- # Find root entity in the loaded level
- search_filter = entity.SearchFilter()
- search_filter.names = ["LandscapeCanvas"]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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")
+ # Open a simple level and instantiate LC_BushFlowerBlender.slice
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+ 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)
+ Report.critical_result(Tests.slice_instantiated, test_slice.IsValid())
- # 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")
+ # Find root entity in the loaded level
+ search_filter = entity.SearchFilter()
+ search_filter.names = ["LandscapeCanvas"]
- # 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")
+ # Allow a few seconds for matching entity to be found
+ helper.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
+ Report.critical_result(Tests.lc_entity_found, slice_root_id.IsValid())
- # 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")
+ # 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
+ Report.critical_result(Tests.spawner_entity_found, spawner_id.IsValid())
- # 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
+ 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 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")
+ # Verify the BushSpawner entity has a Distribution Filter
+ has_distribution_filter = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', spawner_id,
+ distribution_filter_type_id)
+ Report.critical_result(Tests.dist_filter_component_found, has_distribution_filter)
- # 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")
+ # Open Landscape Canvas and the existing graph
+ general.open_pane('Landscape Canvas')
+ open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
+ Report.critical_result(Tests.existing_graph_opened, open_graph.IsValid())
- 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")
+ # 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)
+ Report.critical_result(Tests.dist_filter_node_found, distribution_filter_node is not None)
- # Remove the Distribution Filter
- editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [spawner_distribution_filter_component_id])
- general.idle_wait(1.0)
+ # 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)
+ Report.result(Tests.dist_filter_component_found, has_altitude_filter)
+ Report.result(Tests.dist_filter_node_found, altitude_filter_node is not None)
- # 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")
+ # Remove the Distribution Filter
+ editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [spawner_distribution_filter_component_id])
+ general.idle_wait(1.0)
- 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")
+ # 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)
+ Report.result(Tests.dist_filter_component_removed, not has_distribution_filter)
- # 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")
+ distribution_filter_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast,
+ 'GetAllNodesMatchingEntityComponent',
+ spawner_distribution_filter_component_id)
+ Report.result(Tests.dist_filter_node_removed, not distribution_filter_node)
- # 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")
+ # Add a new child entity of BushSpawner entity
+ box_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', spawner_id)
+ Report.result(Tests.child_entity_added, editor.EditorEntityInfoRequestBus(bus.Event, 'GetParent', box_id) ==
+ spawner_id)
- # Verify the Box Shape node appear on the graph
- box_shape_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', box_id,
- box_shape_type_id)
+ # 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)
+ Report.result(Tests.box_shape_component_found, has_box_shape)
- 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")
+ # Verify the Box Shape node appears 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)
+ Report.result(Tests.box_shape_node_found, box_shape_node is not None)
-test = TestComponentUpdatesUpdateGraph()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(ComponentUpdates_UpdateGraph)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Component_AddedRemoved.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Component_AddedRemoved.py
new file mode 100644
index 0000000000..7f21a26595
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Component_AddedRemoved.py
@@ -0,0 +1,80 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+class Tests:
+ lc_component_added = (
+ "Landscape Canvas component successfully added to entity",
+ "Failed to add Landscape Canvas component to entity"
+ )
+ lc_component_removed = (
+ "Landscape Canvas component successfully removed from entity",
+ "Failed to remove Landscape Canvas component from entity"
+ )
+
+
+def Component_AddedRemoved():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas component can be added to/removed from an entity.
+
+ Expected Behavior:
+ Closing a tabbed graph only closes the appropriate graph.
+
+ Test Steps:
+ 1) Open a simple level
+ 2) Create a new entity
+ 3) Add a Landscape Canvas component to the entity
+ 4) Remove the Landscape Canvas component from the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # Create an Entity at the root of the level
+ newEntityId = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
+
+ # Find the component TypeId for our Landscape Canvas component
+ landscape_canvas_type_id = hydra.get_component_type_id("Landscape Canvas")
+
+ # Add the Landscape Canvas Component to our Entity
+ componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', newEntityId, [landscape_canvas_type_id])
+ components = componentOutcome.GetValue()
+ landscapeCanvasComponent = components[0]
+
+ # Validate the Landscape Canvas Component exists
+ hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, landscape_canvas_type_id)
+ Report.result(Tests.lc_component_added, hasComponent)
+
+ # Remove the Landscape Canvas Component
+ editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [landscapeCanvasComponent])
+
+ # Validate the Landscape Canvas Component is no longer on our Entity
+ hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, landscape_canvas_type_id)
+ Report.result(Tests.lc_component_removed, not hasComponent)
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(Component_AddedRemoved)
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py
deleted file mode 100755
index 971134becf..0000000000
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py
+++ /dev/null
@@ -1,106 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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):
- """
- Summary:
- This test verifies that new graphs can be created in Landscape Canvas.
-
- Expected Behavior:
- New graphs can be created, and proper entity is created to hold graph data with a Landscape Canvas component.
-
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Ensures the root entity created contains a Landscape Canvas component
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
- 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()
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
index b2b9e63a56..417e093567 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
@@ -5,131 +5,132 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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 Edit_DisabledNodeDuplication():
+ """
+ Summary:
+ This test verifies Editor stability after duplicating disabled Landscape Canvas nodes.
- def run_test(self):
- """
- Summary:
- This test verifies Editor stability after duplicating disabled Landscape Canvas nodes.
+ Expected Behavior:
+ Editor remains stable and free of crashes.
- Expected Behavior:
- Editor remains stable and free of crashes.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Create several new nodes, disable the nodes via disabling/deleting components, and duplicate the nodes
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Create several new nodes, disable the nodes via disabling/deleting components, and duplicate the nodes
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ 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
- # 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,
- )
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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')
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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")
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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)
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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'
- }
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # 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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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)
+ # 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)
- dependentComponentName = nodes[nodeName]
- componentTypeId = componentTypeIds[dependentComponentName]
- componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', newEntityId, componentTypeId)
- component = componentOutcome.GetValue()
+ # 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'
+ }
- # 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))
+ # 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)
- # 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))
+ # 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)
- x += 40.0
- y += 40.0
+ dependentComponentName = nodes[nodeName]
+ componentTypeId = componentTypeIds[dependentComponentName]
+ componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', newEntityId, componentTypeId)
+ component = componentOutcome.GetValue()
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # First make sure we can duplicate a node with a dependent component that is disabled
+ editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [component])
+ helper.wait_for_condition(lambda: not editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled',
+ [component]), 1.0)
+ graph.SceneRequestBus(bus.Event, 'DuplicateSelection', newGraphId) # This duplication would cause a crash without the fix
+ Report.info("{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])
+ helper.wait_for_condition(lambda: not editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType',
+ componentTypeIds[dependentComponentName]), 1.0)
+ graph.SceneRequestBus(bus.Event, 'DuplicateSelection', newGraphId) # This duplication would cause a crash without the fix
+ Report.info("{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()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(Edit_DisabledNodeDuplication)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
index a651567f85..a26e16755f 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
@@ -5,133 +5,134 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ slice_spawned = (
+ "Slice instantiated successfully",
+ "Failed to instantiate slice"
+ )
+ lc_entity_found = (
+ "Landscape Canvas entity found",
+ "Failed to find Landscape Canvas entity"
+ )
+ spawner_entity_found = (
+ "Spawner entity found",
+ "Failed to find Spawner entity"
+ )
+ graph_opened = (
+ "Graph successfully opened",
+ "Graph failed to open"
+ )
+ spawner_node_found = (
+ "Vegetation Layer Spawner node found on graph",
+ "Failed to find Vegetation Layer Spawner node on graph"
+ )
+ spawner_node_removed = (
+ "Vegetation Layer Spawner node was successfully removed",
+ "Failed to remove Vegetation Layer Spawner node"
+ )
+def Edit_UndoNodeDelete_SliceEntity():
+ """
+ Summary:
+ This test verifies Editor stability after undoing the deletion of nodes on a slice entity.
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
+ Expected Behavior:
+ Editor remains stable and free of crashes.
+
+ Test Steps:
+ 1) Open a simple level
+ 2) Instantiate a slice with a Landscape Canvas setup
+ 3) Find a specific node on the graph, and delete it
+ 4) Restore the node with Undo
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import os
+
+ import 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 editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # Instantiate slice
+ 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)
+ Report.result(Tests.slice_spawned, test_slice.IsValid())
+
+ # 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
+ helper.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
+ Report.result(Tests.lc_entity_found, slice_root_id.IsValid())
+
+ # 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
+ Report.result(Tests.spawner_entity_found, spawner_id.IsValid())
+
+ # Open Landscape Canvas and the existing graph
+ general.open_pane('Landscape Canvas')
+ open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
+ Report.result(Tests.graph_opened, open_graph.IsValid())
+
+ # 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)
+ Report.result(Tests.spawner_node_found, layer_spawner_node is not None)
+
+ # 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)
+ Report.result(Tests.spawner_node_removed, not layer_spawner_node)
+
+ # 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
+ Report.info("Editor is still responsive")
-class TestUndoNodeDeleteSlice(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="UndoNodeDeleteSlice", args=["level"])
+if __name__ == "__main__":
- def run_test(self):
- """
- Summary:
- This test verifies Editor stability after undoing the deletion of nodes on a slice entity.
+ from editor_python_test_tools.utils import Report
+ Report.start_test(Edit_UndoNodeDelete_SliceEntity)
- Expected Behavior:
- Editor remains stable and free of crashes.
-
- Test Steps:
- 1) Create a new level
- 2) Instantiate a slice with a Landscape Canvas setup
- 3) Find a specific node on the graph, and delete it
- 4) Restore the node with Undo
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
- # 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()
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
index 341e6d3367..c390df7c61 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
@@ -5,190 +5,205 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ preview_entity_set = (
+ "Perlin Noise Gradient component Preview Entity property set to Box Shape EntityId",
+ "Unexpected entity set in Perlin Noise Gradient Preview Entity property"
+ )
+ mixer_inbound_gradient_set_a = (
+ "Gradient Mixer component Inbound Gradient extendable property set to Perlin Noise Gradient EntityId",
+ "Unexpected entity set in Gradient Mixer's Inbound Gradient property"
+ )
+ mixer_inbound_gradient_set_b = (
+ "Gradient Mixer component Inbound Gradient extendable property set to FastNoise Gradient EntityId",
+ "Unexpected entity set in Gradient Mixer's Inbound Gradient property"
+ )
+ mixer_operation_a = (
+ "Layer 1 Operation is set to Initialize",
+ "Layer 1 Operation is not set to Initialize as expected"
+ )
+ mixer_operation_b = (
+ "Layer 2 Operation is set to Average",
+ "Layer 2 Operation is not set to Average as expected"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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 GradientMixer_NodeConstruction():
+ """
+ Summary:
+ This test verifies a Gradient Mixer vegetation setup can be constructed through Landscape Canvas.
- def run_test(self):
- """
- Summary:
- This test verifies a Gradient Mixer vegetation setup can be constructed through Landscape Canvas.
+ Expected Behavior:
+ Entities contain all required components and component references after creating nodes and setting connections
+ on a Landscape Canvas graph.
- Expected Behavior:
- Entities contain all required components and component references after creating nodes and setting connections
- on a Landscape Canvas graph.
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add all necessary nodes to the graph and set connections to form a Gradient Mixer setup
+ 4) Verify all components and component references were properly set during graph construction
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Add all necessary nodes to the graph and set connections to form a Gradient Mixer setup
- 4) Verify all components and component references were properly set during graph construction
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- positionX = 10.0
- positionY = 10.0
- offsetX = 340.0
- offsetY = 100.0
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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
+ # 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 += offsetX
- positionY += offsetY
+ positionX = 10.0
+ positionY = 10.0
+ offsetX = 340.0
+ offsetY = 100.0
- # 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
+ # 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
+ 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
+ # 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
+ 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
+ # 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
- 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')
+ positionX += offsetX
+ positionY += offsetY
- # 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)
+ # 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
- # Delay to allow all the underlying component properties to be updated after the slot connections are made
- general.idle_wait(1.0)
+ 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')
- # 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()
+ # 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)
- # 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")
+ # Delay to allow all the underlying component properties to be updated after the slot connections are made
+ general.idle_wait(1.0)
- # 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")
+ # 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 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 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')
+ Report.result(Tests.preview_entity_set, previewEntityId and boxShapeEntityId.invoke("Equal", previewEntityId))
- # 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')
+ # 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')
+ Report.result(Tests.mixer_inbound_gradient_set_a, inboundGradientEntityId and perlinNoiseEntityId.invoke("Equal", inboundGradientEntityId))
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # 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')
+ Report.result(Tests.mixer_inbound_gradient_set_b, inboundGradientEntityId2 and fastNoiseEntityId.invoke("Equal", inboundGradientEntityId2))
+
+ # Verify that Gradient Mixer Layer Operations are properly set
+ mixer_operation_a = hydra.get_component_property_value(gradientMixerComponent, 'Configuration|Layers|[0]|Operation')
+ mixer_operation_b = hydra.get_component_property_value(gradientMixerComponent, 'Configuration|Layers|[1]|Operation')
+ Report.result(Tests.mixer_operation_a, mixer_operation_a == 0)
+ Report.result(Tests.mixer_operation_b, mixer_operation_b == 6)
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientMixerNodeConstruction()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientMixer_NodeConstruction)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
index 43d39602be..c3952fe34b 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
@@ -5,132 +5,134 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ component_added = (
+ "New entity created with the expected component",
+ "Expected component was not found on entity"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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 GradientModifierNodes_EntityCreatedOnNodeAdd():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+ Expected Behavior:
+ New entities are created when dragging Gradient Modifier nodes to graph area.
- Expected Behavior:
- New entities are created when dragging Gradient Modifier nodes to graph area.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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'
- }
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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)
+ # 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)
- # 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)
+ # 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'
+ }
- 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))
+ # 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)
- x += 40.0
- y += 40.0
+ # 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)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ gradientComponent = gradientModifiers[nodeName]
+ componentTypeId = componentTypeIds[gradientComponent]
+ hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
+ componentTypeId)
+ Report.info(f"Node: {nodeName} | Component: {gradientComponent}")
+ Report.result(Tests.component_added, hasComponent)
+
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientModifierNodeEntityCreate()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientModifierNodes_EntityCreatedOnNodeAdd)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
index f7b4dcf557..d7789a21fb 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
@@ -5,126 +5,129 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ entity_deleted = (
+ "Entity was deleted when node was removed",
+ "Entity was not deleted as expected when node was removed"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
createdEntityId = None
deletedEntityId = None
-class TestGradientModifierNodeEntityDelete(EditorTestHelper):
+def GradientModifierNodes_EntityRemovedOnNodeDelete():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityDelete", args=["level"])
+ Expected Behavior:
+ Entities are removed when Gradient Modifier nodes are deleted from a graph.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
- Expected Behavior:
- Entities are removed when Gradient Modifier nodes are deleted from a graph.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
- 4) Delete the nodes, and ensure the newly created entities are removed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ 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
- :return: None
- """
- def onEntityCreated(parameters):
- global createdEntityId
- createdEntityId = parameters[0]
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityDeleted(parameters):
- global deletedEntityId
- deletedEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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,
- )
+ def onEntityCreated(parameters):
+ global createdEntityId
+ createdEntityId = parameters[0]
- # 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')
+ def onEntityDeleted(parameters):
+ global deletedEntityId
+ deletedEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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
- gradientModifiers = [
- 'DitherGradientModifierNode',
- 'GradientMixerNode',
- 'InvertGradientModifierNode',
- 'LevelsGradientModifierNode',
- 'PosterizeGradientModifierNode',
- 'SmoothStepGradientModifierNode',
- 'ThresholdGradientModifierNode'
- ]
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # 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 gradientModifiers:
- nodePosition = math.Vector2(x, y)
- node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+ # 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)
- removed = graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, node)
+ # 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
+ gradientModifiers = [
+ 'DitherGradientModifierNode',
+ 'GradientMixerNode',
+ 'InvertGradientModifierNode',
+ 'LevelsGradientModifierNode',
+ 'PosterizeGradientModifierNode',
+ 'SmoothStepGradientModifierNode',
+ 'ThresholdGradientModifierNode'
+ ]
- # 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))
+ # 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 gradientModifiers:
+ nodePosition = math.Vector2(x, y)
+ node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ 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
+ Report.info(f"Node: {nodeName}")
+ Report.result(Tests.entity_deleted, removed and createdEntityId.invoke("Equal", deletedEntityId))
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientModifierNodeEntityDelete()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientModifierNodes_EntityRemovedOnNodeDelete)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
index 96eac887cd..c04f9f05f6 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
@@ -5,141 +5,143 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ dependencies_added = (
+ "Node created new Entity with all required components",
+ "Failed to create node with all required components"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newEntityId = None
-class TestGradientNodeComponentDependency(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientNodeComponentDependency", args=["level"])
+def GradientNodes_DependentComponentsAdded():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
+ proper dependent components.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
- proper dependent components.
+ Expected Behavior:
+ All expected component dependencies are met when adding a Gradient Modifier node to a graph.
- Expected Behavior:
- All expected component dependencies are met when adding a Gradient Modifier node to a graph.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure the proper dependent components are
+ added
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure the proper dependent components are
- added
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # Listen for entity creation notifications so we can check if the entity created
- # from adding these gradients nodes has the main target Gradient Component
- # as well as automatically adding all required dependency components
- handler = editor.EditorEntityContextNotificationBusHandler()
- handler.connect()
- handler.add_callback('OnEditorEntityCreated', onEntityCreated)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # Gradient 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
- gradients = {
- 'FastNoiseGradientNode': 'FastNoise Gradient',
- 'ImageGradientNode': 'Image Gradient',
- 'PerlinNoiseGradientNode': 'Perlin Noise Gradient',
- 'RandomNoiseGradientNode': 'Random Noise Gradient'
- }
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Retrieve a mapping of the TypeIds for all the components
- # we will be checking for
- commonComponents = [
- 'Gradient Transform Modifier',
- 'Vegetation Reference Shape'
- ]
- componentNames = []
- for name in gradients:
- componentNames.append(gradients[name])
- componentNames.extend(commonComponents)
- componentTypeIds = hydra.get_component_type_id_map(componentNames)
+ # Listen for entity creation notifications so we can check if the entity created
+ # from adding these gradients nodes has the main target Gradient Component
+ # as well as automatically adding all required dependency components
+ handler = editor.EditorEntityContextNotificationBusHandler()
+ handler.connect()
+ handler.add_callback('OnEditorEntityCreated', onEntityCreated)
- # Create nodes for the gradients that have additional required dependencies and check if
- # the Entity created by adding the node has the appropriate Component and required
- # Gradient Transform Modifier and Vegetation Reference Shape components added automatically to it
- newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
- x = 10.0
- y = 10.0
- for nodeName in gradients:
- nodePosition = math.Vector2(x, y)
- node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+ # Gradient 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
+ gradients = {
+ 'FastNoiseGradientNode': 'FastNoise Gradient',
+ 'ImageGradientNode': 'Image Gradient',
+ 'PerlinNoiseGradientNode': 'Perlin Noise Gradient',
+ 'RandomNoiseGradientNode': 'Random Noise Gradient'
+ }
- gradientComponent = gradients[nodeName]
- components = [gradientComponent] + commonComponents
- success = False
- for component in components:
- componentTypeId = componentTypeIds[component]
- success = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, componentTypeId)
- self.test_success = self.test_success and success
- if not success:
- break
+ # Retrieve a mapping of the TypeIds for all the components
+ # we will be checking for
+ commonComponents = [
+ 'Gradient Transform Modifier',
+ 'Vegetation Reference Shape'
+ ]
+ componentNames = []
+ for name in gradients:
+ componentNames.append(gradients[name])
+ componentNames.extend(commonComponents)
+ componentTypeIds = hydra.get_component_type_id_map(componentNames)
- if success:
- self.log("{node} created new Entity with all required components".format(node=nodeName))
+ # Create nodes for the gradients that have additional required dependencies and check if
+ # the Entity created by adding the node has the appropriate Component and required
+ # Gradient Transform Modifier and Vegetation Reference Shape components added automatically to it
+ newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
+ x = 10.0
+ y = 10.0
+ for nodeName in gradients:
+ nodePosition = math.Vector2(x, y)
+ node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
- x += 40.0
- y += 40.0
+ gradientComponent = gradients[nodeName]
+ components = [gradientComponent] + commonComponents
+ success = False
+ for component in components:
+ componentTypeId = componentTypeIds[component]
+ success = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, componentTypeId)
+ if not success:
+ break
+ Report.info(nodeName)
+ Report.result(Tests.dependencies_added, success)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientNodeComponentDependency()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientNodes_DependentComponentsAdded)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
index a484de8d2a..d5595e342c 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
@@ -5,130 +5,134 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-import os, 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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ component_added = (
+ "New entity created with the expected component",
+ "Expected component was not found on entity"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.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="GradientNodeEntityCreate", args=["level"])
+def GradientNodes_EntityCreatedOnNodeAdd():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+ Expected Behavior:
+ New entities are created when dragging Gradient nodes to graph area.
- Expected Behavior:
- New entities are created when dragging Gradient nodes to graph area.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # Gradient 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
- gradients = {
- 'AltitudeGradientNode': 'Altitude Gradient',
- 'ConstantGradientNode': 'Constant Gradient',
- 'FastNoiseGradientNode': 'FastNoise Gradient',
- 'ImageGradientNode': 'Image Gradient',
- 'PerlinNoiseGradientNode': 'Perlin Noise Gradient',
- 'RandomNoiseGradientNode': 'Random Noise Gradient',
- 'ShapeAreaFalloffGradientNode': 'Shape Falloff Gradient',
- 'SlopeGradientNode': 'Slope Gradient',
- 'SurfaceMaskGradientNode': 'Surface Mask Gradient',
- }
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Retrieve a mapping of the TypeIds for all the components
- # we will be checking for
- componentNames = []
- for name in gradients:
- componentNames.append(gradients[name])
- componentTypeIds = hydra.get_component_type_id_map(componentNames)
+ # 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)
- # 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 gradients:
- nodePosition = math.Vector2(x, y)
- node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+ # Gradient 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
+ gradients = {
+ 'AltitudeGradientNode': 'Altitude Gradient',
+ 'ConstantGradientNode': 'Constant Gradient',
+ 'FastNoiseGradientNode': 'FastNoise Gradient',
+ 'ImageGradientNode': 'Image Gradient',
+ 'PerlinNoiseGradientNode': 'Perlin Noise Gradient',
+ 'RandomNoiseGradientNode': 'Random Noise Gradient',
+ 'ShapeAreaFalloffGradientNode': 'Shape Falloff Gradient',
+ 'SlopeGradientNode': 'Slope Gradient',
+ 'SurfaceMaskGradientNode': 'Surface Mask Gradient',
+ }
- gradientComponent = gradients[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))
+ # Retrieve a mapping of the TypeIds for all the components
+ # we will be checking for
+ componentNames = []
+ for name in gradients:
+ componentNames.append(gradients[name])
+ componentTypeIds = hydra.get_component_type_id_map(componentNames)
- x += 40.0
- y += 40.0
+ # 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 gradients:
+ nodePosition = math.Vector2(x, y)
+ node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ gradientComponent = gradients[nodeName]
+ componentTypeId = componentTypeIds[gradientComponent]
+ hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, componentTypeId)
+ Report.info(f"Node: {nodeName} | Component: {gradientComponent}")
+ Report.result(Tests.component_added, hasComponent)
+
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientNodeEntityCreate()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientNodes_EntityCreatedOnNodeAdd)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
index 2e289ff41b..e5bfbfc7f1 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
@@ -5,129 +5,131 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ entity_deleted = (
+ "Entity was deleted when node was removed",
+ "Entity was not deleted as expected when node was removed"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
createdEntityId = None
deletedEntityId = None
-class TestGradientNodeEntityDelete(EditorTestHelper):
+def GradientNodes_EntityRemovedOnNodeDelete():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityDelete", args=["level"])
+ Expected Behavior:
+ Entities are removed when Gradient nodes are deleted from a graph.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
- Expected Behavior:
- Entities are removed when Gradient nodes are deleted from a graph.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
- 4) Delete the nodes, and ensure the newly created entities are removed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ 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
- :return: None
- """
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityCreated(parameters):
- global createdEntityId
- createdEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- def onEntityDeleted(parameters):
- global deletedEntityId
- deletedEntityId = parameters[0]
+ def onEntityCreated(parameters):
+ global createdEntityId
+ createdEntityId = 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,
- )
+ def onEntityDeleted(parameters):
+ global deletedEntityId
+ deletedEntityId = parameters[0]
- # 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')
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # 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")
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # 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)
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Gradient 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
- gradients = [
- 'AltitudeGradientNode',
- 'ConstantGradientNode',
- 'FastNoiseGradientNode',
- 'ImageGradientNode',
- 'PerlinNoiseGradientNode',
- 'RandomNoiseGradientNode',
- 'ShapeAreaFalloffGradientNode',
- 'SlopeGradientNode',
- 'SurfaceMaskGradientNode',
- ]
+ # 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)
- # 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 gradients:
- nodePosition = math.Vector2(x, y)
- node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+ # Gradient 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
+ gradients = [
+ 'AltitudeGradientNode',
+ 'ConstantGradientNode',
+ 'FastNoiseGradientNode',
+ 'ImageGradientNode',
+ 'PerlinNoiseGradientNode',
+ 'RandomNoiseGradientNode',
+ 'ShapeAreaFalloffGradientNode',
+ 'SlopeGradientNode',
+ 'SurfaceMaskGradientNode',
+ ]
- removed = graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, node)
+ # 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 gradients:
+ nodePosition = math.Vector2(x, y)
+ node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName', newGraph, nodeName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
- # 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))
+ removed = graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, node)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # Verify that the created Entity for this node matches the Entity that gets
+ # deleted when the node is removed
+ Report.info(f"Node: {nodeName}")
+ Report.result(Tests.entity_deleted, removed and createdEntityId.invoke("Equal", deletedEntityId))
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGradientNodeEntityDelete()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GradientNodes_EntityRemovedOnNodeDelete)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
index 0ad1549b60..0f83688206 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
@@ -5,100 +5,99 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ graph_closed = (
+ "Graph closed on entity delete",
+ "Graph is still open after entity delete"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newRootEntityId = None
-class TestGraphClosedOnEntityDelete(EditorTestHelper):
+def GraphClosed_OnEntityDelete():
+ """
+ Summary:
+ This test verifies that Landscape Canvas graphs are auto-closed when the corresponding entity is deleted.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GraphClosedOnEntityDelete", args=["level"])
+ Expected Behavior:
+ When a Landscape Canvas root entity is deleted, the corresponding graph automatically closes.
- def run_test(self):
- """
- Summary:
- This test verifies that Landscape Canvas graphs are auto-closed when the corresponding entity is deleted.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Delete the automatically created entity
+ 4) Verify the open graph is closed
- Expected Behavior:
- When a Landscape Canvas root entity is deleted, the corresponding graph automatically closes.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Delete the automatically created entity
- 4) Verify the open graph is closed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.editor.graph as graph
+ import azlmbr.legacy.general as general
- :return: None
- """
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityCreated(parameters):
- global newRootEntityId
- newRootEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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,
- )
+ def onEntityCreated(parameters):
+ global newRootEntityId
+ newRootEntityId = parameters[0]
- # 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')
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Listen for entity creation notifications so we can store the top-level Entity created
- # when a new graph is created, and then delete it to test if the graph is closed
- handler = editor.EditorEntityContextNotificationBusHandler()
- handler.connect()
- handler.add_callback('OnEditorEntityCreated', onEntityCreated)
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # Create a new graph in Landscape Canvas and verify
- newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
- graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- self.test_success = self.test_success and graphIsOpen
- if graphIsOpen:
- self.log("Graph registered with Landscape Canvas")
+ # Listen for entity creation notifications so we can store the top-level Entity created
+ # when a new graph is created, and then delete it to test if the graph is closed
+ handler = editor.EditorEntityContextNotificationBusHandler()
+ handler.connect()
+ handler.add_callback('OnEditorEntityCreated', onEntityCreated)
- # Delete the top-level Entity created by the new graph
- editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', newRootEntityId)
+ # Create a new graph in Landscape Canvas and verify
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graphIsOpen)
- # We need to delay here because the closing of the graph due to Entity deletion
- # is actually queued in order to workaround an undo/redo issue
- # Alternatively, we could add a notifications bus for AssetEditorRequests
- # that could trigger when graphs are opened/closed and then do the check there
- general.idle_enable(True)
- general.idle_wait(1.0)
+ # Delete the top-level Entity created by the new graph
+ editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', newRootEntityId)
- # Verify that the corresponding graph is no longer open
- graphIsClosed = not graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- self.test_success = self.test_success and graphIsClosed
- if graphIsClosed:
- self.log("The graph is no longer open after deleting the Entity")
+ # We need to delay here because the closing of the graph due to Entity deletion
+ # is actually queued in order to workaround an undo/redo issue
+ # Alternatively, we could add a notifications bus for AssetEditorRequests
+ # that could trigger when graphs are opened/closed and then do the check there
+ general.idle_enable(True)
+ general.idle_wait(1.0)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # Verify that the corresponding graph is no longer open
+ graphIsClosed = not graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_closed, graphIsClosed)
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestGraphClosedOnEntityDelete()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GraphClosed_OnEntityDelete)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
index 374f26d3a4..67c2ec6908 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
@@ -5,82 +5,82 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-import os
-import sys
-import azlmbr.bus as bus
-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'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ graph_closed = (
+ "Graph closed on level change",
+ "Graph is still open after level change"
+ )
-class TestGraphClosedOnLevelChange(EditorTestHelper):
+def GraphClosed_OnLevelChange():
+ """
+ Summary:
+ This test verifies that Landscape Canvas graphs are auto-closed when the currently open level changes.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GraphClosedOnLevelChange", args=["level"])
+ Expected Behavior:
+ When a new level is loaded in the Editor, open Landscape Canvas graphs are automatically closed.
- def run_test(self):
- """
- Summary:
- This test verifies that Landscape Canvas graphs are auto-closed when the currently open level changes.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Open a different level
+ 4) Verify the open graph is closed
- Expected Behavior:
- When a new level is loaded in the Editor, open Landscape Canvas graphs are automatically closed.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Open a different level
- 4) Verify the open graph is closed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ import azlmbr.bus as bus
+ import azlmbr.editor.graph as graph
+ import azlmbr.legacy.general as general
- :return: None
- """
- # 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,
- )
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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')
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Make sure the graph we created is in Landscape Canvas
- graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- self.test_success = self.test_success and graphIsOpen
- if graphIsOpen:
- self.log("Graph registered with Landscape Canvas")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # Open a different level, which should close any open Landscape Canvas graphs
- general.open_level_no_prompt('WhiteBox/EmptyLevel')
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # Make sure the graph we created is now closed
- graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- self.test_success = self.test_success and not graphIsOpen
- if not graphIsOpen:
- self.log("Graph is no longer open in Landscape Canvas")
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
+
+ # Open a different level, which should close any open Landscape Canvas graphs
+ general.open_level_no_prompt('WhiteBox/EmptyLevel')
+
+ # Make sure the graph we created is now closed
+ graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_closed, not graphIsOpen)
-test = TestGraphClosedOnLevelChange()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GraphClosed_OnLevelChange)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
index f8b0cfdb44..83762e0afb 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
@@ -5,95 +5,93 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-import os
-import sys
-import azlmbr.bus as bus
-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'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_open = (
+ "Graph is open in Landscape Canvas",
+ "Graph is not open in Landscape Canvas"
+ )
+ tabbed_graph_closed = (
+ "Tabbed graph closed independently",
+ "Closing tabbed graph resulted in unexpected graphs closing"
+ )
-class TestGraphClosedTabbedGraph(EditorTestHelper):
+def GraphClosed_TabbedGraphClosesIndependently():
+ """
+ Summary:
+ This test verifies that Landscape Canvas tabbed graphs can be independently closed.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GraphClosedTabbedGraph", args=["level"])
+ Expected Behavior:
+ Closing a tabbed graph only closes the appropriate graph.
- def run_test(self):
- """
- Summary:
- This test verifies that Landscape Canvas tabbed graphs can be independently closed.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create several new graphs
+ 3) Close one of the open graphs
+ 4) Ensure the graph properly closed, and other open graphs remain open
- Expected Behavior:
- Closing a tabbed graph only closes the appropriate graph.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create several new graphs
- 3) Close one of the open graphs
- 4) Ensure the graph properly closed, and other open graphs remain open
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ import azlmbr.bus as bus
+ import azlmbr.editor.graph as graph
+ import azlmbr.legacy.general as general
- :return: None
- """
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editor_id = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def create_new_graph():
+ new_graph_id = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editor_id)
+ return new_graph_id
- # Create 3 new graphs 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")
+ def is_graph_open(graph_id):
+ graph_open = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editor_id, graph_id)
+ return graph_open
- newGraphId2 = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
- self.test_success = self.test_success and newGraphId2
- if newGraphId2:
- self.log("2nd new graph created")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- newGraphId3 = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
- self.test_success = self.test_success and newGraphId3
- if newGraphId3:
- self.log("3rd new graph created")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # Make sure the graphs we created are open in Landscape Canvas
- success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- success2 = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId2)
- success3 = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId3)
- self.test_success = self.test_success and success and success2 and success3
- if success and success2 and success3:
- self.log("Graphs registered with Landscape Canvas")
+ # Create 3 new graphs in Landscape Canvas and make sure the graphs we created are open in Landscape Canvas
+ graph1 = create_new_graph()
+ Report.result(Tests.new_graph_created, graph1 is not None)
+ Report.result(Tests.graph_open, is_graph_open(graph1))
- # Close a single graph and verify it was properly closed and other graphs remain open
- success4 = graph.AssetEditorRequestBus(bus.Event, 'CloseGraph', editorId, newGraphId2)
- success = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
- success2 = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId2)
- success3 = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId3)
- self.test_success = self.test_success and success and success3 and success4 and not success2
- if success and success3 and success4 and not success2:
- self.log("Graph 2 was successfully closed")
+ graph2 = create_new_graph()
+ Report.result(Tests.new_graph_created, graph2 is not None)
+ Report.result(Tests.graph_open, is_graph_open(graph2))
+
+ graph3 = create_new_graph()
+ Report.result(Tests.new_graph_created, graph3 is not None)
+ Report.result(Tests.graph_open, is_graph_open(graph3))
+
+ # Close a single graph and verify it was properly closed and other graphs remain open
+ graph.AssetEditorRequestBus(bus.Event, 'CloseGraph', editor_id, graph2)
+ Report.result(Tests.tabbed_graph_closed, not is_graph_open(graph2) and is_graph_open(graph1) and
+ is_graph_open(graph3))
-test = TestGraphClosedTabbedGraph()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GraphClosed_TabbedGraphClosesIndependently)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
index cc7c2ca7dd..c489c738d5 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
@@ -5,155 +5,151 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
-
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import automatedtesting_shared.landscape_canvas_utils as lc
+class Tests:
+ slice_instantiated = (
+ "Slice instantiated successfully",
+ "Failed to instantiate slice"
+ )
+ existing_graph_opened = (
+ "Opened existing graph from slice",
+ "Failed to open existing graph"
+ )
+ node_removed = (
+ "Rotation Modifier node was removed",
+ "Failed to remove Rotation Modifier node"
+ )
+ component_removed = (
+ "Rotation Modifier component was removed from entity",
+ "Rotation Modifier component is still present on entity"
+ )
+ entity_deleted = (
+ "BushSpawner entity was deleted",
+ "Failed to delete BushSpawner entity"
+ )
+ entity_reference_updated = (
+ "Gradient Entity Id reference was properly updated",
+ "Gradient Entity Id reference was not updated properly"
+ )
-class TestGraphUpdatesUpdateComponents(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="GraphUpdatesUpdateComponents", args=["level"])
+def GraphUpdates_UpdateComponent():
+ """
+ Summary:
+ This test verifies that components are properly updated as nodes are added/removed/updated.
- def run_test(self):
- """
- Summary:
- This test verifies that components are properly updated as nodes are added/removed/updated.
+ Expected Behavior:
+ Landscape Canvas node CRUD properly updates component entities.
- Expected Behavior:
- Landscape Canvas node CRUD properly updates component entities.
+ Test Steps:
+ 1. Open Level.
+ 2. Open the graph on LC_BushFlowerBlender.slice
+ 3. Find the Rotation Modifier node on the BushSpawner entity
+ 4. Delete the Rotation Modifier node
+ 5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
+ 6. Delete the Vegetation Layer Spawner node from the graph
+ 7. Ensure BushSpawner entity is deleted
+ 8. Change connection from second Rotation Modifier node to a different Gradient
+ 9. Ensure Gradient reference on component is updated
- Test Steps:
- 1. Open Level.
- 2. Open the graph on LC_BushFlowerBlender.slice
- 3. Find the Rotation Modifier node on the BushSpawner entity
- 4. Delete the Rotation Modifier node
- 5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
- 6. Delete the Vegetation Layer Spawner node from the graph
- 7. Ensure BushSpawner entity is deleted
- 8. Change connection from second Rotation Modifier node to a different Gradient
- 9. Ensure Gradient reference on component is updated
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
- # 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!")
+ import os
- # Search for root entity to ensure slice is loaded
- search_filter = entity.SearchFilter()
- search_filter.names = ["LandscapeCanvas"]
- self.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0, 5.0)
+ 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
- # Find needed entities in the loaded level
- slice_root_id = hydra.find_entity_by_name('LandscapeCanvas')
- bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
- flower_spawner_id = hydra.find_entity_by_name('FlowerSpawner')
- inverted_perlin_noise_id = hydra.find_entity_by_name('Invert')
+ import automatedtesting_shared.landscape_canvas_utils as lc
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # Open Landscape Canvas and the existing graph
- general.open_pane('Landscape Canvas')
- open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
- self.test_success = self.test_success and open_graph_id.IsValid()
- if open_graph_id.IsValid():
- self.log('Graph opened')
+ # Open a simple level and instantiate LC_BushFlowerBlender.slice
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+ 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)
+ Report.critical_result(Tests.slice_instantiated, test_slice.IsValid())
- # Find the Rotation Modifier node on the BushSpawner entity
- rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', bush_spawner_id)
+ # Search for root entity to ensure slice is loaded
+ search_filter = entity.SearchFilter()
+ search_filter.names = ["LandscapeCanvas"]
+ helper.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0, 5.0)
- # Remove the Rotation Modifier node
- graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, rotation_modifier_node[0])
+ # Find needed entities in the loaded level
+ slice_root_id = hydra.find_entity_by_name('LandscapeCanvas')
+ bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
+ flower_spawner_id = hydra.find_entity_by_name('FlowerSpawner')
+ inverted_perlin_noise_id = hydra.find_entity_by_name('Invert')
- # Verify node was removed
- rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', bush_spawner_id)
- self.test_success = self.test_success and not rotation_modifier_node
- if not rotation_modifier_node:
- self.log('Rotation Modifier node was removed')
- else:
- self.log('Rotation Modifier node was not removed')
+ # Open Landscape Canvas and the existing graph
+ general.open_pane('Landscape Canvas')
+ open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
+ Report.critical_result(Tests.existing_graph_opened, open_graph_id.IsValid())
- # Verify the component was removed from the BushSpawner entity
- has_rotation_modifier = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', bush_spawner_id,
- hydra.get_component_type_id('Vegetation Rotation Modifier'))
- self.test_success = self.test_success and not has_rotation_modifier
- if not has_rotation_modifier:
- self.log('Rotation Modifier component was removed from entity')
- else:
- self.log('Rotation Modifier component is still present on entity')
+ # Find the Rotation Modifier node on the BushSpawner entity
+ rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', bush_spawner_id)
- # Find the Vegetation Layer Spawner node on the BushSpawner entity
- layer_spawner_node = lc.find_nodes_matching_entity_component('Vegetation Layer Spawner', bush_spawner_id)
+ # Remove the Rotation Modifier node
+ graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, rotation_modifier_node[0])
- # Remove the Vegetation Layer Spawner node and verify the corresponding entity is deleted
- graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, layer_spawner_node[0])
- bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
- self.test_success = self.test_success and not bush_spawner_id
- if not bush_spawner_id:
- self.log('BushSpawner entity was deleted')
- else:
- self.log('Failed to delete BushSpawner entity')
+ # Verify node was removed
+ rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', bush_spawner_id)
+ Report.result(Tests.node_removed, not rotation_modifier_node)
- # Connect the FlowerSpawner's Rotation Modifier node to the Invert Gradient Modifier node
- rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', flower_spawner_id)
- invert_node = lc.find_nodes_matching_entity_component('Invert Gradient Modifier', inverted_perlin_noise_id)
+ # Verify the component was removed from the BushSpawner entity
+ has_rotation_modifier = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', bush_spawner_id,
+ hydra.get_component_type_id('Vegetation Rotation Modifier'))
+ Report.result(Tests.component_removed, not has_rotation_modifier)
- inbound_gradient_z_slot = graph.GraphModelSlotId('InboundGradientZ')
- outbound_gradient_slot = graph.GraphModelSlotId('OutboundGradient')
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', open_graph_id, invert_node[0],
- outbound_gradient_slot, rotation_modifier_node[0], inbound_gradient_z_slot)
+ # Find the Vegetation Layer Spawner node on the BushSpawner entity
+ layer_spawner_node = lc.find_nodes_matching_entity_component('Vegetation Layer Spawner', bush_spawner_id)
- general.idle_wait(1.0) # Add a small wait to ensure component property has time to update
+ # Remove the Vegetation Layer Spawner node and verify the corresponding entity is deleted
+ graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, layer_spawner_node[0])
+ bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
+ Report.result(Tests.entity_deleted, not bush_spawner_id)
- # Verify the Gradient Entity Id reference on the Rotation Modifier component was properly set
- rotation_type_id = hydra.get_component_type_id('Vegetation Rotation Modifier')
- rotation_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', flower_spawner_id,
- rotation_type_id)
- rotation_component = rotation_outcome.GetValue()
- gradient_reference = hydra.get_component_property_value(rotation_component,
- 'Configuration|Rotation Z|Gradient|Gradient Entity Id')
- gradient_reference_success = gradient_reference == inverted_perlin_noise_id
- self.test_success = self.test_success and gradient_reference_success
- if gradient_reference_success:
- self.log('Gradient Entity Id reference was properly updated')
- else:
- self.log(f'Gradient Entity Id was not updated properly: Expected {inverted_perlin_noise_id.ToString()} -- Got '
- f'{gradient_reference.ToString()}.')
+ # Connect the FlowerSpawner's Rotation Modifier node to the Invert Gradient Modifier node
+ rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', flower_spawner_id)
+ invert_node = lc.find_nodes_matching_entity_component('Invert Gradient Modifier', inverted_perlin_noise_id)
+
+ inbound_gradient_z_slot = graph.GraphModelSlotId('InboundGradientZ')
+ outbound_gradient_slot = graph.GraphModelSlotId('OutboundGradient')
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', open_graph_id, invert_node[0],
+ outbound_gradient_slot, rotation_modifier_node[0], inbound_gradient_z_slot)
+
+ general.idle_wait(1.0) # Add a small wait to ensure component property has time to update
+
+ # Verify the Gradient Entity Id reference on the Rotation Modifier component was properly set
+ rotation_type_id = hydra.get_component_type_id('Vegetation Rotation Modifier')
+ rotation_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', flower_spawner_id,
+ rotation_type_id)
+ rotation_component = rotation_outcome.GetValue()
+ gradient_reference = hydra.get_component_property_value(rotation_component,
+ 'Configuration|Rotation Z|Gradient|Gradient Entity Id')
+ Report.result(Tests.entity_reference_updated, gradient_reference == inverted_perlin_noise_id)
-test = TestGraphUpdatesUpdateComponents()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(GraphUpdates_UpdateComponent)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py
deleted file mode 100755
index ed6f23ae24..0000000000
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py
+++ /dev/null
@@ -1,87 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-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 editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
-
-
-class TestLandscapeCanvasComponentAddedRemoved(EditorTestHelper):
-
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="LandscapeCanvasComponentAddedRemoved", args=["level"])
-
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas component can be added to/removed from an entity.
-
- Expected Behavior:
- Closing a tabbed graph only closes the appropriate graph.
-
- Test Steps:
- 1) Create a new level
- 2) Create a new entity
- 3) Add a Landscape Canvas component to the entity
- 4) Remove the Landscape Canvas component from the entity
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
-
- :return: None
- """
-
- # 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,
- )
-
- # Create an Entity at the root of the level
- newEntityId = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
-
- # Find the component TypeId for our Landscape Canvas component
- landscape_canvas_type_id = hydra.get_component_type_id("Landscape Canvas")
-
- # Add the Landscape Canvas Component to our Entity
- componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', newEntityId, [landscape_canvas_type_id])
- components = componentOutcome.GetValue()
- landscapeCanvasComponent = components[0]
-
- # Validate the Landscape Canvas Component exists
- hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, landscape_canvas_type_id)
- self.test_success = self.test_success and hasComponent
- if hasComponent:
- self.log("Landscape Canvas Component added to Entity")
-
- # Remove the Landscape Canvas Component
- editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [landscapeCanvasComponent])
-
- # Validate the Landscape Canvas Component is no longer on our Entity
- hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId, landscape_canvas_type_id)
- self.test_success = self.test_success and not hasComponent
- if not hasComponent:
- self.log("Landscape Canvas Component removed from Entity")
-
-
-test = TestLandscapeCanvasComponentAddedRemoved()
-test.run()
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py
deleted file mode 100755
index 95da5aa7dd..0000000000
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-import os
-import sys
-
-import azlmbr.math as math
-import azlmbr.paths
-import azlmbr.bus as bus
-import azlmbr.asset as asset
-import azlmbr.slice as slice
-
-sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-
-
-class TestLandscapeCanvasSliceCreateInstantiate(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="LandscapeCanvas_SliceCreateInstantiate", args=["level"])
-
- def run_test(self):
- """
- Summary:
- A slice containing the LandscapeCanvas component can be created/instantiated.
-
- Expected Result:
- Slice is created/processed/instantiated successfully and free of errors/warnings.
-
- Test Steps:
- 1) Create a new level
- 2) Create a new entity with a Landscape Canvas component
- 3) Create a slice of the new entity
- 4) Instantiate a new copy of the slice
-
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
- :return: None
- """
-
- def path_is_valid_asset(asset_path):
- asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", asset_path, math.Uuid(), False)
- return asset_id.invoke("IsValid")
-
- # 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 entity with LandScape Canvas component
- position = math.Vector3(512.0, 512.0, 32.0)
- landscape_canvas = hydra.Entity("landscape_canvas_entity")
- landscape_canvas.create_entity(position, ["Landscape Canvas"])
-
- # Create slice from the created entity
- slice_path = os.path.join("slices", "TestSlice.slice")
- slice.SliceRequestBus(bus.Broadcast, "CreateNewSlice", landscape_canvas.id, slice_path)
-
- # Verify if slice is created
- self.wait_for_condition(lambda: path_is_valid_asset(slice_path), 5.0)
- self.log(f"Slice has been created successfully: {path_is_valid_asset(slice_path)}")
-
- # Instantiate slice
- transform = math.Transform_CreateIdentity()
- asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", slice_path, math.Uuid(), False)
- test_slice = slice.SliceRequestBus(bus.Broadcast, "InstantiateSliceFromAssetId", asset_id, transform)
- self.wait_for_condition(lambda: test_slice.IsValid(), 3.0)
- self.log(f"Slice instantiated: {test_slice.IsValid()}")
-
-
-test = TestLandscapeCanvasSliceCreateInstantiate()
-test.run()
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
index f68bfd91a6..b2bf20411b 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
@@ -5,157 +5,160 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ blender_first_layer_set = (
+ "Spawner entity set as the first layer of the Vegetation Layer Blender component",
+ "Unexpected entity set as the first layer of the Vegetation Layer Blender component"
+ )
+ blender_second_layer_set = (
+ "Blocker entity set as the second layer of the Vegetation Layer Blender component",
+ "Unexpected entity set as the second layer of the Vegetation Layer Blender component"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newEntityId = None
-class TestLayerBlenderNodeConstruction(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="LayerBlenderNodeConstruction", args=["level"])
+def LayerBlender_NodeConstruction():
+ """
+ Summary:
+ This test verifies a Layer Blender vegetation setup can be constructed through Landscape Canvas.
- def run_test(self):
- """
- Summary:
- This test verifies a Layer Blender vegetation setup can be constructed through Landscape Canvas.
+ Expected Behavior:
+ Entities contain all required components and component references after creating nodes and setting connections
+ on a Landscape Canvas graph.
- Expected Behavior:
- Entities contain all required components and component references after creating nodes and setting connections
- on a Landscape Canvas graph.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add all necessary nodes to the graph and set connections to form a Layer Blender setup
+ 4) Verify all components and component references were properly set during graph construction
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Add all necessary nodes to the graph and set connections to form a Layer Blender setup
- 4) Verify all components and component references were properly set during graph construction
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('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)
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- positionX = 10.0
- positionY = 10.0
- offsetX = 340.0
- offsetY = 100.0
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Add a Vegetation Layer Spawner node to the graph
- newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
- layerSpawnerNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, 'SpawnerAreaNode')
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerSpawnerNode, math.Vector2(positionX, positionY))
- layerSpawnerEntityId = newEntityId
+ # 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 += offsetX
- positionY += offsetY
+ positionX = 10.0
+ positionY = 10.0
+ offsetX = 340.0
+ offsetY = 100.0
- # Add a Vegetation Layer Blocker node to the graph
- layerBlockerNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, 'BlockerAreaNode')
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerBlockerNode, math.Vector2(positionX, positionY))
- layerBlockerEntityId = newEntityId
+ # Add a Vegetation Layer Spawner node to the graph
+ newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
+ layerSpawnerNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, 'SpawnerAreaNode')
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerSpawnerNode, math.Vector2(positionX, positionY))
+ layerSpawnerEntityId = newEntityId
- positionX += offsetX
- positionY += offsetY
+ positionX += offsetX
+ positionY += offsetY
- # Add a Vegetation Layer Blender node to the graph
- layerBlenderNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, 'AreaBlenderNode')
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerBlenderNode, math.Vector2(positionX, positionY))
- layerBlenderNodeEntityId = newEntityId
+ # Add a Vegetation Layer Blocker node to the graph
+ layerBlockerNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, 'BlockerAreaNode')
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerBlockerNode, math.Vector2(positionX, positionY))
+ layerBlockerEntityId = newEntityId
- positionX += offsetX
- positionY += offsetY
+ positionX += offsetX
+ positionY += offsetY
- outboundAreaSlotId = graph.GraphModelSlotId('OutboundArea')
- inboundAreaSlotId = graph.GraphModelSlotId('InboundArea')
- inboundAreaSlotId2 = graph.GraphControllerRequestBus(bus.Event, 'ExtendSlot', newGraphId, layerBlenderNode,
- 'InboundArea')
+ # Add a Vegetation Layer Blender node to the graph
+ layerBlenderNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, 'AreaBlenderNode')
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, layerBlenderNode, math.Vector2(positionX, positionY))
+ layerBlenderNodeEntityId = newEntityId
- # Connect slots on our nodes to construct a Vegetation Layer Blender hierarchy
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, layerSpawnerNode, outboundAreaSlotId,
- layerBlenderNode, inboundAreaSlotId)
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, layerBlockerNode, outboundAreaSlotId,
- layerBlenderNode, inboundAreaSlotId2)
+ positionX += offsetX
+ positionY += offsetY
- # Delay to allow all the underlying component properties to be updated after the slot connections are made
- general.idle_wait(1.0)
+ outboundAreaSlotId = graph.GraphModelSlotId('OutboundArea')
+ inboundAreaSlotId = graph.GraphModelSlotId('InboundArea')
+ inboundAreaSlotId2 = graph.GraphControllerRequestBus(bus.Event, 'ExtendSlot', newGraphId, layerBlenderNode,
+ 'InboundArea')
- # Get component info
- layerBlenderTypeId = hydra.get_component_type_id("Vegetation Layer Blender")
- vegetationLayerBlenderOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType',
- layerBlenderNodeEntityId, layerBlenderTypeId)
- layerBlenderComponent = vegetationLayerBlenderOutcome.GetValue()
+ # Connect slots on our nodes to construct a Vegetation Layer Blender hierarchy
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, layerSpawnerNode, outboundAreaSlotId,
+ layerBlenderNode, inboundAreaSlotId)
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, layerBlockerNode, outboundAreaSlotId,
+ layerBlenderNode, inboundAreaSlotId2)
- # Verify the Vegetation Areas properties on our Vegetation Layer Blender component have been set to our area EntityIds
- area1EntityId = hydra.get_component_property_value(layerBlenderComponent, 'Configuration|Vegetation Areas|[0]')
- self.test_success = self.test_success and area1EntityId and layerSpawnerEntityId.invoke("Equal", area1EntityId)
- if area1EntityId and layerSpawnerEntityId.invoke("Equal", area1EntityId):
- self.log("Vegetation Layer Blender component Vegetation Areas[0] property set to Vegetation Layer Spawner EntityId")
+ # Delay to allow all the underlying component properties to be updated after the slot connections are made
+ general.idle_wait(1.0)
- area2EntityId = hydra.get_component_property_value(layerBlenderComponent, 'Configuration|Vegetation Areas|[1]')
- self.test_success = self.test_success and area2EntityId and layerBlockerEntityId.invoke("Equal", area2EntityId)
- if area2EntityId and layerBlockerEntityId.invoke("Equal", area2EntityId):
- self.log("Vegetation Layer Blender component Vegetation Areas[1] property set to Vegetation Layer Blocker EntityId")
+ # Get component info
+ layerBlenderTypeId = hydra.get_component_type_id("Vegetation Layer Blender")
+ vegetationLayerBlenderOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType',
+ layerBlenderNodeEntityId, layerBlenderTypeId)
+ layerBlenderComponent = vegetationLayerBlenderOutcome.GetValue()
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # Verify the Vegetation Areas properties on our Vegetation Layer Blender component have been set to our area EntityIds
+ area1EntityId = hydra.get_component_property_value(layerBlenderComponent, 'Configuration|Vegetation Areas|[0]')
+ Report.result(Tests.blender_first_layer_set, area1EntityId and layerSpawnerEntityId.invoke("Equal", area1EntityId))
+
+ area2EntityId = hydra.get_component_property_value(layerBlenderComponent, 'Configuration|Vegetation Areas|[1]')
+ Report.result(Tests.blender_second_layer_set, area2EntityId and layerBlockerEntityId.invoke("Equal", area2EntityId))
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestLayerBlenderNodeConstruction()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(LayerBlender_NodeConstruction)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
index 5b523e0b38..510c404614 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
@@ -5,164 +5,170 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ component_added = (
+ "Expected component is present on entity",
+ "Expected component was not found on entity"
+ )
+ component_removed = (
+ "Expected component was removed from entity",
+ "Component is unexpectedly still present on entity"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newEntityId = None
-class TestLayerExtenderNodeComponentEntitySync(EditorTestHelper):
+def LayerExtenderNodes_ComponentEntitySync():
+ """
+ Summary:
+ This test verifies that all wrapped nodes can be successfully added to/removed from parent nodes.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="LayerExtenderNodeComponentEntitySync", args=["level"])
+ Expected Behavior:
+ All wrapped extender nodes can be added to/removed from appropriate parent nodes.
- def run_test(self):
- """
- Summary:
- This test verifies that all wrapped nodes can be successfully added to/removed from parent nodes.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add Area Blender and Layer Spawner nodes to the graph, and add/remove each extender node to/from each
- Expected Behavior:
- All wrapped extender nodes can be added to/removed from appropriate parent nodes.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Add Area Blender and Layer Spawner nodes to the graph, and add/remove each extender node to/from each
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ 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
- :return: None
- """
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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,
- )
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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')
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # 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")
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # 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")
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # Listen for entity creation notifications so we can check if the
- # proper components are added when we add nodes
- handler = editor.EditorEntityContextNotificationBusHandler()
- handler.connect()
- handler.add_callback('OnEditorEntityCreated', onEntityCreated)
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Extender mapping with the key being the node name and the value is the
- # expected Component that should be added to the layer Entity for that wrapped node
- extenders = {
- 'AltitudeFilterNode': 'Vegetation Altitude Filter',
- 'DistanceBetweenFilterNode': 'Vegetation Distance Between Filter',
- 'DistributionFilterNode': 'Vegetation Distribution Filter',
- 'ShapeIntersectionFilterNode': 'Vegetation Shape Intersection Filter',
- 'SlopeFilterNode': 'Vegetation Slope Filter',
- 'SurfaceMaskDepthFilterNode': 'Vegetation Surface Mask Depth Filter',
- 'SurfaceMaskFilterNode': 'Vegetation Surface Mask Filter',
- 'PositionModifierNode': 'Vegetation Position Modifier',
- 'RotationModifierNode': 'Vegetation Rotation Modifier',
- 'ScaleModifierNode': 'Vegetation Scale Modifier',
- 'SlopeAlignmentModifierNode': 'Vegetation Slope Alignment Modifier',
- 'AssetWeightSelectorNode': 'Vegetation Asset Weight Selector'
- }
+ # Listen for entity creation notifications so we can check if the
+ # proper components are added when we add nodes
+ handler = editor.EditorEntityContextNotificationBusHandler()
+ handler.connect()
+ handler.add_callback('OnEditorEntityCreated', onEntityCreated)
- # Retrieve a mapping of the TypeIds for all the components
- # we will be checking for
- componentNames = []
- for name in extenders:
- componentNames.append(extenders[name])
- componentTypeIds = hydra.get_component_type_id_map(componentNames)
+ # Extender mapping with the key being the node name and the value is the
+ # expected Component that should be added to the layer Entity for that wrapped node
+ extenders = {
+ 'AltitudeFilterNode': 'Vegetation Altitude Filter',
+ 'DistanceBetweenFilterNode': 'Vegetation Distance Between Filter',
+ 'DistributionFilterNode': 'Vegetation Distribution Filter',
+ 'ShapeIntersectionFilterNode': 'Vegetation Shape Intersection Filter',
+ 'SlopeFilterNode': 'Vegetation Slope Filter',
+ 'SurfaceMaskDepthFilterNode': 'Vegetation Surface Mask Depth Filter',
+ 'SurfaceMaskFilterNode': 'Vegetation Surface Mask Filter',
+ 'PositionModifierNode': 'Vegetation Position Modifier',
+ 'RotationModifierNode': 'Vegetation Rotation Modifier',
+ 'ScaleModifierNode': 'Vegetation Scale Modifier',
+ 'SlopeAlignmentModifierNode': 'Vegetation Slope Alignment Modifier',
+ 'AssetWeightSelectorNode': 'Vegetation Asset Weight Selector'
+ }
- areas = [
- 'AreaBlenderNode',
- 'SpawnerAreaNode'
- ]
+ # Retrieve a mapping of the TypeIds for all the components
+ # we will be checking for
+ componentNames = []
+ for name in extenders:
+ componentNames.append(extenders[name])
+ componentTypeIds = hydra.get_component_type_id_map(componentNames)
- # Add/remove all our supported extender nodes to the Layer Areas and check if the appropriate
- # Components are added/removed to the wrapper node's Entity
- newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
- x = 10.0
- y = 10.0
- for areaName in areas:
- nodePosition = math.Vector2(x, y)
- areaNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, areaName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, areaNode, nodePosition)
+ areas = [
+ 'AreaBlenderNode',
+ 'SpawnerAreaNode'
+ ]
- success = True
- for extenderName in extenders:
- # Add the wrapped node for the extender
- extenderNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast,
- 'CreateNodeForTypeName', newGraph,
- extenderName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, extenderNode, nodePosition)
- graph.GraphControllerRequestBus(bus.Event, 'WrapNode', newGraphId, areaNode, extenderNode)
+ # Add/remove all our supported extender nodes to the Layer Areas and check if the appropriate
+ # Components are added/removed to the wrapper node's Entity
+ newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
+ x = 10.0
+ y = 10.0
+ for areaName in areas:
+ nodePosition = math.Vector2(x, y)
+ areaNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, areaName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, areaNode, nodePosition)
- # Check that the appropriate Component was added when the extender node was added
- extenderComponent = extenders[extenderName]
- componentTypeId = componentTypeIds[extenderComponent]
- success = success and editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
+ success = True
+ for extenderName in extenders:
+ # Add the wrapped node for the extender
+ extenderNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast,
+ 'CreateNodeForTypeName', newGraph,
+ extenderName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, extenderNode, nodePosition)
+ graph.GraphControllerRequestBus(bus.Event, 'WrapNode', newGraphId, areaNode, extenderNode)
+
+ # Check that the appropriate Component was added when the extender node was added
+ extenderComponent = extenders[extenderName]
+ componentTypeId = componentTypeIds[extenderComponent]
+ success = success and editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
+ componentTypeId)
+ Report.info(f"Component: {extenderComponent}")
+ Report.result(Tests.component_added, success)
+ if not success:
+ break
+
+ # Check that the appropriate Component was removed when the extender node was removed
+ graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, extenderNode)
+ success = success and not editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
componentTypeId)
- self.test_success = self.test_success and success
- if not success:
- self.log("{node} failed to add {component} Component".format(node=areaName,
- component=extenderComponent))
- break
+ Report.info(f"Component: {extenderComponent}")
+ Report.result(Tests.component_removed, success)
+ if not success:
+ break
- # Check that the appropriate Component was removed when the extender node was removed
- graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', newGraphId, extenderNode)
- success = success and not editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
- componentTypeId)
- self.test_success = self.test_success and success
- if not success:
- self.log("{node} failed to remove {component} Component".format(node=areaName,
- component=extenderComponent))
- break
+ if success:
+ Report.info(f"{areaName} successfully added and removed all filters/modifiers/selectors")
- if success:
- self.log("{node} successfully added and removed all filters/modifiers/selectors".format(node=areaName))
-
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestLayerExtenderNodeComponentEntitySync()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(LayerExtenderNodes_ComponentEntitySync)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/NewGraph_CreatedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/NewGraph_CreatedSuccessfully.py
new file mode 100644
index 0000000000..d13c5dfa2f
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/NewGraph_CreatedSuccessfully.py
@@ -0,0 +1,111 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ lc_component_added = (
+ "Root entity created with the Landscape Canvas component",
+ "Landscape Canvas component was not found on the root entity"
+ )
+ lc_tool_closed = (
+ "Landscape Canvas tool closed",
+ "Failed to close Landscape Canvas tool"
+ )
+
+
+new_root_entity_id = None
+
+
+def NewGraph_CreatedSuccessfully():
+ """
+ Summary:
+ This test verifies that new graphs can be created in Landscape Canvas.
+
+ Expected Behavior:
+ New graphs can be created, and proper entity is created to hold graph data with a Landscape Canvas component.
+
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Ensures the root entity created contains a Landscape Canvas component
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.editor.graph as graph
+ import azlmbr.legacy.general as general
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
+
+ def on_entity_created(parameters):
+ global new_root_entity_id
+ new_root_entity_id = parameters[0]
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # 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", on_entity_created)
+
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
+
+ # Create a new graph in Landscape Canvas
+ new_graph_id = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, new_graph_id is not None)
+
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, new_graph_id)
+ Report.result(Tests.graph_registered, graph_registered)
+
+ # 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)
+ Report.result(Tests.lc_component_added, success)
+
+ # Close Landscape Canvas tool and verify
+ general.close_pane("Landscape Canvas")
+ Report.result(Tests.lc_tool_closed, not general.is_pane_visible("Landscape Canvas"))
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(NewGraph_CreatedSuccessfully)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
index 0c877535a9..93464c7ad3 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
@@ -5,133 +5,136 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ component_added = (
+ "New entity created with the expected component",
+ "Expected component was not found on entity"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newEntityId = None
-class TestShapeNodeEntityCreate(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityCreate", args=["level"])
+def ShapeNodes_EntityCreatedOnNodeAdd():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+ Expected Behavior:
+ New entities are created when dragging shape nodes to graph area.
- Expected Behavior:
- New entities are created when dragging shape nodes to graph area.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
- :return: None
- """
+ 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
- def onEntityCreated(parameters):
- global newEntityId
- newEntityId = parameters[0]
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # 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,
- )
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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')
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
- # 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")
+ # Open an existing simple level
- # 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")
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
- # Listen for entity creation notifications so we can check if the entity created
- # from adding shape nodes has the appropriate Shape Component
- handler = editor.EditorEntityContextNotificationBusHandler()
- handler.connect()
- handler.add_callback('OnEditorEntityCreated', onEntityCreated)
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
- # Shape 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
- shapes = {
- 'BoxShapeNode': 'Box Shape',
- 'CapsuleShapeNode': 'Capsule Shape',
- 'CompoundShapeNode': 'Compound Shape',
- 'CylinderShapeNode': 'Cylinder Shape',
- 'PolygonPrismShapeNode': 'Polygon Prism Shape',
- 'SphereShapeNode': 'Sphere Shape',
- 'TubeShapeNode': 'Tube Shape',
- 'DiskShapeNode': 'Disk Shape'
- }
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
- # Retrieve a mapping of the TypeIds for all the components
- # we will be checking for
- componentNames = []
- for name in shapes:
- componentNames.append(shapes[name])
- componentTypeIds = hydra.get_component_type_id_map(componentNames)
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
- # Create nodes for all the shapes 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 shapes:
- nodePosition = math.Vector2(x, y)
- node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, nodeName)
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+ # Listen for entity creation notifications so we can check if the entity created
+ # from adding shape nodes has the appropriate Shape Component
+ handler = editor.EditorEntityContextNotificationBusHandler()
+ handler.connect()
+ handler.add_callback('OnEditorEntityCreated', onEntityCreated)
- shapeComponent = shapes[nodeName]
- componentTypeId = componentTypeIds[shapeComponent]
- 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=shapeComponent))
+ # Shape 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
+ shapes = {
+ 'BoxShapeNode': 'Box Shape',
+ 'CapsuleShapeNode': 'Capsule Shape',
+ 'CompoundShapeNode': 'Compound Shape',
+ 'CylinderShapeNode': 'Cylinder Shape',
+ 'PolygonPrismShapeNode': 'Polygon Prism Shape',
+ 'SphereShapeNode': 'Sphere Shape',
+ 'TubeShapeNode': 'Tube Shape',
+ 'DiskShapeNode': 'Disk Shape'
+ }
- x += 40.0
- y += 40.0
+ # Retrieve a mapping of the TypeIds for all the components
+ # we will be checking for
+ componentNames = []
+ for name in shapes:
+ componentNames.append(shapes[name])
+ componentTypeIds = hydra.get_component_type_id_map(componentNames)
- # Stop listening for entity creation notifications
- handler.disconnect()
+ # Create nodes for all the shapes 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 shapes:
+ nodePosition = math.Vector2(x, y)
+ node = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, nodeName)
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, node, nodePosition)
+
+ shapeComponent = shapes[nodeName]
+ componentTypeId = componentTypeIds[shapeComponent]
+ hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', newEntityId,
+ componentTypeId)
+ Report.info(f"Node: {nodeName} | Component: {shapeComponent}")
+ Report.result(Tests.component_added, hasComponent)
+
+ x += 40.0
+ y += 40.0
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
-test = TestShapeNodeEntityCreate()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(ShapeNodes_EntityCreatedOnNodeAdd)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
index 2416e05fdf..d2708f643d 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
@@ -5,127 +5,129 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ entity_deleted = (
+ "Entity was deleted when node was removed",
+ "Entity was not deleted as expected when node was removed"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
createdEntityId = None
deletedEntityId = None
-class TestShapeNodeEntityDelete(EditorTestHelper):
+def ShapeNodes_EntityRemovedOnNodeDelete():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityDelete", args=["level"])
+ Expected Behavior:
+ Entities are removed when shape nodes are deleted from a graph.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Test Steps:
+ 1) Open a simple level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
- Expected Behavior:
- Entities are removed when shape nodes are deleted from a graph.
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
- 4) Delete the nodes, and ensure the newly created entities are removed
+ :return: None
+ """
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ 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
- :return: None
- """
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- def onEntityCreated(parameters):
- global createdEntityId
- createdEntityId = parameters[0]
-
- def onEntityDeleted(parameters):
- global deletedEntityId
- deletedEntityId = parameters[0]
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
- # 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/deletion notifications so we can verify the
- # Entity created when adding a new also gets deleted when the node is deleted
- handler = editor.EditorEntityContextNotificationBusHandler()
- handler.connect()
- handler.add_callback('OnEditorEntityCreated', onEntityCreated)
- handler.add_callback('OnEditorEntityDeleted', onEntityDeleted)
-
- # All of the shape nodes that we support
- shapes = [
- 'BoxShapeNode',
- 'CapsuleShapeNode',
- 'CompoundShapeNode',
- 'CylinderShapeNode',
- 'PolygonPrismShapeNode',
- 'SphereShapeNode',
- 'TubeShapeNode',
- 'DiskShapeNode'
- ]
-
- # Create nodes for all the shapes we support and check if the Entity is created
- # and then deleted when the node is removed
- newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
- x = 10.0
- y = 10.0
- for nodeName in shapes:
- 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/deletion notifications
- handler.disconnect()
+ def onEntityCreated(parameters):
+ global createdEntityId
+ createdEntityId = parameters[0]
+
+ def onEntityDeleted(parameters):
+ global deletedEntityId
+ deletedEntityId = parameters[0]
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
+
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
+
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
+
+ # Listen for entity creation/deletion notifications so we can verify the
+ # Entity created when adding a new also gets deleted when the node is deleted
+ handler = editor.EditorEntityContextNotificationBusHandler()
+ handler.connect()
+ handler.add_callback('OnEditorEntityCreated', onEntityCreated)
+ handler.add_callback('OnEditorEntityDeleted', onEntityDeleted)
+
+ # All of the shape nodes that we support
+ shapes = [
+ 'BoxShapeNode',
+ 'CapsuleShapeNode',
+ 'CompoundShapeNode',
+ 'CylinderShapeNode',
+ 'PolygonPrismShapeNode',
+ 'SphereShapeNode',
+ 'TubeShapeNode',
+ 'DiskShapeNode'
+ ]
+
+ # Create nodes for all the shapes we support and check if the Entity is created
+ # and then deleted when the node is removed
+ newGraph = graph.GraphManagerRequestBus(bus.Broadcast, 'GetGraph', newGraphId)
+ x = 10.0
+ y = 10.0
+ for nodeName in shapes:
+ 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
+ Report.info(f"Node: {nodeName}")
+ Report.result(Tests.entity_deleted, removed and createdEntityId.invoke("Equal", deletedEntityId))
+
+ # Stop listening for entity creation/deletion notifications
+ handler.disconnect()
-test = TestShapeNodeEntityDelete()
-test.run()
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(ShapeNodes_EntityRemovedOnNodeDelete)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Slice_CreateInstantiate.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Slice_CreateInstantiate.py
new file mode 100644
index 0000000000..c5ab08f99a
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Slice_CreateInstantiate.py
@@ -0,0 +1,84 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+class Tests:
+ slice_created = (
+ "Slice created successfully",
+ "Failed to create slice"
+ )
+ slice_instantiated = (
+ "Slice instantiated successfully",
+ "Failed to instantiate slice"
+ )
+
+
+def Slice_CreateInstantiate():
+ """
+ Summary:
+ A slice containing the LandscapeCanvas component can be created/instantiated.
+
+ Expected Result:
+ Slice is created/processed/instantiated successfully and free of errors/warnings.
+
+ Test Steps:
+ 1) Open a simple level
+ 2) Create a new entity with a Landscape Canvas component
+ 3) Create a slice of the new entity
+ 4) Instantiate a new copy of the slice
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
+
+ import os
+
+ import azlmbr.math as math
+ import azlmbr.bus as bus
+ import azlmbr.asset as asset
+ import azlmbr.slice as slice
+
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+
+ def path_is_valid_asset(asset_path):
+ asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", asset_path, math.Uuid(), False)
+ return asset_id.invoke("IsValid")
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # Create entity with Landscape Canvas component
+ position = math.Vector3(512.0, 512.0, 32.0)
+ landscape_canvas = hydra.Entity("landscape_canvas_entity")
+ landscape_canvas.create_entity(position, ["Landscape Canvas"])
+
+ # Create slice from the created entity
+ slice_path = os.path.join("slices", "TestSlice.slice")
+ slice.SliceRequestBus(bus.Broadcast, "CreateNewSlice", landscape_canvas.id, slice_path)
+
+ # Verify if slice is created
+ helper.wait_for_condition(lambda: path_is_valid_asset(slice_path), 5.0)
+ Report.result(Tests.slice_created, path_is_valid_asset(slice_path))
+
+ # Instantiate slice
+ transform = math.Transform_CreateIdentity()
+ asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", slice_path, math.Uuid(), False)
+ test_slice = slice.SliceRequestBus(bus.Broadcast, "InstantiateSliceFromAssetId", asset_id, transform)
+ helper.wait_for_condition(lambda: test_slice.IsValid(), 5.0)
+ Report.result(Tests.slice_instantiated, test_slice.IsValid())
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(Slice_CreateInstantiate)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
index 2156795b1a..3169908621 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
@@ -5,210 +5,217 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
-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
+class Tests:
+ lc_tool_opened = (
+ "Landscape Canvas tool opened",
+ "Failed to open Landscape Canvas tool"
+ )
+ new_graph_created = (
+ "Successfully created new graph",
+ "Failed to create new graph"
+ )
+ graph_registered = (
+ "Graph registered with Landscape Canvas",
+ "Failed to register graph"
+ )
+ preview_entity_set = (
+ "Random Noise Gradient component Preview Entity property set to Box Shape EntityId",
+ "Unexpected entity set in Random Noise Gradient Preview Entity property"
+ )
+ dither_inbound_gradient_set = (
+ "Dither Gradient Modifier component Inbound Gradient property set to Random Noise Gradient EntityId",
+ "Unexpected entity set in Dither Gradient's Inbound Gradient property"
+ )
+ mixer_inbound_gradient_set = (
+ "Gradient Mixer component Inbound Gradient extendable property set to Dither Gradient Modifier EntityId",
+ "Unexpected entity set in Gradient Mixer's Inbound Gradient property"
+ )
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
-import editor_python_test_tools.hydra_editor_utils as hydra
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
newEntityId = None
-class TestSlotConnectionsUpdateComponents(EditorTestHelper):
- def __init__(self):
- EditorTestHelper.__init__(self, log_prefix="SlotConnectionsUpdateComponents", args=["level"])
+def SlotConnections_UpdateComponentReferences():
+ """
+ Summary:
+ This test verifies that the Landscape Canvas slot connections properly update component references.
- def run_test(self):
- """
- Summary:
- This test verifies that the Landscape Canvas slot connections properly update component references.
+ Expected Behavior:
+ A reference created through slot connections in Landscape Canvas is reflected in the Entity Inspector.
- Expected Behavior:
- A reference created through slot connections in Landscape Canvas is reflected in the Entity Inspector.
+ Test Steps:
+ 1) Open an existing level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Several nodes are added to a graph, and connections are set between the nodes
+ 4) Component references are verified via Entity Inspector
- Test Steps:
- 1) Create a new level
- 2) Open Landscape Canvas and create a new graph
- 3) Several nodes are added to a graph, and connections are set between the nodes
- 4) Component references are verified via Entity Inspector
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
- Note:
- - This test file must be called from the Open 3D Engine Editor command terminal
- - Any passed and failed tests are written to the Editor.log file.
- Parsing the file or running a log_monitor are required to observe the test results.
+ :return: None
+ """
+ import 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
- :return: None
- """
+ import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
- # Retrieve the proper component TypeIds per component name
- componentNames = [
- 'Random Noise Gradient',
- 'Dither Gradient Modifier',
- 'Gradient Mixer'
- ]
- componentTypeIds = hydra.get_component_type_id_map(componentNames)
-
- # Helper method for retrieving an EntityId from a specific property on a component
- def getEntityIdFromComponentProperty(targetEntityId, componentTypeName, propertyPath):
- componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', targetEntityId,
- componentTypeIds[componentTypeName])
- if not componentOutcome.IsSuccess():
- return None
-
- component = componentOutcome.GetValue()
- propertyOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentProperty', component,
- propertyPath)
- if not propertyOutcome.IsSuccess():
- return None
-
- return propertyOutcome.GetValue()
-
- 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 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
- randomNoiseNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, 'RandomNoiseGradientNode')
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, randomNoiseNode, math.Vector2(positionX,
- positionY))
- randomNoiseEntityId = newEntityId
-
- positionX += offsetX
- positionY += offsetY
-
- # Add a dither gradient modifier node to the graph
- ditherNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
- newGraph, 'DitherGradientModifierNode')
- graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, ditherNode, math.Vector2(positionX,
- positionY))
- ditherEntityId = 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')
-
- # Connect slots on our nodes to test all slot types like so:
- # Shape -> Gradient -> Gradient Modifier -> Gradient Mixer
- #
- # Which tests the following slot types:
- # * Shape -> Preview Bounds
- # * Gradient Output -> Gradient Modifier
- # * Gradient Output -> Gradient Mixer (extendable slots)
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, boxShapeNode, boundsSlotId,
- randomNoiseNode, previewBoundsSlotId)
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, randomNoiseNode,
- outboundGradientSlotId, ditherNode, inboundGradientSlotId)
- graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, ditherNode,
- outboundGradientSlotId, gradientMixerNode, inboundGradientSlotId)
-
- # Delay to allow all the underlying component properties to be updated after the slot connections are made
- general.idle_wait(1.0)
-
- # Verify the Preview EntityId property on our Random Noise Gradient component has been set to our Box Shape's
- # EntityId
- previewEntityId = getEntityIdFromComponentProperty(randomNoiseEntityId, 'Random Noise Gradient',
- 'Preview Settings|Pin Preview to Shape')
- random_gradient_success = previewEntityId and boxShapeEntityId.invoke("Equal", previewEntityId)
- self.test_success = self.test_success and random_gradient_success
- if random_gradient_success:
- self.log("Random Noise Gradient component Preview Entity property set to Box Shape EntityId")
-
- # Verify the Inbound Gradient EntityId property on our Dither Gradient Modifier component has been set to our
- # Random Noise Gradient's EntityId
- inboundGradientEntityId = getEntityIdFromComponentProperty(ditherEntityId, 'Dither Gradient Modifier',
- 'Configuration|Gradient|Gradient Entity Id')
- dither_gradient_success = inboundGradientEntityId and randomNoiseEntityId.invoke("Equal",
- inboundGradientEntityId)
- self.test_success = self.test_success and dither_gradient_success
- if dither_gradient_success:
- self.log("Dither Gradient Modifier component Inbound Gradient property set to Random Noise Gradient "
- "EntityId")
-
- # Verify the Inbound Gradient Mixer EntityId property on our Gradient Mixer component has been set to our
- # Dither Gradient Modifier's EntityId
- inboundGradientMixerEntityId = getEntityIdFromComponentProperty(gradientMixerEntityId, 'Gradient Mixer',
- 'Configuration|Layers|[0]|Gradient|Gradient Entity Id')
- gradient_mixer_success = inboundGradientMixerEntityId and ditherEntityId.invoke("Equal",
- inboundGradientMixerEntityId)
- self.test_success = self.test_success and gradient_mixer_success
- if gradient_mixer_success:
- self.log("Gradient Mixer component Inbound Gradient extendable property set to Dither Gradient Modifier "
- "EntityId")
-
- # Stop listening for entity creation notifications
- handler.disconnect()
+ editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
-test = TestSlotConnectionsUpdateComponents()
-test.run()
+ # Retrieve the proper component TypeIds per component name
+ componentNames = [
+ 'Random Noise Gradient',
+ 'Dither Gradient Modifier',
+ 'Gradient Mixer'
+ ]
+ componentTypeIds = hydra.get_component_type_id_map(componentNames)
+
+ # Helper method for retrieving an EntityId from a specific property on a component
+ def getEntityIdFromComponentProperty(targetEntityId, componentTypeName, propertyPath):
+ componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', targetEntityId,
+ componentTypeIds[componentTypeName])
+
+ if not componentOutcome.IsSuccess():
+ return None
+
+ component = componentOutcome.GetValue()
+ propertyOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentProperty', component,
+ propertyPath)
+ if not propertyOutcome.IsSuccess():
+ return None
+
+ return propertyOutcome.GetValue()
+
+ def onEntityCreated(parameters):
+ global newEntityId
+ newEntityId = parameters[0]
+
+ # Open an existing simple level
+ helper.init_idle()
+ helper.open_level("Physics", "Base")
+
+ # Open Landscape Canvas tool and verify
+ general.open_pane('Landscape Canvas')
+ Report.critical_result(Tests.lc_tool_opened, general.is_pane_visible('Landscape Canvas'))
+
+ # Create a new graph in Landscape Canvas
+ newGraphId = graph.AssetEditorRequestBus(bus.Event, 'CreateNewGraph', editorId)
+ Report.critical_result(Tests.new_graph_created, newGraphId is not None)
+
+ # Make sure the graph we created is in Landscape Canvas
+ graph_registered = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
+ Report.result(Tests.graph_registered, graph_registered)
+
+ # 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
+ randomNoiseNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, 'RandomNoiseGradientNode')
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, randomNoiseNode, math.Vector2(positionX,
+ positionY))
+ randomNoiseEntityId = newEntityId
+
+ positionX += offsetX
+ positionY += offsetY
+
+ # Add a dither gradient modifier node to the graph
+ ditherNode = landscapecanvas.LandscapeCanvasNodeFactoryRequestBus(bus.Broadcast, 'CreateNodeForTypeName',
+ newGraph, 'DitherGradientModifierNode')
+ graph.GraphControllerRequestBus(bus.Event, 'AddNode', newGraphId, ditherNode, math.Vector2(positionX,
+ positionY))
+ ditherEntityId = 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')
+
+ # Connect slots on our nodes to test all slot types like so:
+ # Shape -> Gradient -> Gradient Modifier -> Gradient Mixer
+ #
+ # Which tests the following slot types:
+ # * Shape -> Preview Bounds
+ # * Gradient Output -> Gradient Modifier
+ # * Gradient Output -> Gradient Mixer (extendable slots)
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, boxShapeNode, boundsSlotId,
+ randomNoiseNode, previewBoundsSlotId)
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, randomNoiseNode,
+ outboundGradientSlotId, ditherNode, inboundGradientSlotId)
+ graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', newGraphId, ditherNode,
+ outboundGradientSlotId, gradientMixerNode, inboundGradientSlotId)
+
+ # Delay to allow all the underlying component properties to be updated after the slot connections are made
+ general.idle_wait(1.0)
+
+
+ # Verify the Preview EntityId property on our Random Noise Gradient component has been set to our Box Shape's
+ # EntityId
+ previewEntityId = getEntityIdFromComponentProperty(randomNoiseEntityId, 'Random Noise Gradient',
+ 'Preview Settings|Pin Preview to Shape')
+ random_gradient_success = previewEntityId and boxShapeEntityId.invoke("Equal", previewEntityId)
+ Report.result(Tests.preview_entity_set, random_gradient_success)
+
+ # Verify the Inbound Gradient EntityId property on our Dither Gradient Modifier component has been set to our
+ # Random Noise Gradient's EntityId
+ inboundGradientEntityId = getEntityIdFromComponentProperty(ditherEntityId, 'Dither Gradient Modifier',
+ 'Configuration|Gradient|Gradient Entity Id')
+ dither_gradient_success = inboundGradientEntityId and randomNoiseEntityId.invoke("Equal",
+ inboundGradientEntityId)
+ Report.result(Tests.dither_inbound_gradient_set, dither_gradient_success)
+
+ # Verify the Inbound Gradient Mixer EntityId property on our Gradient Mixer component has been set to our
+ # Dither Gradient Modifier's EntityId
+ inboundGradientMixerEntityId = getEntityIdFromComponentProperty(gradientMixerEntityId, 'Gradient Mixer',
+ 'Configuration|Layers|[0]|Gradient|Gradient Entity Id')
+ gradient_mixer_success = inboundGradientMixerEntityId and ditherEntityId.invoke("Equal",
+ inboundGradientMixerEntityId)
+ Report.result(Tests.mixer_inbound_gradient_set, gradient_mixer_success)
+
+ # Stop listening for entity creation notifications
+ handler.disconnect()
+
+
+if __name__ == "__main__":
+
+ from editor_python_test_tools.utils import Report
+ Report.start_test(SlotConnections_UpdateComponentReferences)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py
old mode 100755
new mode 100644
index d191a82a58..4ab5a41b85
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py
@@ -105,7 +105,7 @@ class TestGeneralGraphFunctionality(object):
@pytest.mark.test_case_id("C17488412")
@pytest.mark.SUITE_periodic
- @pytest.mark.xfail # https://github.com/o3de/o3de/issues/2201
+ @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
def test_LandscapeCanvas_GraphClosed_OnEntityDelete(self, request, editor, level, launcher_platform):
cfg_args = [level]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main.py
new file mode 100644
index 0000000000..af4855a546
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main.py
@@ -0,0 +1,29 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import os
+import pytest
+import sys
+
+import ly_test_tools.environment.file_system as file_system
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../automatedtesting_shared')
+from base import TestAutomationBase
+
+
+@pytest.mark.SUITE_main
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(TestAutomationBase):
+
+ def test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import SlotConnections_UpdateComponentReferences as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientMixer_NodeConstruction(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientMixer_NodeConstruction as test_module
+ self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main_Optimized.py
new file mode 100644
index 0000000000..68bac24452
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Main_Optimized.py
@@ -0,0 +1,22 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import pytest
+
+from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
+
+
+@pytest.mark.SUITE_periodic
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(EditorTestSuite):
+
+ class test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(EditorSharedTest):
+ from .EditorScripts import SlotConnections_UpdateComponentReferences as test_module
+
+ class test_LandscapeCanvas_GradientMixer_NodeConstruction(EditorSharedTest):
+ from .EditorScripts import GradientMixer_NodeConstruction as test_module
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic.py
new file mode 100644
index 0000000000..ef8b3e492b
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic.py
@@ -0,0 +1,121 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import os
+import pytest
+import sys
+
+import ly_test_tools.environment.file_system as file_system
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../automatedtesting_shared')
+from base import TestAutomationBase
+
+
+@pytest.fixture
+def remove_test_slice(request, workspace, project):
+ file_system.delete([os.path.join(workspace.paths.engine_root(), project, "slices", "TestSlice.slice")], True, True)
+
+ def teardown():
+ file_system.delete([os.path.join(workspace.paths.engine_root(), project, "slices", "TestSlice.slice")], True,
+ True)
+
+ request.addfinalizer(teardown)
+
+
+@pytest.mark.SUITE_periodic
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(TestAutomationBase):
+
+ def test_LandscapeCanvas_AreaNodes_DependentComponentsAdded(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import AreaNodes_DependentComponentsAdded as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_AreaNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import AreaNodes_EntityCreatedOnNodeAdd as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_AreaNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import AreaNodes_EntityRemovedOnNodeDelete as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_LayerExtenderNodes_ComponentEntitySync(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import LayerExtenderNodes_ComponentEntitySync as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_Edit_DisabledNodeDuplication(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import Edit_DisabledNodeDuplication as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_Edit_UndoNodeDelete_SliceEntity(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import Edit_UndoNodeDelete_SliceEntity as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_NewGraph_CreatedSuccessfully(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import NewGraph_CreatedSuccessfully as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_Component_AddedRemoved(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import Component_AddedRemoved as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GraphClosed_OnLevelChange(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GraphClosed_OnLevelChange as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
+ def test_LandscapeCanvas_GraphClosed_OnEntityDelete(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GraphClosed_OnEntityDelete as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GraphClosed_TabbedGraphClosesIndependently(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GraphClosed_TabbedGraph as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_Slice_CreateInstantiate(self, request, workspace, editor, remove_test_slice, launcher_platform):
+ from .EditorScripts import Slice_CreateInstantiate as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientModifierNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientModifierNodes_EntityCreatedOnNodeAdd as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientModifierNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientModifierNodes_EntityRemovedOnNodeDelete as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientNodes_DependentComponentsAdded(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientNodes_DependentComponentsAdded as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientNodes_EntityCreatedOnNodeAdd as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_GraphUpdates_UpdateComponents(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import GraphUpdates_UpdateComponents as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_ComponentUpdates_UpdateGraph(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import ComponentUpdates_UpdateGraph as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_LayerBlender_NodeConstruction(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import LayerBlender_NodeConstruction as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_ShapeNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import ShapeNodes_EntityCreatedOnNodeAdd as test_module
+ self._run_test(request, workspace, editor, test_module)
+
+ def test_LandscapeCanvas_ShapeNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import ShapeNodes_EntityRemovedOnNodeDelete as test_module
+ self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic_Optimized.py
new file mode 100644
index 0000000000..59e8b1fe90
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_LandscapeCanvas_Periodic_Optimized.py
@@ -0,0 +1,89 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+import os
+import pytest
+
+import ly_test_tools.environment.file_system as file_system
+from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
+
+
+@pytest.mark.SUITE_periodic
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(EditorTestSuite):
+
+ class test_LandscapeCanvas_AreaNodes_DependentComponentsAdded(EditorSharedTest):
+ from .EditorScripts import AreaNodes_DependentComponentsAdded as test_module
+
+ class test_LandscapeCanvas_AreaNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
+ from .EditorScripts import AreaNodes_EntityCreatedOnNodeAdd as test_module
+
+ class test_LandscapeCanvas_AreaNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
+ from .EditorScripts import AreaNodes_EntityRemovedOnNodeDelete as test_module
+
+ class test_LandscapeCanvas_LayerExtenderNodes_ComponentEntitySync(EditorSharedTest):
+ from .EditorScripts import LayerExtenderNodes_ComponentEntitySync as test_module
+
+ class test_LandscapeCanvas_Edit_DisabledNodeDuplication(EditorSharedTest):
+ from .EditorScripts import Edit_DisabledNodeDuplication as test_module
+
+ class test_LandscapeCanvas_Edit_UndoNodeDelete_SliceEntity(EditorSharedTest):
+ from .EditorScripts import Edit_UndoNodeDelete_SliceEntity as test_module
+
+ class test_LandscapeCanvas_NewGraph_CreatedSuccessfully(EditorSharedTest):
+ from .EditorScripts import NewGraph_CreatedSuccessfully as test_module
+
+ class test_LandscapeCanvas_Component_AddedRemoved(EditorSharedTest):
+ from .EditorScripts import Component_AddedRemoved as test_module
+
+ class test_LandscapeCanvas_GraphClosed_OnLevelChange(EditorSharedTest):
+ from .EditorScripts import GraphClosed_OnLevelChange as test_module
+
+ @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
+ class test_LandscapeCanvas_GraphClosed_OnEntityDelete(EditorSharedTest):
+ from .EditorScripts import GraphClosed_OnEntityDelete as test_module
+
+ class test_LandscapeCanvas_GraphClosed_TabbedGraphClosesIndependently(EditorSharedTest):
+ from .EditorScripts import GraphClosed_TabbedGraph as test_module
+
+ class test_LandscapeCanvas_Slice_CreateInstantiate(EditorSingleTest):
+ # Custom teardown to remove slice asset created during test
+ def teardown(self, request, workspace, editor, editor_test_results, launcher_platform):
+ file_system.delete([os.path.join(workspace.paths.engine_root(), "AutomatedTesting", "slices",
+ "TestSlice.slice")], True, True)
+ from .EditorScripts import Slice_CreateInstantiate as test_module
+
+ class test_LandscapeCanvas_GradientModifierNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
+ from .EditorScripts import GradientModifierNodes_EntityCreatedOnNodeAdd as test_module
+
+ class test_LandscapeCanvas_GradientModifierNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
+ from .EditorScripts import GradientModifierNodes_EntityRemovedOnNodeDelete as test_module
+
+ class test_LandscapeCanvas_GradientNodes_DependentComponentsAdded(EditorSharedTest):
+ from .EditorScripts import GradientNodes_DependentComponentsAdded as test_module
+
+ class test_LandscapeCanvas_GradientNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
+ from .EditorScripts import GradientNodes_EntityCreatedOnNodeAdd as test_module
+
+ class test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
+ from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
+
+ class test_LandscapeCanvas_GraphUpdates_UpdateComponents(EditorSharedTest):
+ from .EditorScripts import GraphUpdates_UpdateComponents as test_module
+
+ class test_LandscapeCanvas_ComponentUpdates_UpdateGraph(EditorSharedTest):
+ from .EditorScripts import ComponentUpdates_UpdateGraph as test_module
+
+ class test_LandscapeCanvas_LayerBlender_NodeConstruction(EditorSharedTest):
+ from .EditorScripts import LayerBlender_NodeConstruction as test_module
+
+ class test_LandscapeCanvas_ShapeNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
+ from .EditorScripts import ShapeNodes_EntityCreatedOnNodeAdd as test_module
+
+ class test_LandscapeCanvas_ShapeNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
+ from .EditorScripts import ShapeNodes_EntityRemovedOnNodeDelete as test_module
diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py
index 060779082c..341597e36a 100755
--- a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py
+++ b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py
@@ -64,7 +64,8 @@ def C15096740_Material_LibraryUpdatedCorrectly():
# Constants
library_property_path = "Configuration|Physics Material|Library"
- default_material_path = "surfacetypemateriallibrary.physmaterial"
+
+ default_material_path = os.path.join("assets", "physics", "surfacetypemateriallibrary.physmaterial")
new_material_path = os.path.join("physicssurfaces", "default_phys_materials.physmaterial")
helper.init_idle()
@@ -82,7 +83,7 @@ def C15096740_Material_LibraryUpdatedCorrectly():
default_asset = Asset.find_asset_by_path(default_material_path)
test_component.set_component_property_value(library_property_path, default_asset.id)
default_asset.id = test_component.get_component_property_value(library_property_path)
- Report.result(Tests.override_default_library, default_asset.get_path() == default_material_path)
+ Report.result(Tests.override_default_library, default_asset.get_path() == default_material_path.replace(os.sep, '/'))
# 4) Switch it back again to the default material library.
test_component.set_component_property_value(library_property_path, azasset.AssetId())
diff --git a/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt
index 248bf3fdc5..eb37db1943 100644
--- a/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE main
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -38,7 +36,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE sandbox
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py
index 54ea3c7f15..cff8ae8377 100755
--- a/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py
+++ b/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py
@@ -133,7 +133,7 @@ class Physmaterial_Editor:
def _set_path(self):
# type: (str) -> str
if self.document_filename == None:
- self.document_filename = os.path.join(self.project_folder, "surfacetypemateriallibrary.physmaterial")
+ self.document_filename = os.path.join(self.project_folder, "assets", "physics", "surfacetypemateriallibrary.physmaterial")
else:
for (root, directories, root_files) in os.walk(self.project_folder):
for root_file in root_files:
diff --git a/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt
index 1d9c54fa40..48c24d1ebf 100644
--- a/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt
@@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE main
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py b/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py
new file mode 100644
index 0000000000..7a600f7976
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py
@@ -0,0 +1,108 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+# fmt:off
+class Tests():
+ create_new_entity = ("'CreateNewEntity' passed", "'CreateNewEntity' failed")
+ create_prefab = ("'CreatePrefab' passed", "'CreatePrefab' failed")
+ instantiate_prefab = ("'InstantiatePrefab' passed", "'InstantiatePrefab' failed")
+ has_one_child = ("instantiated prefab contains only one child as expected", "instantiated prefab does *not* contain only one child as expected")
+ instantiated_prefab_position = ("instantiated prefab's position is at the expected position", "instantiated prefab's position is *not* at the expected position")
+ delete_prefab = ("'DeleteEntitiesAndAllDescendantsInInstance' passed", "'DeleteEntitiesAndAllDescendantsInInstance' failed")
+ instantiated_prefab_removed = ("instantiated prefab's container entity has been removed", "instantiated prefab's container entity has *not* been removed")
+ instantiated_child_removed = ("instantiated prefab's child entity has been removed", "instantiated prefab's child entity has *not* been removed")
+# fmt:on
+
+def PrefabLevel_BasicWorkflow():
+ """
+ This test will help verify if the following functions related to Prefab work as expected:
+ - CreatePrefab
+ - InstantiatePrefab
+ - DeleteEntitiesAndAllDescendantsInInstance
+ """
+
+ import os
+ import sys
+
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+ import editor_python_test_tools.hydra_editor_utils as hydra
+
+ import azlmbr.bus as bus
+ import azlmbr.entity as entity
+ from azlmbr.entity import EntityId
+ import azlmbr.editor as editor
+ import azlmbr.prefab as prefab
+ from azlmbr.math import Vector3
+ import azlmbr.legacy.general as general
+
+ NEW_PREFAB_NAME = "new_prefab"
+ NEW_PREFAB_FILE_NAME = NEW_PREFAB_NAME + ".prefab"
+ NEW_PREFAB_FILE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), NEW_PREFAB_FILE_NAME)
+ INSTANTIATED_PREFAB_POSITION = Vector3(10.00, 20.0, 30.0)
+ INSTANTIATED_PREFAB_NAME = "instantiated_prefab"
+ INSTANTIATED_CHILD_ENTITY_NAME = "child_1"
+ TEST_LEVEL_FOLDER = "Prefab"
+ TEST_LEVEL_NAME = "Base"
+
+ def find_entity_by_name(entity_name):
+ searchFilter = entity.SearchFilter()
+ searchFilter.names = [entity_name]
+ entityIds = entity.SearchBus(bus.Broadcast, 'SearchEntities', searchFilter)
+ if entityIds and entityIds[0].IsValid():
+ return entityIds[0]
+ return None
+
+ def print_error_if_failed(prefab_operation_result):
+ if not prefab_operation_result.IsSuccess():
+ Report.info(f'Error message: {prefab_operation_result.GetError()}')
+
+
+# Open the test level
+ helper.init_idle()
+ helper.open_level(TEST_LEVEL_FOLDER, TEST_LEVEL_NAME)
+
+# Create a new Entity at the root level
+ new_entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', EntityId())
+ Report.result(Tests.create_new_entity, new_entity_id.IsValid())
+
+# Checks for prefab creation passed or not
+ create_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'CreatePrefabInMemory', [new_entity_id], NEW_PREFAB_FILE_PATH)
+ Report.result(Tests.create_prefab, create_prefab_result.IsSuccess())
+ print_error_if_failed(create_prefab_result)
+
+# Checks for prefab instantiation passed or not
+ instantiate_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'InstantiatePrefab', NEW_PREFAB_FILE_PATH, EntityId(), INSTANTIATED_PREFAB_POSITION)
+ Report.result(Tests.instantiate_prefab, instantiate_prefab_result.IsSuccess() and instantiate_prefab_result.GetValue().IsValid())
+ print_error_if_failed(instantiate_prefab_result)
+
+ container_entity_id = instantiate_prefab_result.GetValue()
+ editor.EditorEntityAPIBus(bus.Event, 'SetName', container_entity_id, INSTANTIATED_PREFAB_NAME)
+
+ children_entity_ids = editor.EditorEntityInfoRequestBus(bus.Event, 'GetChildren', container_entity_id)
+ Report.result(Tests.has_one_child, len(children_entity_ids) is 1)
+
+ child_entity_id = children_entity_ids[0]
+ editor.EditorEntityAPIBus(bus.Event, 'SetName', child_entity_id, INSTANTIATED_CHILD_ENTITY_NAME)
+
+# Checks if the new prefab is at the correct position and if it fails, it will provide the expected postion and the actual postion of the entity in the Editor log
+ actual_prefab_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", container_entity_id)
+ is_at_position = actual_prefab_position.IsClose(INSTANTIATED_PREFAB_POSITION)
+ Report.result(Tests.instantiated_prefab_position, is_at_position)
+ if not is_at_position:
+ Report.info(f'Expected position: {INSTANTIATED_PREFAB_POSITION.ToString()}, actual position: {actual_prefab_position.ToString()}')
+
+# Checks for prefab deletion passed or not
+ delete_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'DeleteEntitiesAndAllDescendantsInInstance', [container_entity_id])
+ Report.result(Tests.delete_prefab, delete_prefab_result.IsSuccess())
+ print_error_if_failed(delete_prefab_result)
+ Report.result(Tests.instantiated_prefab_removed, find_entity_by_name(INSTANTIATED_PREFAB_NAME) is None)
+ Report.result(Tests.instantiated_child_removed, find_entity_by_name(INSTANTIATED_CHILD_ENTITY_NAME) is None)
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(PrefabLevel_BasicWorkflow)
diff --git a/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py
index acd8f60b07..4e3d6ba77f 100644
--- a/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py
+++ b/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py
@@ -16,6 +16,7 @@ from ly_test_tools import LAUNCHERS
sys.path.append (os.path.dirname (os.path.abspath (__file__)) + '/../automatedtesting_shared')
+import ly_test_tools.environment.file_system as file_system
from base import TestAutomationBase
@pytest.mark.SUITE_main
@@ -29,3 +30,8 @@ class TestAutomation(TestAutomationBase):
def test_PrefabLevel_OpensLevelWithEntities(self, request, workspace, editor, launcher_platform):
from . import PrefabLevel_OpensLevelWithEntities as test_module
self._run_prefab_test(request, workspace, editor, test_module)
+
+ def test_PrefabLevel_BasicWorkflow(self, request, workspace, editor, launcher_platform):
+ from . import PrefabLevel_BasicWorkflow as test_module
+ self._run_prefab_test(request, workspace, editor, test_module)
+
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt
index 80b6e9a54e..25988216b2 100644
--- a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt
@@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
@@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE sandbox
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py
index 5c74754449..338389b1c4 100644
--- a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py
+++ b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py
@@ -52,7 +52,7 @@ def Pane_PropertiesChanged_RetainsOnRestart():
from utils import TestHelper as helper
import pyside_utils
- # Lumberyard Imports
+ # O3DE Imports
import azlmbr.legacy.general as general
# Pyside imports
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py b/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py
index b07a34dacd..097d3fb42d 100644
--- a/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py
+++ b/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py
@@ -93,11 +93,11 @@ def ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage():
if entity_dict["name"] == "Controller":
sc_component.get_property_tree()
sc_component.set_component_property_value(
- "Properties|Variable Fields|Variables|[0]|Name,Value|Datum|Datum|EntityToActivate",
+ "Properties|Variables|EntityToActivate|Datum|Datum|value|EntityToActivate",
entity_to_activate.id,
)
sc_component.set_component_property_value(
- "Properties|Variable Fields|Variables|[1]|Name,Value|Datum|Datum|EntityToDeactivate",
+ "Properties|Variables|EntityToDeactivate|Datum|Datum|value|EntityToDeactivate",
entity_to_deactivate.id,
)
return entity
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
index 600911e9f1..5374b0d318 100644
--- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
@@ -11,7 +11,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
if (PAL_TRAIT_BUILD_SERIALIZECONTEXTTOOLS)
list(APPEND additional_dependencies AZ::SerializeContextTools) # test_CLITool_SerializeContextTools depends on it
endif()
- list(APPEND additional_dependencies AZ::AssetBundlerBatch) # test_CLITool_AssetBundlerBatch_Works depends on it
ly_add_pytest(
NAME AutomatedTesting::SmokeTest
@@ -19,33 +18,33 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_smoke"
- TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
AZ::PythonBindingsExample
Legacy::Editor
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
- ${aditional_dependencies}
+ AZ::AzTestRunner
+ AZ::AssetBundlerBatch
+ ${additional_dependencies}
COMPONENT
Smoke
)
ly_add_pytest(
- NAME AutomatedTesting::SandboxTest
- TEST_SUITE sandbox
+ NAME AutomatedTesting::LoadLevelGPU
+ TEST_SUITE smoke
TEST_SERIAL
- PATH ${CMAKE_CURRENT_LIST_DIR}
- PYTEST_MARKS "SUITE_sandbox"
- TIMEOUT 1500
+ TEST_REQUIRES gpu
+ PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_GPULoadLevel_Works.py
+ TIMEOUT 100
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
AZ::PythonBindingsExample
- Legacy::Editor
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
COMPONENT
- Sandbox
+ Smoke
)
ly_add_pytest(
@@ -74,4 +73,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
)
+ ly_add_pytest(
+ NAME AutomatedTesting::LoadLevelCPU
+ TEST_SUITE sandbox
+ PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_CPULoadLevel_Works.py
+ TIMEOUT 100
+ RUNTIME_DEPENDENCIES
+ AZ::AssetProcessor
+ AZ::PythonBindingsExample
+ Legacy::Editor
+ AutomatedTesting.GameLauncher
+ AutomatedTesting.Assets
+ )
+
endif()
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py
index 9a54de856c..71956488fc 100644
--- a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py
+++ b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py
@@ -53,7 +53,7 @@ def Editor_NewExistingLevels_Works():
10) Save, Load and Export an existing level and close editor
Note:
- - This test file must be called from the Lumberyard Editor command terminal
+ - This test file must be called from the O3DE 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.
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py
new file mode 100644
index 0000000000..701dcfab10
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py
@@ -0,0 +1,44 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+
+UI Apps: AutomatedTesting.GameLauncher
+Launch AutomatedTesting.GameLauncher with Simple level
+Test should run in both gpu and non gpu
+"""
+
+import pytest
+import psutil
+
+import ly_test_tools.environment.waiter as waiter
+import editor_python_test_tools.hydra_test_utils as editor_test_utils
+from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
+from ly_remote_console.remote_console_commands import (
+ send_command_and_expect_response as send_command_and_expect_response,
+)
+
+
+@pytest.mark.parametrize("launcher_platform", ["windows"])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+@pytest.mark.parametrize("level", ["Simple"])
+@pytest.mark.SUITE_sandbox
+class TestRemoteConsoleLoadLevelWorks(object):
+ @pytest.fixture
+ def remote_console_instance(self, request):
+ console = RemoteConsole()
+
+ def teardown():
+ if console.connected:
+ console.stop()
+
+ request.addfinalizer(teardown)
+
+ return console
+
+ def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform):
+ expected_lines = ['Level system is loading "Simple"']
+
+ editor_test_utils.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines, null_renderer=True)
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py
new file mode 100644
index 0000000000..7debcab938
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py
@@ -0,0 +1,43 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+
+UI Apps: AutomatedTesting.GameLauncher
+Launch AutomatedTesting.GameLauncher with Simple level
+Test should run in both gpu and non gpu
+"""
+
+import pytest
+import psutil
+
+import ly_test_tools.environment.waiter as waiter
+import editor_python_test_tools.hydra_test_utils as editor_test_utils
+from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
+from ly_remote_console.remote_console_commands import (
+ send_command_and_expect_response as send_command_and_expect_response,
+)
+
+
+@pytest.mark.parametrize("launcher_platform", ["windows"])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+@pytest.mark.parametrize("level", ["Simple"])
+class TestRemoteConsoleLoadLevelWorks(object):
+ @pytest.fixture
+ def remote_console_instance(self, request):
+ console = RemoteConsole()
+
+ def teardown():
+ if console.connected:
+ console.stop()
+
+ request.addfinalizer(teardown)
+
+ return console
+
+ def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform):
+ expected_lines = ['Level system is loading "Simple"']
+
+ editor_test_utils.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines, null_renderer=False)
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py
deleted file mode 100644
index b1606e1910..0000000000
--- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-
-
-UI Apps: AutomatedTesting.GameLauncher
-Launch AutomatedTesting.GameLauncher with Simple level
-Test should run in both gpu and non gpu
-"""
-
-import pytest
-import psutil
-
-# Bail on the test if ly_test_tools doesn't exist.
-pytest.importorskip("ly_test_tools")
-import ly_test_tools.environment.waiter as waiter
-from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
-from ly_remote_console.remote_console_commands import (
- send_command_and_expect_response as send_command_and_expect_response,
-)
-
-
-@pytest.mark.parametrize("launcher_platform", ["windows"])
-@pytest.mark.parametrize("project", ["AutomatedTesting"])
-@pytest.mark.parametrize("level", ["Simple"])
-@pytest.mark.SUITE_sandbox
-class TestRemoteConsoleLoadLevelWorks(object):
- @pytest.fixture
- def remote_console_instance(self, request):
- console = RemoteConsole()
-
- def teardown():
- if console.connected:
- console.stop()
-
- request.addfinalizer(teardown)
-
- return console
-
- def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform):
- expected_lines = ['Level system is loading "Simple"']
-
- self.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines)
-
- def launch_and_validate_results_launcher(
- self,
- launcher,
- level,
- remote_console_instance,
- expected_lines,
- null_renderer=False,
- port_listener_timeout=120,
- log_monitor_timeout=300,
- remote_console_port=4600,
- ):
- """
- Runs the launcher with the specified level, and monitors Game.log for expected lines.
- :param launcher: Configured launcher object to run test against.
- :param level: The level to load in the launcher.
- :param remote_console_instance: Configured Remote Console object.
- :param expected_lines: Expected lines to search log for.
- :oaram null_renderer: Specifies the test does not require the renderer. Defaults to True.
- :param port_listener_timeout: Timeout for verifying successful connection to Remote Console.
- :param log_monitor_timeout: Timeout for monitoring for lines in Game.log
- :param remote_console_port: The port used to communicate with the Remote Console.
- """
-
- def _check_for_listening_port(port):
- """
- Checks to see if the connection to the designated port was established.
- :param port: Port to listen to.
- :return: True if port is listening.
- """
- port_listening = False
- for conn in psutil.net_connections():
- if "port={}".format(port) in str(conn):
- port_listening = True
- return port_listening
-
- if null_renderer:
- launcher.args.extend(["-NullRenderer"])
-
- # Start the Launcher
- with launcher.start():
-
- # Ensure Remote Console can be reached
- waiter.wait_for(
- lambda: _check_for_listening_port(remote_console_port),
- port_listener_timeout,
- exc=AssertionError("Port {} not listening.".format(remote_console_port)),
- )
- remote_console_instance.start(timeout=30)
-
- # Load the specified level in the launcher
- send_command_and_expect_response(
- remote_console_instance, f"loadlevel {level}", "LEVEL_LOAD_END", timeout=30
- )
-
- # Monitor the console for expected lines
- for line in expected_lines:
- assert remote_console_instance.expect_log_line(
- line, log_monitor_timeout
- ), f"Expected line not found: {line}"
diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json
index 09621469c3..94e3dcd84d 100644
--- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -1,17 +1,5 @@
{
"images" : [
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "iPhoneNotificationIcon40x40.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "iPhoneNotificationIcon60x60.png",
- "scale" : "3x"
- },
{
"size" : "29x29",
"idiom" : "iphone",
@@ -48,18 +36,6 @@
"filename" : "iPhoneAppIcon180x180.png",
"scale" : "3x"
},
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "iPadNotificationIcon20x20.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "iPadNotificationIcon40x40.png",
- "scale" : "2x"
- },
{
"size" : "29x29",
"idiom" : "ipad",
@@ -101,16 +77,10 @@
"idiom" : "ipad",
"filename" : "iPadProAppIcon167x167.png",
"scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "iOSAppStoreIcon1024x1024.png",
- "scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
-}
\ No newline at end of file
+}
diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json
index 09621469c3..94e3dcd84d 100644
--- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json
+++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json
@@ -1,17 +1,5 @@
{
"images" : [
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "iPhoneNotificationIcon40x40.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "iPhoneNotificationIcon60x60.png",
- "scale" : "3x"
- },
{
"size" : "29x29",
"idiom" : "iphone",
@@ -48,18 +36,6 @@
"filename" : "iPhoneAppIcon180x180.png",
"scale" : "3x"
},
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "iPadNotificationIcon20x20.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "iPadNotificationIcon40x40.png",
- "scale" : "2x"
- },
{
"size" : "29x29",
"idiom" : "ipad",
@@ -101,16 +77,10 @@
"idiom" : "ipad",
"filename" : "iPadProAppIcon167x167.png",
"scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "iOSAppStoreIcon1024x1024.png",
- "scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
-}
\ No newline at end of file
+}
diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json
index f836f07ee7..67b253d091 100644
--- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json
+++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -1,50 +1,5 @@
{
"images" : [
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "2436h",
- "filename" : "iPhoneLaunchImage1125x2436.png",
- "minimum-system-version" : "11.0",
- "orientation" : "portrait",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "2436h",
- "filename" : "iPhoneLaunchImage2436x1125.png",
- "minimum-system-version" : "11.0",
- "orientation" : "landscape",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "736h",
- "filename" : "iPhoneLaunchImage1242x2208.png",
- "minimum-system-version" : "8.0",
- "orientation" : "portrait",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "736h",
- "filename" : "iPhoneLaunchImage2208x1242.png",
- "minimum-system-version" : "8.0",
- "orientation" : "landscape",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "667h",
- "filename" : "iPhoneLaunchImage750x1334.png",
- "minimum-system-version" : "8.0",
- "orientation" : "portrait",
- "scale" : "2x"
- },
{
"orientation" : "portrait",
"idiom" : "iphone",
@@ -166,4 +121,4 @@
"version" : 1,
"author" : "xcode"
}
-}
\ No newline at end of file
+}
diff --git a/AutomatedTesting/Levels/Prefab/Base/Base.prefab b/AutomatedTesting/Levels/Prefab/Base/Base.prefab
new file mode 100644
index 0000000000..f7e42e7731
--- /dev/null
+++ b/AutomatedTesting/Levels/Prefab/Base/Base.prefab
@@ -0,0 +1,53 @@
+{
+ "ContainerEntity": {
+ "Id": "Entity_[1146574390643]",
+ "Name": "Level",
+ "Components": {
+ "Component_[10641544592923449938]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 10641544592923449938
+ },
+ "Component_[12039882709170782873]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 12039882709170782873
+ },
+ "Component_[12265484671603697631]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 12265484671603697631
+ },
+ "Component_[14126657869720434043]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 14126657869720434043
+ },
+ "Component_[15230859088967841193]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 15230859088967841193,
+ "Parent Entity": ""
+ },
+ "Component_[16239496886950819870]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 16239496886950819870
+ },
+ "Component_[5688118765544765547]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 5688118765544765547
+ },
+ "Component_[6545738857812235305]": {
+ "$type": "SelectionComponent",
+ "Id": 6545738857812235305
+ },
+ "Component_[7247035804068349658]": {
+ "$type": "EditorPrefabComponent",
+ "Id": 7247035804068349658
+ },
+ "Component_[9307224322037797205]": {
+ "$type": "EditorLockComponent",
+ "Id": 9307224322037797205
+ },
+ "Component_[9562516168917670048]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 9562516168917670048
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx
index bccd5cce24..2e55fdd1e7 100644
--- a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx
+++ b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ba9a2cd047a5ee696aaeed882869017a02fd4f5eeee91b6b2bfb830ad1e5ee15
-size 10927631
+oid sha256:c285cdf72ebe4c274f8d1fbab6ff558f9344d4fa62fb9d07cf11f7511ffaaac9
+size 2177072
diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo
new file mode 100644
index 0000000000..2de6d987d7
--- /dev/null
+++ b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo
@@ -0,0 +1,328 @@
+{
+ "values": [
+ {
+ "$type": "ActorGroup",
+ "name": "Jack",
+ "selectedRootBone": "RootNode.jack_root",
+ "id": "{B7194F91-D8A1-5D5D-AC6D-DDEBC087D80D}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "MetaDataRule",
+ "metaData": "AdjustActor -actorID $(ACTORID) -name \"Jack\"\nActorSetCollisionMeshes -actorID $(ACTORID) -lod 0 -nodeList \"\"\nAdjustActor -actorID $(ACTORID) -nodesExcludedFromBounds \"\" -nodeAction \"select\"\nAdjustActor -actorID $(ACTORID) -nodeAction \"replace\" -attachmentNodes \"\"\nAdjustActor -actorID $(ACTORID) -motionExtractionNodeName \"jack_root\"\nAdjustActor -actorID $(ACTORID) -mirrorSetup \"\"\n"
+ }
+ ]
+ }
+ },
+ {
+ "$type": "{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup",
+ "id": "{BF2CCF49-9BE0-5103-987A-84649A974991}",
+ "name": "Jack",
+ "NodeSelectionList": {
+ "unselectedNodes": [
+ "RootNode",
+ "RootNode.jack_root",
+ "RootNode.jack_meshZUp",
+ "RootNode.jack_root.Bip01__pelvis",
+ "RootNode.jack_meshZUp.jack_meshZUp_1",
+ "RootNode.jack_meshZUp.jack_meshZUp_2",
+ "RootNode.jack_root.Bip01__pelvis.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg",
+ "RootNode.jack_root.Bip01__pelvis.spine1",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.Bitangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.SkinWeight_",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.transform",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.Tangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.map1",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.jack",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.Bitangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.SkinWeight_",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.transform",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.Tangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.map1",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.jack",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg",
+ "RootNode.jack_root.Bip01__pelvis.spine1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3.transform"
+ ]
+ }
+ },
+ {
+ "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup",
+ "name": "Jack",
+ "nodeSelectionList": {
+ "selectedNodes": [
+ "RootNode",
+ "RootNode.jack_root",
+ "RootNode.jack_meshZUp",
+ "RootNode.jack_root.Bip01__pelvis",
+ "RootNode.jack_meshZUp.jack_meshZUp_1",
+ "RootNode.jack_meshZUp.jack_meshZUp_2",
+ "RootNode.jack_root.Bip01__pelvis.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg",
+ "RootNode.jack_root.Bip01__pelvis.spine1",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.Bitangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.SkinWeight_",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.transform",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.Tangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.map1",
+ "RootNode.jack_meshZUp.jack_meshZUp_1.jack",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.Bitangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.SkinWeight_",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.transform",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.Tangent",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.map1",
+ "RootNode.jack_meshZUp.jack_meshZUp_2.jack",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg",
+ "RootNode.jack_root.Bip01__pelvis.spine1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.transform",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr",
+ "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball.transform",
+ "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3.transform",
+ "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3.transform"
+ ]
+ },
+ "rules": {
+ "rules": [
+ {
+ "$type": "SkinRule"
+ },
+ {
+ "$type": "MaterialRule"
+ }
+ ]
+ },
+ "id": "{59B1DB76-5B27-5569-8DF6-55296FD0E5D8}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.mtl b/AutomatedTesting/Objects/Characters/Jack/Jack.mtl
deleted file mode 100644
index 2af23cc798..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/Jack.mtl
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf
deleted file mode 100644
index a9530b6d1b..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bb1c97394454a0a0c3b4aaf8380878aac3f7bedc9091ec920963932ad6ad2290
-size 30484
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf
deleted file mode 100644
index 781ff1fe50..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d090219fc20e7c1d9f0c187f976a7cb55e5b27b39e087aa8281ac794f314cb32
-size 22364
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf
deleted file mode 100644
index 0e59a1393d..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8fa78264ca46a2f201e24c3ba6a543e713bf9fd984df0a10f52b191d21077227
-size 106676
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf
deleted file mode 100644
index cc54ba4b64..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:ebf610eecec9a4da2d5c9260c48b81f6a04eaf7686d69850ad9f5d06fdbcf183
-size 12940
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl
deleted file mode 100644
index ebade464ec..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf
deleted file mode 100644
index 3ffabb1464..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:30afe8cf6e4aca846b07ef81747607afb47c0ff88283f363aca29ded9818c3db
-size 8148
diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf
deleted file mode 100644
index e98083d030..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:dba25dd8b3840d01aefb69007919b07befc5365fff714493c87cf1eff644d5dc
-size 8148
diff --git a/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl b/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl
deleted file mode 100644
index 4545010b7e..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl
deleted file mode 100644
index 523dac897f..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl
deleted file mode 100644
index 95c40eeb65..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl
deleted file mode 100644
index e0f18e9f69..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl
deleted file mode 100644
index 3927661f97..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif
deleted file mode 100644
index 378e0ea6ed..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:ca5c900fabf8b5c8c9313a0144886f4da3f812c82e8cffd652d9c61b9bb5b953
-size 4221960
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings
deleted file mode 100644
index 10f3182ac9..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif
deleted file mode 100644
index 5b4a3c3518..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:80f40a78e4b21dd27f5ddf34337e7d0e2119b7cfa08f0eea38d4b1d63808821f
-size 3178996
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif
deleted file mode 100644
index a85ac62f6c..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e5f5e327624e0f1fd35fac141019941b12ad0642c25853be9f7fd5b9b6f91bc5
-size 3168212
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif
deleted file mode 100644
index c861056eea..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:089e74ca9a41967038e16a9107099a73f8e93d39c487ff5bacdde18f418bf761
-size 3176732
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif
deleted file mode 100644
index 6909252726..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d45cd564d2b52575d1ad37b907a7d378871f05f6c9e5569ec73d7973d56599c9
-size 3167984
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif
deleted file mode 100644
index 3254f98355..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:83a872c07f7cbbcb868903429dd8d5a71e8c0b7b0e2cb16cb08b5cb26b02251c
-size 3177492
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif
deleted file mode 100644
index b00a8cd13b..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:81c1bc9545a17232523fd97561013534221b3bf8927feefa52bdc757e294c2e2
-size 3179140
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif
deleted file mode 100644
index 3e2fb9a003..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:99f476a56205c80878be7472857a6430ce6dc40f2eb1558de4933a5b79fa2420
-size 814244
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings
deleted file mode 100644
index aaaf14a9fe..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Reflectance /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif
deleted file mode 100644
index 2c44044576..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:366959c8a31356669d47f58d07157171ed369b3e7549b3b65a8b8d153a1477a6
-size 3179956
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif
deleted file mode 100644
index 4dea311abb..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e839924e03ba99459547df1cf5334de3bdad75b18e76176e430e343a979d9f05
-size 3168472
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif
deleted file mode 100644
index 57d61f505a..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:36f537bb5be89fccba1502e9e8f8dfffbf05ea8aa82ac439305e8c2502b01691
-size 16804800
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings
deleted file mode 100644
index a90d724812..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif
deleted file mode 100644
index a8f5db9a96..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b0457cbbbe1fe7e52fdb9af7ee2bc32df96a453fe248738b35ffe0b8087a28c5
-size 12615988
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings
deleted file mode 100644
index f35416077f..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /M=50,50,50,0,50,50 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif
deleted file mode 100644
index f5ee4b43b2..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:4ba741103d039bddf72d4834c92a5e069285e31b8be2e7f4e8103f9c5c81694f
-size 3167864
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings
deleted file mode 100644
index 8177b5abe6..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif
deleted file mode 100644
index 20fb2114c0..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:4d7cb58f48e4df76214509fc01d5170fd38bc447d56af61f008c04a1653c2d20
-size 12614884
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings
deleted file mode 100644
index 7fbb585758..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /M=50,50,50,0,50,50 /preset=Reflectance /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif
deleted file mode 100644
index 3334a5c39b..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:80a2c56bfcb8c98bf5a72ec9fdb5fcc6eae28ba1c3c26efad5c8a36e6105f1d0
-size 3173936
diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings
deleted file mode 100644
index aaaf14a9fe..0000000000
--- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Reflectance /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override b/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
index 9fa5e26768..e4ea71f652 100644
--- a/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
+++ b/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
@@ -121,9 +121,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override b/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
index afbe6a9d38..e53d3893f8 100644
--- a/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
+++ b/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
@@ -109,9 +109,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override b/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
index 9fa5e26768..e4ea71f652 100644
--- a/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
+++ b/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
@@ -121,9 +121,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override b/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
index 9fa5e26768..e4ea71f652 100644
--- a/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
+++ b/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
@@ -121,9 +121,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override b/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
index 9fa5e26768..e4ea71f652 100644
--- a/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
+++ b/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
@@ -121,9 +121,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/AutomatedTesting/Registry/physxsystemconfiguration.setreg b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
index 02f65b685b..83aad307a6 100644
--- a/AutomatedTesting/Registry/physxsystemconfiguration.setreg
+++ b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
@@ -103,9 +103,10 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
+ "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
},
- "assetHint": "surfacetypemateriallibrary.physmaterial"
+ "loadBehavior": "QueueLoad",
+ "assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
}
}
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a38177714..bd02eeb7ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,8 +28,8 @@ include(cmake/FileUtil.cmake)
include(cmake/PAL.cmake)
include(cmake/PALTools.cmake)
include(cmake/RuntimeDependencies.cmake)
-include(cmake/Install.cmake)
include(cmake/Configurations.cmake) # Requires to be after PAL so we get platform variable definitions
+include(cmake/Install.cmake)
include(cmake/Dependencies.cmake)
include(cmake/Deployment.cmake)
include(cmake/3rdParty.cmake)
diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp
index 56f2e7bdf5..ed810aea29 100644
--- a/Code/Editor/2DViewport.cpp
+++ b/Code/Editor/2DViewport.cpp
@@ -70,9 +70,9 @@ static void OnMenuGrid()
inline Vec3 SnapToSize(Vec3 v, double size)
{
Vec3 snapped;
- snapped.x = floor((v.x / size) + 0.5) * size;
- snapped.y = floor((v.y / size) + 0.5) * size;
- snapped.z = floor((v.z / size) + 0.5) * size;
+ snapped.x = static_cast(floor((v.x / size) + 0.5) * size);
+ snapped.y = static_cast(floor((v.y / size) + 0.5) * size);
+ snapped.z = static_cast(floor((v.z / size) + 0.5) * size);
return snapped;
}
@@ -479,8 +479,8 @@ void Q2DViewport::SetZoom(float fZoomFactor, const QPoint& center)
SetZoomFactor(fZoomFactor);
// Calculate new offset to center zoom on mouse.
- float x2 = center.x();
- float y2 = m_rcClient.height() - center.y();
+ float x2 = static_cast(center.x());
+ float y2 = static_cast(m_rcClient.height() - center.y());
ofsx = -(x2 / s2 - x2 / s1 - ofsx);
ofsy = -(y2 / s2 - y2 / s1 - ofsy);
SetScrollOffset(ofsx, ofsy, true);
@@ -544,21 +544,21 @@ void Q2DViewport::Update()
QPoint Q2DViewport::WorldToView(const Vec3& wp) const
{
Vec3 sp = m_screenTM.TransformPoint(wp);
- QPoint p = QPoint(sp.x, sp.y);
+ QPoint p = QPoint(static_cast(sp.x), static_cast(sp.y));
return p;
}
//////////////////////////////////////////////////////////////////////////
QPoint Q2DViewport::WorldToViewParticleEditor(const Vec3& wp, [[maybe_unused]] int width, [[maybe_unused]] int height) const //Eric@conffx implement for the children class of IDisplayViewport
{
Vec3 sp = m_screenTM.TransformPoint(wp);
- QPoint p = QPoint(sp.x, sp.y);
+ QPoint p = QPoint(static_cast(sp.x), static_cast(sp.y));
return p;
}
//////////////////////////////////////////////////////////////////////////
Vec3 Q2DViewport::ViewToWorld(const QPoint& vp, [[maybe_unused]] bool* collideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const
{
- Vec3 wp = m_screenTM_Inverted.TransformPoint(Vec3(vp.x(), vp.y(), 0));
+ Vec3 wp = m_screenTM_Inverted.TransformPoint(Vec3(static_cast(vp.x()), static_cast(vp.y()), 0.0f));
switch (m_axis)
{
case VPA_XY:
@@ -694,10 +694,10 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers)
Matrix34 viewTM = GetViewTM().GetInverted() * m_screenTM_Inverted;
Matrix34 viewTM_Inv = m_screenTM * GetViewTM();
- Vec3 viewP0 = viewTM.TransformPoint(Vec3(0, 0, 0));
- Vec3 viewP1 = viewTM.TransformPoint(Vec3(m_rcClient.width(), m_rcClient.height(), 0));
+ Vec3 viewP0 = viewTM.TransformPoint(Vec3(0.0f, 0.0f, 0.0f));
+ Vec3 viewP1 = viewTM.TransformPoint(Vec3(static_cast(m_rcClient.width()), static_cast(m_rcClient.height()), 0.0f));
- Vec3 viewP_Text = viewTM.TransformPoint(Vec3(0, m_rcClient.height(), 0));
+ Vec3 viewP_Text = viewTM.TransformPoint(Vec3(0.0f, static_cast(m_rcClient.height()), 0.0f));
if (m_bShowMinorGridLines && (!m_bAutoAdjustGrids || pixelsPerGrid > 5))
{
@@ -806,8 +806,8 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers)
{
Vec3 org = m_screenTM.TransformPoint(Vec3(0, 0, 0));
dc.SetColor(AXIS_GRID_COLOR);
- dc.DrawLine(Vec3(org.x, 0, fZ), Vec3(org.x, height, fZ));
- dc.DrawLine(Vec3(0, org.y, fZ), Vec3(width, org.y, fZ));
+ dc.DrawLine(Vec3(org.x, 0.0f, fZ), Vec3(org.x, static_cast(height), fZ));
+ dc.DrawLine(Vec3(0.0f, org.y, fZ), Vec3(static_cast(width), org.y, fZ));
}
//////////////////////////////////////////////////////////////////////////
}
@@ -860,18 +860,18 @@ void Q2DViewport::DrawAxis(DisplayContext& dc)
int height = m_rcClient.height();
int size = 25;
- Vec3 pos(30, height - 15, 1);
+ Vec3 pos(30.0f, static_cast(height - 15), 1.0f);
dc.SetColor(colx.x, colx.y, colx.z, 1);
- dc.DrawLine(pos, pos + Vec3(size, 0, 0));
+ dc.DrawLine(pos, pos + Vec3(static_cast(size), 0.0f, 0.0f));
- dc.SetColor(coly.x, coly.y, coly.z, 1);
- dc.DrawLine(pos, pos - Vec3(0, size, 0));
+ dc.SetColor(coly.x, coly.y, coly.z, 1.0f);
+ dc.DrawLine(pos, pos - Vec3(0.0f, static_cast(size), 0.0f));
dc.SetColor(m_colorAxisText);
- pos.x -= 3;
- pos.y -= 4;
- pos.z = 2;
+ pos.x -= 3.0f;
+ pos.y -= 4.0f;
+ pos.z = 2.0f;
dc.Draw2dTextLabel(pos.x + size + 4, pos.y - 2, 1, xstr);
dc.Draw2dTextLabel(pos.x + 3, pos.y - size, 1, ystr);
dc.Draw2dTextLabel(pos.x - 5, pos.y + 5, 1, zstr);
@@ -910,10 +910,14 @@ void Q2DViewport::DrawSelection(DisplayContext& dc)
dc.SetColor(SELECTION_RECT_COLOR.x, SELECTION_RECT_COLOR.y, SELECTION_RECT_COLOR.z, 1);
QPoint p1(m_selectedRect.left(), m_selectedRect.top());
QPoint p2(m_selectedRect.right() + 1, m_selectedRect.bottom() +1);
- dc.DrawLine(Vec3(p1.x(), p1.y(), 0), Vec3(p2.x(), p1.y(), 0));
- dc.DrawLine(Vec3(p1.x(), p2.y(), 0), Vec3(p2.x(), p2.y(), 0));
- dc.DrawLine(Vec3(p1.x(), p1.y(), 0), Vec3(p1.x(), p2.y(), 0));
- dc.DrawLine(Vec3(p2.x(), p1.y(), 0), Vec3(p2.x(), p2.y(), 0));
+ dc.DrawLine(
+ Vec3(static_cast(p1.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p1.y()), 0.0f));
+ dc.DrawLine(
+ Vec3(static_cast(p1.x()), static_cast(p2.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p2.y()), 0.0f));
+ dc.DrawLine(
+ Vec3(static_cast(p1.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p1.x()), static_cast(p2.y()), 0.0f));
+ dc.DrawLine(
+ Vec3(static_cast(p2.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p2.y()), 0.0f));
}
}
@@ -952,7 +956,8 @@ void Q2DViewport::DrawViewerMarker(DisplayContext& dc)
dc.SetColor(QColor(0, 0, 255)); // blue
dc.DrawWireBox(-dim * noScale, dim * noScale);
- float fov = GetIEditor()->GetSystem()->GetViewCamera().GetFov();
+ constexpr float DefaultFov = 60.f;
+ float fov = DefaultFov;
Vec3 q[4];
float dist = 30;
@@ -1037,16 +1042,16 @@ AABB Q2DViewport::GetWorldBounds(const QPoint& pnt1, const QPoint& pnt2)
{
case VPA_XY:
case VPA_YX:
- box.min.z = -maxSize;
- box.max.z = maxSize;
+ box.min.z = static_cast(-maxSize);
+ box.max.z = static_cast(maxSize);
break;
case VPA_XZ:
- box.min.y = -maxSize;
- box.max.y = maxSize;
+ box.min.y = static_cast(-maxSize);
+ box.max.y = static_cast(maxSize);
break;
case VPA_YZ:
- box.min.x = -maxSize;
- box.max.x = maxSize;
+ box.min.x = static_cast(-maxSize);
+ box.max.x = static_cast(maxSize);
break;
}
return box;
@@ -1075,32 +1080,32 @@ void Q2DViewport::OnDragSelectRectangle(const QRect &rect, [[maybe_unused]] bool
switch (m_axis)
{
case VPA_XY:
- box.min.z = -maxSize;
- box.max.z = maxSize;
+ box.min.z = static_cast(-maxSize);
+ box.max.z = static_cast(maxSize);
w = box.max.x - box.min.x;
h = box.max.y - box.min.y;
sprintf_s(szNewStatusText, "X:%g Y:%g W:%g H:%g", org.x, org.y, w, h);
break;
case VPA_YX:
- box.min.z = -maxSize;
- box.max.z = maxSize;
+ box.min.z = static_cast(-maxSize);
+ box.max.z = static_cast(maxSize);
w = box.max.y - box.min.y;
h = box.max.x - box.min.x;
sprintf_s(szNewStatusText, "X:%g Y:%g W:%g H:%g", org.x, org.y, w, h);
break;
case VPA_XZ:
- box.min.y = -maxSize;
- box.max.y = maxSize;
+ box.min.y = static_cast(-maxSize);
+ box.max.y = static_cast(maxSize);
w = box.max.x - box.min.x;
h = box.max.z - box.min.z;
sprintf_s(szNewStatusText, "X:%g Z:%g W:%g H:%g", org.x, org.z, w, h);
break;
case VPA_YZ:
- box.min.x = -maxSize;
- box.max.x = maxSize;
+ box.min.x = static_cast(-maxSize);
+ box.max.x = static_cast(maxSize);
w = box.max.y - box.min.y;
h = box.max.z - box.min.z;
diff --git a/Code/Editor/AboutDialog.cpp b/Code/Editor/AboutDialog.cpp
index 8429e86553..f8abe67376 100644
--- a/Code/Editor/AboutDialog.cpp
+++ b/Code/Editor/AboutDialog.cpp
@@ -25,7 +25,7 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
-CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, QWidget* pParent /*=NULL*/)
+CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, QWidget* pParent /*=nullptr*/)
: QDialog(pParent)
, m_ui(new Ui::CAboutDialog)
{
diff --git a/Code/Editor/Animation/SkeletonHierarchy.cpp b/Code/Editor/Animation/SkeletonHierarchy.cpp
deleted file mode 100644
index 3015ff5e27..0000000000
--- a/Code/Editor/Animation/SkeletonHierarchy.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#include "EditorDefs.h"
-#include "SkeletonHierarchy.h"
-
-using namespace Skeleton;
-
-/*
-
- CHierarchy
-
-*/
-
-CHierarchy::CHierarchy()
-{
-}
-
-CHierarchy::~CHierarchy()
-{
-}
-
-//
-
-uint32 CHierarchy::AddNode(const char* name, const QuatT& pose, int32 parent)
-{
- int32 index = FindNodeIndexByName(name);
-
- if (index < 0)
- {
- m_nodes.push_back(SNode());
- index = int32(m_nodes.size() - 1);
- }
-
- m_nodes[index].name = name;
- m_nodes[index].pose = pose;
- m_nodes[index].parent = parent;
- return uint32(index);
-}
-
-int32 CHierarchy::FindNodeIndexByName(const char* name) const
-{
- uint32 count = uint32(m_nodes.size());
- for (uint32 i = 0; i < count; ++i)
- {
- if (::_stricmp(m_nodes[i].name, name))
- {
- continue;
- }
-
- return i;
- }
-
- return -1;
-}
-
-const CHierarchy::SNode* CHierarchy::FindNode(const char* name) const
-{
- int32 index = FindNodeIndexByName(name);
- return index < 0 ? NULL : &m_nodes[index];
-}
-
-void CHierarchy::CreateFrom(IDefaultSkeleton* pIDefaultSkeleton)
-{
- const uint32 jointCount = pIDefaultSkeleton->GetJointCount();
-
- m_nodes.clear();
- m_nodes.reserve(jointCount);
- for (uint32 i = 0; i < jointCount; ++i)
- {
- m_nodes.push_back(SNode());
-
- m_nodes.back().name = pIDefaultSkeleton->GetJointNameByID(int32(i));
- m_nodes.back().pose = pIDefaultSkeleton->GetDefaultAbsJointByID(int32(i));
-
- m_nodes.back().parent = pIDefaultSkeleton->GetJointParentIDByID(int32(i));
- }
-
- ValidateReferences();
-}
-
-void CHierarchy::ValidateReferences()
-{
- uint32 nodeCount = m_nodes.size();
- if (!nodeCount)
- {
- return;
- }
-
- for (uint32 i = 0; i < nodeCount; ++i)
- {
- if (m_nodes[i].parent < nodeCount)
- {
- continue;
- }
-
- m_nodes[i].parent = -1;
- }
-}
-
-void CHierarchy::AbsoluteToRelative(const QuatT* pSource, QuatT* pDestination)
-{
- uint32 count = uint32(m_nodes.size());
- std::vector absolutes(count);
- for (uint32 i = 0; i < count; ++i)
- {
- absolutes[i] = pSource[i];
- }
-
- for (uint32 i = 0; i < count; ++i)
- {
- int32 parent = m_nodes[i].parent;
- if (parent < 0)
- {
- pDestination[i] = absolutes[i];
- continue;
- }
-
- pDestination[i].t = (absolutes[i].t - absolutes[parent].t) * absolutes[parent].q;
- pDestination[i].q = absolutes[parent].q.GetInverted() * absolutes[i].q;
- }
-}
-
-bool CHierarchy::SerializeTo(XmlNodeRef& node)
-{
- XmlNodeRef hierarchy = node->newChild("Hierarchy");
-
- uint32 nodeCount = uint32(m_nodes.size());
- std::vector nodes(nodeCount);
- for (uint32 i = 0; i < nodeCount; ++i)
- {
- XmlNodeRef parent = hierarchy;
- if (m_nodes[i].parent > -1)
- {
- parent = nodes[m_nodes[i].parent];
- }
-
- nodes[i] = parent->newChild("Node");
- nodes[i]->setAttr("name", m_nodes[i].name);
- }
-
- return true;
-}
diff --git a/Code/Editor/Animation/SkeletonHierarchy.h b/Code/Editor/Animation/SkeletonHierarchy.h
deleted file mode 100644
index ad0d8fc7fc..0000000000
--- a/Code/Editor/Animation/SkeletonHierarchy.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H
-#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H
-#pragma once
-
-namespace Skeleton {
- class CHierarchy
- : public _reference_target_t
- {
- public:
- struct SNode
- {
- string name;
- QuatT pose;
-
- int32 parent;
-
- /* TODO: Implement
- uint32 childrenIndex;
- uint32 childrenCount;
- */
- };
-
- public:
- CHierarchy();
- ~CHierarchy();
-
- public:
- uint32 AddNode(const char* name, const QuatT& pose, int32 parent = -1);
- uint32 GetNodeCount() const { return uint32(m_nodes.size()); }
- SNode* GetNode(uint32 index) { return &m_nodes[index]; }
- const SNode* GetNode(uint32 index) const { return &m_nodes[index]; }
- int32 FindNodeIndexByName(const char* name) const;
- const SNode* FindNode(const char* name) const;
- void ClearNodes() { m_nodes.clear(); }
-
- void CreateFrom(IDefaultSkeleton* rIDefaultSkeleton);
- void ValidateReferences();
-
- void AbsoluteToRelative(const QuatT* pSource, QuatT* pDestination);
-
- bool SerializeTo(XmlNodeRef& node);
-
- private:
- std::vector m_nodes;
- };
-} // namespace Skeleton
-
-#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H
diff --git a/Code/Editor/Animation/SkeletonMapper.cpp b/Code/Editor/Animation/SkeletonMapper.cpp
deleted file mode 100644
index 3913801fc8..0000000000
--- a/Code/Editor/Animation/SkeletonMapper.cpp
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#include "EditorDefs.h"
-
-#include "SkeletonMapper.h"
-
-using namespace Skeleton;
-
-/*
-
- CMapper
-
-*/
-
-CMapper::CMapper()
-{
-}
-
-CMapper::~CMapper()
-{
-}
-
-//
-
-void CMapper::CreateFromHierarchy()
-{
- m_nodes.clear();
-
- uint32 nodeCount = m_hierarchy.GetNodeCount();
- m_nodes.resize(nodeCount);
-}
-
-//
-
-uint32 CMapper::CreateLocation(const char* name)
-{
- int32 index = FindLocation(name);
- if (index < 1)
- {
- CMapperLocation* pLocation = new CMapperLocation();
- pLocation->SetName(name);
- m_locations.push_back(pLocation);
- }
- return uint32(m_locations.size() - 1);
-}
-
-void CMapper::ClearLocations()
-{
- uint32 count = uint32(m_nodes.size());
- for (uint32 i = 0; i < count; ++i)
- {
- m_nodes[i].position = NULL;
- m_nodes[i].orientation = NULL;
- }
-
- m_locations.clear();
-}
-
-int32 CMapper::FindLocation(const char* name) const
-{
- uint32 count = uint32(m_locations.size());
- for (uint32 i = 0; i < count; ++i)
- {
- if (::_stricmp(m_locations[i]->GetName(), name))
- {
- continue;
- }
-
- return int32(i);
- }
-
- return -1;
-}
-
-void CMapper::SetLocation(CMapperLocation& location)
-{
- int32 index = FindLocation(location.GetName());
- if (index < 0)
- {
- m_locations.push_back(&location);
- return;
- }
-
- m_locations[index] = &location;
-}
-
-//
-
-bool CMapper::CreateLocationsHierarchy(uint32 index, CHierarchy& hierarchy, int32 hierarchyParent)
-{
- if (NodeHasLocation(index))
- {
- const CHierarchy::SNode* pNode = m_hierarchy.GetNode(index);
- uint32 nodeIndex = hierarchy.AddNode(pNode->name, pNode->pose, hierarchyParent);
- hierarchyParent = uint32(nodeIndex);
- }
-
- std::vector children;
- GetChildrenIndices(index, children);
- uint32 childCount = uint32(children.size());
- for (uint32 i = 0; i < childCount; ++i)
- {
- CreateLocationsHierarchy(children[i], hierarchy, hierarchyParent);
- }
-
- return hierarchy.GetNodeCount() != 0;
-}
-
-bool CMapper::CreateLocationsHierarchy(CHierarchy& hierarchy)
-{
- hierarchy.ClearNodes();
- if (!CreateLocationsHierarchy(0, hierarchy, -1))
- {
- return false;
- }
-
- hierarchy.ValidateReferences();
- return true;
-}
-
-void CMapper::Map(QuatT* pResult)
-{
- uint32 outputCount = m_hierarchy.GetNodeCount();
- std::vector absolutes(outputCount);
- for (uint32 i = 0; i < outputCount; ++i)
- {
- pResult[i].SetIdentity();
- absolutes[i].SetIdentity();
-
- CHierarchy::SNode* pNode = m_hierarchy.GetNode(i);
- if (!pNode)
- {
- continue;
- }
-
- CHierarchy::SNode* pParent = pNode->parent < 0 ?
- NULL : m_hierarchy.GetNode(pNode->parent);
- if (pParent)
- {
- pResult[i].t =
- (pNode->pose.t - pParent->pose.t) * pParent->pose.q;
- }
-
- if (m_nodes[i].position)
- {
- pResult[i].t = m_nodes[i].position->Compute().t;
- }
-
- if (m_nodes[i].orientation)
- {
- absolutes[i] = m_nodes[i].orientation->Compute().q;
- }
- else if (pParent)
- {
- Quat relative = pParent->pose.q.GetInverted() * pNode->pose.q;
- absolutes[i] = absolutes[pNode->parent] * relative;
- }
- }
-
- for (uint32 i = 0; i < outputCount; ++i)
- {
- CHierarchy::SNode* pNode = m_hierarchy.GetNode(i);
- if (!pNode)
- {
- continue;
- }
-
- CHierarchy::SNode* pParent = pNode->parent < 0 ?
- NULL : m_hierarchy.GetNode(pNode->parent);
- if (!pParent)
- {
- pResult[i].q = absolutes[i];
- continue;
- }
-
- pResult[i].q = absolutes[i];
- if (!m_nodes[i].position)
- {
- pResult[i].t = pResult[pNode->parent].t +
- pResult[i].t * absolutes[pNode->parent].GetInverted();
- }
- }
-}
-
-//
-
-bool CMapper::NodeHasLocation(uint32 index)
-{
- if (CMapperOperator* pOperator = m_nodes[index].position)
- {
- if (pOperator->IsOfClass("Location"))
- {
- return true;
- }
- if (pOperator->HasLinksOfClass("Location"))
- {
- return true;
- }
- }
-
- if (CMapperOperator* pOperator = m_nodes[index].orientation)
- {
- if (pOperator->IsOfClass("Location"))
- {
- return true;
- }
- if (pOperator->HasLinksOfClass("Location"))
- {
- return true;
- }
- }
-
- return false;
-}
-
-void CMapper::GetChildrenIndices(uint32 parent, std::vector& children)
-{
- uint32 nodeCount = m_hierarchy.GetNodeCount();
- for (uint32 i = 0; i < nodeCount; ++i)
- {
- if (m_hierarchy.GetNode(i)->parent != parent)
- {
- continue;
- }
-
- children.push_back(i);
- }
-}
-
-bool CMapper::ChildrenHaveLocation(uint32 index)
-{
- std::vector children;
- GetChildrenIndices(index, children);
-
- uint32 childrenCount = uint32(children.size());
- for (uint32 i = 0; i < childrenCount; ++i)
- {
- if (ChildrenHaveLocation(children[i]))
- {
- return true;
- }
- }
-
- return false;
-}
-
-bool CMapper::NodeOrChildrenHaveLocation(uint32 index)
-{
- if (NodeHasLocation(index))
- {
- return true;
- }
-
- std::vector children;
- GetChildrenIndices(index, children);
-
- uint32 childrenCount = uint32(children.size());
- for (uint32 i = 0; i < childrenCount; ++i)
- {
- if (NodeOrChildrenHaveLocation(children[i]))
- {
- return true;
- }
- }
-
- return false;
-}
-
-bool CMapper::SerializeTo(XmlNodeRef& node)
-{
- XmlNodeRef hierarchy = node->newChild("Hierarchy");
-
- uint32 nodeCount = GetNodeCount();
- std::vector nodes(nodeCount);
- for (uint32 i = 0; i < nodeCount; ++i)
- {
- if (!NodeOrChildrenHaveLocation(i))
- {
- continue;
- }
-
- CHierarchy::SNode* pNode = m_hierarchy.GetNode(i);
- if (!pNode)
- {
- return false;
- }
-
- XmlNodeRef xmlParent = hierarchy;
- int32 parent = pNode->parent;
- if (parent > -1)
- {
- xmlParent = nodes[parent];
- }
-
- nodes[i] = xmlParent->newChild("Node");
- nodes[i]->setAttr("name", pNode->name);
-
- if (CMapperOperator* pOperator = m_nodes[i].position)
- {
- XmlNodeRef position = nodes[i]->newChild("Position");
- XmlNodeRef child = position->newChild("Operator");
- if (!pOperator->SerializeWithLinksTo(child))
- {
- return false;
- }
- }
-
- if (CMapperOperator* pOperator = m_nodes[i].orientation)
- {
- XmlNodeRef orientation = nodes[i]->newChild("Orientation");
- XmlNodeRef child = orientation->newChild("Operator");
- if (!pOperator->SerializeWithLinksTo(child))
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool CMapper::SerializeFrom(XmlNodeRef& node, int32 parent)
-{
- int childCount = uint32(node->getChildCount());
- for (int i = 0; i < childCount; ++i)
- {
- XmlNodeRef child = node->getChild(i);
- if (::_stricmp(child->getTag(), "Node"))
- {
- continue;
- }
-
- uint32 index = m_hierarchy.AddNode(child->getAttr("name"), QuatT(IDENTITY), parent);
- if (!SerializeFrom(child, int32(index)))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool CMapper::SerializeFrom(XmlNodeRef& node)
-{
- XmlNodeRef hierarchy = node->findChild("Hierarchy");
- if (!hierarchy)
- {
- return false;
- }
-
- m_hierarchy.ClearNodes();
-
- if (!SerializeFrom(hierarchy, -1))
- {
- return false;
- }
-
- m_nodes.resize(m_hierarchy.GetNodeCount());
-
- return true;
-}
diff --git a/Code/Editor/Animation/SkeletonMapper.h b/Code/Editor/Animation/SkeletonMapper.h
deleted file mode 100644
index 159b019396..0000000000
--- a/Code/Editor/Animation/SkeletonMapper.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H
-#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H
-#pragma once
-
-
-#include "SkeletonHierarchy.h"
-#include "SkeletonMapperOperator.h"
-
-namespace Skeleton {
- class CMapper
- {
- public:
- struct SNode
- {
- _smart_ptr position;
- _smart_ptr orientation;
- };
-
- public:
- CMapper();
- ~CMapper();
-
- public:
- CHierarchy& GetHierarchy() { return m_hierarchy; }
- void CreateFromHierarchy();
-
- uint32 GetNodeCount() const { return uint32(m_nodes.size()); }
- SNode* GetNode(uint32 index) { return &m_nodes[index]; }
- const SNode* GetNode(uint32 index) const { return &m_nodes[index]; }
-
- uint32 CreateLocation(const char* name);
- void ClearLocations();
- int32 FindLocation(const char* name) const;
-
- uint32 GetLocationCount() const { return uint32(m_locations.size()); }
- void SetLocation(CMapperLocation& location);
- CMapperLocation* GetLocation(uint32 index) { return m_locations[index]; }
- const CMapperLocation* GetLocation(uint32 index) const { return m_locations[index]; }
-
- bool CreateLocationsHierarchy(CHierarchy& hierarchy);
-
- void Map(QuatT* pResult);
-
- bool SerializeTo(XmlNodeRef& node);
- bool SerializeFrom(XmlNodeRef& node);
-
- private:
- bool NodeHasLocation(uint32 index);
- bool ChildrenHaveLocation(uint32 index);
- bool NodeOrChildrenHaveLocation(uint32 index);
-
- bool SerializeFrom(XmlNodeRef& node, int32 parent);
-
- bool CreateLocationsHierarchy(uint32 index, CHierarchy& hierarchy, int32 hierarchyParent = -1);
-
- // TEMP
- void GetChildrenIndices(uint32 parent, std::vector& children);
-
- private:
- CHierarchy m_hierarchy;
- std::vector<_smart_ptr > m_locations;
-
- std::vector m_nodes;
- };
-} // namespace Skeleton
-
-#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H
diff --git a/Code/Editor/Animation/SkeletonMapperOperator.cpp b/Code/Editor/Animation/SkeletonMapperOperator.cpp
deleted file mode 100644
index 7a69173bed..0000000000
--- a/Code/Editor/Animation/SkeletonMapperOperator.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#include "EditorDefs.h"
-
-#include "SkeletonMapperOperator.h"
-
-using namespace Skeleton;
-
-/*
-
- CMapperOperatorDesc
-
-*/
-
-std::vector CMapperOperatorDesc::s_descs;
-
-//
-
-CMapperOperatorDesc::CMapperOperatorDesc(const char* name)
-{
- s_descs.push_back(this);
-}
-
-/*
-
- CMapperOperator
-
-*/
-
-CMapperOperator::CMapperOperator(const char* className, uint32 positionCount, uint32 orientationCount)
-{
- m_className = className;
- m_position.resize(positionCount, NULL);
- m_orientation.resize(orientationCount, NULL);
-}
-
-CMapperOperator::~CMapperOperator()
-{
-}
-
-//
-
-bool CMapperOperator::IsOfClass(const char* className)
-{
- if (::_stricmp(m_className, className))
- {
- return false;
- }
-
- return true;
-}
-
-uint32 CMapperOperator::HasLinksOfClass(const char* className)
-{
- uint32 count = 0;
-
- uint32 positionCount = m_position.size();
- for (uint32 i = 0; i < positionCount; ++i)
- {
- CMapperOperator* pOperator = m_position[i];
- if (!pOperator)
- {
- continue;
- }
-
- if (pOperator->IsOfClass(className))
- {
- ++count;
- }
- }
-
- uint32 orientationCount = m_orientation.size();
- for (uint32 i = 0; i < orientationCount; ++i)
- {
- CMapperOperator* pOperator = m_orientation[i];
- if (!pOperator)
- {
- continue;
- }
-
- if (pOperator->IsOfClass(className))
- {
- ++count;
- }
- }
-
- return count;
-}
-
-//
-
-bool CMapperOperator::SerializeTo(XmlNodeRef& node)
-{
- node->setAttr("class", m_className);
-
- uint32 parameterCount = uint32(m_parameters.size());
- for (uint32 i = 0; i < parameterCount; ++i)
- {
- m_parameters[i]->Serialize(node, false);
- }
-
- return true;
-}
-
-bool CMapperOperator::SerializeFrom(XmlNodeRef& node)
-{
- uint32 parameterCount = uint32(m_parameters.size());
- for (uint32 i = 0; i < parameterCount; ++i)
- {
- m_parameters[i]->Serialize(node, true);
- }
-
- return true;
-}
-
-bool CMapperOperator::SerializeWithLinksTo(XmlNodeRef& node)
-{
- if (!SerializeTo(node))
- {
- return false;
- }
-
- uint32 positionCount = uint32(m_position.size());
- for (uint32 i = 0; i < positionCount; ++i)
- {
- CMapperOperator* pOperator = m_position[i];
- if (!pOperator)
- {
- continue;
- }
-
- XmlNodeRef position = node->newChild("Position");
- position->setAttr("index", i);
-
- XmlNodeRef child = position->newChild("Operator");
- if (!pOperator->SerializeWithLinksTo(child))
- {
- return false;
- }
- }
-
- uint32 orientationCount = uint32(m_orientation.size());
- for (uint32 i = 0; i < orientationCount; ++i)
- {
- CMapperOperator* pOperator = m_orientation[i];
- if (!pOperator)
- {
- continue;
- }
-
- XmlNodeRef orientation = node->newChild("Orientation");
- orientation->setAttr("index", i);
-
- XmlNodeRef child = orientation->newChild("Operator");
- if (!pOperator->SerializeWithLinksTo(child))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool CMapperOperator::SerializeWithLinksFrom(XmlNodeRef& node)
-{
- if (!SerializeFrom(node))
- {
- return false;
- }
-
- return true;
-}
-/*
-
- CMapperOperator_Transform
-
-*/
-
-class CMapperOperator_Transform
- : public CMapperOperator
-{
-public:
- CMapperOperator_Transform()
- : CMapperOperator("Transform", 1, 1)
- {
- m_pAngles = new CVariable();
- m_pAngles->SetName("rotation");
- m_pAngles->Set(Vec3(0.0f, 0.0f, 0.0f));
- m_pAngles->SetLimits(-180.0f, 180.0f);
- AddParameter(*m_pAngles);
-
- m_pVector = new CVariable();
- m_pVector->SetName("vector");
- m_pVector->Set(Vec3(0.0f, 0.0f, 0.0f));
- AddParameter(*m_pVector);
-
- m_pScale = new CVariable();
- m_pScale->SetName("scale");
- m_pScale->Set(Vec3(1.0f, 1.0f, 1.0f));
- AddParameter(*m_pScale);
- }
-
- // CMapperOperator
-public:
- virtual QuatT CMapperOperator_Transform::Compute()
- {
- QuatT result(IDENTITY);
- m_pVector->Get(result.t);
-
- Vec3 scale;
- m_pScale->Get(scale);
-
- Vec3 angles;
- m_pAngles->Get(angles);
-
- result.q = Quat::CreateRotationXYZ(
- Ang3(DEG2RAD(angles.x), DEG2RAD(angles.y), DEG2RAD(angles.z)));
-
- if (CMapperOperator* pOperator = GetPosition(0))
- {
- result.t = pOperator->Compute().t.CompMul(scale) + result.t;
- }
- if (CMapperOperator* pOperator = GetOrientation(0))
- {
- result.q = pOperator->Compute().q * result.q;
- }
- return result;
- }
-
-private:
- CVariable* m_pVector;
- CVariable* m_pAngles;
- CVariable* m_pScale;
-};
-
-SkeletonMapperOperatorRegister(Transform, CMapperOperator_Transform)
-
-class CMapperOperator_PositionsToOrientation
- : public CMapperOperator
-{
-public:
- CMapperOperator_PositionsToOrientation()
- : CMapperOperator("PositionsToOrientation", 3, 0)
- {
- }
-
- // CMapperOperator
-public:
- virtual QuatT Compute()
- {
- CMapperOperator* pOperator0 = GetPosition(0);
- CMapperOperator* pOperator1 = GetPosition(1);
- CMapperOperator* pOperator2 = GetPosition(2);
- if (!pOperator0 || !pOperator1 || !pOperator2)
- {
- return QuatT(IDENTITY);
- }
-
- Vec3 p0 = pOperator0->Compute().t;
- Vec3 p1 = pOperator1->Compute().t;
- Vec3 p2 = pOperator2->Compute().t;
-
- Vec3 m = (p1 + p2) * 0.5f;
- Vec3 y = (m - p0).GetNormalized();
- Vec3 z = (p1 - p2).GetNormalized();
- Vec3 x = y % z;
- z = x % y;
-
- Matrix33 m33;
- m33.SetFromVectors(x, y, z);
- QuatT result(IDENTITY);
- result.q = Quat(m33);
- return result;
- }
-};
-
-SkeletonMapperOperatorRegister(PositionsToOrientation, CMapperOperator_PositionsToOrientation)
diff --git a/Code/Editor/Animation/SkeletonMapperOperator.h b/Code/Editor/Animation/SkeletonMapperOperator.h
deleted file mode 100644
index 68bbb84ac7..0000000000
--- a/Code/Editor/Animation/SkeletonMapperOperator.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H
-#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H
-#pragma once
-
-
-#include "../Util/Variable.h"
-
-#undef GetClassName
-
-#define SkeletonMapperOperatorRegister(name, className) \
- class CMapperOperatorDesc_##name \
- : public CMapperOperatorDesc \
- { \
- public: \
- CMapperOperatorDesc_##name() \
- : CMapperOperatorDesc(#name) { } \
- protected: \
- virtual const char* GetName() { return #name; } \
- virtual CMapperOperator* Create() { return new className(); } \
- } mapperOperatorDesc__##name;
-
-namespace Skeleton {
- class CMapperOperator;
-
- class CMapperOperatorDesc
- {
- public:
- static uint32 GetCount() { return uint32(s_descs.size()); }
- static const char* GetName(uint32 index) { return s_descs[index]->GetName(); }
- static CMapperOperator* Create(uint32 index) { return s_descs[index]->Create(); }
-
- private:
- static std::vector s_descs;
-
- public:
- CMapperOperatorDesc(const char* name);
-
- protected:
- virtual const char* GetName() = 0;
- virtual CMapperOperator* Create() = 0;
- };
-
- class CMapperOperator
- : public _reference_target_t
- {
- protected:
- CMapperOperator(const char* className, uint32 positionCount, uint32 orientationCount);
- ~CMapperOperator();
-
- public:
- const char* GetClassName() { return m_className; }
-
- uint32 GetPositionCount() const { return uint32(m_position.size()); }
- void SetPosition(uint32 index, CMapperOperator* pOperator) { m_position[index] = pOperator; }
- CMapperOperator* GetPosition(uint32 index) { return m_position[index]; }
-
- uint32 GetOrientationCount() const { return uint32(m_orientation.size()); }
- void SetOrientation(uint32 index, CMapperOperator* pOperator) { m_orientation[index] = pOperator; }
- CMapperOperator* GetOrientation(uint32 index) { return m_orientation[index]; }
-
- uint32 GetParameterCount() { return uint32(m_parameters.size()); }
- IVariable* GetParameter(uint32 index) { return m_parameters[index]; }
-
- bool IsOfClass(const char* className);
- uint32 HasLinksOfClass(const char* className);
-
- bool SerializeTo(XmlNodeRef& node);
- bool SerializeFrom(XmlNodeRef& node);
-
- bool SerializeWithLinksTo(XmlNodeRef& node);
- bool SerializeWithLinksFrom(XmlNodeRef& node);
-
- protected:
- void AddParameter(IVariable& variable) { m_parameters.push_back(&variable); }
-
- public:
- virtual QuatT Compute() = 0;
-
- private:
- const char* m_className;
- std::vector<_smart_ptr > m_position;
- std::vector<_smart_ptr > m_orientation;
-
- std::vector m_parameters;
- };
-
- class CMapperLocation
- : public CMapperOperator
- {
- public:
- CMapperLocation()
- : CMapperOperator("Location", 0, 0)
- {
- m_pName = new CVariable();
- m_pName->SetName("name");
- m_pName->SetFlags(m_pName->GetFlags() | IVariable::UI_INVISIBLE);
- AddParameter(*m_pName);
-
- m_pAxis = new CVariable();
- m_pAxis->SetName("axis");
- m_pAxis->SetLimits(-3.0f, +3.0f);
- m_pAxis->Set(Vec3(1.0f, 2.0f, 3.0f));
- AddParameter(*m_pAxis);
-
- m_location = QuatT(IDENTITY);
- }
-
- public:
- void SetName(const char* name) { m_pName->Set(name); }
- CString GetName() const { CString s; m_pName->Get(s); return s; }
-
- void SetLocation(const QuatT& location) { m_location = location; }
- const QuatT& GetLocation() const { return m_location; }
-
- // CMapperOperator
- public:
- virtual QuatT Compute()
- {
- Vec3 axis;
- m_pAxis->Get(axis);
-
- uint32 x = fabs_tpl(axis.x);
- uint32 y = fabs_tpl(axis.y);
- uint32 z = fabs_tpl(axis.z);
- if (x < 1 || y < 1 || z < 1 ||
- x > 3 || y > 3 || y > 3 ||
- x == y || x == z || y == z)
- {
- return QuatT(IDENTITY);
- }
-
- Matrix33 matrix;
- matrix.SetFromVectors(
- m_location.q.GetColumn(x - 1) * f32(::sgn(axis.x)),
- m_location.q.GetColumn(y - 1) * f32(::sgn(axis.y)),
- m_location.q.GetColumn(z - 1) * f32(::sgn(axis.z)));
- if (!matrix.IsOrthonormalRH(0.01f))
- {
- return QuatT(IDENTITY);
- }
-
- QuatT result = m_location;
- result.q = Quat(matrix);
- return result;
- }
-
- private:
- CVariable* m_pName;
- CVariable* m_pAxis;
-
- QuatT m_location;
- };
-} // namespace Skeleton
-
-#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H
diff --git a/Code/Editor/AnimationContext.cpp b/Code/Editor/AnimationContext.cpp
index debe5e3b01..6e146faacb 100644
--- a/Code/Editor/AnimationContext.cpp
+++ b/Code/Editor/AnimationContext.cpp
@@ -16,7 +16,6 @@
// Editor
#include "TrackView/TrackViewDialog.h"
-#include "RenderViewport.h"
#include "ViewManager.h"
#include "Objects/SelectionGroup.h"
#include "Include/IObjectManager.h"
@@ -29,7 +28,7 @@ class CMovieCallback
: public IMovieCallback
{
protected:
- virtual void OnMovieCallback(ECallbackReason reason, [[maybe_unused]] IAnimNode* pNode)
+ void OnMovieCallback(ECallbackReason reason, [[maybe_unused]] IAnimNode* pNode) override
{
switch (reason)
{
@@ -49,7 +48,7 @@ protected:
}
}
- void OnSetCamera(const SCameraParams& Params)
+ void OnSetCamera(const SCameraParams& Params) override
{
// Only switch camera when in Play mode.
GUID camObjId = GUID_NULL;
@@ -61,15 +60,6 @@ protected:
{
camObjId = pEditorEntity->GetId();
}
-
- CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport();
- if (CRenderViewport* rvp = viewport_cast(pViewport))
- {
- if (!rvp->IsSequenceCamera())
- {
- return;
- }
- }
}
// Switch camera in active rendering view.
@@ -79,14 +69,14 @@ protected:
}
};
- bool IsSequenceCamUsed() const
+ bool IsSequenceCamUsed() const override
{
if (gEnv->IsEditorGameMode() == true)
{
return true;
}
- if (GetIEditor()->GetViewManager() == NULL)
+ if (GetIEditor()->GetViewManager() == nullptr)
{
return false;
}
@@ -113,7 +103,7 @@ public:
CAnimationContextPostRender(CAnimationContext* pAC)
: m_pAC(pAC){}
- void OnPostRender() const { assert(m_pAC); m_pAC->OnPostRender(); }
+ void OnPostRender() const override { assert(m_pAC); m_pAC->OnPostRender(); }
protected:
CAnimationContext* m_pAC;
@@ -231,7 +221,7 @@ void CAnimationContext::SetSequence(CTrackViewSequence* sequence, bool force, bo
m_pSequence->UnBindFromEditorObjects();
}
m_pSequence = sequence;
-
+
// Notify a new sequence was just selected.
Maestro::EditorSequenceNotificationBus::Broadcast(&Maestro::EditorSequenceNotificationBus::Events::OnSequenceSelected, m_pSequence ? m_pSequence->GetSequenceComponentEntityId() : AZ::EntityId());
@@ -347,7 +337,7 @@ void CAnimationContext::OnSequenceActivated(AZ::EntityId entityId)
{
// Hang onto this because SetSequence() will reset it.
float lastTime = m_mostRecentSequenceTime;
-
+
SetSequence(sequence, false, false);
// Restore the current time.
diff --git a/Code/Editor/AnimationContext.cpp.rej b/Code/Editor/AnimationContext.cpp.rej
deleted file mode 100644
index 3ee0913c9d..0000000000
--- a/Code/Editor/AnimationContext.cpp.rej
+++ /dev/null
@@ -1,11 +0,0 @@
---- Editor/AnimationContext.cpp
-+++ Editor/AnimationContext.cpp
-@@ -612,7 +612,7 @@ void CAnimationContext::UpdateAnimatedLights()
- return;
-
- std::vector entityObjects;
-- GetIEditor()->GetObjectManager()->FindObjectsOfType(entityObjects);
-+ GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, entityObjects);
- std::for_each(std::begin(entityObjects), std::end(entityObjects),
- [this](CBaseObject *pBaseObject)
- {
diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
index 50f8aff144..b164323238 100644
--- a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
+++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
@@ -260,9 +260,7 @@ void AzAssetBrowserRequestHandler::AddContextMenuActions(QWidget* caller, QMenu*
return;
}
- AZStd::string fullFileDirectory;
AZStd::string fullFilePath;
- AZStd::string fileName;
AZStd::string extension;
switch (entry->GetEntryType())
@@ -281,8 +279,6 @@ void AzAssetBrowserRequestHandler::AddContextMenuActions(QWidget* caller, QMenu*
{
AZ::Uuid sourceID = azrtti_cast(entry)->GetSourceUuid();
fullFilePath = entry->GetFullPath();
- fullFileDirectory = fullFilePath.substr(0, fullFilePath.find_last_of(AZ_CORRECT_DATABASE_SEPARATOR));
- fileName = entry->GetName();
AzFramework::StringFunc::Path::GetExtension(fullFilePath.c_str(), extension);
// Add the "Open" menu item.
@@ -369,19 +365,19 @@ void AzAssetBrowserRequestHandler::AddContextMenuActions(QWidget* caller, QMenu*
{
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
- CFileUtil::PopulateQMenu(caller, menu, fileName.c_str(), fullFileDirectory.c_str());
+ CFileUtil::PopulateQMenu(caller, menu, fullFilePath);
}
return;
}
- CFileUtil::PopulateQMenu(caller, menu, fileName.c_str(), fullFileDirectory.c_str());
+ CFileUtil::PopulateQMenu(caller, menu, fullFilePath);
}
break;
case AssetBrowserEntry::AssetEntryType::Folder:
{
- fullFileDirectory = entry->GetFullPath();
- // we are sending an empty filename to indicate that it is a folder and not a file
- CFileUtil::PopulateQMenu(caller, menu, fileName.c_str(), fullFileDirectory.c_str());
+ fullFilePath = entry->GetFullPath();
+
+ CFileUtil::PopulateQMenu(caller, menu, fullFilePath);
}
break;
default:
@@ -679,14 +675,14 @@ void AzAssetBrowserRequestHandler::OpenAssetInAssociatedEditor(const AZ::Data::A
firstValidOpener = &openerDetails;
}
// bind a callback such that when the menu item is clicked, it sets that as the opener to use.
- menu.addAction(openerDetails.m_iconToUse, QObject::tr(openerDetails.m_displayText.c_str()), mainWindow, AZStd::bind(switchToOpener, &openerDetails));
+ menu.addAction(openerDetails.m_iconToUse, QObject::tr(openerDetails.m_displayText.c_str()), mainWindow, [switchToOpener, details = &openerDetails] { return switchToOpener(details); });
}
}
if (numValidOpeners > 1) // more than one option was added
{
menu.addSeparator();
- menu.addAction(QObject::tr("Cancel"), AZStd::bind(switchToOpener, nullptr)); // just something to click on to avoid doing anything.
+ menu.addAction(QObject::tr("Cancel"), [switchToOpener] { return switchToOpener(nullptr); }); // just something to click on to avoid doing anything.
menu.exec(QCursor::pos());
}
else if (numValidOpeners == 1)
diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp
index f1047ae62b..c54fe60c4d 100644
--- a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp
+++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp
@@ -42,7 +42,7 @@ public:
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
}
- ~ListenerForShowAssetEditorEvent()
+ ~ListenerForShowAssetEditorEvent() override
{
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
}
@@ -82,6 +82,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent)
m_ui->m_assetBrowserTableViewWidget->setVisible(false);
m_ui->m_toggleDisplayViewBtn->setVisible(false);
+ m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250));
if (ed_useNewAssetBrowserTableView)
{
m_ui->m_toggleDisplayViewBtn->setVisible(true);
diff --git a/Code/Editor/BaseLibrary.cpp b/Code/Editor/BaseLibrary.cpp
index ee1c85756d..9f26630c2c 100644
--- a/Code/Editor/BaseLibrary.cpp
+++ b/Code/Editor/BaseLibrary.cpp
@@ -24,10 +24,10 @@ class CUndoBaseLibrary
: public IUndoObject
{
public:
- CUndoBaseLibrary(CBaseLibrary* pLib, const QString& description, const QString& selectedItem = 0)
+ CUndoBaseLibrary(CBaseLibrary* pLib, const QString& description, const QString& selectedItem = QString())
: m_pLib(pLib)
, m_description(description)
- , m_redo(0)
+ , m_redo(nullptr)
, m_selectedItem(selectedItem)
{
assert(m_pLib);
@@ -36,16 +36,16 @@ public:
m_pLib->Serialize(m_undo, false);
}
- virtual QString GetEditorObjectName()
+ QString GetEditorObjectName() override
{
return m_selectedItem;
}
protected:
- virtual int GetSize() { return sizeof(CUndoBaseLibrary); }
- virtual QString GetDescription() { return m_description; };
+ int GetSize() override { return sizeof(CUndoBaseLibrary); }
+ QString GetDescription() override { return m_description; };
- virtual void Undo(bool bUndo)
+ void Undo(bool bUndo) override
{
if (bUndo)
{
@@ -57,7 +57,7 @@ protected:
GetIEditor()->Notify(eNotify_OnDataBaseUpdate);
}
- virtual void Redo()
+ void Redo() override
{
m_pLib->Serialize(m_redo, true);
m_pLib->SetModified();
@@ -107,7 +107,7 @@ void CBaseLibrary::RemoveAllItems()
// Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call.
m_pManager->UnregisterItem(m_items[i]);
// Clear library item.
- m_items[i]->m_library = NULL;
+ m_items[i]->m_library = nullptr;
}
m_items.clear();
Release();
@@ -216,7 +216,7 @@ IDataBaseItem* CBaseLibrary::FindItem(const QString& name)
return m_items[i];
}
}
- return NULL;
+ return nullptr;
}
bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const
@@ -233,8 +233,8 @@ bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const
bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary)
{
- assert(name != NULL);
- if (name == NULL)
+ assert(name != nullptr);
+ if (name == nullptr)
{
CryFatalError("The library you are attempting to save has no name specified.");
return false;
@@ -258,9 +258,8 @@ bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary)
}
if (!bRes)
{
- string strMessage;
QByteArray filenameUtf8 = fileName.toUtf8();
- strMessage.Format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data());
+ AZStd::string strMessage = AZStd::string::format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data());
CryMessageBox(strMessage.c_str(), "Saving Error", MB_OK | MB_ICONWARNING);
}
return bRes;
diff --git a/Code/Editor/BaseLibraryItem.cpp b/Code/Editor/BaseLibraryItem.cpp
index fd310eaf9f..b1fba91fad 100644
--- a/Code/Editor/BaseLibraryItem.cpp
+++ b/Code/Editor/BaseLibraryItem.cpp
@@ -16,7 +16,7 @@
#include
-//undo object for multi-changes inside library item. such as set all variables to default values.
+//undo object for multi-changes inside library item. such as set all variables to default values.
//For example: change particle emitter shape will lead to multiple variable changes
class CUndoBaseLibraryItem
: public IUndoObject
@@ -43,7 +43,7 @@ public:
//evaluate size
XmlString xmlStr = m_undoCtx.node->getXML();
m_size = sizeof(CUndoBaseLibraryItem);
- m_size += xmlStr.GetAllocatedMemory();
+ m_size += static_cast(xmlStr.GetAllocatedMemory());
m_size += m_itemPath.length();
m_size += m_description.length();
}
@@ -54,24 +54,24 @@ public:
}
protected:
- virtual int GetSize()
- {
+ int GetSize() override
+ {
return m_size;
}
QString GetDescription() override
- {
- return m_description;
+ {
+ return m_description;
}
- virtual void Undo(bool bUndo)
+ void Undo(bool bUndo) override
{
//find the libItem
IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath);
if (libItem == nullptr)
{
//the undo stack is not reliable any more..
- assert(false);
+ assert(false);
return;
}
@@ -87,7 +87,7 @@ protected:
libItem->Serialize(m_redoCtx);
XmlString xmlStr = m_redoCtx.node->getXML();
- m_size += xmlStr.GetAllocatedMemory();
+ m_size += static_cast(xmlStr.GetAllocatedMemory());
}
//load previous saved data
@@ -95,7 +95,7 @@ protected:
libItem->Serialize(m_undoCtx);
}
- virtual void Redo()
+ void Redo() override
{
//find the libItem
IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath);
@@ -124,7 +124,7 @@ private:
//////////////////////////////////////////////////////////////////////////
CBaseLibraryItem::CBaseLibraryItem()
{
- m_library = 0;
+ m_library = nullptr;
GenerateId();
m_bModified = false;
}
@@ -266,7 +266,7 @@ void CBaseLibraryItem::SetLibrary(CBaseLibrary* pLibrary)
void CBaseLibraryItem::SetModified(bool bModified)
{
m_bModified = bModified;
- if (m_bModified && m_library != NULL)
+ if (m_bModified && m_library != nullptr)
{
m_library->SetModified(bModified);
}
diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp
index 8e555cae8c..7346ffaf8c 100644
--- a/Code/Editor/BaseLibraryManager.cpp
+++ b/Code/Editor/BaseLibraryManager.cpp
@@ -26,7 +26,7 @@ class CUndoBaseLibraryManager
: public IUndoObject
{
public:
- CUndoBaseLibraryManager(CBaseLibraryManager* pMngr, const QString& description, const QString& modifiedManager = 0)
+ CUndoBaseLibraryManager(CBaseLibraryManager* pMngr, const QString& description, const QString& modifiedManager = nullptr)
: m_pMngr(pMngr)
, m_description(description)
, m_editorObject(modifiedManager)
@@ -35,16 +35,16 @@ public:
SerializeTo(m_undos);
}
- virtual QString GetEditorObjectName()
+ QString GetEditorObjectName() override
{
return m_editorObject;
}
protected:
- virtual int GetSize() { return sizeof(CUndoBaseLibraryManager); }
- virtual QString GetDescription() { return m_description; };
+ int GetSize() override { return sizeof(CUndoBaseLibraryManager); }
+ QString GetDescription() override { return m_description; };
- virtual void Undo(bool bUndo)
+ void Undo(bool bUndo) override
{
if (bUndo)
{
@@ -55,7 +55,7 @@ protected:
GetIEditor()->Notify(eNotify_OnDataBaseUpdate);
}
- virtual void Redo()
+ void Redo() override
{
m_pMngr->ClearAll();
UnserializeFrom(m_redos);
@@ -84,7 +84,7 @@ private:
for (int i = 0; i < m_pMngr->GetLibraryCount(); i++)
{
IDataBaseLibrary* library = m_pMngr->GetLibrary(i);
-
+
const char* tag = library->IsLevelLibrary() ? LEVEL_LIBRARY_TAG : LIBRARY_TAG;
XmlNodeRef node = GetIEditor()->GetSystem()->CreateXmlNode(tag);
QString file = library->GetFilename().isEmpty() ? library->GetFilename() : library->GetName();
@@ -203,7 +203,7 @@ int CBaseLibraryManager::FindLibraryIndex(const QString& library)
//////////////////////////////////////////////////////////////////////////
IDataBaseItem* CBaseLibraryManager::FindItem(REFGUID guid) const
{
- CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, (CBaseLibraryItem*)0);
+ CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, nullptr);
return pMtl;
}
@@ -226,7 +226,7 @@ void CBaseLibraryManager::SplitFullItemName(const QString& fullItemName, QString
IDataBaseItem* CBaseLibraryManager::FindItemByName(const QString& fullItemName)
{
AZStd::lock_guard lock(m_itemsNameMapMutex);
- return stl::find_in_map(m_itemsNameMap, fullItemName, 0);
+ return stl::find_in_map(m_itemsNameMap, fullItemName, nullptr);
}
//////////////////////////////////////////////////////////////////////////
@@ -398,7 +398,7 @@ void CBaseLibraryManager::DeleteLibrary(const QString& library, bool forceDelete
UnregisterItem((CBaseLibraryItem*)pLibrary->GetItem(j));
}
pLibrary->RemoveAllItems();
-
+
if (pLibrary->IsLevelLibrary())
{
m_pLevelLibrary = nullptr;
@@ -420,7 +420,7 @@ IDataBaseLibrary* CBaseLibraryManager::GetLibrary(int index) const
//////////////////////////////////////////////////////////////////////////
IDataBaseLibrary* CBaseLibraryManager::GetLevelLibrary() const
{
- IDataBaseLibrary* pLevelLib = NULL;
+ IDataBaseLibrary* pLevelLib = nullptr;
for (int i = 0; i < GetLibraryCount(); i++)
{
@@ -526,14 +526,14 @@ void CBaseLibraryManager::Serialize(XmlNodeRef& node, bool bLoading)
QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QString& libName)
{
// unlikely we'll ever encounter more than 16
- std::vector possibleDuplicates;
+ std::vector possibleDuplicates;
possibleDuplicates.reserve(16);
// search for strings in the database that might have a similar name (ignore case)
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
- for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext())
+ for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
{
- //Check if the item is in the target library first.
+ //Check if the item is in the target library first.
IDataBaseLibrary* itemLibrary = pItem->GetLibrary();
QString itemLibraryName;
if (itemLibrary)
@@ -550,7 +550,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS
const QString& name = pItem->GetName();
if (name.startsWith(srcName, Qt::CaseInsensitive))
{
- possibleDuplicates.push_back(string(name.toUtf8().data()));
+ possibleDuplicates.push_back(AZStd::string(name.toUtf8().data()));
}
}
pEnum->Release();
@@ -560,7 +560,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS
return srcName;
}
- std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const string& strOne, const string& strTwo)
+ std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const AZStd::string& strOne, const AZStd::string& strTwo)
{
// I can assume size sorting since if the length is different, either one of the two strings doesn't
// closely match the string we are trying to duplicate, or it's a bigger number (X1 vs X10)
@@ -590,7 +590,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS
void CBaseLibraryManager::Validate()
{
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
- for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext())
+ for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
{
pItem->Validate();
}
@@ -617,7 +617,7 @@ void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid)
{
return;
}
- CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, (CBaseLibraryItem*)0);
+ CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, nullptr);
if (!pOldItem)
{
pItem->m_guid = newGuid;
@@ -677,7 +677,7 @@ void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem)
{
return;
}
- CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), (CBaseLibraryItem*)0);
+ CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), nullptr);
if (!pOldItem)
{
m_itemsGuidMap[pItem->GetGUID()] = pItem;
@@ -789,7 +789,7 @@ QString CBaseLibraryManager::MakeFullItemName(IDataBaseLibrary* pLibrary, const
void CBaseLibraryManager::GatherUsedResources(CUsedResources& resources)
{
IDataBaseItemEnumerator* pEnum = GetItemEnumerator();
- for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext())
+ for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext())
{
pItem->GatherUsedResources(resources);
}
@@ -815,15 +815,15 @@ void CBaseLibraryManager::OnEditorNotifyEvent(EEditorNotifyEvent event)
switch (event)
{
case eNotify_OnBeginNewScene:
- SetSelectedItem(0);
+ SetSelectedItem(nullptr);
ClearAll();
break;
case eNotify_OnBeginSceneOpen:
- SetSelectedItem(0);
+ SetSelectedItem(nullptr);
ClearAll();
break;
case eNotify_OnCloseScene:
- SetSelectedItem(0);
+ SetSelectedItem(nullptr);
ClearAll();
break;
}
@@ -913,7 +913,7 @@ void CBaseLibraryManager::ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int
{
return;
}
-
+
for (int i = 0; i < m_libs.size(); i++)
{
if (lib == m_libs[i])
diff --git a/Code/Editor/BaseLibraryManager.h b/Code/Editor/BaseLibraryManager.h
index 05f370e632..6f0b905760 100644
--- a/Code/Editor/BaseLibraryManager.h
+++ b/Code/Editor/BaseLibraryManager.h
@@ -73,7 +73,7 @@ public:
virtual IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override;
virtual void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override;
//! Get number of libraries.
- virtual int GetLibraryCount() const override { return m_libs.size(); };
+ virtual int GetLibraryCount() const override { return static_cast(m_libs.size()); };
//! Get number of modified libraries.
virtual int GetModifiedLibraryCount() const override;
diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt
index fca16a2093..9256fd041f 100644
--- a/Code/Editor/CMakeLists.txt
+++ b/Code/Editor/CMakeLists.txt
@@ -238,9 +238,14 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
3rdParty::Qt::Core
3rdParty::Qt::Gui
3rdParty::Qt::Widgets
+ 3rdParty::Qt::Test
Legacy::CryCommon
AZ::AzToolsFramework
+ AZ::AzToolsFramework.Tests
+ AZ::AzFrameworkTestShared
+ AZ::AzToolsFrameworkTestCommon
Legacy::EditorLib
+ Gem::AtomToolsFramework.Static
RUNTIME_DEPENDENCIES
Gem::LmbrCentral
)
diff --git a/Code/Editor/CheckOutDialog.h b/Code/Editor/CheckOutDialog.h
index 7e7054ccdf..9ad64c57cf 100644
--- a/Code/Editor/CheckOutDialog.h
+++ b/Code/Editor/CheckOutDialog.h
@@ -34,7 +34,7 @@ public:
CANCEL = QDialog::Rejected
};
- CCheckOutDialog(const QString& file, QWidget* pParent = NULL); // standard constructor
+ CCheckOutDialog(const QString& file, QWidget* pParent = nullptr); // standard constructor
virtual ~CCheckOutDialog();
// Dialog Data
diff --git a/Code/Editor/Commands/CommandManager.cpp b/Code/Editor/Commands/CommandManager.cpp
index 90059ea195..5f194971f5 100644
--- a/Code/Editor/Commands/CommandManager.cpp
+++ b/Code/Editor/Commands/CommandManager.cpp
@@ -20,8 +20,8 @@
// AzToolsFramework
#include
-CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::s_pFirst = 0;
-CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::s_pLast = 0;
+CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::s_pFirst = nullptr;
+CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::s_pLast = nullptr;
CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::GetFirst()
{
@@ -31,7 +31,7 @@ CAutoRegisterCommandHelper* CAutoRegisterCommandHelper::GetFirst()
CAutoRegisterCommandHelper::CAutoRegisterCommandHelper(void(*registerFunc)(CEditorCommandManager &))
{
m_registerFunc = registerFunc;
- m_pNext = 0;
+ m_pNext = nullptr;
if (!s_pLast)
{
@@ -79,9 +79,9 @@ CEditorCommandManager::~CEditorCommandManager()
m_uiCommands.clear();
}
-string CEditorCommandManager::GetFullCommandName(const string& module, const string& name)
+AZStd::string CEditorCommandManager::GetFullCommandName(const AZStd::string& module, const AZStd::string& name)
{
- string fullName = module;
+ AZStd::string fullName = module;
fullName += ".";
fullName += name;
return fullName;
@@ -91,10 +91,10 @@ bool CEditorCommandManager::AddCommand(CCommand* pCommand, TPfnDeleter deleter)
{
assert(pCommand);
- string module = pCommand->GetModule();
- string name = pCommand->GetName();
+ AZStd::string module = pCommand->GetModule();
+ AZStd::string name = pCommand->GetName();
- if (IsRegistered(module, name) && m_bWarnDuplicate)
+ if (IsRegistered(module.c_str(), name.c_str()) && m_bWarnDuplicate)
{
QString errMsg;
@@ -118,7 +118,7 @@ bool CEditorCommandManager::AddCommand(CCommand* pCommand, TPfnDeleter deleter)
bool CEditorCommandManager::UnregisterCommand(const char* module, const char* name)
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
CommandTable::iterator itr = m_commands.find(fullName);
if (itr != m_commands.end())
@@ -154,7 +154,7 @@ bool CEditorCommandManager::RegisterUICommand(
return false;
}
- return AttachUIInfo(GetFullCommandName(module, name), uiInfo);
+ return AttachUIInfo(GetFullCommandName(module, name).c_str(), uiInfo);
}
bool CEditorCommandManager::AttachUIInfo(const char* fullCmdName, const CCommand0::SUIInfo& uiInfo)
@@ -190,14 +190,14 @@ bool CEditorCommandManager::AttachUIInfo(const char* fullCmdName, const CCommand
return true;
}
-bool CEditorCommandManager::GetUIInfo(const string& module, const string& name, CCommand0::SUIInfo& uiInfo) const
+bool CEditorCommandManager::GetUIInfo(const AZStd::string& module, const AZStd::string& name, CCommand0::SUIInfo& uiInfo) const
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
return GetUIInfo(fullName, uiInfo);
}
-bool CEditorCommandManager::GetUIInfo(const string& fullCmdName, CCommand0::SUIInfo& uiInfo) const
+bool CEditorCommandManager::GetUIInfo(const AZStd::string& fullCmdName, CCommand0::SUIInfo& uiInfo) const
{
CommandTable::const_iterator iter = m_commands.find(fullCmdName);
@@ -223,9 +223,9 @@ int CEditorCommandManager::GenNewCommandId()
return uniqueId++;
}
-QString CEditorCommandManager::Execute(const string& module, const string& name, const CCommand::CArgs& args)
+QString CEditorCommandManager::Execute(const AZStd::string& module, const AZStd::string& name, const CCommand::CArgs& args)
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
CommandTable::iterator iter = m_commands.find(fullName);
if (iter != m_commands.end())
@@ -245,18 +245,18 @@ QString CEditorCommandManager::Execute(const string& module, const string& name,
return "";
}
-QString CEditorCommandManager::Execute(const string& cmdLine)
+QString CEditorCommandManager::Execute(const AZStd::string& cmdLine)
{
- string cmdTxt, argsTxt;
+ AZStd::string cmdTxt, argsTxt;
size_t argStart = cmdLine.find_first_of(' ');
cmdTxt = cmdLine.substr(0, argStart);
argsTxt = "";
- if (argStart != string::npos)
+ if (argStart != AZStd::string::npos)
{
argsTxt = cmdLine.substr(argStart + 1);
- argsTxt.Trim();
+ AZ::StringFunc::TrimWhiteSpace(argsTxt, true, true);
}
CommandTable::iterator itr = m_commands.find(cmdTxt);
@@ -301,7 +301,7 @@ void CEditorCommandManager::Execute(int commandId)
}
}
-void CEditorCommandManager::GetCommandList(std::vector& cmds) const
+void CEditorCommandManager::GetCommandList(std::vector& cmds) const
{
cmds.clear();
cmds.reserve(m_commands.size());
@@ -315,9 +315,9 @@ void CEditorCommandManager::GetCommandList(std::vector& cmds) const
std::sort(cmds.begin(), cmds.end());
}
-string CEditorCommandManager::AutoComplete(const string& substr) const
+AZStd::string CEditorCommandManager::AutoComplete(const AZStd::string& substr) const
{
- std::vector cmds;
+ std::vector cmds;
GetCommandList(cmds);
// If substring is empty return first command.
@@ -358,7 +358,7 @@ string CEditorCommandManager::AutoComplete(const string& substr) const
bool CEditorCommandManager::IsRegistered(const char* module, const char* name) const
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
CommandTable::const_iterator iter = m_commands.find(fullName);
if (iter != m_commands.end())
@@ -373,7 +373,7 @@ bool CEditorCommandManager::IsRegistered(const char* module, const char* name) c
bool CEditorCommandManager::IsRegistered(const char* cmdLine_) const
{
- string cmdTxt, argsTxt, cmdLine(cmdLine_);
+ AZStd::string cmdTxt, argsTxt, cmdLine(cmdLine_);
size_t argStart = cmdLine.find_first_of(' ');
cmdTxt = cmdLine.substr(0, argStart);
CommandTable::const_iterator iter = m_commands.find(cmdTxt);
@@ -402,9 +402,9 @@ bool CEditorCommandManager::IsRegistered(int commandId) const
return false;
}
-void CEditorCommandManager::SetCommandAvailableInScripting(const string& module, const string& name)
+void CEditorCommandManager::SetCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name)
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
CommandTable::iterator iter = m_commands.find(fullName);
if (iter != m_commands.end())
@@ -413,7 +413,7 @@ void CEditorCommandManager::SetCommandAvailableInScripting(const string& module,
}
}
-bool CEditorCommandManager::IsCommandAvailableInScripting(const string& fullCmdName) const
+bool CEditorCommandManager::IsCommandAvailableInScripting(const AZStd::string& fullCmdName) const
{
CommandTable::const_iterator iter = m_commands.find(fullCmdName);
@@ -425,16 +425,16 @@ bool CEditorCommandManager::IsCommandAvailableInScripting(const string& fullCmdN
return false;
}
-bool CEditorCommandManager::IsCommandAvailableInScripting(const string& module, const string& name) const
+bool CEditorCommandManager::IsCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name) const
{
- string fullName = GetFullCommandName(module, name);
+ AZStd::string fullName = GetFullCommandName(module, name);
return IsCommandAvailableInScripting(fullName);
}
-void CEditorCommandManager::LogCommand(const string& fullCmdName, const CCommand::CArgs& args) const
+void CEditorCommandManager::LogCommand(const AZStd::string& fullCmdName, const CCommand::CArgs& args) const
{
- string cmdLine = fullCmdName;
+ AZStd::string cmdLine = fullCmdName;
for (int i = 0; i < args.GetArgCount(); ++i)
{
@@ -509,7 +509,7 @@ void CEditorCommandManager::LogCommand(const string& fullCmdName, const CCommand
if (pScriptTermDialog)
{
- string text = "> ";
+ AZStd::string text = "> ";
text += cmdLine;
text += "\r\n";
pScriptTermDialog->AppendText(text.c_str());
@@ -526,14 +526,14 @@ QString CEditorCommandManager::ExecuteAndLogReturn(CCommand* pCommand, const CCo
return result;
}
-void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::CArgs& argList)
+void CEditorCommandManager::GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList)
{
const char quoteSymbol = '\'';
- int curPos = 0;
- int prevPos = 0;
- string arg = argsTxt.Tokenize(" ", curPos);
-
- while (!arg.empty())
+ size_t curPos = 0;
+ size_t prevPos = 0;
+ AZStd::vector tokens;
+ AZ::StringFunc::Tokenize(argsTxt, tokens, ' ');
+ for(AZStd::string& arg : tokens)
{
if (arg[0] == quoteSymbol) // A special consideration for a quoted string
{
@@ -542,11 +542,11 @@ void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::C
size_t openingQuotePos = argsTxt.find(quoteSymbol, prevPos);
size_t closingQuotePos = argsTxt.find(quoteSymbol, curPos);
- if (closingQuotePos != string::npos)
+ if (closingQuotePos != AZStd::string::npos)
{
arg = argsTxt.substr(openingQuotePos + 1, closingQuotePos - openingQuotePos - 1);
size_t nextArgPos = argsTxt.find(' ', closingQuotePos + 1);
- curPos = nextArgPos != string::npos ? nextArgPos + 1 : argsTxt.length();
+ curPos = nextArgPos != AZStd::string::npos ? nextArgPos + 1 : argsTxt.length();
for (; curPos < argsTxt.length(); ++curPos) // Skip spaces.
{
@@ -565,6 +565,5 @@ void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::C
argList.Add(arg.c_str());
prevPos = curPos;
- arg = argsTxt.Tokenize(" ", curPos);
}
}
diff --git a/Code/Editor/Commands/CommandManager.h b/Code/Editor/Commands/CommandManager.h
index 2ec4a137bc..599754c5d9 100644
--- a/Code/Editor/Commands/CommandManager.h
+++ b/Code/Editor/Commands/CommandManager.h
@@ -38,7 +38,7 @@ public:
void RegisterAutoCommands();
- bool AddCommand(CCommand* pCommand, TPfnDeleter deleter = NULL);
+ bool AddCommand(CCommand* pCommand, TPfnDeleter deleter = nullptr);
bool UnregisterCommand(const char* module, const char* name);
bool RegisterUICommand(
const char* module,
@@ -48,20 +48,20 @@ public:
const AZStd::function& functor,
const CCommand0::SUIInfo& uiInfo);
bool AttachUIInfo(const char* fullCmdName, const CCommand0::SUIInfo& uiInfo);
- bool GetUIInfo(const string& module, const string& name, CCommand0::SUIInfo& uiInfo) const;
- bool GetUIInfo(const string& fullCmdName, CCommand0::SUIInfo& uiInfo) const;
- QString Execute(const string& cmdLine);
- QString Execute(const string& module, const string& name, const CCommand::CArgs& args);
+ bool GetUIInfo(const AZStd::string& module, const AZStd::string& name, CCommand0::SUIInfo& uiInfo) const;
+ bool GetUIInfo(const AZStd::string& fullCmdName, CCommand0::SUIInfo& uiInfo) const;
+ QString Execute(const AZStd::string& cmdLine);
+ QString Execute(const AZStd::string& module, const AZStd::string& name, const CCommand::CArgs& args);
void Execute(int commandId);
- void GetCommandList(std::vector& cmds) const;
+ void GetCommandList(std::vector& cmds) const;
//! Used in the console dialog
- string AutoComplete(const string& substr) const;
+ AZStd::string AutoComplete(const AZStd::string& substr) const;
bool IsRegistered(const char* module, const char* name) const;
bool IsRegistered(const char* cmdLine) const;
bool IsRegistered(int commandId) const;
- void SetCommandAvailableInScripting(const string& module, const string& name);
- bool IsCommandAvailableInScripting(const string& module, const string& name) const;
- bool IsCommandAvailableInScripting(const string& fullCmdName) const;
+ void SetCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name);
+ bool IsCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name) const;
+ bool IsCommandAvailableInScripting(const AZStd::string& fullCmdName) const;
//! Turning off the warning is needed for reloading the ribbon bar.
void TurnDuplicateWarningOn() { m_bWarnDuplicate = true; }
void TurnDuplicateWarningOff() { m_bWarnDuplicate = false; }
@@ -74,7 +74,7 @@ protected:
};
//! A full command name to an actual command mapping
- typedef std::map CommandTable;
+ typedef std::map CommandTable;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
CommandTable m_commands;
@@ -86,9 +86,9 @@ protected:
bool m_bWarnDuplicate;
static int GenNewCommandId();
- static string GetFullCommandName(const string& module, const string& name);
- static void GetArgsFromString(const string& argsTxt, CCommand::CArgs& argList);
- void LogCommand(const string& fullCmdName, const CCommand::CArgs& args) const;
+ static AZStd::string GetFullCommandName(const AZStd::string& module, const AZStd::string& name);
+ static void GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList);
+ void LogCommand(const AZStd::string& fullCmdName, const CCommand::CArgs& args) const;
QString ExecuteAndLogReturn(CCommand* pCommand, const CCommand::CArgs& args);
};
diff --git a/Code/Editor/ConfigGroup.cpp b/Code/Editor/ConfigGroup.cpp
index 4e61c38f4b..74fe6f7b5c 100644
--- a/Code/Editor/ConfigGroup.cpp
+++ b/Code/Editor/ConfigGroup.cpp
@@ -33,7 +33,7 @@ namespace Config
uint32 CConfigGroup::GetVarCount()
{
- return m_vars.size();
+ return static_cast(m_vars.size());
}
IConfigVar* CConfigGroup::GetVar(const char* szName)
@@ -48,7 +48,7 @@ namespace Config
}
}
- return NULL;
+ return nullptr;
}
const IConfigVar* CConfigGroup::GetVar(const char* szName) const
@@ -63,7 +63,7 @@ namespace Config
}
}
- return NULL;
+ return nullptr;
}
IConfigVar* CConfigGroup::GetVar(uint index)
@@ -73,7 +73,7 @@ namespace Config
return m_vars[index];
}
- return NULL;
+ return nullptr;
}
const IConfigVar* CConfigGroup::GetVar(uint index) const
@@ -83,7 +83,7 @@ namespace Config
return m_vars[index];
}
- return NULL;
+ return nullptr;
}
void CConfigGroup::SaveToXML(XmlNodeRef node)
@@ -127,9 +127,9 @@ namespace Config
case IConfigVar::eType_STRING:
{
- string currentValue = 0;
+ AZStd::string currentValue;
var->Get(¤tValue);
- node->setAttr(szName, currentValue);
+ node->setAttr(szName, currentValue.c_str());
break;
}
}
@@ -186,7 +186,7 @@ namespace Config
case IConfigVar::eType_STRING:
{
- string currentValue = 0;
+ AZStd::string currentValue;
var->GetDefault(¤tValue);
QString readValue(currentValue.c_str());
if (node->getAttr(szName, readValue))
diff --git a/Code/Editor/ConfigGroup.h b/Code/Editor/ConfigGroup.h
index 35c0b8e47f..769a29ba8a 100644
--- a/Code/Editor/ConfigGroup.h
+++ b/Code/Editor/ConfigGroup.h
@@ -37,22 +37,22 @@ namespace Config
, m_description(szDescription)
, m_type(varType)
, m_flags(flags)
- , m_ptr(NULL)
+ , m_ptr(nullptr)
{};
virtual ~IConfigVar() = default;
-
+
ILINE EType GetType() const
{
return m_type;
}
- ILINE const string& GetName() const
+ ILINE const AZStd::string& GetName() const
{
return m_name;
}
- ILINE const string& GetDescription() const
+ ILINE const AZStd::string& GetDescription() const
{
return m_description;
}
@@ -71,13 +71,13 @@ namespace Config
static EType TranslateType(const bool&) { return eType_BOOL; }
static EType TranslateType(const int&) { return eType_INT; }
static EType TranslateType(const float&) { return eType_FLOAT; }
- static EType TranslateType(const string&) { return eType_STRING; }
+ static EType TranslateType(const AZStd::string&) { return eType_STRING; }
protected:
EType m_type;
uint8 m_flags;
- string m_name;
- string m_description;
+ AZStd::string m_name;
+ AZStd::string m_description;
void* m_ptr;
ICVar* m_pCVar;
};
diff --git a/Code/Editor/ControlMRU.cpp b/Code/Editor/ControlMRU.cpp
deleted file mode 100644
index 47de13950f..0000000000
--- a/Code/Editor/ControlMRU.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#include "EditorDefs.h"
-#include "ControlMRU.h"
-
-IMPLEMENT_XTP_CONTROL(CControlMRU, CXTPControlRecentFileList)
-
-bool CControlMRU::DoesFileExist(CString& sFileName)
-{
- return (_access(sFileName.GetBuffer(), 0) == 0);
-}
-
-void CControlMRU::OnCalcDynamicSize(DWORD dwMode)
-{
- CRecentFileList* pRecentFileList = GetRecentFileList();
-
- if (!pRecentFileList)
- {
- return;
- }
-
- CString* pArrNames = pRecentFileList->m_arrNames;
-
- assert(pArrNames != NULL);
- if (!pArrNames)
- {
- return;
- }
-
- while (m_nIndex + 1 < m_pControls->GetCount())
- {
- CXTPControl* pControl = m_pControls->GetAt(m_nIndex + 1);
- assert(pControl);
- if (pControl->GetID() >= GetFirstMruID()
- && pControl->GetID() <= GetFirstMruID() + pRecentFileList->m_nSize)
- {
- m_pControls->Remove(pControl);
- }
- else
- {
- break;
- }
- }
-
- if (m_pParent->IsCustomizeMode())
- {
- m_dwHideFlags = 0;
- SetEnabled(TRUE);
- return;
- }
-
- if (pArrNames[0].IsEmpty())
- {
- SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION)));
- SetDescription("No recently opened files");
- m_dwHideFlags = 0;
- SetEnabled(FALSE);
-
- return;
- }
- else
- {
- SetCaption(CString(MAKEINTRESOURCE(IDS_RECENTFILE_CAPTION)));
- SetDescription("Open this document");
- }
-
- m_dwHideFlags |= xtpHideGeneric;
-
- CString sCurDir = (Path::GetEditingGameDataFolder() + "\\").c_str();
- int nCurDir = sCurDir.GetLength();
-
- CString strName;
- CString strTemp;
- int iLastValidMRU = 0;
-
- for (int iMRU = 0; iMRU < pRecentFileList->m_nSize; iMRU++)
- {
- if (!pRecentFileList->GetDisplayName(strName, iMRU, sCurDir.GetBuffer(), nCurDir))
- {
- break;
- }
-
- if (DoesFileExist(pArrNames[iMRU]))
- {
- CString sCurEntryDir = pArrNames[iMRU].Left(nCurDir);
-
- if (sCurEntryDir.CompareNoCase(sCurDir) != 0)
- {
- //unavailable entry (wrong directory)
- continue;
- }
- }
- else
- {
- //invalid entry (not existing)
- continue;
- }
-
- int nId = iMRU + GetFirstMruID();
-
- CXTPControl* pControl = m_pControls->Add(xtpControlButton, nId, _T(""), m_nIndex + iLastValidMRU + 1, TRUE);
- assert(pControl);
-
- pControl->SetCaption(CXTPControlWindowList::ConstructCaption(strName, iLastValidMRU + 1));
- pControl->SetFlags(xtpFlagManualUpdate);
- pControl->SetBeginGroup(iLastValidMRU == 0 && m_nIndex != 0);
- pControl->SetParameter(pArrNames[iMRU]);
-
- CString sDescription = "Open file: " + pArrNames[iMRU];
- pControl->SetDescription(sDescription);
-
- if ((GetFlags() & xtpFlagWrapRow) && iMRU == 0)
- {
- pControl->SetFlags(pControl->GetFlags() | xtpFlagWrapRow);
- }
-
- ++iLastValidMRU;
- }
-
- //if no entry was valid, treat as none would exist
- if (iLastValidMRU == 0)
- {
- SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION)));
- SetDescription("No recently opened files");
- m_dwHideFlags = 0;
- SetEnabled(FALSE);
- }
-}
diff --git a/Code/Editor/ControlMRU.h b/Code/Editor/ControlMRU.h
deleted file mode 100644
index 4ca6562589..0000000000
--- a/Code/Editor/ControlMRU.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#pragma once
-#ifndef CRYINCLUDE_EDITOR_CONTROLMRU_H
-#define CRYINCLUDE_EDITOR_CONTROLMRU_H
-
-class CControlMRU
- : public CXTPControlRecentFileList
-{
-protected:
- virtual void OnCalcDynamicSize(DWORD dwMode);
-
-private:
- DECLARE_XTP_CONTROL(CControlMRU)
- bool DoesFileExist(CString& sFileName);
-};
-#endif // CRYINCLUDE_EDITOR_CONTROLMRU_H
diff --git a/Code/Editor/Controls/BitmapToolTip.h b/Code/Editor/Controls/BitmapToolTip.h
index d4bb89c625..5b7c56cbf3 100644
--- a/Code/Editor/Controls/BitmapToolTip.h
+++ b/Code/Editor/Controls/BitmapToolTip.h
@@ -42,7 +42,7 @@ public:
CBitmapToolTip(QWidget* parent = nullptr);
virtual ~CBitmapToolTip();
- BOOL Create(const RECT& rect);
+ bool Create(const RECT& rect);
// Attributes
public:
diff --git a/Code/Editor/Controls/ColorGradientCtrl.cpp b/Code/Editor/Controls/ColorGradientCtrl.cpp
index 555d285192..446e5810c5 100644
--- a/Code/Editor/Controls/ColorGradientCtrl.cpp
+++ b/Code/Editor/Controls/ColorGradientCtrl.cpp
@@ -29,7 +29,7 @@ CColorGradientCtrl::CColorGradientCtrl(QWidget* parent)
m_nHitKeyIndex = -1;
m_nKeyDrawRadius = 3;
m_bTracking = false;
- m_pSpline = 0;
+ m_pSpline = nullptr;
m_fMinTime = -1;
m_fMaxTime = 1;
m_fMinValue = -1;
@@ -72,7 +72,7 @@ void CColorGradientCtrl::resizeEvent(QResizeEvent* event)
m_grid.rect = m_rcGradient;
if (m_bNoZoom)
{
- m_grid.zoom.x = m_grid.rect.width();
+ m_grid.zoom.x = static_cast(m_grid.rect.width());
}
m_rcKeys = rc;
@@ -106,11 +106,6 @@ QPoint CColorGradientCtrl::KeyToPoint(int nKey)
QPoint CColorGradientCtrl::TimeToPoint(float time)
{
return QPoint(m_grid.WorldToClient(Vec2(time, 0)).x(), m_rcGradient.height() / 2);
-
- QPoint point;
- point.rx() = (time - m_fMinTime) * (m_rcGradient.width() / (m_fMaxTime - m_fMinTime)) + m_rcGradient.left();
- point.ry() = m_rcGradient.height() / 2;
- return point;
}
//////////////////////////////////////////////////////////////////////////
@@ -474,7 +469,7 @@ void CColorGradientCtrl::SetActiveKey(int nIndex)
}
/////////////////////////////////////////////////////////////////////////////
-void CColorGradientCtrl::SetSpline(ISplineInterpolator* pSpline, BOOL bRedraw)
+void CColorGradientCtrl::SetSpline(ISplineInterpolator* pSpline, bool bRedraw)
{
if (pSpline != m_pSpline)
{
@@ -501,7 +496,7 @@ ISplineInterpolator* CColorGradientCtrl::GetSpline()
/////////////////////////////////////////////////////////////////////////////
void CColorGradientCtrl::keyPressEvent(QKeyEvent* event)
{
- BOOL bProcessed = false;
+ bool bProcessed = false;
if (m_nActiveKey != -1 && m_pSpline)
{
diff --git a/Code/Editor/Controls/ColorGradientCtrl.h b/Code/Editor/Controls/ColorGradientCtrl.h
index 9533fecdfa..80d8b966f4 100644
--- a/Code/Editor/Controls/ColorGradientCtrl.h
+++ b/Code/Editor/Controls/ColorGradientCtrl.h
@@ -54,7 +54,7 @@ public:
// Lock value of first and last key to be the same.
void LockFirstAndLastKeys(bool bLock) { m_bLockFirstLastKey = bLock; }
- void SetSpline(ISplineInterpolator* pSpline, BOOL bRedraw = FALSE);
+ void SetSpline(ISplineInterpolator* pSpline, bool bRedraw = false);
ISplineInterpolator* GetSpline();
void SetTimeMarker(float fTime);
diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp
index 9f1921395c..dbe7ba3472 100644
--- a/Code/Editor/Controls/ConsoleSCB.cpp
+++ b/Code/Editor/Controls/ConsoleSCB.cpp
@@ -62,14 +62,14 @@ public:
}
protected:
- void highlightBlock(const QString &text)
+ void highlightBlock(const QString &text) override
{
auto pos = -1;
QTextCharFormat myClassFormat;
myClassFormat.setFontWeight(QFont::Bold);
myClassFormat.setBackground(Qt::yellow);
- while (1)
+ while (true)
{
pos = text.indexOf(m_searchTerm, pos+1, Qt::CaseInsensitive);
@@ -180,7 +180,7 @@ bool ConsoleLineEdit::event(QEvent* ev)
if (newStr.isEmpty())
{
- newStr = GetIEditor()->GetCommandManager()->AutoComplete(cstring.toUtf8().data());
+ newStr = GetIEditor()->GetCommandManager()->AutoComplete(cstring.toUtf8().data()).c_str();
}
}
@@ -211,7 +211,7 @@ void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev)
{
if (commandManager->IsRegistered(str.toUtf8().data()))
{
- commandManager->Execute(QtUtil::ToString(str));
+ commandManager->Execute(str.toUtf8().data());
}
else
{
@@ -220,7 +220,7 @@ void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev)
}
// If a history command was reused directly via up arrow enter, do not reset history index
- if (m_history.size() > 0 && m_historyIndex < m_history.size() && m_history[m_historyIndex] == str)
+ if (m_history.size() > 0 && m_historyIndex < static_cast(m_history.size()) && m_history[m_historyIndex] == str)
{
m_bReusedHistory = true;
}
@@ -338,6 +338,8 @@ CConsoleSCB::CConsoleSCB(QWidget* parent)
connect(findPreviousAction, &QAction::triggered, this, &CConsoleSCB::findPrevious);
ui->findPrevButton->addAction(findPreviousAction);
+ GetIEditor()->RegisterNotifyListener(this);
+
connect(ui->button, &QPushButton::clicked, this, &CConsoleSCB::showVariableEditor);
connect(ui->findButton, &QPushButton::clicked, this, &CConsoleSCB::toggleConsoleSearch);
connect(ui->textEdit, &ConsoleTextEdit::searchBarRequested, this, [this]
@@ -376,6 +378,8 @@ CConsoleSCB::~CConsoleSCB()
{
AzToolsFramework::EditorPreferencesNotificationBus::Handler::BusDisconnect();
+ GetIEditor()->UnregisterNotifyListener(this);
+
s_consoleSCB = nullptr;
CLogFile::AttachEditBox(nullptr);
}
@@ -562,15 +566,15 @@ static void OnVariableUpdated([[maybe_unused]] int row, ICVar* pCVar)
static CVarBlock* VarBlockFromConsoleVars()
{
IConsole* console = GetIEditor()->GetSystem()->GetIConsole();
- std::vector cmds;
+ AZStd::vector cmds;
cmds.resize(console->GetNumVars());
- size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size());
+ size_t cmdCount = console->GetSortedVars(cmds);
CVarBlock* vb = new CVarBlock;
- IVariable* pVariable = 0;
+ IVariable* pVariable = nullptr;
for (int i = 0; i < cmdCount; i++)
{
- ICVar* pCVar = console->GetCVar(cmds[i]);
+ ICVar* pCVar = console->GetCVar(cmds[i].data());
if (!pCVar)
{
continue;
@@ -602,7 +606,7 @@ static CVarBlock* VarBlockFromConsoleVars()
pCVar->AddOnChangeFunctor(onChange);
pVariable->SetDescription(pCVar->GetHelp());
- pVariable->SetName(cmds[i]);
+ pVariable->SetName(cmds[i].data());
// Transfer the custom limits have they have been set for this variable
if (pCVar->HasCustomLimits())
@@ -829,15 +833,15 @@ static void SetEditorRange(EditorType* editor, IVariable* var)
// If this variable has custom limits set, then use that as the min/max
// Otherwise, the min/max for the input box will be bounded by the type
// limit, but the slider will be constricted to a smaller default range
- static const double defaultMin = -100.0f;
- static const double defaultMax = 100.0f;
+ static const float defaultMin = -100.0f;
+ static const float defaultMax = 100.0f;
if (var->HasCustomLimits())
{
- editor->setRange(min, max);
+ editor->setRange(static_cast(min), static_cast(max));
}
else
{
- editor->setSoftRange(defaultMin, defaultMax);
+ editor->setSoftRange(static_cast(defaultMin), static_cast(defaultMax));
}
// Set the step size. The default variable step is 0, so if it's
@@ -846,7 +850,7 @@ static void SetEditorRange(EditorType* editor, IVariable* var)
// use that for the int values
if (step > 0)
{
- editor->spinbox()->setSingleStep(step);
+ editor->spinbox()->setSingleStep(static_cast(step));
}
else if (auto doubleSpinBox = qobject_cast(editor->spinbox()))
{
@@ -1352,4 +1356,19 @@ CConsoleSCB* CConsoleSCB::GetCreatedInstance()
return s_consoleSCB;
}
+void CConsoleSCB::OnEditorNotifyEvent(EEditorNotifyEvent event)
+{
+ switch (event)
+ {
+ case eNotify_OnBeginGameMode:
+ if (gSettings.clearConsoleOnGameModeStart)
+ {
+ ui->textEdit->clear();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
#include
diff --git a/Code/Editor/Controls/ConsoleSCB.h b/Code/Editor/Controls/ConsoleSCB.h
index 98bf4b391d..f51786e2a5 100644
--- a/Code/Editor/Controls/ConsoleSCB.h
+++ b/Code/Editor/Controls/ConsoleSCB.h
@@ -159,6 +159,7 @@ private:
class CConsoleSCB
: public QWidget
, private AzToolsFramework::EditorPreferencesNotificationBus::Handler
+ , public IEditorNotifyListener
{
Q_OBJECT
public:
@@ -187,6 +188,8 @@ private Q_SLOTS:
void findNext();
private:
+ void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
+
QScopedPointer ui;
int m_richEditTextLength;
diff --git a/Code/Editor/Controls/ConsoleSCBMFC.cpp b/Code/Editor/Controls/ConsoleSCBMFC.cpp
deleted file mode 100644
index 3337997811..0000000000
--- a/Code/Editor/Controls/ConsoleSCBMFC.cpp
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-#include "EditorDefs.h"
-#include "ConsoleSCBMFC.h"
-#include "PropertiesDialog.h"
-#include "QtViewPaneManager.h"
-#include "Core/QtEditorApplication.h"
-
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-namespace MFC
-{
-
-static CPropertiesDialog* gPropertiesDlg = nullptr;
-static CString mfc_popup_helper(HWND hwnd, int x, int y);
-static CConsoleSCB* s_consoleSCB = nullptr;
-
-static QString RemoveColorCode(const QString& text, int& iColorCode)
-{
- QString cleanString;
- cleanString.reserve(text.size());
-
- const int textSize = text.size();
- for (int i = 0; i < textSize; ++i)
- {
- QChar c = text.at(i);
- bool isLast = i == textSize - 1;
- if (c == '$' && !isLast && text.at(i + 1).isDigit())
- {
- if (iColorCode == 0)
- {
- iColorCode = text.at(i + 1).digitValue();
- }
- ++i;
- continue;
- }
-
- if (c == '\r' || c == '\n')
- {
- ++i;
- continue;
- }
-
- cleanString.append(c);
- }
-
- return cleanString;
-}
-
-ConsoleLineEdit::ConsoleLineEdit(QWidget* parent)
- : QLineEdit(parent)
- , m_historyIndex(0)
- , m_bReusedHistory(false)
-{
-}
-
-void ConsoleLineEdit::mousePressEvent(QMouseEvent* ev)
-{
- if (ev->type() == QEvent::MouseButtonPress && ev->button() & Qt::RightButton)
- {
- Q_EMIT variableEditorRequested();
- }
-
- QLineEdit::mousePressEvent(ev);
-}
-
-void ConsoleLineEdit::mouseDoubleClickEvent(QMouseEvent* ev)
-{
- Q_EMIT variableEditorRequested();
-}
-
-bool ConsoleLineEdit::event(QEvent* ev)
-{
- // Tab key doesn't go to keyPressEvent(), must be processed here
-
- if (ev->type() != QEvent::KeyPress)
- {
- return QLineEdit::event(ev);
- }
-
- QKeyEvent* ke = static_cast(ev);
- if (ke->key() != Qt::Key_Tab)
- {
- return QLineEdit::event(ev);
- }
-
- QString inputStr = text();
- QString newStr;
-
- QStringList tokens = inputStr.split(" ");
- inputStr = tokens.isEmpty() ? QString() : tokens.first();
- IConsole* console = GetIEditor()->GetSystem()->GetIConsole();
-
- const bool ctrlPressed = ke->modifiers() & Qt::ControlModifier;
- CString cstring = QtUtil::ToCString(inputStr); // TODO: Use QString once the backend stops using QString
- if (ctrlPressed)
- {
- newStr = QtUtil::ToString(console->AutoCompletePrev(cstring));
- }
- else
- {
- newStr = QtUtil::ToString(console->ProcessCompletion(cstring));
- newStr = QtUtil::ToString(console->AutoComplete(cstring));
-
- if (newStr.isEmpty())
- {
- newStr = QtUtil::ToQString(GetIEditor()->GetCommandManager()->AutoComplete(QtUtil::ToString(newStr)));
- }
- }
-
- if (!newStr.isEmpty())
- {
- newStr += " ";
- setText(newStr);
- }
-
- deselect();
- return true;
-}
-
-void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev)
-{
- IConsole* console = GetIEditor()->GetSystem()->GetIConsole();
- auto commandManager = GetIEditor()->GetCommandManager();
-
- console->ResetAutoCompletion();
-
- switch (ev->key())
- {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- {
- QString str = text().trimmed();
- if (!str.isEmpty())
- {
- if (commandManager->IsRegistered(QtUtil::ToCString(str)))
- {
- commandManager->Execute(QtUtil::ToString(str));
- }
- else
- {
- CLogFile::WriteLine(QtUtil::ToCString(str));
- GetIEditor()->GetSystem()->GetIConsole()->ExecuteString(QtUtil::ToCString(str));
- }
-
- // If a history command was reused directly via up arrow enter, do not reset history index
- if (m_history.size() > 0 && m_historyIndex < m_history.size() && m_history[m_historyIndex] == str)
- {
- m_bReusedHistory = true;
- }
- else
- {
- m_historyIndex = m_history.size();
- }
-
- // Do not add the same string if it is the top of the stack, but allow duplicate entries otherwise
- if (m_history.isEmpty() || m_history.back() != str)
- {
- m_history.push_back(str);
- if (!m_bReusedHistory)
- {
- m_historyIndex = m_history.size();
- }
- }
- }
- else
- {
- m_historyIndex = m_history.size();
- }
-
- setText(QString());
- break;
- }
- case Qt::Key_AsciiTilde: // ~
- case Qt::Key_Agrave: // `
- // disable log.
- GetIEditor()->ShowConsole(false);
- setText(QString());
- m_historyIndex = m_history.size();
- break;
- case Qt::Key_Escape:
- setText(QString());
- m_historyIndex = m_history.size();
- break;
- case Qt::Key_Up:
- DisplayHistory(false /*bForward*/);
- break;
- case Qt::Key_Down:
- DisplayHistory(true /*bForward*/);
- break;
- default:
- QLineEdit::keyPressEvent(ev);
- }
-}
-
-void ConsoleLineEdit::DisplayHistory(bool bForward)
-{
- if (m_history.isEmpty())
- {
- return;
- }
-
- // Immediately after reusing a history entry, ensure up arrow re-displays command just used
- if (!m_bReusedHistory || bForward)
- {
- m_historyIndex = static_cast(clamp_tpl(static_cast(m_historyIndex) + (bForward ? 1 : -1), 0, m_history.size() - 1));
- }
- m_bReusedHistory = false;
-
- setText(m_history[m_historyIndex]);
-}
-
-ConsoleTextEdit::ConsoleTextEdit(QWidget* parent)
- : QTextEdit(parent)
-{
-}
-
-
-Lines CConsoleSCB::s_pendingLines;
-
-CConsoleSCB::CConsoleSCB(QWidget* parent)
- : QWidget(parent)
- , ui(new Ui::ConsoleMFC())
- , m_richEditTextLength(0)
- , m_backgroundTheme(gSettings.consoleBackgroundColorTheme)
-{
- m_lines = s_pendingLines;
- s_pendingLines.clear();
- s_consoleSCB = this;
- ui->setupUi(this);
- setMinimumHeight(120);
-
- // Setup the color table for the default (light) theme
- m_colorTable << QColor(0, 0, 0)
- << QColor(0, 0, 0)
- << QColor(0, 0, 200) // blue
- << QColor(0, 200, 0) // green
- << QColor(200, 0, 0) // red
- << QColor(0, 200, 200) // cyan
- << QColor(128, 112, 0) // yellow
- << QColor(200, 0, 200) // red+blue
- << QColor(0x000080ff)
- << QColor(0x008f8f8f);
- OnStyleSettingsChanged();
-
- connect(ui->button, &QPushButton::clicked, this, &CConsoleSCB::showVariableEditor);
- connect(ui->lineEdit, &MFC::ConsoleLineEdit::variableEditorRequested, this, &MFC::CConsoleSCB::showVariableEditor);
- connect(Editor::EditorQtApplication::instance(), &Editor::EditorQtApplication::skinChanged, this, &MFC::CConsoleSCB::OnStyleSettingsChanged);
-
- if (GetIEditor()->IsInConsolewMode())
- {
- // Attach / register edit box
- //CLogFile::AttachEditBox(m_edit.GetSafeHwnd()); // FIXME
- }
-}
-
-CConsoleSCB::~CConsoleSCB()
-{
- s_consoleSCB = nullptr;
- delete gPropertiesDlg;
- gPropertiesDlg = nullptr;
- CLogFile::AttachEditBox(nullptr);
-}
-
-void CConsoleSCB::RegisterViewClass()
-{
- QtViewOptions opts;
- opts.preferedDockingArea = Qt::BottomDockWidgetArea;
- opts.isDeletable = false;
- opts.isStandard = true;
- opts.showInMenu = true;
- opts.builtInActionId = ID_VIEW_CONSOLEWINDOW;
- opts.sendViewPaneNameBackToAmazonAnalyticsServers = true;
- RegisterQtViewPane(GetIEditor(), LyViewPane::Console, LyViewPane::CategoryTools, opts);
-}
-
-void CConsoleSCB::OnStyleSettingsChanged()
-{
- ui->button->setIcon(QIcon(QString(":/controls/img/cvar_dark.bmp")));
-
- // Set the debug/warning text colors appropriately for the background theme
- // (e.g. not have black text on black background)
- QColor textColor = Qt::black;
- m_backgroundTheme = gSettings.consoleBackgroundColorTheme;
- if (m_backgroundTheme == SEditorSettings::ConsoleColorTheme::Dark)
- {
- textColor = Qt::white;
- }
- m_colorTable[0] = textColor;
- m_colorTable[1] = textColor;
-
- QColor bgColor;
- if (!GetIEditor()->IsInConsolewMode() && CConsoleSCB::GetCreatedInstance() && m_backgroundTheme == SEditorSettings::ConsoleColorTheme::Dark)
- {
- bgColor = Qt::black;
- }
- else
- {
- bgColor = Qt::white;
- }
-
- ui->textEdit->setStyleSheet(QString("QTextEdit{ background: %1 }").arg(bgColor.name(QColor::HexRgb)));
-
- // Clear out the console text when we change our background color since
- // some of the previous text colors may not be appropriate for the
- // new background color
- ui->textEdit->clear();
-}
-
-void CConsoleSCB::showVariableEditor()
-{
- const QPoint cursorPos = QCursor::pos();
- CString str = mfc_popup_helper(0, cursorPos.x(), cursorPos.y());
- if (!str.IsEmpty())
- {
- ui->lineEdit->setText(QtUtil::ToQString(str));
- }
-}
-
-void CConsoleSCB::SetInputFocus()
-{
- ui->lineEdit->setFocus();
- ui->lineEdit->setText(QString());
-}
-
-void CConsoleSCB::AddToConsole(const QString& text, bool bNewLine)
-{
- m_lines.push_back({ text, bNewLine });
- FlushText();
-}
-
-void CConsoleSCB::FlushText()
-{
- if (m_lines.empty())
- {
- return;
- }
-
- // Store our current cursor in case we need to restore it, and check if
- // the user has scrolled the text edit away from the bottom
- const QTextCursor oldCursor = ui->textEdit->textCursor();
- QScrollBar* scrollBar = ui->textEdit->verticalScrollBar();
- const int oldScrollValue = scrollBar->value();
- bool scrolledOffBottom = oldScrollValue != scrollBar->maximum();
-
- ui->textEdit->moveCursor(QTextCursor::End);
- QTextCursor textCursor = ui->textEdit->textCursor();
-
- while (!m_lines.empty())
- {
- ConsoleLine line = m_lines.front();
- m_lines.pop_front();
-
- int iColor = 0;
- QString text = MFC::RemoveColorCode(line.text, iColor);
- if (iColor < 0 || iColor >= m_colorTable.size())
- {
- iColor = 0;
- }
-
- if (line.newLine)
- {
- text = QtUtil::trimRight(text);
- text = "\r\n" + text;
- }
-
- QTextCharFormat format;
- const QColor color(m_colorTable[iColor]);
- format.setForeground(color);
-
- if (iColor != 0)
- {
- format.setFontWeight(QFont::Bold);
- }
-
- textCursor.setCharFormat(format);
- textCursor.insertText(text);
- }
-
- // If the user has selected some text in the text edit area or has scrolled
- // away from the bottom, then restore the previous cursor and keep the scroll
- // bar in the same location
- if (oldCursor.hasSelection() || scrolledOffBottom)
- {
- ui->textEdit->setTextCursor(oldCursor);
- scrollBar->setValue(oldScrollValue);
- }
- // Otherwise scroll to the bottom so the latest text can be seen
- else
- {
- scrollBar->setValue(scrollBar->maximum());
- }
-}
-
-QSize CConsoleSCB::minimumSizeHint() const
-{
- return QSize(-1, -1);
-}
-
-QSize CConsoleSCB::sizeHint() const
-{
- return QSize(100, 100);
-}
-
-/** static */
-void CConsoleSCB::AddToPendingLines(const QString& text, bool bNewLine)
-{
- s_pendingLines.push_back({ text, bNewLine });
-}
-
-static CVarBlock* VarBlockFromConsoleVars()
-{
- IConsole* console = GetIEditor()->GetSystem()->GetIConsole();
- std::vector cmds;
- cmds.resize(console->GetNumVars());
- size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size());
-
- CVarBlock* vb = new CVarBlock;
- IVariable* pVariable = 0;
- for (int i = 0; i < cmdCount; i++)
- {
- ICVar* pCVar = console->GetCVar(cmds[i]);
- if (!pCVar)
- {
- continue;
- }
- int varType = pCVar->GetType();
-
- switch (varType)
- {
- case CVAR_INT:
- pVariable = new CVariable();
- pVariable->Set(pCVar->GetIVal());
- break;
- case CVAR_FLOAT:
- pVariable = new CVariable();
- pVariable->Set(pCVar->GetFVal());
- break;
- case CVAR_STRING:
- pVariable = new CVariable();
- pVariable->Set(pCVar->GetString());
- break;
- default:
- assert(0);
- }
-
- pVariable->SetDescription(pCVar->GetHelp());
- pVariable->SetName(cmds[i]);
-
- if (pVariable)
- {
- vb->AddVariable(pVariable);
- }
- }
- return vb;
-}
-
-static void OnConsoleVariableUpdated(IVariable* pVar)
-{
- if (!pVar)
- {
- return;
- }
- CString varName = pVar->GetName();
- ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(varName);
- if (!pCVar)
- {
- return;
- }
- if (pVar->GetType() == IVariable::INT)
- {
- int val;
- pVar->Get(val);
- pCVar->Set(val);
- }
- else if (pVar->GetType() == IVariable::FLOAT)
- {
- float val;
- pVar->Get(val);
- pCVar->Set(val);
- }
- else if (pVar->GetType() == IVariable::STRING)
- {
- CString val;
- pVar->Get(val);
- pCVar->Set(val);
- }
-}
-
-static CString mfc_popup_helper(HWND hwnd, int x, int y)
-{
- IConsole* console = GetIEditor()->GetSystem()->GetIConsole();
-
- TSmartPtr vb = VarBlockFromConsoleVars();
- XmlNodeRef node;
- if (!gPropertiesDlg)
- {
- gPropertiesDlg = new CPropertiesDialog("Console Variables", node, AfxGetMainWnd(), true);
- }
- if (!gPropertiesDlg->m_hWnd)
- {
- gPropertiesDlg->Create(CPropertiesDialog::IDD, AfxGetMainWnd());
- gPropertiesDlg->SetUpdateCallback(AZStd::bind(OnConsoleVariableUpdated, AZStd::placeholders::_1));
- }
- gPropertiesDlg->ShowWindow(SW_SHOW);
- gPropertiesDlg->BringWindowToTop();
- gPropertiesDlg->GetPropertyCtrl()->AddVarBlock(vb);
-
- return "";
-}
-
-CConsoleSCB* CConsoleSCB::GetCreatedInstance()
-{
- return s_consoleSCB;
-}
-
-} // namespace MFC
-
-#include
diff --git a/Code/Editor/Controls/FolderTreeCtrl.cpp b/Code/Editor/Controls/FolderTreeCtrl.cpp
index 17b6dccac7..b1cbb9414e 100644
--- a/Code/Editor/Controls/FolderTreeCtrl.cpp
+++ b/Code/Editor/Controls/FolderTreeCtrl.cpp
@@ -400,7 +400,7 @@ void CFolderTreeCtrl::RemoveEmptyFolderItems(const QString& folder)
void CFolderTreeCtrl::Edit(const QString& path)
{
- CFileUtil::EditTextFile(QtUtil::ToString(path), 0, IFileUtil::FILE_TYPE_SCRIPT);
+ CFileUtil::EditTextFile(path.toUtf8().data(), 0, IFileUtil::FILE_TYPE_SCRIPT);
}
void CFolderTreeCtrl::ShowInExplorer(const QString& path)
diff --git a/Code/Editor/Controls/HotTrackingTreeCtrl.cpp b/Code/Editor/Controls/HotTrackingTreeCtrl.cpp
index 917d02155b..54152a9fd4 100644
--- a/Code/Editor/Controls/HotTrackingTreeCtrl.cpp
+++ b/Code/Editor/Controls/HotTrackingTreeCtrl.cpp
@@ -19,22 +19,22 @@ CHotTrackingTreeCtrl::CHotTrackingTreeCtrl(QWidget* parent)
: QTreeWidget(parent)
{
setMouseTracking(true);
- m_hHoverItem = NULL;
+ m_hHoverItem = nullptr;
}
void CHotTrackingTreeCtrl::mouseMoveEvent(QMouseEvent* event)
{
QTreeWidgetItem* hItem = itemAt(event->pos());
- if (m_hHoverItem != NULL)
+ if (m_hHoverItem != nullptr)
{
QFont font = m_hHoverItem->font(0);
font.setBold(false);
m_hHoverItem->setFont(0, font);
- m_hHoverItem = NULL;
+ m_hHoverItem = nullptr;
}
- if (hItem != NULL)
+ if (hItem != nullptr)
{
QFont font = hItem->font(0);
font.setBold(true);
diff --git a/Code/Editor/Controls/ImageHistogramCtrl.cpp b/Code/Editor/Controls/ImageHistogramCtrl.cpp
index 7218c0cd38..252bf4f09b 100644
--- a/Code/Editor/Controls/ImageHistogramCtrl.cpp
+++ b/Code/Editor/Controls/ImageHistogramCtrl.cpp
@@ -175,7 +175,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
penSpikes = penColor;
painter.setPen(Qt::black);
painter.setBrush(Qt::white);
- rcGraph = QRect(QPoint(m_graphMargin, m_graphMargin), QPoint(abs(rc.width() - m_graphMargin), abs(rc.height() * m_graphHeightPercent)));
+ rcGraph = QRect(QPoint(m_graphMargin, m_graphMargin), QPoint(abs(rc.width() - m_graphMargin), static_cast(abs(rc.height() * m_graphHeightPercent))));
painter.drawRect(rcGraph);
painter.setPen(penSpikes);
@@ -193,7 +193,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
{
float scale = 0;
- i = ((float)x / graphWidth) * (kNumColorLevels - 1);
+ i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1));
i = CLAMP(i, 0, kNumColorLevels - 1);
switch (m_drawMode)
@@ -244,8 +244,8 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
}
}
- crtX = rcGraph.left() + x + 1;
- painter.drawLine(crtX, graphBottom, crtX, graphBottom - scale * graphHeight);
+ crtX = static_cast(rcGraph.left() + x + 1);
+ painter.drawLine(crtX, graphBottom, crtX, static_cast(graphBottom - scale * graphHeight));
}
}
else
@@ -258,9 +258,9 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
for (size_t x = 0, xCount = abs(rcGraph.width()); x < xCount; ++x)
{
- i = ((float)x / graphWidth) * (kNumColorLevels - 1);
+ i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1));
i = CLAMP(i, 0, kNumColorLevels - 1);
- crtX = rcGraph.left() + x + 1;
+ crtX = static_cast(rcGraph.left() + x + 1);
scaleR = scaleG = scaleB = scaleA = 0;
if (m_maxCount[0])
@@ -283,10 +283,10 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
scaleA = (float)m_count[3][i] / m_maxCount[3];
}
- heightR = graphBottom - scaleR * graphHeight;
- heightG = graphBottom - scaleG * graphHeight;
- heightB = graphBottom - scaleB * graphHeight;
- heightA = graphBottom - scaleA * graphHeight;
+ heightR = static_cast(graphBottom - scaleR * graphHeight);
+ heightG = static_cast(graphBottom - scaleG * graphHeight);
+ heightB = static_cast(graphBottom - scaleB * graphHeight);
+ heightA = static_cast(graphBottom - scaleA * graphHeight);
if (lastHeight[0] == INT_MAX)
{
@@ -350,7 +350,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
for (size_t x = 0, xCount = abs(rcGraph.width()); x < xCount; ++x)
{
pos = (float)x / graphWidth;
- i = (float)((int)(pos * kNumColorLevels) % aThirdOfNumColorLevels) / aThirdOfNumColorLevels * kNumColorLevels;
+ i = static_cast((float)((int)(pos * kNumColorLevels) % aThirdOfNumColorLevels) / aThirdOfNumColorLevels * kNumColorLevels);
i = CLAMP(i, 0, kNumColorLevels - 1);
scale = 0;
@@ -385,7 +385,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event)
}
painter.setPen(pPen);
- painter.drawLine(rcGraph.left() + x + 1, graphBottom, rcGraph.left() + x + 1, graphBottom - scale * graphHeight);
+ painter.drawLine(rcGraph.left() + static_cast(x) + 1, graphBottom, rcGraph.left() + static_cast(x) + 1, static_cast(graphBottom - scale * graphHeight));
}
// then draw 3 lines so we separate the channels
diff --git a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp b/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp
index c438858e81..b47a535d2a 100644
--- a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp
+++ b/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp
@@ -422,7 +422,7 @@ void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e)
curr_x = histogramRect.left() + x + 1;
- int i = ((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1);
+ int i = static_cast(((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1));
if (m_histrogramMode == eHistogramMode_SplitRGB)
{
// Filter out to area which we are interested
@@ -446,7 +446,7 @@ void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e)
scale = (float)m_histogram.m_count[c][i] / m_histogram.m_maxCount[c];
}
- int height = graphBottom - graphHeight * scale;
+ int height = static_cast(graphBottom - graphHeight * scale);
if (last_height == INT_MAX)
{
last_height = height;
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp
index fde5642b05..4fb18e438c 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp
@@ -56,8 +56,8 @@ CReflectedVarAnimation AnimationPropertyCtrl::value() const
void AnimationPropertyCtrl::OnApplyClicked()
{
QStringList cSelectedAnimations;
- size_t nTotalAnimations(0);
- size_t nCurrentAnimation(0);
+ int nTotalAnimations(0);
+ int nCurrentAnimation(0);
QString combinedString = GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("animation");
SplitString(combinedString, cSelectedAnimations, ',');
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp
index bf87f2017d..c228fbda09 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp
@@ -10,7 +10,6 @@
// Editor
#include "PropertyCtrl.h"
-#include "PropertyAnimationCtrl.h"
#include "PropertyResourceCtrl.h"
#include "PropertyGenericCtrl.h"
#include "PropertyMiscCtrl.h"
@@ -22,9 +21,7 @@ void RegisterReflectedVarHandlers()
if (!registered)
{
registered = true;
- EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler());
- EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler());
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
index 1916ce5e16..8ff83dd894 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
@@ -73,16 +73,6 @@ void GenericPopupPropertyEditor::SetPropertyType(PropertyType type)
m_propertyType = type;
}
-void ReverbPresetPropertyEditor::onEditClicked()
-{
- CSelectEAXPresetDlg PresetDlg(this);
- PresetDlg.SetCurrPreset(GetValue());
- if (PresetDlg.exec() == QDialog::Accepted)
- {
- SetValue(PresetDlg.GetCurrPreset());
- }
-}
-
void SequencePropertyEditor::onEditClicked()
{
CSelectSequenceDialog gtDlg(this);
@@ -132,7 +122,9 @@ void LocalStringPropertyEditor::onEditClicked()
if (pMgr->GetLocalizedInfoByIndex(i, sInfo))
{
item.desc = tr("English Text:\r\n");
- item.desc += QString::fromWCharArray(Unicode::Convert(sInfo.sUtf8TranslatedText).c_str());
+ AZStd::wstring utf8TranslatedTextW;
+ AZStd::to_wstring(utf8TranslatedTextW, sInfo.sUtf8TranslatedText);
+ item.desc += QString::fromWCharArray(utf8TranslatedTextW.c_str());
item.name = sInfo.sKey;
items.push_back(item);
}
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h
index 2296773f0a..b6b14cf125 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h
@@ -96,15 +96,6 @@ public:
}
};
-class ReverbPresetPropertyEditor
- : public GenericPopupPropertyEditor
-{
-public:
- ReverbPresetPropertyEditor(QWidget* pParent = nullptr)
- : GenericPopupPropertyEditor(pParent){}
- void onEditClicked() override;
-};
-
class MissionObjPropertyEditor
: public GenericPopupPropertyEditor
{
@@ -155,7 +146,6 @@ public:
// So we use our own
#define CONST_AZ_CRC(name, value) AZ::u32(value)
-using ReverbPresetPropertyHandler = GenericPopupWidgetHandler;
using MissionObjPropertyHandler = GenericPopupWidgetHandler;
using SequencePropertyHandler = GenericPopupWidgetHandler;
using SequenceIdPropertyHandler = GenericPopupWidgetHandler;
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp
index 92c33aefc2..b9f7e12e95 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp
@@ -145,7 +145,7 @@ bool UserPopupWidgetHandler::ReadValuesIntoGUI(size_t index, UserPropertyEditor*
QWidget* FloatCurveHandler::CreateGUI(QWidget *pParent)
{
CSplineCtrl *cSpline = new CSplineCtrl(pParent);
- cSpline->SetUpdateCallback(AZStd::bind(&FloatCurveHandler::OnSplineChange, this, AZStd::placeholders::_1));
+ cSpline->SetUpdateCallback([this](CSplineCtrl* spl) { OnSplineChange(spl); });
cSpline->SetTimeRange(0, 1);
cSpline->SetValueRange(0, 1);
cSpline->SetGrid(12, 12);
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp
index d3ae6aaecf..c5ccc599d6 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp
@@ -17,9 +17,9 @@
// AzToolsFramework
#include
#include
+#include
// Editor
-#include "IResourceSelectorHost.h"
#include "Controls/QToolTipWidget.h"
#include "Controls/BitmapToolTip.h"
@@ -35,8 +35,8 @@ BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/)
void BrowseButton::SetPathAndEmit(const QString& path)
{
- //only emit if path changes, except for ePropertyGeomCache. Old property control
- if (path != m_path || m_propertyType == ePropertyGeomCache)
+ //only emit if path changes. Old property control
+ if (path != m_path)
{
m_path = path;
emit PathChanged(m_path);
@@ -78,21 +78,6 @@ private:
// Filters for texture.
selection = AssetSelectionModel::AssetGroupSelection("Texture");
}
- else if (m_propertyType == ePropertyModel)
- {
- // Filters for models.
- selection = AssetSelectionModel::AssetGroupSelection("Geometry");
- }
- else if (m_propertyType == ePropertyGeomCache)
- {
- // Filters for geom caches.
- selection = AssetSelectionModel::AssetTypeSelection("Geom Cache");
- }
- else if (m_propertyType == ePropertyFile)
- {
- // Filters for files.
- selection = AssetSelectionModel::AssetTypeSelection("File");
- }
else
{
return;
@@ -106,14 +91,7 @@ private:
switch (m_propertyType)
{
case ePropertyTexture:
- case ePropertyModel:
newPath.replace("\\\\", "/");
- }
- switch (m_propertyType)
- {
- case ePropertyTexture:
- case ePropertyModel:
- case ePropertyFile:
if (newPath.size() > MAX_PATH)
{
newPath.resize(MAX_PATH);
@@ -125,26 +103,51 @@ private:
}
};
-class ResourceSelectorButton
+class AudioControlSelectorButton
: public BrowseButton
{
public:
- AZ_CLASS_ALLOCATOR(ResourceSelectorButton, AZ::SystemAllocator, 0);
+ AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0);
- ResourceSelectorButton(PropertyType type, QWidget* pParent = nullptr)
+ AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr)
: BrowseButton(type, pParent)
{
- setToolTip(tr("Select resource"));
+ setToolTip(tr("Select Audio Control"));
}
private:
void OnClicked() override
{
- SResourceSelectorContext x;
- x.parentWidget = this;
- x.typeName = Prop::GetPropertyTypeToResourceType(m_propertyType);
- QString newPath = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, m_path);
- SetPathAndEmit(newPath);
+ AZStd::string resourceResult;
+ auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType
+ {
+ switch (type)
+ {
+ case ePropertyAudioTrigger:
+ return AzToolsFramework::AudioPropertyType::Trigger;
+ case ePropertyAudioRTPC:
+ return AzToolsFramework::AudioPropertyType::Rtpc;
+ case ePropertyAudioSwitch:
+ return AzToolsFramework::AudioPropertyType::Switch;
+ case ePropertyAudioSwitchState:
+ return AzToolsFramework::AudioPropertyType::SwitchState;
+ case ePropertyAudioEnvironment:
+ return AzToolsFramework::AudioPropertyType::Environment;
+ case ePropertyAudioPreloadRequest:
+ return AzToolsFramework::AudioPropertyType::Preload;
+ default:
+ return AzToolsFramework::AudioPropertyType::NumTypes;
+ }
+ };
+
+ auto propType = ConvertLegacyAudioPropertyType(m_propertyType);
+ if (propType != AzToolsFramework::AudioPropertyType::NumTypes)
+ {
+ AzToolsFramework::AudioControlSelectorRequestBus::EventResult(
+ resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource,
+ AZStd::string_view{ m_path.toUtf8().constData() });
+ SetPathAndEmit(QString{ resourceResult.c_str() });
+ }
}
};
@@ -235,18 +238,13 @@ void FileResourceSelectorWidget::SetPropertyType(PropertyType type)
AddButton(new TextureEditButton);
m_previewToolTip.reset(new CBitmapToolTip);
break;
- case ePropertyModel:
- case ePropertyGeomCache:
case ePropertyAudioTrigger:
case ePropertyAudioSwitch:
case ePropertyAudioSwitchState:
case ePropertyAudioRTPC:
case ePropertyAudioEnvironment:
case ePropertyAudioPreloadRequest:
- AddButton(new ResourceSelectorButton(type));
- break;
- case ePropertyFile:
- AddButton(new FileBrowseButton(type));
+ AddButton(new AudioControlSelectorButton(type));
break;
default:
break;
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp
deleted file mode 100644
index 323fe2a07a..0000000000
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-
-// Description : implementation file
-
-#include "EditorDefs.h"
-
-#include "ReflectedPropertiesPanel.h"
-
-/////////////////////////////////////////////////////////////////////////////
-// ReflectedPropertiesPanel dialog
-
-
-ReflectedPropertiesPanel::ReflectedPropertiesPanel(QWidget* pParent)
- : ReflectedPropertyControl(pParent)
-{
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ReflectedPropertiesPanel::DeleteVars()
-{
- ClearVarBlock();
- m_updateCallbacks.clear();
- m_varBlock = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ReflectedPropertiesPanel::SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
-{
- assert(vb);
-
- m_varBlock = vb;
-
- RemoveAllItems();
- m_varBlock = vb;
- AddVarBlock(m_varBlock, category);
-
- SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
-
- // When new object set all previous callbacks freed.
- m_updateCallbacks.clear();
- if (updCallback)
- {
- stl::push_back_unique(m_updateCallbacks, updCallback);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ReflectedPropertiesPanel::AddVars(CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
-{
- assert(vb);
-
- bool bNewBlock = false;
- // Make a clone of properties.
- if (!m_varBlock)
- {
- RemoveAllItems();
- m_varBlock = vb->Clone(true);
- AddVarBlock(m_varBlock, category);
- bNewBlock = true;
- }
- m_varBlock->Wire(vb);
-
- if (bNewBlock)
- {
- SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
-
- // When new object set all previous callbacks freed.
- m_updateCallbacks.clear();
- }
-
- if (updCallback)
- {
- stl::push_back_unique(m_updateCallbacks, updCallback);
- }
-}
-
-void ReflectedPropertiesPanel::OnPropertyChanged(IVariable* pVar)
-{
- std::list::iterator iter;
- for (iter = m_updateCallbacks.begin(); iter != m_updateCallbacks.end(); ++iter)
- {
- (*iter)->operator()(pVar);
- }
-}
-
-
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h
deleted file mode 100644
index cd551c63e2..0000000000
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#ifndef CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
-#define CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
-
-#pragma once
-
-#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h"
-#include "Util/Variable.h"
-
-/////////////////////////////////////////////////////////////////////////////
-// ReflectedPropertiesPanel dialog
-
-AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
-//This class is a port of ReflectedPropertiesPanel to use the ReflectedPropertyControl
-class SANDBOX_API ReflectedPropertiesPanel
- : public ReflectedPropertyControl
-{
-AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
-public:
- ReflectedPropertiesPanel(QWidget* pParent = nullptr); // standard constructor
-
- void DeleteVars();
- void AddVars(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
-
- void SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
-
-protected:
- void OnPropertyChanged(IVariable* pVar);
-
-protected:
- AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
- TSmartPtr m_varBlock;
-
- std::list m_updateCallbacks;
- AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
-};
-
-
-#endif // CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp
index 89938d9735..40ea71f577 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp
@@ -198,12 +198,12 @@ void ReflectedPropertyControl::CreateItems(XmlNodeRef node)
void ReflectedPropertyControl::CreateItems(XmlNodeRef node, CVarBlockPtr& outBlockPtr, IVariable::OnSetCallback* func, bool splitCamelCaseIntoWords)
{
- SelectItem(0);
+ SelectItem(nullptr);
outBlockPtr = new CVarBlock;
for (size_t i = 0, iGroupCount(node->getChildCount()); i < iGroupCount; ++i)
{
- XmlNodeRef groupNode = node->getChild(i);
+ XmlNodeRef groupNode = node->getChild(static_cast(i));
if (groupNode->haveAttr("hidden"))
{
@@ -308,7 +308,7 @@ void ReflectedPropertyControl::CreateItems(XmlNodeRef node, CVarBlockPtr& outBlo
int nMin(0), nMax(0);
if (child->getAttr("min", nMin) && child->getAttr("max", nMax))
{
- intVar->SetLimits(nMin, nMax);
+ intVar->SetLimits(static_cast(nMin), static_cast(nMax));
}
}
else if (!azstricmp(type, "float"))
@@ -505,7 +505,7 @@ void ReflectedPropertyControl::RemoveAllItems()
void ReflectedPropertyControl::ClearVarBlock()
{
RemoveAllItems();
- m_pVarBlock = 0;
+ m_pVarBlock = nullptr;
}
void ReflectedPropertyControl::RecreateAllItems()
@@ -560,7 +560,7 @@ void ReflectedPropertyControl::RequestPropertyContextMenu(AzToolsFramework::Inst
// Popup Menu with Event selection.
QMenu menu;
- UINT i = 0;
+ unsigned int i = 0;
const int ePPA_CustomItemBase = 10; // reserved from 10 to 99
const int ePPA_CustomPopupBase = 100; // reserved from 100 to x*100+100 where x is size of m_customPopupMenuPopups
@@ -595,12 +595,12 @@ void ReflectedPropertyControl::RequestPropertyContextMenu(AzToolsFramework::Inst
action->setData(ePPA_CustomItemBase + i);
}
- for (UINT j = 0; j < m_customPopupMenuPopups.size(); ++j)
+ for (unsigned int j = 0; j < m_customPopupMenuPopups.size(); ++j)
{
SCustomPopupMenu* pMenuInfo = &m_customPopupMenuPopups[j];
QMenu* pSubMenu = menu.addMenu(pMenuInfo->m_text);
- for (UINT k = 0; k < pMenuInfo->m_subMenuText.size(); ++k)
+ for (UINT k = 0; k < static_cast(pMenuInfo->m_subMenuText.size()); ++k)
{
const UINT uID = ePPA_CustomPopupBase + ePPA_CustomPopupBase * j + k;
QAction *action = pSubMenu->addAction(pMenuInfo->m_subMenuText[k]);
@@ -688,11 +688,11 @@ void ReflectedPropertyControl::OnItemChange(ReflectedPropertyItem *item, bool de
// callback until after the current event queue is processed, so that we aren't changing other widgets
// as a ton of them are still being created.
Qt::ConnectionType connectionType = deferCallbacks ? Qt::QueuedConnection : Qt::DirectConnection;
- if (m_updateVarFunc != 0 && m_bEnableCallback)
+ if (m_updateVarFunc && m_bEnableCallback)
{
QMetaObject::invokeMethod(this, "DoUpdateCallback", connectionType, Q_ARG(IVariable*, item->GetVariable()));
}
- if (m_updateObjectFunc != 0 && m_bEnableCallback)
+ if (m_updateObjectFunc && m_bEnableCallback)
{
// KDAB: This callback has same signature as DoUpdateCallback. I think the only reason there are 2 is because some
// EntityObject registers callback and some derived objects want to register their own callback. the normal UpdateCallback
@@ -709,7 +709,7 @@ void ReflectedPropertyControl::DoUpdateCallback(IVariable *var)
const bool variableStillExists = FindVariable(var);
AZ_Assert(variableStillExists, "This variable and the item containing it were destroyed during a deferred callback. Change to non-deferred callback.");
- if (m_updateVarFunc == 0 || !variableStillExists)
+ if (!m_updateVarFunc || !variableStillExists)
{
return;
}
@@ -724,7 +724,7 @@ void ReflectedPropertyControl::DoUpdateObjectCallback(IVariable *var)
const bool variableStillExists = FindVariable(var);
AZ_Assert(variableStillExists, "This variable and the item containing it were destroyed during a deferred callback. Change to non-deferred callback.");
- if (m_updateVarFunc == 0 || !variableStillExists)
+ if ( !m_updateVarFunc || !variableStillExists)
{
return;
}
@@ -904,7 +904,7 @@ void ReflectedPropertyControl::SetUndoCallback(UndoCallback &callback)
void ReflectedPropertyControl::ClearUndoCallback()
{
- m_undoFunc = 0;
+ m_undoFunc = nullptr;
}
bool ReflectedPropertyControl::FindVariable(IVariable *categoryItem) const
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp
index 0bea6902c9..af418c6e0d 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp
@@ -82,7 +82,7 @@ public:
}
//helps implement ReflectedPropertyControl::ReplaceVarBlock
- void ReplaceVarBlock(CVarBlock *varBlock)
+ void ReplaceVarBlock(CVarBlock *varBlock) override
{
m_containerVar->Clear();
UpdateCommon(m_item->GetVariable(), varBlock);
@@ -172,8 +172,8 @@ ReflectedPropertyItem::ReflectedPropertyItem(ReflectedPropertyControl *control,
if (parent)
parent->AddChild(this);
- m_onSetCallback = AZStd::bind(&ReflectedPropertyItem::OnVariableChange, this, AZStd::placeholders::_1);
- m_onSetEnumCallback = AZStd::bind(&ReflectedPropertyItem::OnVariableEnumChange, this, AZStd::placeholders::_1);
+ m_onSetCallback = [this](IVariable* var) { OnVariableChange(var); };
+ m_onSetEnumCallback = [this](IVariable* var) { OnVariableEnumChange(var); };
}
ReflectedPropertyItem::~ReflectedPropertyItem()
@@ -207,7 +207,7 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
ReleaseVariable();
m_pVariable = pInputVar;
- assert(m_pVariable != NULL);
+ assert(m_pVariable != nullptr);
m_pVariable->AddOnSetCallback(&m_onSetCallback);
m_pVariable->AddOnSetEnumCallback(&m_onSetEnumCallback);
@@ -255,9 +255,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
case ePropertySelection:
m_reflectedVarAdapter = new ReflectedVarEnumAdapter;
break;
- case ePropertyAnimation:
- m_reflectedVarAdapter = new ReflectedVarAnimationAdapter;
- break;
case ePropertyColor:
m_reflectedVarAdapter = new ReflectedVarColorAdapter;
break;
@@ -265,7 +262,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
m_reflectedVarAdapter = new ReflectedVarUserAdapter;
break;
case ePropertyEquip:
- case ePropertyReverbPreset:
case ePropertyGameToken:
case ePropertyMissionObj:
case ePropertySequence:
@@ -276,15 +272,12 @@ void ReflectedPropertyItem::SetVariable(IVariable *var)
m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type);
break;
case ePropertyTexture:
- case ePropertyModel:
- case ePropertyGeomCache:
case ePropertyAudioTrigger:
case ePropertyAudioSwitch:
case ePropertyAudioSwitchState:
case ePropertyAudioRTPC:
case ePropertyAudioEnvironment:
case ePropertyAudioPreloadRequest:
- case ePropertyFile:
m_reflectedVarAdapter = new ReflectedVarResourceAdapter;
break;
case ePropertyFloatCurve:
@@ -332,7 +325,7 @@ void ReflectedPropertyItem::RemoveAllChildren()
{
for (int i = 0; i < m_childs.size(); i++)
{
- m_childs[i]->m_parent = 0;
+ m_childs[i]->m_parent = nullptr;
}
m_childs.clear();
@@ -473,7 +466,7 @@ void ReflectedPropertyItem::ReleaseVariable()
m_pVariable->RemoveOnSetCallback(&m_onSetCallback);
m_pVariable->RemoveOnSetEnumCallback(&m_onSetEnumCallback);
}
- m_pVariable = 0;
+ m_pVariable = nullptr;
delete m_reflectedVarAdapter;
m_reflectedVarAdapter = nullptr;
}
@@ -569,7 +562,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo
break;
case ePropertyTexture:
- case ePropertyModel:
value.replace('\\', '/');
break;
}
@@ -578,8 +570,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo
switch (m_type)
{
case ePropertyTexture:
- case ePropertyModel:
- case ePropertyFile:
if (value.length() >= MAX_PATH)
{
value = value.left(MAX_PATH);
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.h
index 0abf7d295c..9bd34f3f7c 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.h
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.h
@@ -122,7 +122,7 @@ protected:
public:
//! Get number of child nodes.
- int GetChildCount() const { return m_childs.size(); };
+ int GetChildCount() const { return static_cast(m_childs.size()); };
//! Get Child by id.
ReflectedPropertyItem* GetChild(int index) const { return m_childs[index]; }
PropertyType GetType() const { return m_type; }
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp
index 5b9c5b8063..263c17a8bb 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp
@@ -31,12 +31,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
->Field("description", &CReflectedVar::m_description)
->Field("varName", &CReflectedVar::m_varName);
- serializeContext->Class ()
- ->Version(1)
- ->Field("animation", &CReflectedVarAnimation::m_animation)
- ->Field("entityID", &CReflectedVarAnimation::m_entityID)
- ;
-
serializeContext->Class ()
->Version(1)
->Field("path", &CReflectedVarResource::m_path)
@@ -76,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
AZ::EditContext* ec = serializeContext->GetEditContext();
if (ec)
{
- ec->Class< CReflectedVarAnimation >("VarAnimation", "Animation")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAnimation::varName)
- ->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAnimation::description)
- ;
-
ec->Class< CReflectedVarResource >("VarResource", "Resource")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName)
@@ -284,8 +272,6 @@ AZ::u32 CReflectedVarGenericProperty::handler()
return AZ_CRC("ePropertyShader", 0xc40932f1);
case ePropertyEquip:
return AZ_CRC("ePropertyEquip", 0x66ffd290);
- case ePropertyReverbPreset:
- return AZ_CRC("ePropertyReverbPreset", 0x51469f38);
case ePropertyDeprecated0:
return AZ_CRC("ePropertyCustomAction", 0x4ffa5ba5);
case ePropertyGameToken:
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h
index 634f2efd3a..a15f8326d1 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h
@@ -265,32 +265,8 @@ public:
AZ::Vector3 m_color;
};
-//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
-class CReflectedVarAnimation
- : public CReflectedVar
-{
-public:
- AZ_RTTI(CReflectedVarAnimation, "{635D982E-23EC-463F-8F33-4FC2C19D5673}", CReflectedVar)
-
- CReflectedVarAnimation(const AZStd::string& name)
- : CReflectedVar(name)
- , m_entityID(0)
- {}
- CReflectedVarAnimation()
- : m_entityID(0){}
-
- AZStd::string varName() const { return m_varName; }
- AZStd::string description() const { return m_description; }
-
- AZStd::string m_animation;
- AZ::EntityId m_entityID;
-};
-
//Class to hold:
// ePropertyTexture (IVariable::DT_TEXTURE)
-// ePropertyMaterial (IVariable::DT_MATERIAL)
-// ePropertyModel (IVariable::DT_OBJECT)
-// ePropertyGeomCache (IVariable::DT_GEOM_CACHE)
// ePropertyAudioTrigger (IVariable::DT_AUDIO_TRIGGER)
// ePropertyAudioSwitch (IVariable::DT_AUDIO_SWITCH )
// ePropertyAudioSwitchState (IVariable::DT_AUDIO_SWITCH_STATE)
@@ -344,7 +320,6 @@ public:
AZStd::vector m_itemDescriptions;
};
-//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
class CReflectedVarSpline
: public CReflectedVar
{
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp
index 20e86c6838..b3f1b35461 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp
@@ -39,20 +39,20 @@ namespace {
hardMin = desc.m_bHardMin;
hardMax = desc.m_bHardMax;
}
- reflectedVar->m_softMinVal = min;
- reflectedVar->m_softMaxVal = max;
+ reflectedVar->m_softMinVal = static_cast(min);
+ reflectedVar->m_softMaxVal = static_cast(max);
if (hardMin)
{
- reflectedVar->m_minVal = min;
+ reflectedVar->m_minVal = static_cast(min);
}
else
{
- reflectedVar->m_minVal = std::numeric_limits::lowest();
+ reflectedVar->m_minVal = std::numeric_limits::lowest();
}
if (hardMax)
{
- reflectedVar->m_maxVal = max;
+ reflectedVar->m_maxVal = static_cast(max);
}
else
{
@@ -64,9 +64,9 @@ namespace {
../Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp:59:38: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-int-float-conversion]
reflectedVar->m_maxVal = std::numeric_limits::max();
*/
- reflectedVar->m_maxVal = static_cast(std::numeric_limits::max());
+ reflectedVar->m_maxVal = static_cast(std::numeric_limits::max());
}
- reflectedVar->m_stepSize = step;
+ reflectedVar->m_stepSize = static_cast(step);
}
}
@@ -95,9 +95,9 @@ void ReflectedVarIntAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
{
int intValue;
pVariable->Get(intValue);
- value = intValue;
+ value = static_cast(intValue);
}
- m_reflectedVar->m_value = std::round(value * m_valueMultiplier);
+ m_reflectedVar->m_value = static_cast(std::round(value * m_valueMultiplier));
}
void ReflectedVarIntAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
@@ -362,14 +362,14 @@ void ReflectedVarColorAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
Vec3 v(0, 0, 0);
pVariable->Get(v);
const QColor col = ColorLinearToGamma(ColorF(v.x, v.y, v.z));
- m_reflectedVar->m_color.Set(col.redF(), col.greenF(), col.blueF());
+ m_reflectedVar->m_color.Set(static_cast(col.redF()), static_cast(col.greenF()), static_cast(col.blueF()));
}
else
{
int col(0);
pVariable->Get(col);
const QColor qcolor = ColorToQColor((uint32)col);
- m_reflectedVar->m_color.Set(qcolor.redF(), qcolor.greenF(), qcolor.blueF());
+ m_reflectedVar->m_color.Set(static_cast(qcolor.redF()), static_cast(qcolor.greenF()), static_cast(qcolor.blueF()));
}
}
@@ -382,9 +382,9 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
}
else
{
- int ir = m_reflectedVar->m_color.GetX() * 255.0f;
- int ig = m_reflectedVar->m_color.GetY() * 255.0f;
- int ib = m_reflectedVar->m_color.GetZ() * 255.0f;
+ int ir = static_cast(m_reflectedVar->m_color.GetX() * 255.0f);
+ int ig = static_cast(m_reflectedVar->m_color.GetY() * 255.0f);
+ int ib = static_cast(m_reflectedVar->m_color.GetZ() * 255.0f);
pVariable->Set(static_cast(RGB(ir, ig, ib)));
}
@@ -392,25 +392,6 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
-void ReflectedVarAnimationAdapter::SetVariable(IVariable *pVariable)
-{
- m_reflectedVar.reset(new CReflectedVarAnimation(pVariable->GetHumanName().toUtf8().data()));
- m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
-}
-
-void ReflectedVarAnimationAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
-{
- m_reflectedVar->m_entityID = static_cast(pVariable->GetUserData().value());
- m_reflectedVar->m_animation = pVariable->GetDisplayValue().toUtf8().data();
-}
-
-void ReflectedVarAnimationAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
-{
- pVariable->SetUserData(static_cast(m_reflectedVar->m_entityID));
- pVariable->SetDisplayValue(m_reflectedVar->m_animation.c_str());
-
-}
-
void ReflectedVarResourceAdapter::SetVariable(IVariable *pVariable)
{
m_reflectedVar.reset(new CReflectedVarResource(pVariable->GetHumanName().toUtf8().data()));
@@ -429,7 +410,7 @@ void ReflectedVarResourceAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
void ReflectedVarResourceAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
{
- const bool bForceModified = (m_reflectedVar->m_propertyType == ePropertyGeomCache);
+ const bool bForceModified = false;
pVariable->SetForceModified(bForceModified);
pVariable->SetDisplayValue(m_reflectedVar->m_path.c_str());
@@ -473,7 +454,7 @@ void ReflectedVarUserAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
//extract the list of custom items from the IVariable user data
IVariable::IGetCustomItems* pGetCustomItems = static_cast (pVariable->GetUserData().value());
- if (pGetCustomItems != 0)
+ if (pGetCustomItems != nullptr)
{
std::vector items;
QString dlgTitle;
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h
index 07bb72413a..9c49f1ae1a 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h
+++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h
@@ -218,20 +218,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
-class EDITOR_CORE_API ReflectedVarAnimationAdapter
- : public ReflectedVarAdapter
-{
-public:
- void SetVariable(IVariable* pVariable) override;
- void SyncReflectedVarToIVar(IVariable* pVariable) override;
- void SyncIVarToReflectedVar(IVariable* pVariable) override;
- CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
-private:
-AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
- QScopedPointer m_reflectedVar;
-AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
-};
-
class EDITOR_CORE_API ReflectedVarResourceAdapter
: public ReflectedVarAdapter
{
diff --git a/Code/Editor/Controls/SplineCtrl.cpp b/Code/Editor/Controls/SplineCtrl.cpp
index 63481d27df..80d30b37ad 100644
--- a/Code/Editor/Controls/SplineCtrl.cpp
+++ b/Code/Editor/Controls/SplineCtrl.cpp
@@ -30,7 +30,7 @@ CSplineCtrl::CSplineCtrl(QWidget* parent)
m_nHitKeyIndex = -1;
m_nKeyDrawRadius = 3;
m_bTracking = false;
- m_pSpline = 0;
+ m_pSpline = nullptr;
m_gridX = 10;
m_gridY = 10;
m_fMinTime = -1;
@@ -40,7 +40,7 @@ CSplineCtrl::CSplineCtrl(QWidget* parent)
m_fTooltipScaleX = 1;
m_fTooltipScaleY = 1;
m_bLockFirstLastKey = false;
- m_pTimelineCtrl = 0;
+ m_pTimelineCtrl = nullptr;
m_bSelectedKeys.reserve(0);
@@ -86,13 +86,13 @@ QPoint CSplineCtrl::KeyToPoint(int nKey)
QPoint CSplineCtrl::TimeToPoint(float time)
{
QPoint point;
- point.setX((time - m_fMinTime) * (m_rcSpline.width() / (m_fMaxTime - m_fMinTime)) + m_rcSpline.left());
+ point.setX(static_cast((time - m_fMinTime) * (m_rcSpline.width() / (m_fMaxTime - m_fMinTime)) + m_rcSpline.left()));
float val = 0;
if (m_pSpline)
{
m_pSpline->InterpolateFloat(time, val);
}
- point.setY((floor((m_fMaxValue - val) * (m_rcSpline.height() / (m_fMaxValue - m_fMinValue)) + 0.5f) + m_rcSpline.top()));
+ point.setY(static_cast((floor((m_fMaxValue - val) * (m_rcSpline.height() / (m_fMaxValue - m_fMinValue)) + 0.5f) + m_rcSpline.top())));
return point;
}
@@ -417,7 +417,7 @@ void CSplineCtrl::SetActiveKey(int nIndex)
}
/////////////////////////////////////////////////////////////////////////////
-void CSplineCtrl::SetSpline(ISplineInterpolator* pSpline, BOOL bRedraw)
+void CSplineCtrl::SetSpline(ISplineInterpolator* pSpline, bool bRedraw)
{
if (pSpline != m_pSpline)
{
@@ -596,7 +596,7 @@ CSplineCtrl::EHitCode CSplineCtrl::HitTest(const QPoint& point)
///////////////////////////////////////////////////////////////////////////////
void CSplineCtrl::StartTracking()
{
- m_bTracking = TRUE;
+ m_bTracking = true;
GetIEditor()->BeginUndo();
@@ -674,7 +674,7 @@ void CSplineCtrl::StopTracking()
GetIEditor()->AcceptUndo("Spline Move");
- m_bTracking = FALSE;
+ m_bTracking = false;
}
//////////////////////////////////////////////////////////////////////////
diff --git a/Code/Editor/Controls/SplineCtrl.h b/Code/Editor/Controls/SplineCtrl.h
index e90fc1820e..ec5b3e52ce 100644
--- a/Code/Editor/Controls/SplineCtrl.h
+++ b/Code/Editor/Controls/SplineCtrl.h
@@ -59,7 +59,7 @@ public:
// Lock value of first and last key to be the same.
void LockFirstAndLastKeys(bool bLock) { m_bLockFirstLastKey = bLock; }
- void SetSpline(ISplineInterpolator* pSpline, BOOL bRedraw = FALSE);
+ void SetSpline(ISplineInterpolator* pSpline, bool bRedraw = false);
ISplineInterpolator* GetSpline();
void SetTimeMarker(float fTime);
diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp
index 2afc3f16aa..f299ce185d 100644
--- a/Code/Editor/Controls/SplineCtrlEx.cpp
+++ b/Code/Editor/Controls/SplineCtrlEx.cpp
@@ -69,8 +69,8 @@ protected:
AbstractSplineWidget* pCtrl = FindControl(m_pCtrl);
m_splineEntries.resize(m_splineEntries.size() + 1);
SplineEntry& entry = m_splineEntries.back();
- ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : 0);
- entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : 0);
+ ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : nullptr);
+ entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : nullptr);
entry.pSpline = pSpline;
const int numKeys = pSpline->GetKeyCount();
@@ -81,10 +81,10 @@ protected:
}
}
- virtual int GetSize() { return sizeof(*this); }
- virtual QString GetDescription() { return "UndoSplineCtrlEx"; };
+ int GetSize() override { return sizeof(*this); }
+ QString GetDescription() override { return "UndoSplineCtrlEx"; };
- virtual void Undo(bool bUndo)
+ void Undo(bool bUndo) override
{
AbstractSplineWidget* pCtrl = FindControl(m_pCtrl);
if (pCtrl)
@@ -104,7 +104,7 @@ protected:
}
}
- virtual void Redo()
+ void Redo() override
{
AbstractSplineWidget* pCtrl = FindControl(m_pCtrl);
if (pCtrl)
@@ -127,14 +127,14 @@ private:
std::vector keySelectionFlags;
_smart_ptr undo;
_smart_ptr redo;
- string id;
+ AZStd::string id;
ISplineInterpolator* pSpline;
};
void SerializeSplines(_smart_ptr SplineEntry::* backup, bool bLoading)
{
AbstractSplineWidget* pCtrl = FindControl(m_pCtrl);
- ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : 0);
+ ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : nullptr);
for (auto it = m_splineEntries.begin(); it != m_splineEntries.end(); ++it)
{
SplineEntry& entry = *it;
@@ -157,19 +157,19 @@ private:
}
public:
- typedef std::list CSplineCtrls;
+ using CSplineCtrls = std::list;
static AbstractSplineWidget* FindControl(AbstractSplineWidget* pCtrl)
{
if (!pCtrl)
{
- return 0;
+ return nullptr;
}
auto iter = std::find(s_activeCtrls.begin(), s_activeCtrls.end(), pCtrl);
if (iter == s_activeCtrls.end())
{
- return 0;
+ return nullptr;
}
return *iter;
@@ -193,10 +193,10 @@ public:
static CSplineCtrls s_activeCtrls;
- virtual bool IsSelectionChanged() const
+ bool IsSelectionChanged() const override
{
AbstractSplineWidget* pCtrl = FindControl(m_pCtrl);
- ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : 0);
+ ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : nullptr);
for (auto it = m_splineEntries.begin(); it != m_splineEntries.end(); ++it)
{
@@ -256,11 +256,11 @@ SplineWidget::~SplineWidget()
AbstractSplineWidget::AbstractSplineWidget()
: m_defaultKeyTangentType(SPLINE_KEY_TANGENT_NONE)
{
- m_pTimelineCtrl = 0;
+ m_pTimelineCtrl = nullptr;
m_totalSplineCount = 0;
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
m_nHitDimension = -1;
m_bHitIncomingHandle = true;
@@ -301,7 +301,7 @@ AbstractSplineWidget::AbstractSplineWidget()
m_boLeftMouseButtonDown = false;
- m_pSplineSet = 0;
+ m_pSplineSet = nullptr;
m_controlAmplitude = false;
@@ -641,7 +641,7 @@ QPoint AbstractSplineWidget::TimeToPoint(float time, ISplineInterpolator* pSplin
//////////////////////////////////////////////////////////////////////////
float AbstractSplineWidget::TimeToXOfs(float x)
{
- return WorldToClient(Vec2(float(x), 0.0f)).x();
+ return static_cast(WorldToClient(Vec2(float(x), 0.0f)).x());
}
//////////////////////////////////////////////////////////////////////////
@@ -832,8 +832,8 @@ void SplineWidget::DrawSpline(QPainter* painter, SSplineInfo& splineInfo, float
int nTotalNumberOfDimensions(0);
int nCurrentDimension(0);
- int left = TimeToXOfs(startTime);//rcClip.left;
- int right = TimeToXOfs(endTime);//rcClip.right;
+ int left = static_cast(TimeToXOfs(startTime));//rcClip.left;
+ int right = static_cast(TimeToXOfs(endTime));//rcClip.right;
QPoint p0 = TimeToPoint(pSpline->GetKeyTime(0), pSpline);
QPoint p1 = TimeToPoint(pSpline->GetKeyTime(pSpline->GetKeyCount() - 1), pSpline);
@@ -898,7 +898,7 @@ void SplineWidget::DrawSpline(QPainter* painter, SSplineInfo& splineInfo, float
if ((x == right && pointsInLine >= 0) || (pointsInLine > 0 && fabs(lineStart.y() + gradient * (pt.x() - lineStart.x()) - pt.y()) > 1.0f))
{
- lineStart = QPoint(pt.x() - 1, lineStart.y() + gradient * (pt.x() - 1 - lineStart.x()));
+ lineStart = QPoint(pt.x() - 1, static_cast(lineStart.y() + gradient * (pt.x() - 1 - lineStart.x())));
path.lineTo(lineStart);
gradient = float(pt.y() - lineStart.y()) / (pt.x() - lineStart.x());
pointsInLine = 1;
@@ -1063,7 +1063,7 @@ void SplineWidget::DrawTimeMarker(QPainter* painter)
float x = TimeToXOfs(m_fTimeMarker);
if (x >= m_rcSpline.left() && x <= m_rcSpline.right() + 1)
{
- painter->drawLine(x, m_rcSpline.top(), x, m_rcSpline.bottom() + 1);
+ painter->drawLine(static_cast(x), m_rcSpline.top(), static_cast(x), m_rcSpline.bottom() + 1);
}
painter->setPen(pOldPen);
}
@@ -1583,7 +1583,7 @@ bool AbstractSplineWidget::IsKeySelected(ISplineInterpolator* pSpline, int nKey,
int AbstractSplineWidget::GetNumSelected()
{
int nSelected = 0;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
if (ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline)
{
@@ -1633,7 +1633,7 @@ void SplineWidget::wheelEvent(QWheelEvent* event)
void SplineWidget::keyPressEvent(QKeyEvent* e)
{
- BOOL bProcessed = false;
+ bool bProcessed = false;
switch (e->key())
{
@@ -1780,7 +1780,7 @@ void AbstractSplineWidget::SetHorizontalExtent([[maybe_unused]] int min, [[maybe
//si.nPage = max(0,m_rcClient.Width() - m_leftOffset*2);
//si.nPage = 1;
//si.nPage = 1;
- SetScrollInfo( SB_HORZ,&si,TRUE );
+ SetScrollInfo( SB_HORZ,&si,true );
*/
}
@@ -1792,7 +1792,7 @@ ISplineInterpolator* AbstractSplineWidget::HitSpline(const QPoint& point)
return m_pHitSpline;
}
- return NULL;
+ return nullptr;
}
//////////////////////////////////////////////////////////////////////////////
@@ -1806,8 +1806,8 @@ AbstractSplineWidget::EHitCode AbstractSplineWidget::HitTest(const QPoint& point
PointToTimeValue(point, time, val);
m_hitCode = HIT_NOTHING;
- m_pHitSpline = NULL;
- m_pHitDetailSpline = NULL;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
m_nHitDimension = -1;
m_bHitIncomingHandle = true;
@@ -1818,7 +1818,7 @@ AbstractSplineWidget::EHitCode AbstractSplineWidget::HitTest(const QPoint& point
}
// For each Spline...
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
ISplineInterpolator* pDetailSpline = m_splines[splineIndex].pDetailSpline;
@@ -1856,7 +1856,7 @@ AbstractSplineWidget::EHitCode AbstractSplineWidget::HitTest(const QPoint& point
// Check tangent handles first.
{
QPoint incomingHandlePt, outgoingHandlePt, pt;
- if (GetTangentHandlePts(incomingHandlePt, pt, outgoingHandlePt, splineIndex, i, nCurrentDimension))
+ if (GetTangentHandlePts(incomingHandlePt, pt, outgoingHandlePt, static_cast(splineIndex), static_cast(i), nCurrentDimension))
{
// For the incoming handle
if (abs(incomingHandlePt.x() - point.x()) < 4 && abs(incomingHandlePt.y() - point.y()) < 4)
@@ -1968,12 +1968,12 @@ void AbstractSplineWidget::StopTracking()
void AbstractSplineWidget::ScaleAmplitudeKeys(float time, float startValue, float offset)
{
//TODO: Test it in the facial animation pane and fix it...
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
m_nHitDimension = -1;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2071,13 +2071,13 @@ void AbstractSplineWidget::TimeScaleKeys(float time, float startTime, float endT
float timeScaleC = endTime - startTime * timeScaleM;
// Loop through all keys that are selected.
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
float affectedRangeMin = FLT_MAX;
float affectedRangeMax = -FLT_MAX;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2145,8 +2145,8 @@ void AbstractSplineWidget::TimeScaleKeys(float time, float startTime, float endT
}
}
- int rangeMin = TimeToXOfs(affectedRangeMin);
- int rangeMax = TimeToXOfs(affectedRangeMax);
+ int rangeMin = static_cast(TimeToXOfs(affectedRangeMin));
+ int rangeMax = static_cast(TimeToXOfs(affectedRangeMax));
if (m_timeRange.start == affectedRangeMin)
{
@@ -2179,12 +2179,12 @@ void AbstractSplineWidget::ValueScaleKeys(float startValue, float endValue)
}
// Loop through all keys that are selected.
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
m_nHitDimension = -1;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2212,8 +2212,8 @@ void AbstractSplineWidget::ValueScaleKeys(float startValue, float endValue)
//////////////////////////////////////////////////////////////////////////
void AbstractSplineWidget::MoveSelectedKeys(Vec2 offset, bool copyKeys)
{
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
m_nHitDimension = -1;
@@ -2223,7 +2223,7 @@ void AbstractSplineWidget::MoveSelectedKeys(Vec2 offset, bool copyKeys)
}
// For each spline...
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2275,8 +2275,8 @@ void AbstractSplineWidget::RemoveKey(ISplineInterpolator* pSpline, int nKey)
SendNotifyEvent(SPLN_BEFORE_CHANGE);
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
if (nKey != -1)
{
@@ -2294,11 +2294,11 @@ void AbstractSplineWidget::RemoveSelectedKeys()
SendNotifyEvent(SPLN_BEFORE_CHANGE);
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2338,7 +2338,7 @@ void AbstractSplineWidget::RemoveSelectedKeyTimesImpl()
StoreUndo();
SendNotifyEvent(SPLN_BEFORE_CHANGE);
- for (int splineIndex = 0, end = m_splines.size(); splineIndex < end; ++splineIndex)
+ for (size_t splineIndex = 0, end = m_splines.size(); splineIndex < end; ++splineIndex)
{
std::vector::iterator itTime = m_keyTimes.begin(), endTime = m_keyTimes.end();
for (int keyIndex = 0, endIndex = m_splines[splineIndex].pSpline->GetKeyCount(); keyIndex < endIndex; )
@@ -2376,9 +2376,9 @@ void AbstractSplineWidget::RedrawWindowAroundMarker()
{
UpdateKeyTimes();
std::vector::iterator itKeyTime = std::lower_bound(m_keyTimes.begin(), m_keyTimes.end(), KeyTime(m_fTimeMarker, 0));
- int keyTimeIndex = (itKeyTime != m_keyTimes.end() ? itKeyTime - m_keyTimes.begin() : m_keyTimes.size());
- int redrawRangeStart = (keyTimeIndex >= 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex - 2].time) : m_rcSpline.left());
- int redrawRangeEnd = (keyTimeIndex < int(m_keyTimes.size()) - 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time) : m_rcSpline.right() + 1);
+ size_t keyTimeIndex = (itKeyTime != m_keyTimes.end() ? itKeyTime - m_keyTimes.begin() : m_keyTimes.size());
+ int redrawRangeStart = (keyTimeIndex >= 2 ? static_cast(TimeToXOfs(m_keyTimes[keyTimeIndex - 2].time)) : m_rcSpline.left());
+ int redrawRangeEnd = (keyTimeIndex < m_keyTimes.size() - 2 ? static_cast(TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time)) : m_rcSpline.right() + 1);
QRect rc(QPoint(redrawRangeStart, m_rcSpline.top()), QPoint(redrawRangeEnd, m_rcSpline.bottom() + 1) - QPoint(1, 1));
rc = rc.normalized().intersected(m_rcSpline);
@@ -2478,7 +2478,7 @@ void AbstractSplineWidget::ClearSelection()
{
ConditionalStoreUndo();
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2521,7 +2521,7 @@ void AbstractSplineWidget::StoreUndo()
if (CUndo::IsRecording() && !m_pCurrentUndo)
{
std::vector splines(m_splines.size());
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
splines[splineIndex] = m_splines[splineIndex].pSpline;
}
@@ -2558,13 +2558,13 @@ public:
};
void AbstractSplineWidget::DuplicateSelectedKeys()
{
- m_pHitSpline = 0;
- m_pHitDetailSpline = 0;
+ m_pHitSpline = nullptr;
+ m_pHitDetailSpline = nullptr;
m_nHitKeyIndex = -1;
- typedef std::vector KeysToAddContainer;
+ using KeysToAddContainer = std::vector;
KeysToAddContainer keysToInsert;
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2600,7 +2600,7 @@ void AbstractSplineWidget::ZeroAll()
{
GetIEditor()->BeginUndo();
- typedef std::vector SplineContainer;
+ using SplineContainer = std::vector;
SplineContainer splines;
for (int splineIndex = 0; splineIndex < int(m_splines.size()); ++splineIndex)
{
@@ -2632,7 +2632,7 @@ void AbstractSplineWidget::KeyAll()
{
GetIEditor()->BeginUndo();
- typedef std::vector SplineContainer;
+ using SplineContainer = std::vector;
SplineContainer splines;
for (int splineIndex = 0; splineIndex < int(m_splines.size()); ++splineIndex)
{
@@ -2664,7 +2664,7 @@ void AbstractSplineWidget::KeyAll()
//////////////////////////////////////////////////////////////////////////
void AbstractSplineWidget::SelectAll()
{
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -2815,7 +2815,7 @@ void AbstractSplineWidget::SelectRectangle(const QRect& rc, bool bSelect)
{
std::swap(t0, t1);
}
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
ISplineInterpolator* pDetailSpline = m_splines[splineIndex].pDetailSpline;
@@ -3031,7 +3031,7 @@ void AbstractSplineWidget::ModifySelectedKeysFlags(int nRemoveFlags, int nAddFla
SendNotifyEvent(SPLN_BEFORE_CHANGE);
- for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
+ for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -3188,7 +3188,7 @@ void AbstractSplineWidget::GotoNextKey(bool previousKey)
{
bool boFoundTheSelectedKey(false);
- for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
+ for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
for (int i = 0; i < pSpline->GetKeyCount(); i++)
@@ -3230,7 +3230,7 @@ void AbstractSplineWidget::GotoNextKey(bool previousKey)
}
else
{
- for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
+ for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
@@ -3281,7 +3281,7 @@ void AbstractSplineWidget::RemoveAllKeysButThis()
{
std::vector keys;
- for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
+ for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex)
{
ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline;
diff --git a/Code/Editor/Controls/SplineCtrlEx.h b/Code/Editor/Controls/SplineCtrlEx.h
index 8592febf88..711cbcf8d4 100644
--- a/Code/Editor/Controls/SplineCtrlEx.h
+++ b/Code/Editor/Controls/SplineCtrlEx.h
@@ -53,8 +53,8 @@ class QRubberBand;
class ISplineSet
{
public:
- virtual ISplineInterpolator* GetSplineFromID(const string& id) = 0;
- virtual string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
+ virtual ISplineInterpolator* GetSplineFromID(const AZStd::string& id) = 0;
+ virtual AZStd::string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
virtual int GetSplineCount() const = 0;
virtual int GetKeyCountAtTime(float time, float threshold) const = 0;
};
@@ -98,7 +98,7 @@ public:
void AddSpline(ISplineInterpolator * pSpline, ISplineInterpolator * pDetailSpline, QColor anColorArray[4]);
void RemoveSpline(ISplineInterpolator* pSpline);
void RemoveAllSplines();
- int GetSplineCount() const { return m_splines.size(); }
+ int GetSplineCount() const { return static_cast(m_splines.size()); }
ISplineInterpolator* GetSpline(int nIndex) const { return m_splines[nIndex].pSpline; }
void SetTimeMarker(float fTime);
diff --git a/Code/Editor/Controls/TextEditorCtrl.cpp b/Code/Editor/Controls/TextEditorCtrl.cpp
index 5961c9d9a3..c372138d80 100644
--- a/Code/Editor/Controls/TextEditorCtrl.cpp
+++ b/Code/Editor/Controls/TextEditorCtrl.cpp
@@ -53,7 +53,7 @@ void CTextEditorCtrl::LoadFile(const QString& sFileName)
size_t length = file.GetLength();
QByteArray text;
- text.resize(length);
+ text.resize(static_cast(length));
file.ReadRaw(text.data(), length);
setPlainText(text);
diff --git a/Code/Editor/Controls/TimelineCtrl.cpp b/Code/Editor/Controls/TimelineCtrl.cpp
index d1590c5346..8159084784 100644
--- a/Code/Editor/Controls/TimelineCtrl.cpp
+++ b/Code/Editor/Controls/TimelineCtrl.cpp
@@ -25,9 +25,9 @@ static const QColor ltgrayCol = QColor(110, 110, 110);
QColor InterpolateColor(const QColor& c1, const QColor& c2, float fraction)
{
- const int r = (c2.red() - c1.red()) * fraction + c1.red();
- const int g = (c2.green() - c1.green()) * fraction + c1.green();
- const int b = (c2.blue() - c1.blue()) * fraction + c1.blue();
+ const int r = static_cast(static_cast(c2.red() - c1.red()) * fraction + c1.red());
+ const int g = static_cast(static_cast(c2.green() - c1.green()) * fraction + c1.green());
+ const int b = static_cast(static_cast(c2.blue() - c1.blue()) * fraction + c1.blue());
return QColor(r, g, b);
}
@@ -58,7 +58,7 @@ TimelineWidget::TimelineWidget(QWidget* parent /* = nullptr */)
m_bIgnoreSetTime = false;
- m_pKeyTimeSet = 0;
+ m_pKeyTimeSet = nullptr;
m_markerStyle = MARKER_STYLE_SECONDS;
m_fps = 30.0f;
@@ -120,7 +120,7 @@ float TimelineWidget::SnapTime(float time)
{
double t = floor((double)time * m_ticksStep + 0.5);
t = t / m_ticksStep;
- return t;
+ return static_cast(t);
}
//////////////////////////////////////////////////////////////////////////
@@ -153,10 +153,10 @@ void TimelineWidget::DrawTicks(QPainter* painter)
painter->setPen(redpen);
int x = TimeToClient(m_fTimeMarker);
painter->setBrush(Qt::NoBrush);
- painter->drawRect(QRect(QPoint(x - 3, rc.top()), QPoint(x + 2, rc.bottom())));
+ painter->drawRect(QRect(QPoint(x - 3, static_cast(rc.top())), QPoint(x + 2, static_cast(rc.bottom()))));
painter->setPen(redpen);
- painter->drawLine(x, rc.top(), x, rc.bottom());
+ painter->drawLine(x, static_cast(rc.top()), x, static_cast(rc.bottom()));
painter->setBrush(Qt::NoBrush);
// Draw vertical line showing current time.
@@ -190,7 +190,7 @@ void TimelineWidget::DrawTicks(QPainter* painter)
float keyTime = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f);
int x2 = TimeToClient(keyTime);
- painter->drawRect(QRect(QPoint(x2 - 1, rc.top()), QPoint(x2 + 2, rc.bottom())));
+ painter->drawRect(QRect(QPoint(x2 - 1, static_cast(rc.top())), QPoint(x2 + 2, static_cast(rc.bottom()))));
}
painter->setPen(pOldPen);
diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp
index 3c27c25c9a..3724993604 100644
--- a/Code/Editor/Core/LevelEditorMenuHandler.cpp
+++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp
@@ -80,12 +80,12 @@ namespace
, m_trigger(trigger)
{}
- virtual ~EditorListener()
+ ~EditorListener() override
{
GetIEditor()->UnregisterNotifyListener(this);
}
- void OnEditorNotifyEvent(EEditorNotifyEvent event)
+ void OnEditorNotifyEvent(EEditorNotifyEvent event) override
{
m_trigger(event);
}
@@ -544,12 +544,12 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
auto snapMenu = modifyMenu.AddMenu(tr("Snap"));
- snapMenu.AddAction(ID_SNAPANGLE);
+ snapMenu.AddAction(AzToolsFramework::SnapAngle);
auto transformModeMenu = modifyMenu.AddMenu(tr("Transform Mode"));
- transformModeMenu.AddAction(ID_EDITMODE_MOVE);
- transformModeMenu.AddAction(ID_EDITMODE_ROTATE);
- transformModeMenu.AddAction(ID_EDITMODE_SCALE);
+ transformModeMenu.AddAction(AzToolsFramework::EditModeMove);
+ transformModeMenu.AddAction(AzToolsFramework::EditModeRotate);
+ transformModeMenu.AddAction(AzToolsFramework::EditModeScale);
editMenu.AddSeparator();
diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp
index 5a4763d8e8..dd784ce10d 100644
--- a/Code/Editor/Core/QtEditorApplication.cpp
+++ b/Code/Editor/Core/QtEditorApplication.cpp
@@ -206,11 +206,8 @@ namespace
static void LogToDebug([[maybe_unused]] QtMsgType Type, [[maybe_unused]] const QMessageLogContext& Context, const QString& message)
{
-#if defined(WIN32) || defined(WIN64)
- OutputDebugStringW(L"Qt: ");
- OutputDebugStringW(reinterpret_cast(message.utf16()));
- OutputDebugStringW(L"\n");
-#endif
+ AZ::Debug::Platform::OutputToDebugger("Qt", message.toUtf8().data());
+ AZ::Debug::Platform::OutputToDebugger(nullptr, "\n");
}
}
@@ -423,7 +420,7 @@ namespace Editor
{
UINT rawInputSize;
const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
- GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize);
+ GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &rawInputSize, rawInputHeaderSize);
AZStd::array rawInputBytesArray;
LPBYTE rawInputBytes = rawInputBytesArray.data();
diff --git a/Code/Editor/Core/Tests/test_Main.cpp b/Code/Editor/Core/Tests/test_Main.cpp
index c0772753c6..3d3e286f18 100644
--- a/Code/Editor/Core/Tests/test_Main.cpp
+++ b/Code/Editor/Core/Tests/test_Main.cpp
@@ -26,7 +26,7 @@ class EditorCoreTestEnvironment
public:
AZ_TEST_CLASS_ALLOCATOR(EditorCoreTestEnvironment);
- virtual ~EditorCoreTestEnvironment()
+ ~EditorCoreTestEnvironment() override
{
}
@@ -52,7 +52,7 @@ protected:
}
private:
- AZ::AllocatorScope