@@ -62164,7 +62164,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
|
||||
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME">
|
||||
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME</source>
|
||||
<comment>Simple Type: EntityID C++ Type: const EntityId&</comment>
|
||||
<translation type="unfinished">Entity</translation>
|
||||
<translation type="unfinished">EntityID</translation>
|
||||
</message>
|
||||
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP">
|
||||
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP</source>
|
||||
@@ -62202,7 +62202,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
|
||||
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME">
|
||||
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME</source>
|
||||
<comment>Simple Type: EntityID C++ Type: const EntityId&</comment>
|
||||
<translation type="unfinished">Entity</translation>
|
||||
<translation type="unfinished">EntityId</translation>
|
||||
</message>
|
||||
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP">
|
||||
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP</source>
|
||||
@@ -81852,7 +81852,7 @@ The element is removed from its current parent and added as a child of the new p
|
||||
<message id="HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME">
|
||||
<source>HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME</source>
|
||||
<comment>Simple Type: EntityID C++ Type: const EntityId&</comment>
|
||||
<translation type="unfinished">Entity</translation>
|
||||
<translation type="unfinished">EntityID</translation>
|
||||
</message>
|
||||
<message id="HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP">
|
||||
<source>HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP</source>
|
||||
@@ -89198,7 +89198,7 @@ The element is removed from its current parent and added as a child of the new p
|
||||
<message id="HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME">
|
||||
<source>HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME</source>
|
||||
<comment>Simple Type: EntityID C++ Type: const EntityId&</comment>
|
||||
<translation type="unfinished">Entity</translation>
|
||||
<translation type="unfinished">EntityID</translation>
|
||||
</message>
|
||||
<message id="HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP">
|
||||
<source>HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP</source>
|
||||
@@ -89236,7 +89236,7 @@ The element is removed from its current parent and added as a child of the new p
|
||||
<message id="HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME">
|
||||
<source>HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME</source>
|
||||
<comment>Simple Type: EntityID C++ Type: const EntityId&</comment>
|
||||
<translation type="unfinished">Entity</translation>
|
||||
<translation type="unfinished">EntityID</translation>
|
||||
</message>
|
||||
<message id="HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP">
|
||||
<source>HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP</source>
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<Class name="float" field="ProjectorNearPlane" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}" value="0.0000000" specializationTypeId="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
<Class name="AzFramework::SimpleAssetReference<LmbrCentral::TextureAsset>" field="ProjectorTexture" type="{68E92460-5C0C-4031-9620-6F1A08763243}" version="1" specializationTypeId="{68E92460-5C0C-4031-9620-6F1A08763243}">
|
||||
<Class name="SimpleAssetReferenceBase" field="BaseClass1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1" specializationTypeId="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
|
||||
<Class name="AZStd::string" field="AssetPath" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="engineassets/textures/defaults/spot_default.dds" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="AZStd::string" field="AssetPath" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AzFramework::SimpleAssetReference<LmbrCentral::MaterialAsset>" field="ProjectorMaterial" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1" specializationTypeId="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}">
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf441215a769562f88aa20711aee68dadcbf02597d1e2270547055e8e6aec6a3
|
||||
size 77
|
||||
@@ -1,178 +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
|
||||
--
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
|
||||
|
||||
GeomCache =
|
||||
{
|
||||
Properties = {
|
||||
geomcacheFile = "EngineAssets/GeomCaches/defaultGeomCache.cax",
|
||||
bPlaying = 0,
|
||||
fStartTime = 0,
|
||||
bLooping = 0,
|
||||
objectStandIn = "",
|
||||
materialStandInMaterial = "",
|
||||
objectFirstFrameStandIn = "",
|
||||
materialFirstFrameStandInMaterial = "",
|
||||
objectLastFrameStandIn = "",
|
||||
materialLastFrameStandInMaterial = "",
|
||||
fStandInDistance = 0,
|
||||
fStreamInDistance = 0,
|
||||
Physics = {
|
||||
bPhysicalize = 0,
|
||||
}
|
||||
},
|
||||
|
||||
Editor={
|
||||
Icon = "animobject.bmp",
|
||||
IconOnTop = 1,
|
||||
},
|
||||
|
||||
bPlaying = 0,
|
||||
currentTime = 0,
|
||||
precacheTime = 0,
|
||||
bPrecachedOutputTriggered = false,
|
||||
}
|
||||
|
||||
function GeomCache:OnLoad(table)
|
||||
self.currentTime = table.currentTime;
|
||||
end
|
||||
|
||||
function GeomCache:OnSave(table)
|
||||
table.currentTime = self.currentTime;
|
||||
end
|
||||
|
||||
function GeomCache:OnSpawn()
|
||||
self.currentTime = self.Properties.fStartTime;
|
||||
self:SetFromProperties();
|
||||
end
|
||||
|
||||
function GeomCache:OnReset()
|
||||
self.currentTime = self.Properties.fStartTime;
|
||||
self.bPrecachedOutputTriggered = true;
|
||||
self:SetFromProperties();
|
||||
end
|
||||
|
||||
function GeomCache:SetFromProperties()
|
||||
local Properties = self.Properties;
|
||||
|
||||
if (Properties.geomcacheFile == "") then
|
||||
do return end;
|
||||
end
|
||||
|
||||
self:LoadGeomCache(0, Properties.geomcacheFile);
|
||||
|
||||
self.bPlaying = Properties.bPlaying;
|
||||
if (self.bPlaying == 0) then
|
||||
self.currentTime = Properties.fStartTime;
|
||||
end
|
||||
|
||||
self:SetGeomCachePlaybackTime(self.currentTime);
|
||||
self:SetGeomCacheParams(Properties.bLooping, Properties.objectStandIn, Properties.materialStandInMaterial, Properties.objectFirstFrameStandIn,
|
||||
Properties.materialFirstFrameStandInMaterial, Properties.objectLastFrameStandIn, Properties.materialLastFrameStandInMaterial,
|
||||
Properties.fStandInDistance, Properties.fStreamInDistance);
|
||||
self:SetGeomCacheStreaming(false, 0);
|
||||
|
||||
if (Properties.Physics.bPhysicalize == 1) then
|
||||
local tempPhysParams = EntityCommon.TempPhysParams;
|
||||
self:Physicalize(0, PE_ARTICULATED, tempPhysParams);
|
||||
end
|
||||
|
||||
self:Activate(1);
|
||||
end
|
||||
|
||||
function GeomCache:PhysicalizeThis()
|
||||
local Physics = self.Properties.Physics;
|
||||
EntityCommon.PhysicalizeRigid(self, 0, Physics, false);
|
||||
end
|
||||
|
||||
function GeomCache:OnUpdate(dt)
|
||||
if (self.bPlaying == 1) then
|
||||
self:SetGeomCachePlaybackTime(self.currentTime);
|
||||
end
|
||||
|
||||
if (self:IsGeomCacheStreaming() and not self.bPrecachedOutputTriggered) then
|
||||
local precachedTime = self:GetGeomCachePrecachedTime();
|
||||
if (precachedTime >= self.precacheTime) then
|
||||
self:ActivateOutput("Precached", true);
|
||||
self.bPrecachedOutputTriggered = true;
|
||||
end
|
||||
end
|
||||
|
||||
if (self.bPlaying == 1) then
|
||||
self.currentTime = self.currentTime + dt;
|
||||
end
|
||||
end
|
||||
|
||||
function GeomCache:OnPropertyChange()
|
||||
self:SetFromProperties();
|
||||
end
|
||||
|
||||
function GeomCache:Event_Start(sender, val)
|
||||
self.bPlaying = 1;
|
||||
end
|
||||
|
||||
function GeomCache:Event_Stop(sender, value)
|
||||
self.bPlaying = 0;
|
||||
end
|
||||
|
||||
function GeomCache:Event_SetTime(sender, value)
|
||||
self.currentTime = value;
|
||||
end
|
||||
|
||||
function GeomCache:Event_StartStreaming(sender, value)
|
||||
self.bPrecachedOutputTriggered = false;
|
||||
self:SetGeomCacheStreaming(true, self.currentTime);
|
||||
end
|
||||
|
||||
function GeomCache:Event_StopStreaming(sender, value)
|
||||
self:SetGeomCacheStreaming(false, 0);
|
||||
end
|
||||
|
||||
function GeomCache:Event_PrecacheTime(sender, value)
|
||||
self.precacheTime = value;
|
||||
end
|
||||
|
||||
function GeomCache:Event_Hide(sender, value)
|
||||
self:Hide(1);
|
||||
end
|
||||
|
||||
function GeomCache:Event_Unhide(sender, value)
|
||||
self:Hide(0);
|
||||
end
|
||||
|
||||
function GeomCache:Event_StopDrawing(sender, value)
|
||||
self:SetGeomCacheDrawing(false);
|
||||
end
|
||||
|
||||
function GeomCache:Event_StartDrawing(sender, value)
|
||||
self:SetGeomCacheDrawing(true);
|
||||
end
|
||||
|
||||
GeomCache.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Start = { GeomCache.Event_Start, "any" },
|
||||
Stop = { GeomCache.Event_Stop, "any" },
|
||||
SetTime = { GeomCache.Event_SetTime, "float" },
|
||||
StartStreaming = { GeomCache.Event_StartStreaming, "any" },
|
||||
StopStreaming = { GeomCache.Event_StopStreaming, "any" },
|
||||
PrecacheTime = { GeomCache.Event_PrecacheTime, "float" },
|
||||
Hide = { GeomCache.Event_Hide, "any" },
|
||||
Unhide = { GeomCache.Event_Unhide, "any" },
|
||||
StopDrawing = { GeomCache.Event_StopDrawing, "any" },
|
||||
StartDrawing = { GeomCache.Event_StartDrawing, "any" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Precached = "bool",
|
||||
},
|
||||
}
|
||||
@@ -8,11 +8,12 @@
|
||||
|
||||
if(NOT PROJECT_NAME)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
include(cmake/CompilerSettings.cmake)
|
||||
project(AutomatedTesting
|
||||
LANGUAGES C CXX
|
||||
VERSION 1.0.0.0
|
||||
)
|
||||
include(EngineFinder.cmake OPTIONAL)
|
||||
include(cmake/EngineFinder.cmake OPTIONAL)
|
||||
find_package(o3de REQUIRED)
|
||||
o3de_initialize()
|
||||
else()
|
||||
|
||||
@@ -54,6 +54,7 @@ set(ENABLED_GEMS
|
||||
AWSMetrics
|
||||
PrefabBuilder
|
||||
AudioSystem
|
||||
Terrain
|
||||
Profiler
|
||||
Multiplayer
|
||||
)
|
||||
|
||||
+54
@@ -14,6 +14,7 @@ from datetime import datetime
|
||||
import ly_test_tools.log.log_monitor
|
||||
|
||||
from AWS.common import constants
|
||||
from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
|
||||
from .aws_metrics_custom_thread import AWSMetricsThread
|
||||
|
||||
# fixture imports
|
||||
@@ -200,6 +201,59 @@ class TestAWSMetricsWindows(object):
|
||||
for thread in operational_threads:
|
||||
thread.join()
|
||||
|
||||
@pytest.mark.parametrize('level', ['AWS/Metrics'])
|
||||
def test_realtime_and_batch_analytics_no_global_accountid(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
aws_utils: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
aws_metrics_utils: pytest.fixture):
|
||||
"""
|
||||
Verify that the metrics events are sent to CloudWatch and S3 for analytics.
|
||||
"""
|
||||
# Remove top-level account ID from resource mappings
|
||||
resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
|
||||
# Start Kinesis analytics application on a separate thread to avoid blocking the test.
|
||||
kinesis_analytics_application_thread = AWSMetricsThread(target=update_kinesis_analytics_application_status,
|
||||
args=(aws_metrics_utils, resource_mappings, True))
|
||||
kinesis_analytics_application_thread.start()
|
||||
|
||||
log_monitor = setup(launcher, asset_processor)
|
||||
|
||||
# Kinesis analytics application needs to be in the running state before we start the game launcher.
|
||||
kinesis_analytics_application_thread.join()
|
||||
launcher.args = ['+LoadLevel', level]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
start_time = datetime.utcnow()
|
||||
with launcher.start(launch_ap=False):
|
||||
monitor_metrics_submission(log_monitor)
|
||||
|
||||
# Verify that real-time analytics metrics are delivered to CloudWatch.
|
||||
aws_metrics_utils.verify_cloud_watch_delivery(
|
||||
AWS_METRICS_FEATURE_NAME,
|
||||
'TotalLogins',
|
||||
[],
|
||||
start_time)
|
||||
logger.info('Real-time metrics are sent to CloudWatch.')
|
||||
|
||||
# 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)))
|
||||
operational_threads.append(
|
||||
AWSMetricsThread(target=verify_operational_metrics,
|
||||
args=(aws_metrics_utils, resource_mappings, 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 operational_threads:
|
||||
thread.join()
|
||||
|
||||
@pytest.mark.parametrize('level', ['AWS/Metrics'])
|
||||
def test_unauthorized_user_request_rejected(self,
|
||||
level: str,
|
||||
|
||||
+36
@@ -12,6 +12,7 @@ import pytest
|
||||
import ly_test_tools.log.log_monitor
|
||||
|
||||
from AWS.common import constants
|
||||
from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
|
||||
|
||||
# fixture imports
|
||||
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
|
||||
@@ -70,6 +71,41 @@ class TestAWSClientAuthWindows(object):
|
||||
halt_on_unexpected=True,
|
||||
)
|
||||
assert result, 'Anonymous credentials fetched successfully.'
|
||||
|
||||
@pytest.mark.parametrize('level', ['AWS/ClientAuth'])
|
||||
def test_anonymous_credentials_no_global_accountid(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
asset_processor: pytest.fixture
|
||||
):
|
||||
"""
|
||||
Test to verify AWS Cognito Identity pool anonymous authorization.
|
||||
|
||||
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.
|
||||
"""
|
||||
# Remove top-level account ID from resource mappings
|
||||
resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
|
||||
|
||||
asset_processor.start()
|
||||
asset_processor.wait_for_idle()
|
||||
|
||||
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]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
|
||||
with launcher.start(launch_ap=False):
|
||||
result = log_monitor.monitor_log_for_lines(
|
||||
expected_lines=['(Script) - Success anonymous credentials'],
|
||||
unexpected_lines=['(Script) - Fail anonymous credentials'],
|
||||
halt_on_unexpected=True,
|
||||
)
|
||||
assert result, 'Anonymous credentials fetched successfully.'
|
||||
|
||||
def test_password_signin_credentials(self,
|
||||
launcher: pytest.fixture,
|
||||
|
||||
@@ -18,6 +18,7 @@ import ly_test_tools.environment.process_utils as process_utils
|
||||
import ly_test_tools.o3de.asset_processor_utils as asset_processor_utils
|
||||
|
||||
from AWS.common import constants
|
||||
from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
|
||||
|
||||
# fixture imports
|
||||
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
|
||||
@@ -141,3 +142,51 @@ class TestAWSCoreAWSResourceInteraction(object):
|
||||
'The expected file wasn\'t successfully downloaded.'
|
||||
# clean up the file directories.
|
||||
shutil.rmtree(s3_download_dir)
|
||||
|
||||
@pytest.mark.parametrize('expected_lines', [
|
||||
['(Script) - [S3] Head object request is done',
|
||||
'(Script) - [S3] Head object success: Object example.txt is found.',
|
||||
'(Script) - [S3] Get object success: Object example.txt is downloaded.',
|
||||
'(Script) - [Lambda] Completed Invoke',
|
||||
'(Script) - [Lambda] Invoke success: {"statusCode": 200, "body": {}}',
|
||||
'(Script) - [DynamoDB] Results finished']])
|
||||
@pytest.mark.parametrize('unexpected_lines', [
|
||||
['(Script) - [S3] Head object error: No response body.',
|
||||
'(Script) - [S3] Get object error: Request validation failed, output file directory doesn\'t exist.',
|
||||
'(Script) - Request validation failed, output file miss full path.',
|
||||
'(Script) - ']])
|
||||
def test_scripting_behavior_no_global_accountid(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
aws_utils: pytest.fixture,
|
||||
expected_lines: typing.List[str],
|
||||
unexpected_lines: typing.List[str]):
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
|
||||
log_monitor, s3_download_dir = setup(launcher, asset_processor)
|
||||
write_test_data_to_dynamodb_table(resource_mappings, aws_utils)
|
||||
|
||||
launcher.args = ['+LoadLevel', level]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
|
||||
with launcher.start(launch_ap=False):
|
||||
result = log_monitor.monitor_log_for_lines(
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
halt_on_unexpected=True
|
||||
)
|
||||
|
||||
assert result, "Expected lines weren't found."
|
||||
|
||||
assert os.path.exists(os.path.join(s3_download_dir, 'output.txt')), \
|
||||
'The expected file wasn\'t successfully downloaded.'
|
||||
# clean up the file directories.
|
||||
shutil.rmtree(s3_download_dir)
|
||||
|
||||
@@ -102,3 +102,17 @@ class ResourceMappings:
|
||||
|
||||
def get_resource_name_id(self, resource_key: str):
|
||||
return self._resource_mappings[AWS_RESOURCE_MAPPINGS_KEY][resource_key]['Name/ID']
|
||||
|
||||
def clear_select_keys(self, resource_keys=None) -> None:
|
||||
"""
|
||||
Clears values from select resource mapping keys.
|
||||
:param resource_keys: list of keys to clear out
|
||||
"""
|
||||
with open(self._resource_mapping_file_path) as file_content:
|
||||
resource_mappings = json.load(file_content)
|
||||
|
||||
for key in resource_keys:
|
||||
resource_mappings[key] = ''
|
||||
|
||||
with open(self._resource_mapping_file_path, 'w') as file_content:
|
||||
json.dump(resource_mappings, file_content, indent=4)
|
||||
@@ -41,6 +41,10 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C36525661")
|
||||
class AtomEditorComponents_EntityReferenceAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_EntityReferenceAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078121")
|
||||
class AtomEditorComponents_ExposureControlAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_ExposureControlAdded as test_module
|
||||
@@ -57,10 +61,18 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_HDRColorGradingAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_HDRColorGradingAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078116")
|
||||
class AtomEditorComponents_HDRiSkyboxAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_HDRiSkyboxAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078117")
|
||||
class AtomEditorComponents_LightAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C36525662")
|
||||
class AtomEditorComponents_LookModificationAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_LookModificationAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078123")
|
||||
class AtomEditorComponents_MaterialAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_MaterialAdded as test_module
|
||||
@@ -98,5 +110,9 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C36525666")
|
||||
class AtomEditorComponents_SSAOAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_SSAOAdded as test_module
|
||||
|
||||
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
|
||||
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
|
||||
|
||||
@@ -172,8 +172,7 @@ def create_basic_atom_level(level_name):
|
||||
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_path = os.path.join("LightingPresets", "default_iblskyboxcm.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)
|
||||
|
||||
@@ -57,11 +57,13 @@ class AtomComponentProperties:
|
||||
def camera(property: str = 'name') -> str:
|
||||
"""
|
||||
Camera component properties.
|
||||
- 'Field of view': Sets the value for the camera's FOV (Field of View) in degrees, i.e. 60.0
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Camera',
|
||||
'Field of view': 'Controller|Configuration|Field of view'
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@@ -202,11 +204,13 @@ class AtomComponentProperties:
|
||||
def grid(property: str = 'name') -> str:
|
||||
"""
|
||||
Grid component properties.
|
||||
- 'Secondary Grid Spacing': The spacing value for the secondary grid, i.e. 1.0
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Grid',
|
||||
'Secondary Grid Spacing': 'Controller|Configuration|Secondary Grid Spacing',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@@ -231,11 +235,13 @@ class AtomComponentProperties:
|
||||
def hdri_skybox(property: str = 'name') -> str:
|
||||
"""
|
||||
HDRi Skybox component properties.
|
||||
- 'Cubemap Texture': Asset.id for the cubemap texture to set.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'HDRi Skybox',
|
||||
'Cubemap Texture': 'Controller|Configuration|Cubemap Texture',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@@ -259,12 +265,16 @@ class AtomComponentProperties:
|
||||
Look Modification component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
- 'Enable look modification' Toggle active state of the component True/False
|
||||
- 'Color Grading LUT' Asset.id for the LUT used for affecting level look.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Look Modification',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
'Enable look modification': 'Controller|Configuration|Enable look modification',
|
||||
'Color Grading LUT': 'Controller|Configuration|Color Grading LUT',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@@ -274,12 +284,14 @@ class AtomComponentProperties:
|
||||
Material component properties. Requires one of Actor OR Mesh component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Only one of these is required at a time for this component.\n
|
||||
- 'Material Asset': the material Asset.id of the material.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Material',
|
||||
'requires': [AtomComponentProperties.actor(), AtomComponentProperties.mesh()],
|
||||
'Material Asset': 'Default Material|Material Asset',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:954d7d0df47c840a24e313893800eb3126d0c0d47c3380926776b51833778db7
|
||||
oid sha256:aee1fd4d5264e5ef1676b507409ce70af6358cf1ff368d9aeb17f7b2597dfbca
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e81c19128f42ba362a2d5f3ccf159dfbc942d67ceeb1ac8c21f295a6fd9d2ce5
|
||||
oid sha256:d4787cdafbcc2fe71c1cb3f1da53a249db839a9df539a9e88be43ccd6d8e4d6a
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5e20801213e065b6ea8c95ede81c23faa9b6dc70a2002dc5bced293e1bed989f
|
||||
oid sha256:5fac5bf41c9b16b6fbd762868e5cf514376af92d6ef7ebb9e819f024f1a3e1a7
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e250f812e594e5152bf2d6f23caa8b53b78276bfdf344d7a8d355dd96cb995c0
|
||||
oid sha256:7a23969670499524725535e8be7428b55b6f3e887cc24e2e903f7ea821a6d1a5
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95be359041f8291c74b335297a4dfe9902a180510f24a181b15e1a5ba4d3b024
|
||||
oid sha256:2f1f4d8865c56ed7f96f339c39e5feb4e0dbc6c6a8b4a7843b4166381b06b00d
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:07e09d3eb5bf0cee3d9b3752aaad40f3ead1dcc5ddd837a6226fadde55d57274
|
||||
oid sha256:5d4ee5641e19eef08dd6b93d2f4054a1aae2165325416ed2cbf0b8243f2c0b06
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:118e43e4b915e262726183467cc4b82f244565213fea5b6bfe02be07f0851ab1
|
||||
oid sha256:55c8f0d1790bb12660b7557630efca297b2a1b59e6c93167a2563da79e0a8255
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc2ce3256a6552975962c9e113c52c1a22bf3817d417151f6f60640dd568e0fa
|
||||
oid sha256:082ff368b621e12b083d96562a0889b11a1d683767a74296cbe6d8732830e9e8
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:287d98890b35427688999760f9d066bcbff1a3bc9001534241dc212b32edabd8
|
||||
oid sha256:78cc62d89782899747875b41abee57c2efdfacf4c8af6511c88f82d76eaae4ca
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:66e91c92c868167c850078cd91714db47e10a96e23cc30191994486bd79c353f
|
||||
oid sha256:3d6719326f4dacae278d1723090ce1182193b793f250963af8be4b2c298e8841
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d950d173f5101820c5e18205401ca08ce5feeff2302ac2920b292750d86a8fa4
|
||||
oid sha256:9e492bb394fb18fb117f8a5b61cd2789922f9d6e88fc83189b5b6d59ffb1c3ef
|
||||
size 6220817
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72eddb7126eae0c839b933886e0fb69d78229f72d49ef13199de28df2b7879db
|
||||
oid sha256:caca85f7728f660daae36afc81d681ba2de2377c516eb3c637599de5c94012aa
|
||||
size 6220817
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
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:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
entity_reference_creation = (
|
||||
"Entity Reference Entity successfully created",
|
||||
"Entity Reference Entity failed to be created")
|
||||
entity_reference_component = (
|
||||
"Entity has an Entity Reference component",
|
||||
"Entity failed to find Entity Reference component")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_EntityReference_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the Entity Reference component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create an Entity Reference entity with no components.
|
||||
2) Add Entity Reference component to Entity Reference entity.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Enter/Exit game mode.
|
||||
6) Test IsHidden.
|
||||
7) Test IsVisible.
|
||||
8) Delete Entity Reference entity.
|
||||
9) UNDO deletion.
|
||||
10) REDO deletion.
|
||||
11) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create an Entity Reference entity with no components.
|
||||
entity_reference_entity = EditorEntity.create_editor_entity(AtomComponentProperties.entity_reference())
|
||||
Report.critical_result(Tests.entity_reference_creation, entity_reference_entity.exists())
|
||||
|
||||
# 2. Add Entity Reference component to Entity Reference entity.
|
||||
entity_reference_component = entity_reference_entity.add_component(
|
||||
AtomComponentProperties.entity_reference())
|
||||
Report.critical_result(
|
||||
Tests.entity_reference_component,
|
||||
entity_reference_entity.has_component(AtomComponentProperties.entity_reference()))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not entity_reference_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, entity_reference_entity.exists())
|
||||
|
||||
# 5. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 6. Test IsHidden.
|
||||
entity_reference_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, entity_reference_entity.is_hidden() is True)
|
||||
|
||||
# 7. Test IsVisible.
|
||||
entity_reference_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, entity_reference_entity.is_visible() is True)
|
||||
|
||||
# 8. Delete Entity Reference entity.
|
||||
entity_reference_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not entity_reference_entity.exists())
|
||||
|
||||
# 9. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, entity_reference_entity.exists())
|
||||
|
||||
# 10. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not entity_reference_entity.exists())
|
||||
|
||||
# 11. Look for errors and asserts.
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_EntityReference_AddedToEntity)
|
||||
+2
-2
@@ -151,7 +151,7 @@ def AtomEditorComponents_GlobalSkylightIBL_AddedToEntity():
|
||||
Report.result(Tests.is_visible, global_skylight_entity.is_visible() is True)
|
||||
|
||||
# 8. Set the Diffuse Image asset on the Global Skylight (IBL) entity.
|
||||
diffuse_image_path = os.path.join("LightingPresets", "greenwich_park_02_4k_iblskyboxcm.exr.streamingimage")
|
||||
diffuse_image_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
diffuse_image_asset = Asset.find_asset_by_path(diffuse_image_path, False)
|
||||
global_skylight_component.set_component_property_value(
|
||||
AtomComponentProperties.global_skylight('Diffuse Image'), diffuse_image_asset.id)
|
||||
@@ -161,7 +161,7 @@ def AtomEditorComponents_GlobalSkylightIBL_AddedToEntity():
|
||||
AtomComponentProperties.global_skylight('Diffuse Image')))
|
||||
|
||||
# 9. Set the Specular Image asset on the Global Light (IBL) entity.
|
||||
specular_image_path = os.path.join("LightingPresets", "greenwich_park_02_4k_iblskyboxcm.exr.streamingimage")
|
||||
specular_image_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
specular_image_asset = Asset.find_asset_by_path(specular_image_path, False)
|
||||
global_skylight_component.set_component_property_value(
|
||||
AtomComponentProperties.global_skylight('Specular Image'), specular_image_asset.id)
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
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:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
hdri_skybox_entity_creation = (
|
||||
"HDRi Skybox successfully created",
|
||||
"HDRi Skybox failed to be created")
|
||||
hdri_skybox_component = (
|
||||
"Entity has an HDRi Skybox component",
|
||||
"Entity failed to find HDRi Skybox component")
|
||||
cubemap_property_set = (
|
||||
"Cubemap property set on HDRi Skybox component",
|
||||
"Couldn't set Cubemap property on HDRi Skybox component")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_HDRiSkybox_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the HDRi Skybox component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create an HDRi Skybox with no components.
|
||||
2) Add an HDRi Skybox component to HDRi Skybox.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Enter/Exit game mode.
|
||||
6) Test IsHidden.
|
||||
7) Test IsVisible.
|
||||
8) Delete HDRi Skybox.
|
||||
9) UNDO deletion.
|
||||
10) REDO deletion.
|
||||
11) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create an HDRi Skybox with no components.
|
||||
hdri_skybox_entity = EditorEntity.create_editor_entity(
|
||||
AtomComponentProperties.hdri_skybox())
|
||||
Report.critical_result(Tests.hdri_skybox_entity_creation,
|
||||
hdri_skybox_entity.exists())
|
||||
|
||||
# 2. Add an HDRi Skybox component to HDRi Skybox.
|
||||
hdri_skybox_component = hdri_skybox_entity.add_component(
|
||||
AtomComponentProperties.hdri_skybox())
|
||||
Report.critical_result(
|
||||
Tests.hdri_skybox_component,
|
||||
hdri_skybox_entity.has_component(AtomComponentProperties.hdri_skybox()))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not hdri_skybox_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, hdri_skybox_entity.exists())
|
||||
|
||||
|
||||
# 5. Set Cubemap Texture on HDRi Skybox component.
|
||||
skybox_cubemap_asset_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
skybox_cubemap_material_asset = Asset.find_asset_by_path(skybox_cubemap_asset_path, False)
|
||||
hdri_skybox_component.set_component_property_value(
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture'), skybox_cubemap_material_asset.id)
|
||||
get_cubemap_property = hdri_skybox_component.get_component_property_value(
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture'))
|
||||
Report.result(Tests.cubemap_property_set, get_cubemap_property == skybox_cubemap_material_asset.id)
|
||||
|
||||
|
||||
# 6. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 7. Test IsHidden.
|
||||
hdri_skybox_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, hdri_skybox_entity.is_hidden() is True)
|
||||
|
||||
# 8. Test IsVisible.
|
||||
hdri_skybox_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, hdri_skybox_entity.is_visible() is True)
|
||||
|
||||
# 9. Delete hdri_skybox entity.
|
||||
hdri_skybox_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not hdri_skybox_entity.exists())
|
||||
|
||||
# 10. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, hdri_skybox_entity.exists())
|
||||
|
||||
# 11. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not hdri_skybox_entity.exists())
|
||||
|
||||
# 12. Look for errors or asserts.
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_HDRiSkybox_AddedToEntity)
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
"""
|
||||
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:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
look_modification_creation = (
|
||||
"Look Modification Entity successfully created",
|
||||
"Look Modification Entity failed to be created")
|
||||
look_modification_component = (
|
||||
"Entity has a Look Modification component",
|
||||
"Entity failed to find Look Modification component")
|
||||
look_modification_disabled = (
|
||||
"Look Modification component disabled",
|
||||
"Look Modification component was not disabled")
|
||||
postfx_layer_component = (
|
||||
"Entity has a PostFX Layer component",
|
||||
"Entity did not have an PostFX Layer component")
|
||||
look_modification_enabled = (
|
||||
"Look Modification component enabled",
|
||||
"Look Modification component was not enabled")
|
||||
enable_look_modification_parameter_enabled = (
|
||||
"Enable look modification parameter enabled",
|
||||
"Enable look modification parameter was not enabled")
|
||||
color_grading_lut_set = (
|
||||
"Entity has the Color Grading LUT set",
|
||||
"Entity did not the Color Grading LUT set")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_LookModification_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the Look Modification component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create an Look Modification entity with no components.
|
||||
2) Add Look Modification component to Look Modification entity.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Verify Look Modification component not enabled.
|
||||
6) Add PostFX Layer component since it is required by the Look Modification component.
|
||||
7) Verify Look Modification component is enabled.
|
||||
8) Enable the "Enable Look Modification" parameter.
|
||||
9) Add LUT asset to the Color Grading LUT parameter.
|
||||
9) Enter/Exit game mode.
|
||||
10) Test IsHidden.
|
||||
11) Test IsVisible.
|
||||
12) Delete Look Modification entity.
|
||||
13) UNDO deletion.
|
||||
14) REDO deletion.
|
||||
15) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create an Look Modification entity with no components.
|
||||
look_modification_entity = EditorEntity.create_editor_entity(AtomComponentProperties.look_modification())
|
||||
Report.critical_result(Tests.look_modification_creation, look_modification_entity.exists())
|
||||
|
||||
# 2. Add Look Modification component to Look Modification entity.
|
||||
look_modification_component = look_modification_entity.add_component(
|
||||
AtomComponentProperties.look_modification())
|
||||
Report.critical_result(
|
||||
Tests.look_modification_component,
|
||||
look_modification_entity.has_component(AtomComponentProperties.look_modification()))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not look_modification_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, look_modification_entity.exists())
|
||||
|
||||
# 5. Verify Look Modification component not enabled.
|
||||
Report.result(Tests.look_modification_disabled, not look_modification_component.is_enabled())
|
||||
|
||||
# 6. Add PostFX Layer component since it is required by the Look Modification component.
|
||||
look_modification_entity.add_component(AtomComponentProperties.postfx_layer())
|
||||
Report.result(
|
||||
Tests.postfx_layer_component,
|
||||
look_modification_entity.has_component(AtomComponentProperties.postfx_layer()))
|
||||
|
||||
# 7. Verify Look Modification component is enabled.
|
||||
Report.result(Tests.look_modification_enabled, look_modification_component.is_enabled())
|
||||
|
||||
# 8. Enable the "Enable look modification" parameter.
|
||||
look_modification_component.set_component_property_value(
|
||||
AtomComponentProperties.look_modification('Enable look modification'), True)
|
||||
Report.result(Tests.enable_look_modification_parameter_enabled,
|
||||
look_modification_component.get_component_property_value(
|
||||
AtomComponentProperties.look_modification('Enable look modification')) is True)
|
||||
|
||||
# 9. Set the Color Grading LUT asset on the Look Modification entity.
|
||||
color_grading_lut_path = os.path.join("ColorGrading", "TestData", "Photoshop", "inv-Log2-48nits",
|
||||
"test_3dl_32_lut.azasset")
|
||||
color_grading_lut_asset = Asset.find_asset_by_path(color_grading_lut_path, False)
|
||||
look_modification_component.set_component_property_value(
|
||||
AtomComponentProperties.look_modification('Color Grading LUT'), color_grading_lut_asset.id)
|
||||
Report.result(
|
||||
Tests.color_grading_lut_set,
|
||||
color_grading_lut_asset.id == look_modification_component.get_component_property_value(
|
||||
AtomComponentProperties.look_modification('Color Grading LUT')))
|
||||
|
||||
# 10. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 11. Test IsHidden.
|
||||
look_modification_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, look_modification_entity.is_hidden() is True)
|
||||
|
||||
# 12. Test IsVisible.
|
||||
look_modification_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, look_modification_entity.is_visible() is True)
|
||||
|
||||
# 13. Delete Look Modification entity.
|
||||
look_modification_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not look_modification_entity.exists())
|
||||
|
||||
# 14. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, look_modification_entity.exists())
|
||||
|
||||
# 15. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not look_modification_entity.exists())
|
||||
|
||||
# 16. Look for errors and asserts.
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_LookModification_AddedToEntity)
|
||||
@@ -0,0 +1,182 @@
|
||||
"""
|
||||
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:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
ssao_creation = (
|
||||
"SSAO Entity successfully created",
|
||||
"SSAO Entity failed to be created")
|
||||
ssao_component = (
|
||||
"Entity has a SSAO component",
|
||||
"Entity failed to find SSAO component")
|
||||
ssao_disabled = (
|
||||
"SSAO component disabled",
|
||||
"SSAO component was not disabled.")
|
||||
postfx_layer_component = (
|
||||
"Entity has a PostFX Layer component",
|
||||
"Entity did not have an PostFX Layer component")
|
||||
ssao_enabled = (
|
||||
"SSAO component enabled",
|
||||
"SSAO component was not enabled.")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_SSAO_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the SSAO component can be added to an entity and has the expected functionality.
|
||||
Screen Space Ambient Occlusion (SSAO) is a PostFX shadow lighting effect.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create a SSAO entity with no components.
|
||||
2) Add SSAO component to SSAO entity.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Verify SSAO component not enabled.
|
||||
6) Add PostFX Layer component since it is required by the SSAO component.
|
||||
7) Verify SSAO component is enabled.
|
||||
8) Enter/Exit game mode.
|
||||
9) Test IsHidden.
|
||||
10) Test IsVisible.
|
||||
11) Delete SSAO entity.
|
||||
12) UNDO deletion.
|
||||
13) REDO deletion.
|
||||
14) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create a SSAO entity with no components.
|
||||
ssao_entity = EditorEntity.create_editor_entity(AtomComponentProperties.ssao())
|
||||
Report.critical_result(Tests.ssao_creation, ssao_entity.exists())
|
||||
|
||||
# 2. Add SSAO component to SSAO entity.
|
||||
ssao_component = ssao_entity.add_component(AtomComponentProperties.ssao())
|
||||
Report.critical_result(
|
||||
Tests.ssao_component,
|
||||
ssao_entity.has_component(AtomComponentProperties.ssao()))
|
||||
ssao_component.get_property_tree()
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not ssao_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, ssao_entity.exists())
|
||||
|
||||
# 5. Verify SSAO component not enabled.
|
||||
Report.result(Tests.ssao_disabled, not ssao_component.is_enabled())
|
||||
|
||||
# 6. Add PostFX Layer component since it is required by the SSAO component.
|
||||
ssao_entity.add_component(AtomComponentProperties.postfx_layer())
|
||||
Report.result(
|
||||
Tests.postfx_layer_component,
|
||||
ssao_entity.has_component(AtomComponentProperties.postfx_layer()))
|
||||
|
||||
# 7. Verify SSAO component is enabled.
|
||||
Report.result(Tests.ssao_enabled, ssao_component.is_enabled())
|
||||
|
||||
# 8. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 9. Test IsHidden.
|
||||
ssao_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, ssao_entity.is_hidden() is True)
|
||||
|
||||
# 10. Test IsVisible.
|
||||
ssao_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, ssao_entity.is_visible() is True)
|
||||
|
||||
# 11. Delete SSAO entity.
|
||||
ssao_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not ssao_entity.exists())
|
||||
|
||||
# 12. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, ssao_entity.exists())
|
||||
|
||||
# 13. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not ssao_entity.exists())
|
||||
|
||||
# 14. Look for errors and asserts.
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_SSAO_AddedToEntity)
|
||||
@@ -6,30 +6,70 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests :
|
||||
camera_component_added = ("Camera component was added", "Camera component wasn't added")
|
||||
camera_fov_set = ("Camera component FOV property set", "Camera component FOV property wasn't set")
|
||||
directional_light_component_added = ("Directional Light component added", "Directional Light component wasn't added")
|
||||
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
|
||||
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
|
||||
global_skylight_component_added = ("Global Skylight (IBL) component added", "Global Skylight (IBL) component wasn't added")
|
||||
global_skylight_diffuse_image_set = ("Global Skylight Diffuse Image property set", "Global Skylight Diffuse Image property wasn't set")
|
||||
global_skylight_specular_image_set = ("Global Skylight Specular Image property set", "Global Skylight Specular Image property wasn't set")
|
||||
ground_plane_material_asset_set = ("Ground Plane Material Asset was set", "Ground Plane Material Asset wasn't set")
|
||||
ground_plane_material_component_added = ("Ground Plane Material component added", "Ground Plane Material component wasn't added")
|
||||
ground_plane_mesh_asset_set = ("Ground Plane Mesh Asset property was set", "Ground Plane Mesh Asset property wasn't set")
|
||||
hdri_skybox_component_added = ("HDRi Skybox component added", "HDRi Skybox component wasn't added")
|
||||
hdri_skybox_cubemap_texture_set = ("HDRi Skybox Cubemap Texture property set", "HDRi Skybox Cubemap Texture property wasn't set")
|
||||
mesh_component_added = ("Mesh component added", "Mesh component wasn't added")
|
||||
no_assert_occurred = ("No asserts detected", "Asserts were detected")
|
||||
no_error_occurred = ("No errors detected", "Errors were detected")
|
||||
secondary_grid_spacing = ("Secondary Grid Spacing set", "Secondary Grid Spacing not set")
|
||||
sphere_material_component_added = ("Sphere Material component added", "Sphere Material component wasn't added")
|
||||
sphere_material_set = ("Sphere Material Asset was set", "Sphere Material Asset wasn't set")
|
||||
sphere_mesh_asset_set = ("Sphere Mesh Asset was set", "Sphere Mesh Asset wasn't set")
|
||||
viewport_set = ("Viewport set to correct size", "Viewport not set to correct size")
|
||||
# fmt: on
|
||||
class Tests:
|
||||
camera_component_added = (
|
||||
"Camera component was added",
|
||||
"Camera component wasn't added")
|
||||
camera_fov_set = (
|
||||
"Camera component FOV property set",
|
||||
"Camera component FOV property wasn't set")
|
||||
directional_light_component_added = (
|
||||
"Directional Light component added",
|
||||
"Directional Light component wasn't added")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
global_skylight_component_added = (
|
||||
"Global Skylight (IBL) component added",
|
||||
"Global Skylight (IBL) component wasn't added")
|
||||
global_skylight_diffuse_image_set = (
|
||||
"Global Skylight Diffuse Image property set",
|
||||
"Global Skylight Diffuse Image property wasn't set")
|
||||
global_skylight_specular_image_set = (
|
||||
"Global Skylight Specular Image property set",
|
||||
"Global Skylight Specular Image property wasn't set")
|
||||
ground_plane_material_asset_set = (
|
||||
"Ground Plane Material Asset was set",
|
||||
"Ground Plane Material Asset wasn't set")
|
||||
ground_plane_material_component_added = (
|
||||
"Ground Plane Material component added",
|
||||
"Ground Plane Material component wasn't added")
|
||||
ground_plane_mesh_asset_set = (
|
||||
"Ground Plane Mesh Asset property was set",
|
||||
"Ground Plane Mesh Asset property wasn't set")
|
||||
hdri_skybox_component_added = (
|
||||
"HDRi Skybox component added",
|
||||
"HDRi Skybox component wasn't added")
|
||||
hdri_skybox_cubemap_texture_set = (
|
||||
"HDRi Skybox Cubemap Texture property set",
|
||||
"HDRi Skybox Cubemap Texture property wasn't set")
|
||||
mesh_component_added = (
|
||||
"Mesh component added",
|
||||
"Mesh component wasn't added")
|
||||
no_assert_occurred = (
|
||||
"No asserts detected",
|
||||
"Asserts were detected")
|
||||
no_error_occurred = (
|
||||
"No errors detected",
|
||||
"Errors were detected")
|
||||
secondary_grid_spacing = (
|
||||
"Secondary Grid Spacing set",
|
||||
"Secondary Grid Spacing not set")
|
||||
sphere_material_component_added = (
|
||||
"Sphere Material component added",
|
||||
"Sphere Material component wasn't added")
|
||||
sphere_material_set = (
|
||||
"Sphere Material Asset was set",
|
||||
"Sphere Material Asset wasn't set")
|
||||
sphere_mesh_asset_set = (
|
||||
"Sphere Mesh Asset was set",
|
||||
"Sphere Mesh Asset wasn't set")
|
||||
viewport_set = (
|
||||
"Viewport set to correct size",
|
||||
"Viewport not set to correct size")
|
||||
|
||||
|
||||
def AtomGPU_BasicLevelSetup_SetsUpLevel():
|
||||
@@ -77,19 +117,17 @@ def AtomGPU_BasicLevelSetup_SetsUpLevel():
|
||||
import os
|
||||
from math import isclose
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
from Atom.atom_utils.screenshot_utils import ScreenshotHelper
|
||||
|
||||
MATERIAL_COMPONENT_NAME = "Material"
|
||||
MESH_COMPONENT_NAME = "Mesh"
|
||||
SCREENSHOT_NAME = "AtomBasicLevelSetup"
|
||||
SCREEN_WIDTH = 1280
|
||||
SCREEN_HEIGHT = 720
|
||||
@@ -98,24 +136,24 @@ def AtomGPU_BasicLevelSetup_SetsUpLevel():
|
||||
def initial_viewport_setup(screen_width, screen_height):
|
||||
general.set_viewport_size(screen_width, screen_height)
|
||||
general.update_viewport()
|
||||
result = isclose(
|
||||
a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) and isclose(
|
||||
a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1)
|
||||
|
||||
return result
|
||||
TestHelper.wait_for_condition(
|
||||
function=lambda: isclose(a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1)
|
||||
and isclose(a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1),
|
||||
timeout_in_seconds=4.0
|
||||
)
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
helper.init_idle()
|
||||
helper.open_level("", "Base")
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Close error windows and display helpers then update the viewport size.
|
||||
helper.close_error_windows()
|
||||
helper.close_display_helpers()
|
||||
TestHelper.close_error_windows()
|
||||
TestHelper.close_display_helpers()
|
||||
initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
general.update_viewport()
|
||||
Report.critical_result(Tests.viewport_set, initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
# 2. Create Default Level Entity.
|
||||
default_level_entity_name = "Default Level"
|
||||
@@ -123,168 +161,167 @@ def AtomGPU_BasicLevelSetup_SetsUpLevel():
|
||||
math.Vector3(0.0, 0.0, 0.0), default_level_entity_name)
|
||||
|
||||
# 3. Create Grid Entity as a child entity of the Default Level Entity.
|
||||
grid_name = "Grid"
|
||||
grid_entity = EditorEntity.create_editor_entity(grid_name, default_level_entity.id)
|
||||
grid_entity = EditorEntity.create_editor_entity(AtomComponentProperties.grid(), default_level_entity.id)
|
||||
|
||||
# 4. Add Grid component to Grid Entity and set Secondary Grid Spacing.
|
||||
grid_component = grid_entity.add_component(grid_name)
|
||||
secondary_grid_spacing_property = "Controller|Configuration|Secondary Grid Spacing"
|
||||
grid_component = grid_entity.add_component(AtomComponentProperties.grid())
|
||||
secondary_grid_spacing_value = 1.0
|
||||
grid_component.set_component_property_value(secondary_grid_spacing_property, secondary_grid_spacing_value)
|
||||
grid_component.set_component_property_value(
|
||||
AtomComponentProperties.grid('Secondary Grid Spacing'), secondary_grid_spacing_value)
|
||||
secondary_grid_spacing_set = grid_component.get_component_property_value(
|
||||
secondary_grid_spacing_property) == secondary_grid_spacing_value
|
||||
AtomComponentProperties.grid('Secondary Grid Spacing')) == secondary_grid_spacing_value
|
||||
Report.result(Tests.secondary_grid_spacing, secondary_grid_spacing_set)
|
||||
|
||||
# 5. Create Global Skylight (IBL) Entity as a child entity of the Default Level Entity.
|
||||
global_skylight_name = "Global Skylight (IBL)"
|
||||
global_skylight_entity = EditorEntity.create_editor_entity(global_skylight_name, default_level_entity.id)
|
||||
global_skylight_entity = EditorEntity.create_editor_entity(
|
||||
AtomComponentProperties.global_skylight(), default_level_entity.id)
|
||||
|
||||
# 6. Add HDRi Skybox component to the Global Skylight (IBL) Entity.
|
||||
hdri_skybox_name = "HDRi Skybox"
|
||||
hdri_skybox_component = global_skylight_entity.add_component(hdri_skybox_name)
|
||||
Report.result(Tests.hdri_skybox_component_added, global_skylight_entity.has_component(hdri_skybox_name))
|
||||
hdri_skybox_component = global_skylight_entity.add_component(AtomComponentProperties.hdri_skybox())
|
||||
Report.result(Tests.hdri_skybox_component_added, global_skylight_entity.has_component(
|
||||
AtomComponentProperties.hdri_skybox()))
|
||||
|
||||
# 7. Add Global Skylight (IBL) component to the Global Skylight (IBL) Entity.
|
||||
global_skylight_component = global_skylight_entity.add_component(global_skylight_name)
|
||||
Report.result(Tests.global_skylight_component_added, global_skylight_entity.has_component(global_skylight_name))
|
||||
global_skylight_component = global_skylight_entity.add_component(AtomComponentProperties.global_skylight())
|
||||
Report.result(Tests.global_skylight_component_added, global_skylight_entity.has_component(
|
||||
AtomComponentProperties.global_skylight()))
|
||||
|
||||
# 8. Set the Cubemap Texture property of the HDRi Skybox component.
|
||||
global_skylight_image_asset_path = os.path.join(
|
||||
"LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage")
|
||||
global_skylight_image_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", global_skylight_image_asset_path, math.Uuid(), False)
|
||||
hdri_skybox_cubemap_texture_property = "Controller|Configuration|Cubemap Texture"
|
||||
global_skylight_image_asset_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
global_skylight_image_asset = Asset.find_asset_by_path(global_skylight_image_asset_path, False)
|
||||
hdri_skybox_component.set_component_property_value(
|
||||
hdri_skybox_cubemap_texture_property, global_skylight_image_asset)
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture'), global_skylight_image_asset.id)
|
||||
Report.result(
|
||||
Tests.hdri_skybox_cubemap_texture_set,
|
||||
hdri_skybox_component.get_component_property_value(
|
||||
hdri_skybox_cubemap_texture_property) == global_skylight_image_asset)
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture')) == global_skylight_image_asset.id)
|
||||
|
||||
# 9. Set the Diffuse Image property of the Global Skylight (IBL) component.
|
||||
# Re-use the same image that was used in the previous test step.
|
||||
global_skylight_diffuse_image_property = "Controller|Configuration|Diffuse Image"
|
||||
global_skylight_diffuse_image_asset_path = os.path.join(
|
||||
"LightingPresets", "default_iblskyboxcm_ibldiffuse.exr.streamingimage")
|
||||
global_skylight_diffuse_image_asset = Asset.find_asset_by_path(global_skylight_diffuse_image_asset_path, False)
|
||||
global_skylight_component.set_component_property_value(
|
||||
global_skylight_diffuse_image_property, global_skylight_image_asset)
|
||||
AtomComponentProperties.global_skylight('Diffuse Image'), global_skylight_diffuse_image_asset.id)
|
||||
Report.result(
|
||||
Tests.global_skylight_diffuse_image_set,
|
||||
global_skylight_component.get_component_property_value(
|
||||
global_skylight_diffuse_image_property) == global_skylight_image_asset)
|
||||
AtomComponentProperties.global_skylight('Diffuse Image')) == global_skylight_diffuse_image_asset.id)
|
||||
|
||||
# 10. Set the Specular Image property of the Global Skylight (IBL) component.
|
||||
# Re-use the same image that was used in the previous test step.
|
||||
global_skylight_specular_image_property = "Controller|Configuration|Specular Image"
|
||||
global_skylight_specular_image_asset_path = os.path.join(
|
||||
"LightingPresets", "default_iblskyboxcm_iblspecular.exr.streamingimage")
|
||||
global_skylight_specular_image_asset = Asset.find_asset_by_path(
|
||||
global_skylight_specular_image_asset_path, False)
|
||||
global_skylight_component.set_component_property_value(
|
||||
global_skylight_specular_image_property, global_skylight_image_asset)
|
||||
AtomComponentProperties.global_skylight('Specular Image'), global_skylight_specular_image_asset.id)
|
||||
global_skylight_specular_image_set = global_skylight_component.get_component_property_value(
|
||||
global_skylight_specular_image_property)
|
||||
AtomComponentProperties.global_skylight('Specular Image'))
|
||||
Report.result(
|
||||
Tests.global_skylight_specular_image_set, global_skylight_specular_image_set == global_skylight_image_asset)
|
||||
Tests.global_skylight_specular_image_set,
|
||||
global_skylight_specular_image_set == global_skylight_specular_image_asset.id)
|
||||
|
||||
# 11. Create a Ground Plane Entity with a Material component that is a child entity of the Default Level Entity.
|
||||
ground_plane_name = "Ground Plane"
|
||||
ground_plane_entity = EditorEntity.create_editor_entity(ground_plane_name, default_level_entity.id)
|
||||
ground_plane_material_component = ground_plane_entity.add_component(MATERIAL_COMPONENT_NAME)
|
||||
ground_plane_material_component = ground_plane_entity.add_component(AtomComponentProperties.material())
|
||||
Report.result(
|
||||
Tests.ground_plane_material_component_added, ground_plane_entity.has_component(MATERIAL_COMPONENT_NAME))
|
||||
Tests.ground_plane_material_component_added,
|
||||
ground_plane_entity.has_component(AtomComponentProperties.material()))
|
||||
|
||||
# 12. Set the Material Asset property of the Material component for the Ground Plane Entity.
|
||||
ground_plane_entity.set_local_uniform_scale(32.0)
|
||||
ground_plane_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_chrome.azmaterial")
|
||||
ground_plane_material_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False)
|
||||
ground_plane_material_asset_property = "Default Material|Material Asset"
|
||||
ground_plane_material_asset = Asset.find_asset_by_path(ground_plane_material_asset_path, False)
|
||||
ground_plane_material_component.set_component_property_value(
|
||||
ground_plane_material_asset_property, ground_plane_material_asset)
|
||||
AtomComponentProperties.material('Material Asset'), ground_plane_material_asset.id)
|
||||
Report.result(
|
||||
Tests.ground_plane_material_asset_set,
|
||||
ground_plane_material_component.get_component_property_value(
|
||||
ground_plane_material_asset_property) == ground_plane_material_asset)
|
||||
AtomComponentProperties.material('Material Asset')) == ground_plane_material_asset.id)
|
||||
|
||||
# 13. Add the Mesh component to the Ground Plane Entity and set the Mesh component Mesh Asset property.
|
||||
ground_plane_mesh_component = ground_plane_entity.add_component(MESH_COMPONENT_NAME)
|
||||
Report.result(Tests.mesh_component_added, ground_plane_entity.has_component(MESH_COMPONENT_NAME))
|
||||
ground_plane_mesh_asset_path = os.path.join("Objects", "plane.azmodel")
|
||||
ground_plane_mesh_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False)
|
||||
ground_plane_mesh_asset_property = "Controller|Configuration|Mesh Asset"
|
||||
ground_plane_mesh_component = ground_plane_entity.add_component(AtomComponentProperties.mesh())
|
||||
Report.result(Tests.mesh_component_added, ground_plane_entity.has_component(AtomComponentProperties.mesh()))
|
||||
ground_plane_mesh_asset_path = os.path.join("TestData", "Objects", "plane.azmodel")
|
||||
ground_plane_mesh_asset = Asset.find_asset_by_path(ground_plane_mesh_asset_path, False)
|
||||
ground_plane_mesh_component.set_component_property_value(
|
||||
ground_plane_mesh_asset_property, ground_plane_mesh_asset)
|
||||
AtomComponentProperties.mesh('Mesh Asset'), ground_plane_mesh_asset.id)
|
||||
Report.result(
|
||||
Tests.ground_plane_mesh_asset_set,
|
||||
ground_plane_mesh_component.get_component_property_value(
|
||||
ground_plane_mesh_asset_property) == ground_plane_mesh_asset)
|
||||
AtomComponentProperties.mesh('Mesh Asset')) == ground_plane_mesh_asset.id)
|
||||
|
||||
# 14. Create a Directional Light Entity as a child entity of the Default Level Entity.
|
||||
directional_light_name = "Directional Light"
|
||||
directional_light_entity = EditorEntity.create_editor_entity_at(
|
||||
math.Vector3(0.0, 0.0, 10.0), directional_light_name, default_level_entity.id)
|
||||
math.Vector3(0.0, 0.0, 10.0), AtomComponentProperties.directional_light(), default_level_entity.id)
|
||||
|
||||
# 15. Add Directional Light component to Directional Light Entity and set entity rotation.
|
||||
directional_light_entity.add_component(directional_light_name)
|
||||
directional_light_entity.add_component(AtomComponentProperties.directional_light())
|
||||
directional_light_entity_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * -90.0, 0.0, 0.0)
|
||||
directional_light_entity.set_local_rotation(directional_light_entity_rotation)
|
||||
Report.result(
|
||||
Tests.directional_light_component_added, directional_light_entity.has_component(directional_light_name))
|
||||
Tests.directional_light_component_added, directional_light_entity.has_component(
|
||||
AtomComponentProperties.directional_light()))
|
||||
|
||||
# 16. Create a Sphere Entity as a child entity of the Default Level Entity then add a Material component.
|
||||
sphere_entity = EditorEntity.create_editor_entity_at(
|
||||
math.Vector3(0.0, 0.0, 1.0), "Sphere", default_level_entity.id)
|
||||
sphere_material_component = sphere_entity.add_component(MATERIAL_COMPONENT_NAME)
|
||||
Report.result(Tests.sphere_material_component_added, sphere_entity.has_component(MATERIAL_COMPONENT_NAME))
|
||||
sphere_material_component = sphere_entity.add_component(AtomComponentProperties.material())
|
||||
Report.result(Tests.sphere_material_component_added, sphere_entity.has_component(
|
||||
AtomComponentProperties.material()))
|
||||
|
||||
# 17. Set the Material Asset property of the Material component for the Sphere Entity.
|
||||
sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial")
|
||||
sphere_material_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False)
|
||||
sphere_material_asset_property = "Default Material|Material Asset"
|
||||
sphere_material_component.set_component_property_value(sphere_material_asset_property, sphere_material_asset)
|
||||
sphere_material_asset = Asset.find_asset_by_path(sphere_material_asset_path, False)
|
||||
sphere_material_component.set_component_property_value(
|
||||
AtomComponentProperties.material('Material Asset'), sphere_material_asset.id)
|
||||
Report.result(Tests.sphere_material_set, sphere_material_component.get_component_property_value(
|
||||
sphere_material_asset_property) == sphere_material_asset)
|
||||
AtomComponentProperties.material('Material Asset')) == sphere_material_asset.id)
|
||||
|
||||
# 18. Add Mesh component to Sphere Entity and set the Mesh Asset property for the Mesh component.
|
||||
sphere_mesh_component = sphere_entity.add_component(MESH_COMPONENT_NAME)
|
||||
sphere_mesh_component = sphere_entity.add_component(AtomComponentProperties.mesh())
|
||||
sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel")
|
||||
sphere_mesh_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False)
|
||||
sphere_mesh_asset_property = "Controller|Configuration|Mesh Asset"
|
||||
sphere_mesh_component.set_component_property_value(sphere_mesh_asset_property, sphere_mesh_asset)
|
||||
sphere_mesh_asset = Asset.find_asset_by_path(sphere_mesh_asset_path, False)
|
||||
sphere_mesh_component.set_component_property_value(
|
||||
AtomComponentProperties.mesh('Mesh Asset'), sphere_mesh_asset.id)
|
||||
Report.result(Tests.sphere_mesh_asset_set, sphere_mesh_component.get_component_property_value(
|
||||
sphere_mesh_asset_property) == sphere_mesh_asset)
|
||||
AtomComponentProperties.mesh('Mesh Asset')) == sphere_mesh_asset.id)
|
||||
|
||||
# 19. Create a Camera Entity as a child entity of the Default Level Entity then add a Camera component.
|
||||
camera_name = "Camera"
|
||||
camera_entity = EditorEntity.create_editor_entity_at(
|
||||
math.Vector3(5.5, -12.0, 9.0), camera_name, default_level_entity.id)
|
||||
camera_component = camera_entity.add_component(camera_name)
|
||||
Report.result(Tests.camera_component_added, camera_entity.has_component(camera_name))
|
||||
math.Vector3(5.5, -12.0, 9.0), AtomComponentProperties.camera(), default_level_entity.id)
|
||||
camera_component = camera_entity.add_component(AtomComponentProperties.camera())
|
||||
Report.result(Tests.camera_component_added, camera_entity.has_component(AtomComponentProperties.camera()))
|
||||
|
||||
# 20. Set the Camera Entity rotation value and set the Camera component Field of View value.
|
||||
camera_entity_rotation = math.Vector3(
|
||||
DEGREE_RADIAN_FACTOR * -27.0, DEGREE_RADIAN_FACTOR * -12.0, DEGREE_RADIAN_FACTOR * 25.0)
|
||||
camera_entity.set_local_rotation(camera_entity_rotation)
|
||||
camera_fov_property = "Controller|Configuration|Field of view"
|
||||
camera_fov_value = 60.0
|
||||
camera_component.set_component_property_value(camera_fov_property, camera_fov_value)
|
||||
camera_component.set_component_property_value(AtomComponentProperties.camera('Field of view'), camera_fov_value)
|
||||
azlmbr.camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id)
|
||||
Report.result(Tests.camera_fov_set, camera_component.get_component_property_value(
|
||||
camera_fov_property) == camera_fov_value)
|
||||
AtomComponentProperties.camera('Field of view')) == camera_fov_value)
|
||||
|
||||
# 21. Enter game mode.
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
helper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=4.0)
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
TestHelper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=4.0)
|
||||
|
||||
# 22. Take screenshot.
|
||||
ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{SCREENSHOT_NAME}.ppm")
|
||||
|
||||
# 23. Exit game mode.
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=4.0)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
TestHelper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=4.0)
|
||||
|
||||
# 24. Look for errors.
|
||||
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
Report.result(Tests.no_assert_occurred, not error_tracer.has_asserts)
|
||||
Report.result(Tests.no_error_occurred, not error_tracer.has_errors)
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -106,8 +106,7 @@ def run():
|
||||
components=["HDRi Skybox", "Global Skylight (IBL)"],
|
||||
parent_id=default_level.id
|
||||
)
|
||||
global_skylight_image_asset_path = os.path.join(
|
||||
"LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage")
|
||||
global_skylight_image_asset_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
global_skylight_image_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", global_skylight_image_asset_path, math.Uuid(), False)
|
||||
global_skylight.get_set_test(0, "Controller|Configuration|Cubemap Texture", global_skylight_image_asset)
|
||||
|
||||
@@ -56,6 +56,9 @@ add_subdirectory(streaming)
|
||||
## Smoke ##
|
||||
add_subdirectory(smoke)
|
||||
|
||||
## Terrain ##
|
||||
add_subdirectory(Terrain)
|
||||
|
||||
## AWS ##
|
||||
add_subdirectory(AWS)
|
||||
|
||||
|
||||
+2
-1
@@ -132,6 +132,7 @@ class EditorEntity:
|
||||
|
||||
def __init__(self, id: azlmbr.entity.EntityId):
|
||||
self.id: azlmbr.entity.EntityId = id
|
||||
self.components: List[EditorComponent] = []
|
||||
|
||||
# Creation functions
|
||||
@classmethod
|
||||
@@ -279,7 +280,7 @@ class EditorEntity:
|
||||
), f"Failure: Could not add component: '{new_comp.get_component_name()}' to entity: '{self.get_name()}'"
|
||||
new_comp.id = add_component_outcome.GetValue()[0]
|
||||
components.append(new_comp)
|
||||
|
||||
self.components.append(new_comp)
|
||||
return components
|
||||
|
||||
def get_components_of_type(self, component_names: list) -> List[EditorComponent]:
|
||||
|
||||
+4
@@ -57,6 +57,10 @@ def add_level_component(component_name):
|
||||
level_component_list, entity.EntityType().Level)
|
||||
level_component_outcome = editor.EditorLevelComponentAPIBus(bus.Broadcast, 'AddComponentsOfType',
|
||||
[level_component_type_ids_list[0]])
|
||||
if not level_component_outcome.IsSuccess():
|
||||
print('Failed to add {} level component'.format(component_name))
|
||||
return None
|
||||
|
||||
level_component = level_component_outcome.GetValue()[0]
|
||||
return level_component
|
||||
|
||||
|
||||
@@ -91,4 +91,16 @@ class TestAutomation(TestAutomationBase):
|
||||
@revert_physics_config
|
||||
def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import Physics_UndoRedoWorksOnEntityWithPhysComponents as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@pytest.mark.GROUP_tick
|
||||
@pytest.mark.xfail(reason="Test still under development.")
|
||||
def test_Tick_InterpolatedRigidBodyMotionIsSmooth(self, request, workspace, editor, launcher_platform):
|
||||
from .tests.tick import Tick_InterpolatedRigidBodyMotionIsSmooth as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@pytest.mark.GROUP_tick
|
||||
@pytest.mark.xfail(reason="Test still under development.")
|
||||
def test_Tick_CharacterGameplayComponentMotionIsSmooth(self, request, workspace, editor, launcher_platform):
|
||||
from .tests.tick import Tick_CharacterGameplayComponentMotionIsSmooth as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@@ -60,7 +60,7 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest):
|
||||
class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
|
||||
|
||||
global_extra_cmdline_args = ['-BatchMode', '-autotest_mode',
|
||||
'extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]']
|
||||
'--regset=/Amazon/Preferences/EnablePrefabSystem=true']
|
||||
|
||||
@staticmethod
|
||||
def get_number_parallel_editors():
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
Test Case Title : Verify that an entity with a character gameplay component moves smoothly.
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
create_entity = ("Created test entity", "Failed to create test entity")
|
||||
character_controller_added = ("Added PhysX Character Controller component", "Failed to add PhysX Character Controller component")
|
||||
character_gameplay_added = ("Added PhysX Character Gameplay component", "Failed to add PhysX Character Gameplay component")
|
||||
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
|
||||
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
|
||||
character_motion_smooth = ("Character motion passed smoothness threshold", "Failed to meet smoothness threshold for character motion")
|
||||
# fmt: on
|
||||
|
||||
|
||||
def Tick_CharacterGameplayComponentMotionIsSmooth():
|
||||
"""
|
||||
Summary:
|
||||
Create entity with PhysX Character Controller and PhysX Character Gameplay components.
|
||||
Verify that the motion of the character controller under gravity is smooth.
|
||||
|
||||
Expected Behavior:
|
||||
1) The motion of the character controller under gravity is a smooth curve, rather than an erratic/jittery movement.
|
||||
|
||||
Test Steps:
|
||||
1) Load the empty level
|
||||
2) Create an entity
|
||||
3) Add a PhysX Character Controller Component and PhysX Character Gameplay component
|
||||
4) Enter game mode and collect data for the character controller's z co-ordinate and the time values for a series of frames
|
||||
5) Check if the motion of the character controller was sufficiently smooth
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# imports
|
||||
import os
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
import numpy as np
|
||||
|
||||
# constants
|
||||
COEFFICIENT_OF_DETERMINATION_THRESHOLD = 1 - 1e-4 # curves with values below this are not considered sufficiently smooth
|
||||
|
||||
helper.init_idle()
|
||||
# 1) Load the empty level
|
||||
helper.open_level("", "Base")
|
||||
|
||||
# 2) Create an entity
|
||||
test_entity = Entity.create_editor_entity("test_entity")
|
||||
Report.result(Tests.create_entity, test_entity.id.IsValid())
|
||||
|
||||
azlmbr.components.TransformBus(
|
||||
azlmbr.bus.Event, "SetWorldTranslation", test_entity.id, math.Vector3(0.0, 0.0, 0.0))
|
||||
|
||||
# 3) Add character controller and character gameplay components
|
||||
character_controller_component = test_entity.add_component("PhysX Character Controller")
|
||||
Report.result(Tests.character_controller_added, test_entity.has_component("PhysX Character Controller"))
|
||||
character_gameplay_component = test_entity.add_component("PhysX Character Gameplay")
|
||||
Report.result(Tests.character_gameplay_added, test_entity.has_component("PhysX Character Gameplay"))
|
||||
|
||||
# 4) Enter game mode and collect data for the rigid body's z co-ordinate and the time values for a series of frames
|
||||
t = []
|
||||
z = []
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
game_entity_id = general.find_game_entity("test_entity")
|
||||
for frame in range(100):
|
||||
t.append(azlmbr.components.TickRequestBus(azlmbr.bus.Broadcast, "GetTimeAtCurrentTick").GetSeconds())
|
||||
z.append(azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldZ", game_entity_id))
|
||||
general.idle_wait_frames(1)
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 5) Test that the z vs t curve is sufficiently smooth (if the interpolation is not working well, the curve will be less smooth)
|
||||
# normalize the t and z data
|
||||
t = np.array(t) - np.mean(t)
|
||||
z = np.array(z) - np.mean(z)
|
||||
# fit a polynomial to the z vs t curve
|
||||
fit = np.poly1d(np.polyfit(t, z, 4))
|
||||
residual = fit(t) - z
|
||||
# calculate the coefficient of determination (a measure of how closely the polynomial curve fits the data)
|
||||
# if the coefficient is very close to 1, then the curve fits the data very well, suggesting that the rigid body motion is smooth
|
||||
# if the coefficient is significantly less than 1, then the z values vary more erratically relative to the smooth curve,
|
||||
# indicating that the motion of the rigid body is not smooth
|
||||
coefficient_of_determination = (1 - np.sum(residual * residual) / np.sum(z * z))
|
||||
Report.result(Tests.character_motion_smooth, bool(coefficient_of_determination > COEFFICIENT_OF_DETERMINATION_THRESHOLD))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Tick_CharacterGameplayComponentMotionIsSmooth)
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
Test Case Title : Verify that a rigid body with "Interpolate motion" option selected moves smoothly.
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
create_entity = ("Created test entity", "Failed to create test entity")
|
||||
rigid_body_added = ("Added PhysX Rigid Body component", "Failed to add PhysX Rigid Body component")
|
||||
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
|
||||
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
|
||||
rigid_body_smooth = ("Rigid body motion passed smoothness threshold", "Failed to meet smoothness threshold for rigid body motion")
|
||||
# fmt: on
|
||||
|
||||
|
||||
def Tick_InterpolatedRigidBodyMotionIsSmooth():
|
||||
"""
|
||||
Summary:
|
||||
Create entity with PhysX Rigid Body component and turn on the Interpolate motion setting.
|
||||
Verify that the position of the rigid body varies smoothly with time.
|
||||
|
||||
Expected Behavior:
|
||||
1) The motion of the rigid body under gravity is a smooth curve, rather than an erratic/jittery movement.
|
||||
|
||||
Test Steps:
|
||||
1) Load the empty level
|
||||
2) Create an entity
|
||||
3) Add rigid body component
|
||||
4) Enter game mode and collect data for the rigid body's z co-ordinate and the time values for a series of frames
|
||||
5) Check if the motion of the rigid body was sufficiently smooth
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# imports
|
||||
import os
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
import numpy as np
|
||||
|
||||
# constants
|
||||
COEFFICIENT_OF_DETERMINATION_THRESHOLD = 1 - 1e-4 # curves with values below this are not considered sufficiently smooth
|
||||
|
||||
helper.init_idle()
|
||||
# 1) Load the empty level
|
||||
helper.open_level("", "Base")
|
||||
|
||||
# 2) Create an entity
|
||||
test_entity = Entity.create_editor_entity("test_entity")
|
||||
Report.result(Tests.create_entity, test_entity.id.IsValid())
|
||||
|
||||
azlmbr.components.TransformBus(
|
||||
azlmbr.bus.Event, "SetWorldTranslation", test_entity.id, math.Vector3(0.0, 0.0, 0.0))
|
||||
|
||||
# 3) Add rigid body component
|
||||
rigid_body_component = test_entity.add_component("PhysX Rigid Body")
|
||||
rigid_body_component.set_component_property_value("Configuration|Interpolate motion", True)
|
||||
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearDamping", test_entity.id, 0.0)
|
||||
Report.result(Tests.rigid_body_added, test_entity.has_component("PhysX Rigid Body"))
|
||||
|
||||
# 4) Enter game mode and collect data for the rigid body's z co-ordinate and the time values for a series of frames
|
||||
t = []
|
||||
z = []
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
game_entity_id = general.find_game_entity("test_entity")
|
||||
for frame in range(100):
|
||||
t.append(azlmbr.components.TickRequestBus(azlmbr.bus.Broadcast, "GetTimeAtCurrentTick").GetSeconds())
|
||||
z.append(azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldZ", game_entity_id))
|
||||
general.idle_wait_frames(1)
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 5) Test that the z vs t curve is sufficiently smooth (if the interpolation is not working well, the curve will be less smooth)
|
||||
# normalize the t and z data
|
||||
t = np.array(t) - np.mean(t)
|
||||
z = np.array(z) - np.mean(z)
|
||||
# fit a polynomial to the z vs t curve
|
||||
fit = np.poly1d(np.polyfit(t, z, 4))
|
||||
residual = fit(t) - z
|
||||
# calculate the coefficient of determination (a measure of how closely the polynomial curve fits the data)
|
||||
# if the coefficient is very close to 1, then the curve fits the data very well, suggesting that the rigid body motion is smooth
|
||||
# if the coefficient is significantly less than 1, then the z values vary more erratically relative to the smooth curve,
|
||||
# indicating that the motion of the rigid body is not smooth
|
||||
coefficient_of_determination = (1 - np.sum(residual * residual) / np.sum(z * z))
|
||||
Report.result(Tests.rigid_body_smooth, bool(coefficient_of_determination > COEFFICIENT_OF_DETERMINATION_THRESHOLD))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Tick_InterpolatedRigidBodyMotionIsSmooth)
|
||||
@@ -218,6 +218,7 @@ class FileManagement:
|
||||
src_file_path = os.path.join(src_path, src_file)
|
||||
if os.path.exists(target_file_path):
|
||||
fs.unlock_file(target_file_path)
|
||||
os.makedirs(target_path, exist_ok=True)
|
||||
shutil.copyfile(src_file_path, target_file_path)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -12,7 +12,6 @@ import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ly_test_tools import LAUNCHERS
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared')
|
||||
|
||||
from base import TestAutomationBase
|
||||
@@ -28,38 +27,38 @@ class TestAutomation(TestAutomationBase):
|
||||
batch_mode=batch_mode,
|
||||
autotest_mode=autotest_mode)
|
||||
|
||||
def test_PrefabLevel_OpensLevelWithEntities(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabLevel_OpensLevelWithEntities as test_module
|
||||
def test_OpenLevel_ContainingTwoEntities(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.open_level import OpenLevel_ContainingTwoEntities as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreatePrefab as test_module
|
||||
def test_CreatePrefab_WithSingleEntity(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.create_prefab import CreatePrefab_WithSingleEntity as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_PrefabBasicWorkflow_InstantiatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_InstantiatePrefab as test_module
|
||||
def test_InstantiatePrefab_ContainingASingleEntity(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.instantiate_prefab import InstantiatePrefab_ContainingASingleEntity as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateAndDeletePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndDeletePrefab as test_module
|
||||
def test_DeletePrefab_ContainingASingleEntity(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.delete_prefab import DeletePrefab_ContainingASingleEntity as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateAndReparentPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndReparentPrefab as test_module
|
||||
def test_ReparentPrefab_UnderAnotherPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.reparent_prefab import ReparentPrefab_UnderAnotherPrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateReparentAndDetachPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateReparentAndDetachPrefab as test_module
|
||||
def test_DetachPrefab_UnderAnotherPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.detach_prefab import DetachPrefab_UnderAnotherPrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateAndDuplicatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndDuplicatePrefab as test_module
|
||||
def test_DuplicatePrefab_ContainingASingleEntity(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.duplicate_prefab import DuplicatePrefab_ContainingASingleEntity as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_PrefabComplexWorflow_CreatePrefabOfChildEntity(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabComplexWorflow_CreatePrefabOfChildEntity as test_module
|
||||
def test_CreatePrefab_UnderAnEntity(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.create_prefab import CreatePrefab_UnderAnEntity as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
def test_PrefabComplexWorflow_CreatePrefabInsidePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabComplexWorflow_CreatePrefabInsidePrefab as test_module
|
||||
def test_CreatePrefab_UnderAnotherPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from Prefab.tests.create_prefab import CreatePrefab_UnderAnotherPrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabComplexWorflow_CreatePrefabOfChildEntity():
|
||||
def CreatePrefab_UnderAnEntity():
|
||||
"""
|
||||
Test description:
|
||||
- Creates two entities, parent and child. Child entity has Parent entity as its parent.
|
||||
@@ -18,7 +18,7 @@ def PrefabComplexWorflow_CreatePrefabOfChildEntity():
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -49,4 +49,4 @@ def PrefabComplexWorflow_CreatePrefabOfChildEntity():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabComplexWorflow_CreatePrefabOfChildEntity)
|
||||
Report.start_test(CreatePrefab_UnderAnEntity)
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabComplexWorflow_CreatePrefabInsidePrefab():
|
||||
def CreatePrefab_UnderAnotherPrefab():
|
||||
"""
|
||||
Test description:
|
||||
- Creates an entity with a physx collider
|
||||
@@ -17,7 +17,7 @@ def PrefabComplexWorflow_CreatePrefabInsidePrefab():
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -54,4 +54,4 @@ def PrefabComplexWorflow_CreatePrefabInsidePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabComplexWorflow_CreatePrefabInsidePrefab)
|
||||
Report.start_test(CreatePrefab_UnderAnotherPrefab)
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreatePrefab():
|
||||
def CreatePrefab_WithSingleEntity():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
@@ -13,7 +13,7 @@ def PrefabBasicWorkflow_CreatePrefab():
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -26,4 +26,4 @@ def PrefabBasicWorkflow_CreatePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreatePrefab)
|
||||
Report.start_test(CreatePrefab_WithSingleEntity)
|
||||
+3
-3
@@ -5,14 +5,14 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateAndDeletePrefab():
|
||||
def DeletePrefab_ContainingASingleEntity():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -29,4 +29,4 @@ def PrefabBasicWorkflow_CreateAndDeletePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndDeletePrefab)
|
||||
Report.start_test(DeletePrefab_ContainingASingleEntity)
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateReparentAndDetachPrefab():
|
||||
def DetachPrefab_UnderAnotherPrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab'
|
||||
@@ -18,7 +18,7 @@ def PrefabBasicWorkflow_CreateReparentAndDetachPrefab():
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -48,4 +48,4 @@ def PrefabBasicWorkflow_CreateReparentAndDetachPrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateReparentAndDetachPrefab)
|
||||
Report.start_test(DetachPrefab_UnderAnotherPrefab)
|
||||
+3
-3
@@ -5,14 +5,14 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateAndDuplicatePrefab():
|
||||
def DuplicatePrefab_ContainingASingleEntity():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -29,4 +29,4 @@ def PrefabBasicWorkflow_CreateAndDuplicatePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndDuplicatePrefab)
|
||||
Report.start_test(DuplicatePrefab_ContainingASingleEntity)
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_InstantiatePrefab():
|
||||
def InstantiatePrefab_ContainingASingleEntity():
|
||||
|
||||
from azlmbr.math import Vector3
|
||||
|
||||
@@ -15,7 +15,7 @@ def PrefabBasicWorkflow_InstantiatePrefab():
|
||||
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -30,4 +30,4 @@ def PrefabBasicWorkflow_InstantiatePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_InstantiatePrefab)
|
||||
Report.start_test(InstantiatePrefab_ContainingASingleEntity)
|
||||
+2
-2
@@ -14,7 +14,7 @@ class Tests():
|
||||
|
||||
# fmt:on
|
||||
|
||||
def PrefabLevel_OpensLevelWithEntities():
|
||||
def OpenLevel_ContainingTwoEntities():
|
||||
"""
|
||||
Opens the level that contains 2 entities, "EmptyEntity" and "EntityWithPxCollider".
|
||||
This test makes sure that both entities exist after opening the level and that:
|
||||
@@ -70,4 +70,4 @@ def PrefabLevel_OpensLevelWithEntities():
|
||||
if __name__ == "__main__":
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabLevel_OpensLevelWithEntities)
|
||||
Report.start_test(OpenLevel_ContainingTwoEntities)
|
||||
+3
-3
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateAndReparentPrefab():
|
||||
def ReparentPrefab_UnderAnotherPrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab'
|
||||
@@ -18,7 +18,7 @@ def PrefabBasicWorkflow_CreateAndReparentPrefab():
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
import Prefab.tests.PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
@@ -45,4 +45,4 @@ def PrefabBasicWorkflow_CreateAndReparentPrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndReparentPrefab)
|
||||
Report.start_test(ReparentPrefab_UnderAnotherPrefab)
|
||||
@@ -8,42 +8,54 @@ import azlmbr.bus
|
||||
import azlmbr.asset
|
||||
import azlmbr.editor
|
||||
import azlmbr.math
|
||||
import azlmbr.legacy.general
|
||||
|
||||
def raise_and_stop(msg):
|
||||
print (msg)
|
||||
print('Starting mock asset tests')
|
||||
handler = azlmbr.editor.EditorEventBusHandler()
|
||||
|
||||
def on_notify_editor_initialized(args):
|
||||
# These tests are meant to check that the test_asset.mock source asset turned into
|
||||
# a test_asset.mock_asset product asset via the Python asset builder system
|
||||
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
|
||||
mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset'
|
||||
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False)
|
||||
if (assetId.is_valid() is False):
|
||||
print(f'Mock AssetId is not valid! Got {assetId.to_string()} instead')
|
||||
else:
|
||||
print(f'Mock AssetId is valid!')
|
||||
|
||||
assetIdString = assetId.to_string()
|
||||
if (assetIdString.endswith(':528cca58') is False):
|
||||
print(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!')
|
||||
else:
|
||||
print(f'Mock AssetId has expected sub-id for {mockAssetPath}!')
|
||||
|
||||
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):
|
||||
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 (assetId.is_valid()):
|
||||
print(f'AssetId found for asset ({generatedModelAssetPath}) found')
|
||||
else:
|
||||
print(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!')
|
||||
|
||||
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')
|
||||
|
||||
# clear up notification handler
|
||||
global handler
|
||||
handler.disconnect()
|
||||
handler = None
|
||||
|
||||
print('Finished mock asset tests')
|
||||
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
|
||||
|
||||
# These tests are meant to check that the test_asset.mock source asset turned into
|
||||
# a test_asset.mock_asset product asset via the Python asset builder system
|
||||
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
|
||||
mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset'
|
||||
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False)
|
||||
if (assetId.is_valid() is False):
|
||||
raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead')
|
||||
|
||||
assetIdString = assetId.to_string()
|
||||
if (assetIdString.endswith(':528cca58') is False):
|
||||
raise_and_stop(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!')
|
||||
|
||||
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):
|
||||
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 (assetId.is_valid()):
|
||||
print(f'AssetId found for asset ({generatedModelAssetPath}) found')
|
||||
else:
|
||||
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_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')
|
||||
handler.connect()
|
||||
handler.add_callback('NotifyEditorInitialized', on_notify_editor_initialized)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::TerrainTests_Main
|
||||
TEST_SUITE main
|
||||
TEST_SERIAL
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::Editor
|
||||
AZ::AssetProcessor
|
||||
AutomatedTesting.Assets
|
||||
COMPONENT
|
||||
Terrain
|
||||
)
|
||||
|
||||
endif()
|
||||
+89
@@ -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
|
||||
"""
|
||||
|
||||
#fmt: off
|
||||
class Tests():
|
||||
create_test_entity = ("Entity created successfully", "Failed to create Entity")
|
||||
add_axis_aligned_box_shape = ("Axis Aligned Box Shape component added", "Failed to add Axis Aligned Box Shape component")
|
||||
add_terrain_collider = ("Terrain Physics Heightfield Collider component added", "Failed to add a Terrain Physics Heightfield Collider component")
|
||||
box_dimensions_changed = ("Aabb dimensions changed successfully", "Failed change Aabb dimensions")
|
||||
configuration_changed = ("Terrain size changed successfully", "Failed terrain size change")
|
||||
#fmt: on
|
||||
|
||||
def TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges():
|
||||
"""
|
||||
Summary:
|
||||
Test aspects of the Terrain Physics Heightfield Collider through the BehaviorContext and the Property Tree.
|
||||
|
||||
Test Steps:
|
||||
Expected Behavior:
|
||||
The Editor is stable there are no warnings or errors.
|
||||
|
||||
Test Steps:
|
||||
1) Load the base level
|
||||
2) Create test entity
|
||||
3) Start the Tracer to catch any errors and warnings
|
||||
4) Add the Axis Aligned Box Shape and Terrain Physics Heightfield Collider components
|
||||
5) Change the Axis Aligned Box Shape dimensions
|
||||
6) Check the Heightfield provider is returning the correct size
|
||||
7) Verify there are no errors and warnings in the logs
|
||||
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from editor_python_test_tools.utils import Report, Tracer
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.physics as physics
|
||||
import azlmbr.math as azmath
|
||||
import azlmbr.bus as bus
|
||||
import sys
|
||||
import math
|
||||
|
||||
SET_BOX_X_SIZE = 5.0
|
||||
SET_BOX_Y_SIZE = 6.0
|
||||
EXPECTED_COLUMN_SIZE = SET_BOX_X_SIZE + 1
|
||||
EXPECTED_ROW_SIZE = SET_BOX_Y_SIZE + 1
|
||||
helper.init_idle()
|
||||
|
||||
# 1) Load the level
|
||||
helper.open_level("", "Base")
|
||||
|
||||
# 2) Create test entity
|
||||
test_entity = EditorEntity.create_editor_entity("TestEntity")
|
||||
Report.result(Tests.create_test_entity, test_entity.id.IsValid())
|
||||
|
||||
# 3) Start the Tracer to catch any errors and warnings
|
||||
with Tracer() as section_tracer:
|
||||
# 4) Add the Axis Aligned Box Shape and Terrain Physics Heightfield Collider components
|
||||
aaBoxShape_component = test_entity.add_component("Axis Aligned Box Shape")
|
||||
Report.result(Tests.add_axis_aligned_box_shape, test_entity.has_component("Axis Aligned Box Shape"))
|
||||
terrainPhysics_component = test_entity.add_component("Terrain Physics Heightfield Collider")
|
||||
Report.result(Tests.add_terrain_collider, test_entity.has_component("Terrain Physics Heightfield Collider"))
|
||||
|
||||
# 5) Change the Axis Aligned Box Shape dimensions
|
||||
aaBoxShape_component.set_component_property_value("Axis Aligned Box Shape|Box Configuration|Dimensions", azmath.Vector3(SET_BOX_X_SIZE, SET_BOX_Y_SIZE, 1.0))
|
||||
add_check = aaBoxShape_component.get_component_property_value("Axis Aligned Box Shape|Box Configuration|Dimensions") == azmath.Vector3(SET_BOX_X_SIZE, SET_BOX_Y_SIZE, 1.0)
|
||||
Report.result(Tests.box_dimensions_changed, add_check)
|
||||
|
||||
# 6) Check the Heightfield provider is returning the correct size
|
||||
columns = physics.HeightfieldProviderRequestsBus(bus.Broadcast, "GetHeightfieldGridColumns")
|
||||
rows = physics.HeightfieldProviderRequestsBus(bus.Broadcast, "GetHeightfieldGridRows")
|
||||
Report.result(Tests.configuration_changed, math.isclose(columns, EXPECTED_COLUMN_SIZE) and math.isclose(rows, EXPECTED_ROW_SIZE))
|
||||
|
||||
helper.wait_for_condition(lambda: section_tracer.has_errors or section_tracer.has_asserts, 1.0)
|
||||
for error_info in section_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in section_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges)
|
||||
@@ -0,0 +1,164 @@
|
||||
"""
|
||||
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_terrain_spawner_entity = ("Terrain_spawner_entity created successfully", "Failed to create terrain_spawner_entity")
|
||||
create_height_provider_entity = ("Height_provider_entity created successfully", "Failed to create height_provider_entity")
|
||||
create_test_ball = ("Ball created successfully", "Failed to create Ball")
|
||||
box_dimensions_changed = ("Aabb dimensions changed successfully", "Failed change Aabb dimensions")
|
||||
shape_changed = ("Shape changed successfully", "Failed Shape change")
|
||||
entity_added = ("Entity added successfully", "Failed Entity add")
|
||||
frequency_changed = ("Frequency changed successfully", "Failed Frequency change")
|
||||
shape_set = ("Shape set to Sphere successfully", "Failed to set Sphere shape")
|
||||
test_collision = ("Ball collided with terrain", "Ball failed to collide with terrain")
|
||||
no_errors_and_warnings_found = ("No errors and warnings found", "Found errors and warnings")
|
||||
#fmt: on
|
||||
|
||||
def Terrain_SupportsPhysics():
|
||||
"""
|
||||
Summary:
|
||||
Test aspects of the TerrainHeightGradientList through the BehaviorContext and the Property Tree.
|
||||
|
||||
Test Steps:
|
||||
Expected Behavior:
|
||||
The Editor is stable there are no warnings or errors.
|
||||
|
||||
Test Steps:
|
||||
1) Load the base level
|
||||
2) Create 2 test entities, one parent at 512.0, 512.0, 50.0 and one child at the default position and add the required components
|
||||
2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time
|
||||
3) Start the Tracer to catch any errors and warnings
|
||||
4) Change the Axis Aligned Box Shape dimensions
|
||||
5) Set the Vegetation Shape reference to TestEntity1
|
||||
6) Set the FastNoise gradient frequency to 0.01
|
||||
7) Set the Gradient List to TestEntity2
|
||||
8) Set the PhysX Collider to Sphere mode
|
||||
9) Disable and Enable the Terrain Gradient List so that it is recognised
|
||||
10) Enter game mode and test if the ball hits the heightfield within 3 seconds
|
||||
11) Verify there are no errors and warnings in the logs
|
||||
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import TestHelper as helper, Report
|
||||
from editor_python_test_tools.utils import Report, Tracer
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
import azlmbr.math as azmath
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import math
|
||||
|
||||
SET_BOX_X_SIZE = 1024.0
|
||||
SET_BOX_Y_SIZE = 1024.0
|
||||
SET_BOX_Z_SIZE = 100.0
|
||||
|
||||
helper.init_idle()
|
||||
|
||||
# 1) Load the level
|
||||
helper.open_level("", "Base")
|
||||
helper.wait_for_condition(lambda: general.get_current_level_name() == "Base", 2.0)
|
||||
|
||||
#1a) Load the level components
|
||||
hydra.add_level_component("Terrain World")
|
||||
hydra.add_level_component("Terrain World Renderer")
|
||||
|
||||
# 2) Create 2 test entities, one parent at 512.0, 512.0, 50.0 and one child at the default position and add the required components
|
||||
entity1_components_to_add = ["Axis Aligned Box Shape", "Terrain Layer Spawner", "Terrain Height Gradient List", "Terrain Physics Heightfield Collider", "PhysX Heightfield Collider"]
|
||||
entity2_components_to_add = ["Vegetation Reference Shape", "Gradient Transform Modifier", "FastNoise Gradient"]
|
||||
ball_components_to_add = ["Sphere Shape", "PhysX Collider", "PhysX Rigid Body"]
|
||||
terrain_spawner_entity = hydra.Entity("TestEntity1")
|
||||
terrain_spawner_entity.create_entity(azmath.Vector3(512.0, 512.0, 50.0), entity1_components_to_add)
|
||||
Report.result(Tests.create_terrain_spawner_entity, terrain_spawner_entity.id.IsValid())
|
||||
height_provider_entity = hydra.Entity("TestEntity2")
|
||||
height_provider_entity.create_entity(azmath.Vector3(0.0, 0.0, 0.0), entity2_components_to_add,terrain_spawner_entity.id)
|
||||
Report.result(Tests.create_height_provider_entity, height_provider_entity.id.IsValid())
|
||||
# 2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time
|
||||
ball = hydra.Entity("Ball")
|
||||
ball.create_entity(azmath.Vector3(600.0, 600.0, 46.0), ball_components_to_add)
|
||||
Report.result(Tests.create_test_ball, ball.id.IsValid())
|
||||
# Give everything a chance to finish initializing.
|
||||
general.idle_wait_frames(1)
|
||||
|
||||
# 3) Start the Tracer to catch any errors and warnings
|
||||
with Tracer() as section_tracer:
|
||||
# 4) Change the Axis Aligned Box Shape dimensions
|
||||
box_dimensions = azmath.Vector3(SET_BOX_X_SIZE, SET_BOX_Y_SIZE, SET_BOX_Z_SIZE)
|
||||
terrain_spawner_entity.get_set_test(0, "Axis Aligned Box Shape|Box Configuration|Dimensions", box_dimensions)
|
||||
box_shape_dimensions = hydra.get_component_property_value(terrain_spawner_entity.components[0], "Axis Aligned Box Shape|Box Configuration|Dimensions")
|
||||
Report.result(Tests.box_dimensions_changed, box_dimensions == box_shape_dimensions)
|
||||
|
||||
# 5) Set the Vegetaion Shape reference to TestEntity1
|
||||
height_provider_entity.get_set_test(0, "Configuration|Shape Entity Id", terrain_spawner_entity.id)
|
||||
entityId = hydra.get_component_property_value(height_provider_entity.components[0], "Configuration|Shape Entity Id")
|
||||
Report.result(Tests.shape_changed, entityId == terrain_spawner_entity.id)
|
||||
|
||||
# 6) Set the FastNoise Gradient frequency to 0.01
|
||||
Frequency = 0.01
|
||||
height_provider_entity.get_set_test(2, "Configuration|Frequency", Frequency)
|
||||
FrequencyVal = hydra.get_component_property_value(height_provider_entity.components[2], "Configuration|Frequency")
|
||||
Report.result(Tests.frequency_changed, math.isclose(Frequency, FrequencyVal, abs_tol = 0.00001))
|
||||
|
||||
# 7) Set the Gradient List to TestEntity2
|
||||
propertyTree = hydra.get_property_tree(terrain_spawner_entity.components[2])
|
||||
propertyTree.add_container_item("Configuration|Gradient Entities", 0, height_provider_entity.id)
|
||||
checkID = propertyTree.get_container_item("Configuration|Gradient Entities", 0)
|
||||
Report.result(Tests.entity_added, checkID.GetValue() == height_provider_entity.id)
|
||||
|
||||
# 8) Set the PhysX Collider to Sphere mode
|
||||
shape = 0
|
||||
hydra.get_set_test(ball, 1, "Shape Configuration|Shape", shape)
|
||||
setShape = hydra.get_component_property_value(ball.components[1], "Shape Configuration|Shape")
|
||||
Report.result(Tests.shape_set, shape == setShape)
|
||||
|
||||
# 9) Disable and Enable the Terrain Gradient List so that it is recognised
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, 'EnableComponents', [terrain_spawner_entity.components[2]])
|
||||
|
||||
general.enter_game_mode()
|
||||
|
||||
general.idle_wait_frames(1)
|
||||
|
||||
# 10) Enter game mode and test if the ball hits the heightfield within 3 seconds
|
||||
TIMEOUT = 3.0
|
||||
|
||||
class Collider:
|
||||
id = general.find_game_entity("Ball")
|
||||
touched_ground = False
|
||||
|
||||
terrain_id = general.find_game_entity("TestEntity1")
|
||||
|
||||
def on_collision_begin(args):
|
||||
other_id = args[0]
|
||||
if other_id.Equal(terrain_id):
|
||||
Report.info("Touched ground")
|
||||
Collider.touched_ground = True
|
||||
|
||||
handler = azlmbr.physics.CollisionNotificationBusHandler()
|
||||
handler.connect(Collider.id)
|
||||
handler.add_callback("OnCollisionBegin", on_collision_begin)
|
||||
|
||||
helper.wait_for_condition(lambda: Collider.touched_ground, TIMEOUT)
|
||||
Report.result(Tests.test_collision, Collider.touched_ground)
|
||||
|
||||
general.exit_game_mode()
|
||||
|
||||
# 11) Verify there are no errors and warnings in the logs
|
||||
helper.wait_for_condition(lambda: section_tracer.has_errors or section_tracer.has_asserts, 1.0)
|
||||
for error_info in section_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in section_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Terrain_SupportsPhysics)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
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
|
||||
|
||||
"""
|
||||
|
||||
# This suite consists of all test cases that are passing and have been verified.
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ly_test_tools import LAUNCHERS
|
||||
from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSharedTest
|
||||
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
class TestAutomation(EditorTestSuite):
|
||||
|
||||
class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSharedTest):
|
||||
from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module
|
||||
|
||||
class test_Terrain_SupportsPhysics(EditorSharedTest):
|
||||
from .EditorScripts import Terrain_SupportsPhysics as test_module
|
||||
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
+1
-1
@@ -158,7 +158,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
|
||||
else:
|
||||
cmd.append(f"--{key}")
|
||||
if append_defaults:
|
||||
cmd.append(f"--project-path={os.path.join(workspace.paths.engine_root(), workspace.project)}")
|
||||
cmd.append(f"--project-path={workspace.paths.project()}")
|
||||
return cmd
|
||||
|
||||
# ******
|
||||
|
||||
+55
-222
@@ -88,214 +88,6 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
bundler_batch_helper.call_bundles(help="")
|
||||
bundler_batch_helper.call_bundleSeed(help="")
|
||||
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.assetpipeline
|
||||
@pytest.mark.test_case_id("C16877175")
|
||||
@pytest.mark.skip("'animations/animationeditorfiles/sample1.animgraph' missing, needs investigation")
|
||||
def test_WindowsAndMac_CreateAssetList_DependenciesCorrect(self, workspace, bundler_batch_helper):
|
||||
r"""
|
||||
Tests that an asset list created maps dependencies correctly.
|
||||
testdependencieslevel\level.pak and lists of known dependencies are used for validation
|
||||
|
||||
Test Steps:
|
||||
1. Create an asset list from the level.pak
|
||||
2. Create Lists of expected assets in the level.pak
|
||||
3. Add lists of expected assets to a single list
|
||||
4. Compare list of expected assets to actual assets
|
||||
"""
|
||||
helper = bundler_batch_helper
|
||||
|
||||
# Create the asset list file
|
||||
helper.call_assetLists(
|
||||
addSeed=r"levels\testdependencieslevel\level.pak",
|
||||
assetListFile=helper['asset_info_file_request']
|
||||
)
|
||||
|
||||
assert os.path.isfile(helper["asset_info_file_result"])
|
||||
|
||||
# Lists of known relative locations of assets
|
||||
default_level_assets = [
|
||||
"engineassets/texturemsg/defaultnouvs.dds",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.1",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.2",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.3",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.4",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.5",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.6",
|
||||
"engineassets/texturemsg/defaultnouvs.dds.7",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds.1",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds.2",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds.3",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds.4",
|
||||
"engineassets/texturemsg/defaultnouvs_ddn.dds.5",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds.1",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds.2",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds.3",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds.4",
|
||||
"engineassets/texturemsg/defaultnouvs_spec.dds.5",
|
||||
"engineassets/textures/defaults/16_grey.dds",
|
||||
"engineassets/textures/cubemap/default_level_cubemap.dds",
|
||||
"engineassets/textures/cubemap/default_level_cubemap.dds.1",
|
||||
"engineassets/textures/cubemap/default_level_cubemap.dds.2",
|
||||
"engineassets/textures/cubemap/default_level_cubemap.dds.3",
|
||||
"engineassets/textures/cubemap/default_level_cubemap.dds.4",
|
||||
"engineassets/textures/cubemap/default_level_cubemap_diff.dds",
|
||||
"engineassets/materials/water/ocean_default.mtl",
|
||||
"engineassets/textures/defaults/spot_default.dds",
|
||||
"engineassets/textures/defaults/spot_default.dds.1",
|
||||
"engineassets/textures/defaults/spot_default.dds.2",
|
||||
"engineassets/textures/defaults/spot_default.dds.3",
|
||||
"engineassets/textures/defaults/spot_default.dds.4",
|
||||
"engineassets/textures/defaults/spot_default.dds.5",
|
||||
"materials/material_terrain_default.mtl",
|
||||
"textures/skys/night/half_moon.dds",
|
||||
"textures/skys/night/half_moon.dds.1",
|
||||
"textures/skys/night/half_moon.dds.2",
|
||||
"textures/skys/night/half_moon.dds.3",
|
||||
"textures/skys/night/half_moon.dds.4",
|
||||
"textures/skys/night/half_moon.dds.5",
|
||||
"textures/skys/night/half_moon.dds.6",
|
||||
"engineassets/materials/sky/sky.mtl",
|
||||
"levels/testdependencieslevel/level.pak",
|
||||
"levels/testdependencieslevel/terrain/cover.ctc",
|
||||
"levels/testdependencieslevel/terraintexture.pak",
|
||||
]
|
||||
|
||||
sequence_material_cube_assets = [
|
||||
"textures/test_texture_sequence/test_texture_sequence000.dds",
|
||||
"textures/test_texture_sequence/test_texture_sequence001.dds",
|
||||
"textures/test_texture_sequence/test_texture_sequence002.dds",
|
||||
"textures/test_texture_sequence/test_texture_sequence003.dds",
|
||||
"textures/test_texture_sequence/test_texture_sequence004.dds",
|
||||
"textures/test_texture_sequence/test_texture_sequence005.dds",
|
||||
"objects/_primitives/_box_1x1.cgf",
|
||||
"materials/test_texture_sequence.mtl",
|
||||
"objects/_primitives/_box_1x1.mtl",
|
||||
"textures/_primitives/middle_gray_checker.dds",
|
||||
"textures/_primitives/middle_gray_checker.dds.1",
|
||||
"textures/_primitives/middle_gray_checker.dds.2",
|
||||
"textures/_primitives/middle_gray_checker.dds.3",
|
||||
"textures/_primitives/middle_gray_checker.dds.4",
|
||||
"textures/_primitives/middle_gray_checker.dds.5",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds.1",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds.2",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds.3",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds.4",
|
||||
"textures/_primitives/middle_gray_checker_ddn.dds.5",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds.1",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds.2",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds.3",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds.4",
|
||||
"textures/_primitives/middle_gray_checker_spec.dds.5",
|
||||
]
|
||||
|
||||
character_with_simplified_material_assets = [
|
||||
"objects/characters/jack/jack.actor",
|
||||
"objects/characters/jack/jack.mtl",
|
||||
"objects/characters/jack/textures/jack_diff.dds",
|
||||
"objects/characters/jack/textures/jack_diff.dds.1",
|
||||
"objects/characters/jack/textures/jack_diff.dds.2",
|
||||
"objects/characters/jack/textures/jack_diff.dds.3",
|
||||
"objects/characters/jack/textures/jack_diff.dds.4",
|
||||
"objects/characters/jack/textures/jack_diff.dds.5",
|
||||
"objects/characters/jack/textures/jack_diff.dds.6",
|
||||
"objects/characters/jack/textures/jack_diff.dds.7",
|
||||
"objects/characters/jack/textures/jack_spec.dds",
|
||||
"objects/characters/jack/textures/jack_spec.dds.1",
|
||||
"objects/characters/jack/textures/jack_spec.dds.2",
|
||||
"objects/characters/jack/textures/jack_spec.dds.3",
|
||||
"objects/characters/jack/textures/jack_spec.dds.4",
|
||||
"objects/characters/jack/textures/jack_spec.dds.5",
|
||||
"objects/characters/jack/textures/jack_spec.dds.6",
|
||||
"objects/characters/jack/textures/jack_spec.dds.7",
|
||||
"objects/default/editorprimitive.mtl",
|
||||
"engineassets/textures/grey.dds",
|
||||
"animations/animationeditorfiles/sample0.animgraph",
|
||||
"animations/motions/jack_death_fall_back_zup.motion",
|
||||
"animations/animationeditorfiles/sample1.animgraph",
|
||||
"animations/animationeditorfiles/sample0.motionset",
|
||||
"animations/motions/rin_jump.motion",
|
||||
"animations/animationeditorfiles/sample1.motionset",
|
||||
"animations/motions/rin_idle.motion",
|
||||
"animations/motions/jack_idle_aim_zup.motion",
|
||||
]
|
||||
|
||||
spawner_assets = [
|
||||
"slices/sphere.dynamicslice",
|
||||
"objects/default/primitive_sphere.cgf",
|
||||
"test1.luac",
|
||||
"test2.luac",
|
||||
]
|
||||
|
||||
ui_canvas_assets = [
|
||||
"fonts/vera.ttf",
|
||||
"fonts/vera.font",
|
||||
"scriptcanvas/mainmenu.scriptcanvas_compiled",
|
||||
"fonts/vera.fontfamily",
|
||||
"ui/canvas/start.uicanvas",
|
||||
"fonts/vera-italic.font",
|
||||
"ui/textureatlas/sample.texatlasidx",
|
||||
"fonts/vera-bold-italic.ttf",
|
||||
"fonts/vera-bold.font",
|
||||
"ui/textures/prefab/button_normal.dds",
|
||||
"ui/textures/prefab/button_normal.sprite",
|
||||
"fonts/vera-italic.ttf",
|
||||
"ui/textureatlas/sample.dds",
|
||||
"fonts/vera-bold-italic.font",
|
||||
"fonts/vera-bold.ttf",
|
||||
"ui/textures/prefab/button_disabled.dds",
|
||||
"ui/textures/prefab/button_disabled.sprite",
|
||||
]
|
||||
|
||||
wwise_and_atl_assets = [
|
||||
"libs/gameaudio/wwise/levels/testdependencieslevel/test_dependencies_level.xml",
|
||||
"sounds/wwise/test_bank3.bnk",
|
||||
"sounds/wwise/test_bank4.bnk",
|
||||
"sounds/wwise/test_bank5.bnk",
|
||||
"sounds/wwise/test_bank1.bnk",
|
||||
"sounds/wwise/init.bnk",
|
||||
"sounds/wwise/499820003.wem",
|
||||
"sounds/wwise/196049145.wem",
|
||||
]
|
||||
|
||||
particle_library_assets = [
|
||||
"libs/particles/milestone2particles.xml",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds.1",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds.2",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds.3",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds.4",
|
||||
"textures/milestone2/particles/fx_launchermuzzlering_01.dds.5",
|
||||
"textures/milestone2/particles/fx_sparkstreak_01.dds",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds.1",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds.2",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds.3",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds.4",
|
||||
"textures/milestone2/particles/fx_launchermuzzlefront_01.dds.5",
|
||||
]
|
||||
|
||||
lens_flares_library_assets = ["libs/flares/flares.xml", "textures/lights/flare01.dds"]
|
||||
|
||||
expected_assets_list = default_level_assets
|
||||
expected_assets_list.extend(sequence_material_cube_assets)
|
||||
expected_assets_list.extend(character_with_simplified_material_assets)
|
||||
expected_assets_list.extend(spawner_assets)
|
||||
expected_assets_list.extend(ui_canvas_assets)
|
||||
expected_assets_list.extend(wwise_and_atl_assets)
|
||||
expected_assets_list.extend(particle_library_assets)
|
||||
expected_assets_list.extend(lens_flares_library_assets) # All expected assets
|
||||
|
||||
# Get actual calculated dependencies from the asset list created
|
||||
actual_assets_list = []
|
||||
for rel_path in helper.get_asset_relative_paths(helper["asset_info_file_result"]):
|
||||
actual_assets_list.append(rel_path)
|
||||
|
||||
assert sorted(actual_assets_list) == sorted(expected_assets_list)
|
||||
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.assetpipeline
|
||||
@@ -310,9 +102,9 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
3. Read and store contents of asset list into memory
|
||||
4. Attempt to create a new asset list in without using --allowOverwrites
|
||||
5. Verify that Asset Bundler returns false
|
||||
6. Verify that file contents of the orignally created asset list did not change from what was stored in memory
|
||||
6. Verify that file contents of the originally created asset list did not change from what was stored in memory
|
||||
7. Attempt to create a new asset list without debug while allowing overwrites
|
||||
8. Verify that file contents of the orignally created asset list changed from what was stored in memory
|
||||
8. Verify that file contents of the originally created asset list changed from what was stored in memory
|
||||
"""
|
||||
helper = bundler_batch_helper
|
||||
seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
|
||||
@@ -919,7 +711,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
# Extra arguments for pattern comparison
|
||||
cmd.extend([f"--filePatternType={pattern_type}", f"--filePattern={pattern}"])
|
||||
if workspace.project:
|
||||
cmd.append(f'--project-path={project_name}')
|
||||
cmd.append(f'--project-path={workspace.paths.project()}')
|
||||
return cmd
|
||||
# End generate_compare_command()
|
||||
|
||||
@@ -960,7 +752,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
output_mac_asset_list = helper.platform_file_name(last_output_arg, platform)
|
||||
|
||||
# Build execution command
|
||||
cmd = generate_compare_command(platform_arg, workspace.project)
|
||||
cmd = generate_compare_command(platform_arg, workspace.paths.project())
|
||||
|
||||
# Execute command
|
||||
subprocess.check_call(cmd)
|
||||
@@ -995,7 +787,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
f"--comparisonRulesFile={rule_file}",
|
||||
f"--comparisonType={args[1]}",
|
||||
r"--addComparison",
|
||||
f"--project-path={workspace.project}",
|
||||
f"--project-path={workspace.paths.project()}",
|
||||
]
|
||||
if args[1] == "4":
|
||||
# If pattern comparison, append a few extra arguments
|
||||
@@ -1117,7 +909,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
"--addDefaultSeedListFiles",
|
||||
"--platform=pc",
|
||||
"--print",
|
||||
f"--project-path={workspace.project}"
|
||||
f"--project-path={workspace.paths.project()}"
|
||||
],
|
||||
universal_newlines=True,
|
||||
)
|
||||
@@ -1189,7 +981,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
# Make sure file gets deleted on teardown
|
||||
request.addfinalizer(lambda: fs.delete([bundle_result_path], True, False))
|
||||
|
||||
bundles_folder = os.path.join(workspace.paths.engine_root(), workspace.project, "Bundles")
|
||||
bundles_folder = os.path.join(workspace.paths.project(), "Bundles")
|
||||
level_pak = r"levels\testdependencieslevel\level.pak"
|
||||
bundle_request_path = os.path.join(bundles_folder, "bundle.pak")
|
||||
bundle_result_path = os.path.join(bundles_folder,
|
||||
@@ -1243,23 +1035,64 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
|
||||
2. Verify file was created
|
||||
3. Verify that only the expected assets are present in the created asset list
|
||||
"""
|
||||
expected_assets = [
|
||||
expected_assets = sorted([
|
||||
"ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
|
||||
"ui/textures/prefab/button_normal.sprite"
|
||||
]
|
||||
"ui/textures/prefab/button_disabled.tif.streamingimage",
|
||||
"ui/textures/prefab/tooltip_sliced.tif.streamingimage",
|
||||
"ui/textures/prefab/button_normal.tif.streamingimage"
|
||||
])
|
||||
# Printing these lists out can save a step in debugging if this test fails on Jenkins.
|
||||
logger.info(f"expected_assets: {expected_assets}")
|
||||
|
||||
skip_assets = sorted([
|
||||
"ui/scripts/lyshineexamples/animation/multiplesequences.luac",
|
||||
"ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac",
|
||||
"fonts/vera.fontfamily",
|
||||
"fonts/vera-italic.font",
|
||||
"fonts/vera.font",
|
||||
"fonts/vera-bold.font",
|
||||
"fonts/vera-bold-italic.font",
|
||||
"fonts/vera-italic.ttf",
|
||||
"fonts/vera.ttf",
|
||||
"fonts/vera-bold.ttf",
|
||||
"fonts/vera-bold-italic.ttf"
|
||||
])
|
||||
logger.info(f"skip_assets: {skip_assets}")
|
||||
|
||||
expected_and_skip_assets = sorted(expected_assets + skip_assets)
|
||||
# Printing both together to make it quick to compare the results in the logs for a test failure on Jenkins
|
||||
logger.info(f"expected_and_skip_assets: {expected_and_skip_assets}")
|
||||
|
||||
# First, generate an asset info file without skipping, to get a list that can be used as a baseline to verify
|
||||
# the files were actually skipped, and not just missing.
|
||||
bundler_batch_helper.call_assetLists(
|
||||
assetListFile=bundler_batch_helper['asset_info_file_request'],
|
||||
addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas"
|
||||
)
|
||||
assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
|
||||
assets_in_no_skip_list = []
|
||||
for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]):
|
||||
assets_in_no_skip_list.append(rel_path)
|
||||
assets_in_no_skip_list = sorted(assets_in_no_skip_list)
|
||||
logger.info(f"assets_in_no_skip_list: {assets_in_no_skip_list}")
|
||||
assert assets_in_no_skip_list == expected_and_skip_assets
|
||||
|
||||
# Now generate an asset info file using the skip command, and verify the skip files are not in the list.
|
||||
bundler_batch_helper.call_assetLists(
|
||||
assetListFile=bundler_batch_helper['asset_info_file_request'],
|
||||
addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
|
||||
skip="ui/textures/prefab/button_disabled.sprite,ui/scripts/lyshineexamples/animation/multiplesequences.luac,"
|
||||
"ui/textures/prefab/tooltip_sliced.sprite,ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac,fonts/vera.fontfamily,fonts/vera-italic.font,"
|
||||
"fonts/vera.font,fonts/vera-bold.font,fonts/vera-bold-italic.font,fonts/vera-italic.ttf,fonts/vera.ttf,fonts/vera-bold.ttf,fonts/vera-bold-italic.ttf"
|
||||
allowOverwrites="",
|
||||
skip=','.join(skip_assets)
|
||||
)
|
||||
|
||||
assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
|
||||
assets_in_list = []
|
||||
for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]):
|
||||
assets_in_list.append(rel_path)
|
||||
assets_in_list = sorted(assets_in_list)
|
||||
logger.info(f"assets_in_list: {assets_in_list}")
|
||||
assert assets_in_list == expected_assets
|
||||
|
||||
assert sorted(assets_in_list) == sorted(expected_assets)
|
||||
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.assetpipeline
|
||||
|
||||
@@ -165,7 +165,7 @@ class TestAutomationBase:
|
||||
for line in f.readlines():
|
||||
error_str += f"|{log_basename}| {line}"
|
||||
except Exception as ex:
|
||||
error_str += "-- No log available --"
|
||||
error_str += f"-- No log available ({ex})--"
|
||||
|
||||
pytest.fail(error_str)
|
||||
|
||||
|
||||
+12
-7
@@ -62,7 +62,7 @@ def AssetBrowser_SearchFiltering():
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
|
||||
def verify_files_appeared(model, allowed_asset_extentions, parent_index=QtCore.QModelIndex()):
|
||||
def verify_files_appeared(model, allowed_asset_extensions, parent_index=QtCore.QModelIndex()):
|
||||
indexes = [parent_index]
|
||||
while len(indexes) > 0:
|
||||
parent_index = indexes.pop(0)
|
||||
@@ -71,7 +71,7 @@ def AssetBrowser_SearchFiltering():
|
||||
cur_data = cur_index.data(Qt.DisplayRole)
|
||||
if (
|
||||
"." in cur_data
|
||||
and (cur_data.lower().split(".")[-1] not in allowed_asset_extentions)
|
||||
and (cur_data.lower().split(".")[-1] not in allowed_asset_extensions)
|
||||
and not cur_data[-1] == ")"
|
||||
):
|
||||
Report.info(f"Incorrect file found: {cur_data}")
|
||||
@@ -94,16 +94,21 @@ def AssetBrowser_SearchFiltering():
|
||||
Report.info("Asset Browser is already open")
|
||||
editor_window = pyside_utils.get_editor_main_window()
|
||||
app = QtWidgets.QApplication.instance()
|
||||
|
||||
# 3) Type the name of an asset in the search bar and make sure only one asset is filtered in Asset browser
|
||||
|
||||
# 3) Type the name of an asset in the search bar and make sure it is filtered to and selectable
|
||||
asset_browser = editor_window.findChild(QtWidgets.QDockWidget, "Asset Browser")
|
||||
search_bar = asset_browser.findChild(QtWidgets.QLineEdit, "textSearch")
|
||||
search_bar.setText("cedar.fbx")
|
||||
asset_browser_tree = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTreeViewWidget")
|
||||
model_index = pyside_utils.find_child_by_pattern(asset_browser_tree, "cedar.fbx")
|
||||
pyside_utils.item_view_index_mouse_click(asset_browser_tree, model_index)
|
||||
asset_browser_table = asset_browser.findChild(QtWidgets.QTreeView, "m_assetBrowserTableViewWidget")
|
||||
found = await pyside_utils.wait_for_condition(lambda: pyside_utils.find_child_by_pattern(asset_browser_table, "cedar.fbx"), 5.0)
|
||||
if found:
|
||||
model_index = pyside_utils.find_child_by_pattern(asset_browser_table, "cedar.fbx")
|
||||
else:
|
||||
Report.result(Tests.asset_filtered, found)
|
||||
pyside_utils.item_view_index_mouse_click(asset_browser_table, model_index)
|
||||
is_filtered = await pyside_utils.wait_for_condition(
|
||||
lambda: asset_browser_tree.indexBelow(asset_browser_tree.currentIndex()) == QtCore.QModelIndex(), 5.0)
|
||||
lambda: asset_browser_table.currentIndex() == model_index, 5.0)
|
||||
Report.result(Tests.asset_filtered, is_filtered)
|
||||
|
||||
# 4) Click the "X" in the search bar.
|
||||
|
||||
+2
-2
@@ -84,8 +84,8 @@ def AssetBrowser_TreeNavigation():
|
||||
|
||||
# 3) Collapse all files initially
|
||||
main_window = editor_window.findChild(QtWidgets.QMainWindow)
|
||||
asset_browser = pyside_utils.find_child_by_hierarchy(main_window, ..., "Asset Browser")
|
||||
tree = pyside_utils.find_child_by_hierarchy(asset_browser, ..., "m_assetBrowserTreeViewWidget")
|
||||
asset_browser = pyside_utils.find_child_by_pattern(main_window, text="Asset Browser", type=QtWidgets.QDockWidget)
|
||||
tree = pyside_utils.find_child_by_pattern(asset_browser, "m_assetBrowserTreeViewWidget")
|
||||
scroll_area = tree.findChild(QtWidgets.QWidget, "qt_scrollarea_vcontainer")
|
||||
scroll_bar = scroll_area.findChild(QtWidgets.QScrollBar)
|
||||
tree.collapseAll()
|
||||
|
||||
@@ -140,13 +140,13 @@ def Docking_BasicDockedTools():
|
||||
|
||||
# 2.5,6) Send a console command.
|
||||
console_line_edit = console.findChild(QtWidgets.QLineEdit, "lineEdit")
|
||||
console_line_edit.setText("t_Scale 2")
|
||||
console_line_edit.setText("t_simulationTickScale 2")
|
||||
QtTest.QTest.keyClick(console_line_edit, QtCore.Qt.Key_Enter)
|
||||
general.get_cvar("t_Scale")
|
||||
Report.result(Tests.docked_console_works, general.get_cvar("t_Scale") == "2")
|
||||
general.get_cvar("t_simulationTickScale")
|
||||
Report.result(Tests.docked_console_works, general.get_cvar("t_simulationTickScale") == "2")
|
||||
|
||||
# Reset the altered cvar
|
||||
console_line_edit.setText("t_Scale 1")
|
||||
console_line_edit.setText("t_simulationTickScale 1")
|
||||
QtTest.QTest.keyClick(console_line_edit, QtCore.Qt.Key_Enter)
|
||||
|
||||
run_test()
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
"""
|
||||
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:
|
||||
entities_sorted = (
|
||||
"Entities sorted in the expected order",
|
||||
"Entities sorted in an incorrect order",
|
||||
)
|
||||
|
||||
|
||||
def EntityOutliner_EntityOrdering():
|
||||
"""
|
||||
Summary:
|
||||
Verify that manual entity ordering in the entity outliner works and is stable.
|
||||
|
||||
Expected Behavior:
|
||||
Several entities are created, some are manually ordered, and their order
|
||||
is maintained, even when new entities are added.
|
||||
|
||||
Test Steps:
|
||||
1) Open the empty Prefab Base level
|
||||
2) Add 5 entities to the outliner
|
||||
3) Move "Entity1" to the top of the order
|
||||
4) Move "Entity4" to the bottom of the order
|
||||
5) Add another new entity, ensure the rest of the order is unchanged
|
||||
"""
|
||||
|
||||
import editor_python_test_tools.pyside_utils as pyside_utils
|
||||
import azlmbr.legacy.general as general
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from PySide2 import QtCore, QtWidgets, QtGui, QtTest
|
||||
|
||||
# Grab the Editor, Entity Outliner, and Outliner Model
|
||||
editor_window = pyside_utils.get_editor_main_window()
|
||||
entity_outliner = pyside_utils.find_child_by_hierarchy(
|
||||
editor_window, ..., "EntityOutlinerWidgetUI", ..., "m_objectTree"
|
||||
)
|
||||
entity_outliner_model = entity_outliner.model()
|
||||
|
||||
# Get the outliner index for the root prefab container entity
|
||||
def get_root_prefab_container_index():
|
||||
return entity_outliner_model.index(0, 0)
|
||||
|
||||
# Get the outliner index for the top level entity of a given name
|
||||
def index_for_name(name):
|
||||
root_index = get_root_prefab_container_index()
|
||||
for row in range(entity_outliner_model.rowCount(root_index)):
|
||||
row_index = entity_outliner_model.index(row, 0, root_index)
|
||||
if row_index.data() == name:
|
||||
return row_index
|
||||
return None
|
||||
|
||||
# Validate that the outliner top level entity order matches the expected order
|
||||
def verify_entities_sorted(expected_order):
|
||||
actual_order = []
|
||||
root_index = get_root_prefab_container_index()
|
||||
for row in range(entity_outliner_model.rowCount(root_index)):
|
||||
row_index = entity_outliner_model.index(row, 0, root_index)
|
||||
actual_order.append(row_index.data())
|
||||
|
||||
sorted_correctly = actual_order == expected_order
|
||||
Report.result(Tests.entities_sorted, sorted_correctly)
|
||||
if not sorted_correctly:
|
||||
print(f"Expected entity order: {expected_order}")
|
||||
print(f"Actual entity order: {actual_order}")
|
||||
|
||||
# Creates an entity from the outliner context menu
|
||||
def create_entity():
|
||||
pyside_utils.trigger_context_menu_entry(
|
||||
entity_outliner, "Create entity", index=get_root_prefab_container_index()
|
||||
)
|
||||
# Wait a tick after entity creation to let events process
|
||||
general.idle_wait(0.0)
|
||||
|
||||
# Moves an entity (wrapped by move_entity_before and move_entity_after)
|
||||
def _move_entity(source_name, target_name, move_after=False):
|
||||
source_index = index_for_name(source_name)
|
||||
target_index = index_for_name(target_name)
|
||||
|
||||
target_row = target_index.row()
|
||||
if move_after:
|
||||
target_row += 1
|
||||
|
||||
# Generate MIME data and directly inject it into the model instead of
|
||||
# generating mouse click operations, as it's more reliable and we're
|
||||
# testing the underlying drag & drop logic as opposed to Qt's mouse
|
||||
# handling here
|
||||
mime_data = entity_outliner_model.mimeData([source_index])
|
||||
entity_outliner_model.dropMimeData(
|
||||
mime_data, QtCore.Qt.MoveAction, target_row, 0, target_index.parent()
|
||||
)
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
# Move an entity before another entity in the order by dragging the source above the target
|
||||
move_entity_before = lambda source_name, target_name: _move_entity(
|
||||
source_name, target_name, move_after=False
|
||||
)
|
||||
# Move an entity after another entity in the order by dragging the source beloew the target
|
||||
move_entity_after = lambda source_name, target_name: _move_entity(
|
||||
source_name, target_name, move_after=True
|
||||
)
|
||||
|
||||
expected_order = []
|
||||
|
||||
# 1) Open the empty Prefab Base level
|
||||
helper.init_idle()
|
||||
helper.open_level("Prefab", "Base")
|
||||
|
||||
# 2) Add 5 entities to the outliner
|
||||
ENTITIES_TO_ADD = 5
|
||||
for i in range(ENTITIES_TO_ADD):
|
||||
create_entity()
|
||||
|
||||
# Our new entity should be given a name with a number automatically
|
||||
new_entity = f"Entity{i+1}"
|
||||
# The new entity should be added to the top of its parent entity
|
||||
expected_order = [new_entity] + expected_order
|
||||
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 3) Move "Entity1" to the top of the order
|
||||
move_entity_before("Entity1", "Entity5")
|
||||
expected_order = ["Entity1", "Entity5", "Entity4", "Entity3", "Entity2"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 4) Move "Entity4" to the bottom of the order
|
||||
move_entity_after("Entity4", "Entity2")
|
||||
expected_order = ["Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 5) Add another new entity, ensure the rest of the order is unchanged
|
||||
create_entity()
|
||||
expected_order = ["Entity6", "Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
|
||||
Report.start_test(EntityOutliner_EntityOrdering)
|
||||
@@ -41,3 +41,15 @@ class TestAutomation(TestAutomationBase):
|
||||
from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module
|
||||
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False,
|
||||
use_null_renderer=False)
|
||||
|
||||
def test_EntityOutlienr_EntityOrdering(self, request, workspace, editor, launcher_platform):
|
||||
from .EditorScripts import EntityOutliner_EntityOrdering as test_module
|
||||
self._run_test(
|
||||
request,
|
||||
workspace,
|
||||
editor,
|
||||
test_module,
|
||||
batch_mode=False,
|
||||
autotest_mode=True,
|
||||
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
|
||||
)
|
||||
|
||||
@@ -43,7 +43,6 @@ class TestAutomationNoAutoTestMode(EditorTestSuite):
|
||||
class test_InputBindings_Add_Remove_Input_Events(EditorSharedTest):
|
||||
from .EditorScripts import InputBindings_Add_Remove_Input_Events as test_module
|
||||
|
||||
@pytest.mark.skip(reason="Crashes Editor: ATOM-15493")
|
||||
class test_AssetPicker_UI_UX(EditorSharedTest):
|
||||
from .EditorScripts import AssetPicker_UI_UX as test_module
|
||||
|
||||
@@ -60,7 +59,6 @@ class TestAutomationAutoTestMode(EditorTestSuite):
|
||||
class test_AssetBrowser_TreeNavigation(EditorSharedTest):
|
||||
from .EditorScripts import AssetBrowser_TreeNavigation as test_module
|
||||
|
||||
@pytest.mark.skip(reason="Crashes Editor: ATOM-15493")
|
||||
class test_AssetBrowser_SearchFiltering(EditorSharedTest):
|
||||
from .EditorScripts import AssetBrowser_SearchFiltering as test_module
|
||||
|
||||
@@ -74,6 +72,5 @@ class TestAutomationAutoTestMode(EditorTestSuite):
|
||||
class test_Menus_FileMenuOptions_Work(EditorSharedTest):
|
||||
from .EditorScripts import Menus_FileMenuOptions as test_module
|
||||
|
||||
|
||||
class test_BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(EditorSharedTest):
|
||||
from .EditorScripts import BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD as test_module
|
||||
|
||||
@@ -34,12 +34,10 @@ class TestAutomation(TestAutomationBase):
|
||||
from .EditorScripts import AssetBrowser_TreeNavigation as test_module
|
||||
self._run_test(request, workspace, editor, test_module, batch_mode=False)
|
||||
|
||||
@pytest.mark.skip(reason="Crashes Editor: ATOM-15493")
|
||||
def test_AssetBrowser_SearchFiltering(self, request, workspace, editor, launcher_platform):
|
||||
from .EditorScripts import AssetBrowser_SearchFiltering as test_module
|
||||
self._run_test(request, workspace, editor, test_module, batch_mode=False)
|
||||
|
||||
@pytest.mark.skip(reason="Crashes Editor: ATOM-15493")
|
||||
def test_AssetPicker_UI_UX(self, request, workspace, editor, launcher_platform):
|
||||
from .EditorScripts import AssetPicker_UI_UX as test_module
|
||||
self._run_test(request, workspace, editor, test_module, autotest_mode=False, batch_mode=False)
|
||||
|
||||
@@ -24,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
LargeWorlds
|
||||
)
|
||||
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::DynamicVegetationTests_Periodic
|
||||
TEST_SERIAL
|
||||
@@ -39,6 +38,20 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
LargeWorlds
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::DynamicVegetationTests_Periodic_Optimized
|
||||
TEST_SERIAL
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg/TestSuite_Periodic_Optimized.py
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
AutomatedTesting.Assets
|
||||
AutomatedTesting.GameLauncher
|
||||
COMPONENT
|
||||
LargeWorlds
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::DynamicVegetationTests_Main_Optimized
|
||||
TEST_SERIAL
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
|
||||
def DynVegUtils_TempPrefabCreationWorks():
|
||||
"""
|
||||
Summary:
|
||||
An existing level is opened. Each Prefab setup to be spawned by Dynamic Vegetation tests is created in memory and
|
||||
validated against existing test slice components/mesh assignments.
|
||||
|
||||
Expected Behavior:
|
||||
Temporary prefabs contain the expected components/assets.
|
||||
|
||||
Test Steps:
|
||||
1) Open an existing level
|
||||
2) Create each of the necessary temporary Mesh prefabs, and validate the component/mesh setups
|
||||
3) Create the necessary temporary PhysX Collider, and validate the component setup
|
||||
4) Report errors/asserts
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.math as math
|
||||
|
||||
from Prefab.tests import PrefabTestUtils as prefab_test_utils
|
||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||
from editor_python_test_tools.utils import Report, Tracer
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from editor_python_test_tools.prefab_utils import PrefabInstance
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Create dictionary for prefab filenames and paths to create using helper function
|
||||
mesh_prefabs = {
|
||||
"PinkFlower": os.path.join("assets", "objects", "foliage", "grass_flower_pink.azmodel"),
|
||||
"PurpleFlower": os.path.join("assets", "objects", "foliage", "grass_flower_purple.azmodel"),
|
||||
"1m_Cube": os.path.join("objects", "_primitives", "_box_1x1.azmodel"),
|
||||
"CedarTree": os.path.join("assets", "objects", "foliage", "cedar.azmodel"),
|
||||
"Bush": os.path.join("assets", "objects", "foliage", "bush_privet_01.azmodel"),
|
||||
}
|
||||
|
||||
# 1) Open an existing simple level
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# 2) Create each of the Mesh asset prefabs and validate that the prefab created successfully
|
||||
for prefab_filename, asset_path in mesh_prefabs.items():
|
||||
mesh_prefab_created = (
|
||||
f"Temporary mesh prefab: {prefab_filename} created successfully",
|
||||
f"Failed to create temporary mesh prefab: {prefab_filename}"
|
||||
)
|
||||
prefab = dynveg.create_temp_mesh_prefab(asset_path, prefab_filename)
|
||||
Report.result(mesh_prefab_created, helper.wait_for_condition(lambda:
|
||||
PrefabInstance.is_valid(prefab[1]), 3.0))
|
||||
|
||||
# 3) Create temp PhysX Collider prefab and validate that the prefab created successfully
|
||||
physx_prefab_filename = "CedarTree_Collision"
|
||||
physx_collider_prefab_created = (
|
||||
f"Temporary mesh prefab: {physx_prefab_filename} created successfully",
|
||||
f"Failed to create temporary mesh prefab: {physx_prefab_filename}"
|
||||
)
|
||||
test_physx_mesh_asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", os.path.join(
|
||||
"assets", "objects", "foliage", "cedar.pxmesh"), math.Uuid(), False)
|
||||
dynveg.create_temp_physx_mesh_collider(test_physx_mesh_asset_id, physx_prefab_filename)
|
||||
Report.result(physx_collider_prefab_created, helper.wait_for_condition(lambda:
|
||||
PrefabInstance.is_valid(prefab[1]), 3.0))
|
||||
|
||||
# 4) Report errors/asserts
|
||||
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(DynVegUtils_TempPrefabCreationWorks)
|
||||
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
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_main
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
class TestAutomation(EditorTestSuite):
|
||||
|
||||
global_extra_cmdline_args = ["-BatchMode", "-autotest_mode", "--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
|
||||
|
||||
class test_DynVegUtils_TempPrefabCreationWorks(EditorSharedTest):
|
||||
from .EditorScripts import DynVegUtils_TempPrefabCreationWorks as test_module
|
||||
+39
@@ -19,6 +19,45 @@ import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
|
||||
def create_temp_mesh_prefab(mesh_asset_path, prefab_filename):
|
||||
# Create initial entity
|
||||
root = EditorEntity.create_editor_entity(name=prefab_filename)
|
||||
assert root.exists(), "Failed to create entity"
|
||||
# Add mesh component
|
||||
mesh_component = root.add_component("Mesh")
|
||||
assert root.has_component("Mesh") and mesh_component.is_enabled(), "Failed to add/activate Mesh component"
|
||||
# Assign the specified mesh asset
|
||||
mesh_asset = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", mesh_asset_path, math.Uuid(), False)
|
||||
mesh_component.set_component_property_value("Controller|Configuration|Mesh Asset", mesh_asset)
|
||||
assert mesh_component.get_component_property_value("Controller|Configuration|Mesh Asset") == mesh_asset, \
|
||||
"Failed to set Mesh asset"
|
||||
# Create and return the temporary/in-memory prefab
|
||||
temp_prefab = Prefab.create_prefab([root], prefab_filename)
|
||||
return temp_prefab
|
||||
|
||||
|
||||
def create_temp_physx_mesh_collider(physx_mesh_id, prefab_filename):
|
||||
# Create initial entity
|
||||
root = EditorEntity.create_editor_entity(name=prefab_filename)
|
||||
assert root.exists(), "Failed to create entity"
|
||||
# Add PhysX Collider component
|
||||
collider_component = root.add_component("PhysX Collider")
|
||||
assert root.has_component("PhysX Collider") and collider_component.is_enabled(), \
|
||||
"Failed to add/activate PhysX Collider component"
|
||||
# Set the Collider's Shape Configuration field to PhysicsAsset, and assign the specified PhysX Mesh asset
|
||||
collider_component.set_component_property_value("Shape Configuration|Shape", 7)
|
||||
assert collider_component.get_component_property_value("Shape Configuration|Shape") == 7, \
|
||||
"Failed to set Collider Shape to PhysicsAsset"
|
||||
collider_component.set_component_property_value("Shape Configuration|Asset|PhysX Mesh", physx_mesh_id)
|
||||
assert collider_component.get_component_property_value("Shape Configuration|Asset|PhysX Mesh") == physx_mesh_id, \
|
||||
"Failed to assign PhysX Mesh asset"
|
||||
# Create and return the temporary/in-memory prefab
|
||||
temp_prefab = Prefab.create_prefab([root], prefab_filename)
|
||||
return temp_prefab
|
||||
|
||||
|
||||
def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z):
|
||||
|
||||
@@ -13,7 +13,10 @@ import os
|
||||
import pytest
|
||||
import subprocess
|
||||
|
||||
import ly_test_tools
|
||||
|
||||
|
||||
@pytest.mark.skipif(not ly_test_tools.WINDOWS, reason="Only succeeds on windows https://github.com/o3de/o3de/issues/5539")
|
||||
@pytest.mark.SUITE_smoke
|
||||
class TestCLIToolSerializeContextToolsWorks(object):
|
||||
def test_CLITool_SerializeContextTools_Works(self, build_directory):
|
||||
|
||||
@@ -11,10 +11,13 @@ Test should run in both gpu and non gpu
|
||||
import pytest
|
||||
import os
|
||||
from automatedtesting_shared.base import TestAutomationBase
|
||||
|
||||
import ly_test_tools
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
|
||||
|
||||
@pytest.mark.SUITE_smoke
|
||||
@pytest.mark.skipif(not ly_test_tools.WINDOWS, reason="Only succeeds on windows https://github.com/o3de/o3de/issues/5539")
|
||||
@pytest.mark.parametrize("launcher_platform", ["windows_editor"])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["temp_level"])
|
||||
@@ -28,4 +31,4 @@ class TestAutomation(TestAutomationBase):
|
||||
|
||||
from . import Editor_NewExistingLevels_Works as test_module
|
||||
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
self._run_test(request, workspace, editor, test_module, extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=false"])
|
||||
|
||||
@@ -1,52 +1,61 @@
|
||||
{
|
||||
"ContainerEntity": {
|
||||
"Id": "ContainerEntity",
|
||||
"Name": "Base",
|
||||
"Id": "Entity_[1146574390643]",
|
||||
"Name": "Level",
|
||||
"Components": {
|
||||
"Component_[10182366347512475253]": {
|
||||
"$type": "EditorPrefabComponent",
|
||||
"Id": 10182366347512475253
|
||||
"Component_[10641544592923449938]": {
|
||||
"$type": "EditorInspectorComponent",
|
||||
"Id": 10641544592923449938
|
||||
},
|
||||
"Component_[12917798267488243668]": {
|
||||
"$type": "EditorPendingCompositionComponent",
|
||||
"Id": 12917798267488243668
|
||||
},
|
||||
"Component_[3261249813163778338]": {
|
||||
"Component_[12039882709170782873]": {
|
||||
"$type": "EditorOnlyEntityComponent",
|
||||
"Id": 3261249813163778338
|
||||
"Id": 12039882709170782873
|
||||
},
|
||||
"Component_[3837204912784440039]": {
|
||||
"$type": "EditorDisabledCompositionComponent",
|
||||
"Id": 3837204912784440039
|
||||
"Component_[12265484671603697631]": {
|
||||
"$type": "EditorPendingCompositionComponent",
|
||||
"Id": 12265484671603697631
|
||||
},
|
||||
"Component_[4272963378099646759]": {
|
||||
"Component_[14126657869720434043]": {
|
||||
"$type": "EditorEntitySortComponent",
|
||||
"Id": 14126657869720434043,
|
||||
"ChildEntityOrderEntryArray": [
|
||||
{
|
||||
"EntityId": ""
|
||||
},
|
||||
{
|
||||
"EntityId": "",
|
||||
"SortIndex": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"Component_[15230859088967841193]": {
|
||||
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
|
||||
"Id": 4272963378099646759,
|
||||
"Id": 15230859088967841193,
|
||||
"Parent Entity": ""
|
||||
},
|
||||
"Component_[4848458548047175816]": {
|
||||
"$type": "EditorVisibilityComponent",
|
||||
"Id": 4848458548047175816
|
||||
"Component_[16239496886950819870]": {
|
||||
"$type": "EditorDisabledCompositionComponent",
|
||||
"Id": 16239496886950819870
|
||||
},
|
||||
"Component_[5787060997243919943]": {
|
||||
"$type": "EditorInspectorComponent",
|
||||
"Id": 5787060997243919943
|
||||
},
|
||||
"Component_[7804170251266531779]": {
|
||||
"$type": "EditorLockComponent",
|
||||
"Id": 7804170251266531779
|
||||
},
|
||||
"Component_[7874177159288365422]": {
|
||||
"$type": "EditorEntitySortComponent",
|
||||
"Id": 7874177159288365422
|
||||
},
|
||||
"Component_[8018146290632383969]": {
|
||||
"Component_[5688118765544765547]": {
|
||||
"$type": "EditorEntityIconComponent",
|
||||
"Id": 8018146290632383969
|
||||
"Id": 5688118765544765547
|
||||
},
|
||||
"Component_[8452360690590857075]": {
|
||||
"Component_[6545738857812235305]": {
|
||||
"$type": "SelectionComponent",
|
||||
"Id": 8452360690590857075
|
||||
"Id": 6545738857812235305
|
||||
},
|
||||
"Component_[7247035804068349658]": {
|
||||
"$type": "EditorPrefabComponent",
|
||||
"Id": 7247035804068349658
|
||||
},
|
||||
"Component_[9307224322037797205]": {
|
||||
"$type": "EditorLockComponent",
|
||||
"Id": 9307224322037797205
|
||||
},
|
||||
"Component_[9562516168917670048]": {
|
||||
"$type": "EditorVisibilityComponent",
|
||||
"Id": 9562516168917670048
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
# File to tweak compiler settings before compiler detection happens (before project() is called)
|
||||
# We dont have PAL enabled at this point, so we can only use pure-CMake variables
|
||||
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
include(cmake/Platform/Linux/CompilerSettings_linux.cmake)
|
||||
endif()
|
||||
@@ -1,3 +1,4 @@
|
||||
# {BEGIN_LICENSE}
|
||||
#
|
||||
# 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.
|
||||
@@ -5,18 +6,34 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
# {END_LICENSE}
|
||||
# This file is copied during engine registration. Edits to this file will be lost next
|
||||
# time a registration happens.
|
||||
|
||||
include_guard()
|
||||
|
||||
# Read the engine name from the project_json file
|
||||
file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json)
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/project.json project_json)
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/project.json)
|
||||
|
||||
string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine)
|
||||
if(json_error)
|
||||
message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}")
|
||||
message(FATAL_ERROR "Unable to read key 'engine' from 'project.json'\nError: ${json_error}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_MODULE_PATH)
|
||||
foreach(module_path ${CMAKE_MODULE_PATH})
|
||||
if(EXISTS ${module_path}/Findo3de.cmake)
|
||||
file(READ ${module_path}/../engine.json engine_json)
|
||||
string(JSON engine_name ERROR_VARIABLE json_error GET ${engine_json} engine_name)
|
||||
if(json_error)
|
||||
message(FATAL_ERROR "Unable to read key 'engine_name' from 'engine.json'\nError: ${json_error}")
|
||||
endif()
|
||||
if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name)
|
||||
return() # Engine being forced through CMAKE_MODULE_PATH
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{USERPROFILE} AND EXISTS $ENV{USERPROFILE})
|
||||
@@ -25,6 +42,11 @@ else()
|
||||
set(manifest_path $ENV{HOME}/.o3de/o3de_manifest.json) # Unix
|
||||
endif()
|
||||
|
||||
set(registration_error [=[
|
||||
Engine registration is required before configuring a project.
|
||||
Run 'scripts/o3de register --this-engine' from the engine root.
|
||||
]=])
|
||||
|
||||
# Read the ~/.o3de/o3de_manifest.json file and look through the 'engines_path' object.
|
||||
# Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path.
|
||||
if(EXISTS ${manifest_path})
|
||||
@@ -33,36 +55,38 @@ if(EXISTS ${manifest_path})
|
||||
|
||||
string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path)
|
||||
if(json_error)
|
||||
message(FATAL_ERROR "Unable to read key 'engines_path' from '${manifest_path}', error: ${json_error}")
|
||||
message(FATAL_ERROR "Unable to read key 'engines_path' from '${manifest_path}'\nError: ${json_error}\n${registration_error}")
|
||||
endif()
|
||||
|
||||
string(JSON engines_path_type ERROR_VARIABLE json_error TYPE ${manifest_json} engines_path)
|
||||
if(json_error OR NOT ${engines_path_type} STREQUAL "OBJECT")
|
||||
message(FATAL_ERROR "Type of 'engines_path' in '${manifest_path}' is not a JSON Object, error: ${json_error}")
|
||||
message(FATAL_ERROR "Type of 'engines_path' in '${manifest_path}' is not a JSON Object\nError: ${json_error}")
|
||||
endif()
|
||||
|
||||
math(EXPR engines_path_count "${engines_path_count}-1")
|
||||
foreach(engine_path_index RANGE ${engines_path_count})
|
||||
string(JSON engine_name ERROR_VARIABLE json_error MEMBER ${manifest_json} engines_path ${engine_path_index})
|
||||
if(json_error)
|
||||
message(FATAL_ERROR "Unable to read 'engines_path/${engine_path_index}' from '${manifest_path}', error: ${json_error}")
|
||||
message(FATAL_ERROR "Unable to read 'engines_path/${engine_path_index}' from '${manifest_path}'\nError: ${json_error}")
|
||||
endif()
|
||||
|
||||
if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name)
|
||||
string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines_path ${engine_name})
|
||||
if(json_error)
|
||||
message(FATAL_ERROR "Unable to read value from 'engines_path/${engine_name}', error: ${json_error}")
|
||||
message(FATAL_ERROR "Unable to read value from 'engines_path/${engine_name}'\nError: ${json_error}")
|
||||
endif()
|
||||
|
||||
if(engine_path)
|
||||
list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake")
|
||||
break()
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message(FATAL_ERROR "The project.json uses engine name '${LY_ENGINE_NAME_TO_USE}' but no engine with that name has been registered.\n${registration_error}")
|
||||
else()
|
||||
# If the user is passing CMAKE_MODULE_PATH we assume thats where we will find the engine
|
||||
if(NOT CMAKE_MODULE_PATH)
|
||||
message(FATAL_ERROR "Engine registration is required before configuring a project. Please register an engine by running 'scripts/o3de register --this-engine'")
|
||||
message(FATAL_ERROR "O3DE Manifest file not found.\n${registration_error}")
|
||||
endif()
|
||||
endif()
|
||||
@@ -234,7 +234,7 @@ void Q2DViewport::UpdateContent(int flags)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point)
|
||||
void Q2DViewport::OnRButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point)
|
||||
{
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
@@ -246,9 +246,6 @@ void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p
|
||||
setFocus();
|
||||
}
|
||||
|
||||
// Check Edit Tool.
|
||||
MouseCallback(eMouseRDown, point, modifiers);
|
||||
|
||||
SetCurrentCursor(STD_CURSOR_MOVE, QString());
|
||||
|
||||
// Save the mouse down position
|
||||
@@ -273,17 +270,8 @@ void Q2DViewport::OnRButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers,
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point)
|
||||
void Q2DViewport::OnMButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// User pressed the middle mouse button
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Check Edit Tool.
|
||||
if (MouseCallback(eMouseMDown, point, modifiers))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the mouse down position
|
||||
m_RMouseDownPos = point;
|
||||
|
||||
@@ -300,14 +288,8 @@ void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Q2DViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point)
|
||||
void Q2DViewport::OnMButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point)
|
||||
{
|
||||
// Check Edit Tool.
|
||||
if (MouseCallback(eMouseMUp, point, modifiers))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetViewMode(NothingMode);
|
||||
|
||||
ReleaseMouse();
|
||||
@@ -547,13 +529,6 @@ QPoint Q2DViewport::WorldToView(const Vec3& wp) const
|
||||
QPoint p = QPoint(static_cast<int>(sp.x), static_cast<int>(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(static_cast<int>(sp.x), static_cast<int>(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
|
||||
|
||||
@@ -50,8 +50,6 @@ public:
|
||||
//! Map world space position to viewport position.
|
||||
QPoint WorldToView(const Vec3& wp) const override;
|
||||
|
||||
QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const override; //Eric@conffx
|
||||
|
||||
//! Map viewport position to world space position.
|
||||
Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override;
|
||||
//! Map viewport position to world space ray from camera.
|
||||
@@ -64,7 +62,6 @@ public:
|
||||
|
||||
// ovverided from CViewport.
|
||||
float GetScreenScaleFactor(const Vec3& worldPoint) const override;
|
||||
float GetScreenScaleFactor([[maybe_unused]] const CCamera& camera, [[maybe_unused]] const Vec3& object_position) override { return 1; } //Eric@conffx
|
||||
|
||||
// Overrided from CViewport.
|
||||
void OnDragSelectRectangle(const QRect &rect, bool bNormalizeRect = false) override;
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>General Availability</string>
|
||||
<string>development</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
|
||||
@@ -152,15 +152,6 @@ ActionManager::ActionWrapper& ActionManager::ActionWrapper::SetMenu(DynamicMenu*
|
||||
return *this;
|
||||
}
|
||||
|
||||
ActionManager::ActionWrapper& ActionManager::ActionWrapper::SetApplyHoverEffect()
|
||||
{
|
||||
// Our standard toolbar icons, when hovered on, get a white color effect.
|
||||
// But for this to work we need .pngs that look good with this effect, so this only works with the standard toolbars
|
||||
// and looks very ugly for other toolbars, including toolbars loaded from XML (which just show a white rectangle)
|
||||
m_action->setProperty("IconHasHoverEffect", true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ActionManager::ActionWrapper& ActionManager::ActionWrapper::SetReserved()
|
||||
{
|
||||
m_action->setProperty("Reserved", true);
|
||||
|
||||
@@ -151,7 +151,6 @@ public:
|
||||
}
|
||||
|
||||
ActionWrapper& SetMenu(DynamicMenu* menu);
|
||||
ActionWrapper& SetApplyHoverEffect();
|
||||
|
||||
operator QAction*() const {
|
||||
return m_action;
|
||||
|
||||
@@ -10,24 +10,21 @@
|
||||
|
||||
#include "AnimationBipedBoneNames.h"
|
||||
|
||||
namespace EditorAnimationBones
|
||||
namespace EditorAnimationBones::Biped
|
||||
{
|
||||
namespace Biped
|
||||
{
|
||||
const char* Pelvis = "Bip01 Pelvis";
|
||||
const char* Head = "Bip01 Head";
|
||||
const char* Weapon = "weapon_bone";
|
||||
const char* Pelvis = "Bip01 Pelvis";
|
||||
const char* Head = "Bip01 Head";
|
||||
const char* Weapon = "weapon_bone";
|
||||
|
||||
const char* LeftEye = "eye_bone_left";
|
||||
const char* RightEye = "eye_bone_right";
|
||||
const char* LeftEye = "eye_bone_left";
|
||||
const char* RightEye = "eye_bone_right";
|
||||
|
||||
const char* Spine[5] = { "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Spine3", "Bip01 Spine4" };
|
||||
const char* Neck[2] = { "Bip01 Neck", "Bip01 Neck1" };
|
||||
const char* Spine[5] = { "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Spine3", "Bip01 Spine4" };
|
||||
const char* Neck[2] = { "Bip01 Neck", "Bip01 Neck1" };
|
||||
|
||||
const char* LeftHeel = "Bip01 L Heel";
|
||||
const char* LeftToe[2] = { "Bip01 L Toe0", "Bip01 L Toe1" };
|
||||
const char* LeftHeel = "Bip01 L Heel";
|
||||
const char* LeftToe[2] = { "Bip01 L Toe0", "Bip01 L Toe1" };
|
||||
|
||||
const char* RightHeel = "Bip01 R Heel";
|
||||
const char* RightToe[2] = { "Bip01 R Toe0", "Bip01 R Toe1" };
|
||||
}
|
||||
}
|
||||
const char* RightHeel = "Bip01 R Heel";
|
||||
const char* RightToe[2] = { "Bip01 R Toe0", "Bip01 R Toe1" };
|
||||
} // namespace EditorAnimationBones::Biped
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/EntityObject.h"
|
||||
|
||||
#include <AzCore/Time/ITime.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Movie Callback.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -499,25 +501,24 @@ void CAnimationContext::Update()
|
||||
return;
|
||||
}
|
||||
|
||||
ITimer* pTimer = GetIEditor()->GetSystem()->GetITimer();
|
||||
const AZ::TimeUs frameDeltaTimeUs = AZ::GetSimulationTickDeltaTimeUs();
|
||||
const float frameDeltaTime = AZ::TimeUsToSeconds(frameDeltaTimeUs);
|
||||
|
||||
if (!m_bAutoRecording)
|
||||
{
|
||||
AnimateActiveSequence();
|
||||
|
||||
float dt = pTimer->GetFrameTime();
|
||||
m_currTime += dt * m_fTimeScale;
|
||||
m_currTime += frameDeltaTime * m_fTimeScale;
|
||||
|
||||
if (!m_recording)
|
||||
{
|
||||
GetIEditor()->GetMovieSystem()->PreUpdate(dt);
|
||||
GetIEditor()->GetMovieSystem()->PostUpdate(dt);
|
||||
GetIEditor()->GetMovieSystem()->PreUpdate(frameDeltaTime);
|
||||
GetIEditor()->GetMovieSystem()->PostUpdate(frameDeltaTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float dt = pTimer->GetFrameTime();
|
||||
m_fRecordingCurrTime += dt * m_fTimeScale;
|
||||
m_fRecordingCurrTime += frameDeltaTime * m_fTimeScale;
|
||||
if (fabs(m_fRecordingCurrTime - m_currTime) > m_fRecordingTimeStep)
|
||||
{
|
||||
m_currTime += m_fRecordingTimeStep;
|
||||
@@ -644,7 +645,9 @@ void CAnimationContext::OnPostRender()
|
||||
{
|
||||
SAnimContext ac;
|
||||
ac.dt = 0;
|
||||
ac.fps = GetIEditor()->GetSystem()->GetITimer()->GetFrameRate();
|
||||
const AZ::TimeUs frameDeltaTimeUs = AZ::GetSimulationTickDeltaTimeUs();
|
||||
const float frameDeltaTime = AZ::TimeUsToSeconds(frameDeltaTimeUs);
|
||||
ac.fps = 1.0f / frameDeltaTime;
|
||||
ac.time = m_currTime;
|
||||
ac.singleFrame = true;
|
||||
ac.forcePlay = true;
|
||||
@@ -797,7 +800,9 @@ void CAnimationContext::AnimateActiveSequence()
|
||||
|
||||
SAnimContext ac;
|
||||
ac.dt = 0;
|
||||
ac.fps = GetIEditor()->GetSystem()->GetITimer()->GetFrameRate();
|
||||
const AZ::TimeUs frameDeltaTimeUs = AZ::GetSimulationTickDeltaTimeUs();
|
||||
const float frameDeltaTime = AZ::TimeUsToSeconds(frameDeltaTimeUs);
|
||||
ac.fps = 1.0f / frameDeltaTime;
|
||||
ac.time = m_currTime;
|
||||
ac.singleFrame = true;
|
||||
ac.forcePlay = true;
|
||||
|
||||
@@ -140,7 +140,7 @@ bool AssetImporterManager::OnBrowseFiles()
|
||||
bool encounteredCrate = false;
|
||||
QStringList invalidFiles;
|
||||
|
||||
for (QString path : fileDialog.selectedFiles())
|
||||
for (const QString& path : fileDialog.selectedFiles())
|
||||
{
|
||||
QString fileName = GetFileName(path);
|
||||
QFileInfo info(path);
|
||||
|
||||
@@ -199,41 +199,6 @@ namespace AzAssetBrowserRequestHandlerPrivate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper utility - determines if the thing being dragged is a FBX from the scene import pipeline
|
||||
// This is important to differentiate.
|
||||
// when someone drags a MTL file directly into the viewport, even from a FBX, we want to spawn it as a decal
|
||||
// but when someone drags a FBX that contains MTL files, we want only to spawn the meshes.
|
||||
// so we have to specifically differentiate here between the mimeData type that contains the source as the root
|
||||
// (dragging the fbx file itself)
|
||||
// and one which contains the actual product at its root.
|
||||
|
||||
bool IsDragOfFBX(const QMimeData* mimeData)
|
||||
{
|
||||
AZStd::vector<AssetBrowserEntry*> entries;
|
||||
if (!AssetBrowserEntry::FromMimeData(mimeData, entries))
|
||||
{
|
||||
// if mimedata does not even contain entries, no point in proceeding.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto entry : entries)
|
||||
{
|
||||
if (entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Source)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// this is a source file. Is it the filetype we're looking for?
|
||||
if (SourceAssetBrowserEntry* source = azrtti_cast<SourceAssetBrowserEntry*>(entry))
|
||||
{
|
||||
if (AzFramework::StringFunc::Equal(source->GetExtension().c_str(), ".fbx", false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AzAssetBrowserRequestHandler::AzAssetBrowserRequestHandler()
|
||||
|
||||
@@ -671,7 +671,7 @@ AzToolsFramework::PropertyRowWidget* ReflectedPropertyControl::FindPropertyRowWi
|
||||
return nullptr;
|
||||
}
|
||||
const AzToolsFramework::ReflectedPropertyEditor::WidgetList& widgets = m_editor->GetWidgets();
|
||||
for (auto instance : widgets)
|
||||
for (const auto& instance : widgets)
|
||||
{
|
||||
if (instance.second->label() == item->GetPropertyName())
|
||||
{
|
||||
|
||||
+13
-19
@@ -80,7 +80,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <AzQtComponents/Utilities/QtPluginPaths.h>
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/ITimer.h>
|
||||
#include <CryCommon/ILevelSystem.h>
|
||||
|
||||
// Editor
|
||||
@@ -371,10 +370,8 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
ON_COMMAND(ID_EDIT_FETCH, OnEditFetch)
|
||||
ON_COMMAND(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE, OnFileExportToGameNoSurfaceTexture)
|
||||
ON_COMMAND(ID_VIEW_SWITCHTOGAME, OnViewSwitchToGame)
|
||||
MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_VIEW_SWITCHTOGAME_FULLSCREEN, [this]() {
|
||||
ed_previewGameInFullscreen_once = true;
|
||||
OnViewSwitchToGame();
|
||||
});
|
||||
ON_COMMAND(ID_VIEW_SWITCHTOGAME_VIEWPORT, OnViewSwitchToGame)
|
||||
ON_COMMAND(ID_VIEW_SWITCHTOGAME_FULLSCREEN, OnViewSwitchToGameFullScreen)
|
||||
ON_COMMAND(ID_MOVE_OBJECT, OnMoveObject)
|
||||
ON_COMMAND(ID_RENAME_OBJ, OnRenameObj)
|
||||
ON_COMMAND(ID_UNDO, OnUndo)
|
||||
@@ -1361,16 +1358,6 @@ void CCryEditApp::CompileCriticalAssets() const
|
||||
assetsInQueueNotifcation.BusDisconnect();
|
||||
CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready."));
|
||||
|
||||
// VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others,
|
||||
// so that by the time we ask for them there is a greater likelihood that they're already good to go.
|
||||
// these can be loaded later but are still important:
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/");
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials");
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches");
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects");
|
||||
|
||||
// some are specifically extra important and will cause issues if missing completely:
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf");
|
||||
}
|
||||
|
||||
bool CCryEditApp::ConnectToAssetProcessor() const
|
||||
@@ -2584,6 +2571,12 @@ void CCryEditApp::OnViewSwitchToGame()
|
||||
GetIEditor()->SetInGameMode(inGame);
|
||||
}
|
||||
|
||||
void CCryEditApp::OnViewSwitchToGameFullScreen()
|
||||
{
|
||||
ed_previewGameInFullscreen_once = true;
|
||||
OnViewSwitchToGame();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnExportSelectedObjects()
|
||||
{
|
||||
@@ -3974,9 +3967,8 @@ void CCryEditApp::OpenLUAEditor(const char* files)
|
||||
}
|
||||
}
|
||||
|
||||
const char* engineRoot = nullptr;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
|
||||
AZ_Assert(engineRoot != nullptr, "Unable to communicate to AzFramework::ApplicationRequests::Bus");
|
||||
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
|
||||
AZ_Assert(!engineRoot.empty(), "Unable to query Engine Path");
|
||||
|
||||
AZStd::string_view exePath;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
|
||||
@@ -3995,7 +3987,7 @@ void CCryEditApp::OpenLUAEditor(const char* files)
|
||||
#endif
|
||||
"%s", argumentQuoteString, aznumeric_cast<int>(exePath.size()), exePath.data(), argumentQuoteString);
|
||||
|
||||
AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot);
|
||||
AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot.c_str());
|
||||
StartProcessDetached(process.c_str(), processArgs.c_str());
|
||||
}
|
||||
|
||||
@@ -4196,6 +4188,8 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
"\nThis could be because of incorrectly configured components, or missing required gems."
|
||||
"\nSee other errors for more details.");
|
||||
|
||||
AzToolsFramework::EditorEventsBus::Broadcast(&AzToolsFramework::EditorEvents::NotifyEditorInitialized);
|
||||
|
||||
if (didCryEditStart)
|
||||
{
|
||||
app->EnableOnIdle();
|
||||
|
||||
@@ -212,6 +212,7 @@ public:
|
||||
void OnEditFetch();
|
||||
void OnFileExportToGameNoSurfaceTexture();
|
||||
void OnViewSwitchToGame();
|
||||
void OnViewSwitchToGameFullScreen();
|
||||
void OnViewDeploy();
|
||||
void DeleteSelectedEntities(bool includeDescendants);
|
||||
void OnMoveObject();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Time/ITime.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <MathConversion.h>
|
||||
|
||||
@@ -749,7 +750,9 @@ bool CCryEditDoc::OnOpenDocument(const QString& lpszPathName)
|
||||
|
||||
bool CCryEditDoc::BeforeOpenDocument(const QString& lpszPathName, TOpenDocContext& context)
|
||||
{
|
||||
CTimeValue loading_start_time = gEnv->pTimer->GetAsyncTime();
|
||||
const AZ::TimeMs timeMs = AZ::GetRealElapsedTimeMs();
|
||||
const double timeSec = AZ::TimeMsToSecondsDouble(timeMs);
|
||||
const CTimeValue loading_start_time(timeSec);
|
||||
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
@@ -790,7 +793,7 @@ bool CCryEditDoc::BeforeOpenDocument(const QString& lpszPathName, TOpenDocContex
|
||||
|
||||
bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context)
|
||||
{
|
||||
CTimeValue& loading_start_time = context.loading_start_time;
|
||||
const CTimeValue& loading_start_time = context.loading_start_time;
|
||||
|
||||
bool isPrefabEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
@@ -860,7 +863,9 @@ bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context)
|
||||
|
||||
StartStreamingLoad();
|
||||
|
||||
CTimeValue loading_end_time = gEnv->pTimer->GetAsyncTime();
|
||||
const AZ::TimeMs timeMs = AZ::GetRealElapsedTimeMs();
|
||||
const double timeSec = AZ::TimeMsToSecondsDouble(timeMs);
|
||||
const CTimeValue loading_end_time(timeSec);
|
||||
|
||||
CLogFile::FormatLine("-----------------------------------------------------------");
|
||||
CLogFile::FormatLine("Successfully opened document %s", context.absoluteLevelPath.toUtf8().data());
|
||||
@@ -1123,7 +1128,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
const QString oldLevelPattern = QDir(oldLevelFolder).absoluteFilePath("*.*");
|
||||
const QString oldLevelName = Path::GetFile(GetLevelPathName());
|
||||
const QString oldLevelXml = Path::ReplaceExtension(oldLevelName, "xml");
|
||||
AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskAndInZips);
|
||||
AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), AZ::IO::FileSearchLocation::Any);
|
||||
if (findHandle)
|
||||
{
|
||||
do
|
||||
|
||||
@@ -40,10 +40,10 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
namespace
|
||||
{
|
||||
// File name extension for python files
|
||||
const QString s_kPythonFileNameSpec = "*.py";
|
||||
const QString s_kPythonFileNameSpec("*.py");
|
||||
|
||||
// Tree root element name
|
||||
const QString s_kRootElementName = "Python Scripts";
|
||||
const QString s_kRootElementName("Python Scripts");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
#include <CryFile.h>
|
||||
#include <ISystem.h>
|
||||
#include <IIndexedMesh.h>
|
||||
#include <ITimer.h>
|
||||
#include <IXml.h>
|
||||
#include <IMovieSystem.h>
|
||||
|
||||
|
||||
@@ -145,6 +145,15 @@ namespace SandboxEditor
|
||||
}
|
||||
};
|
||||
|
||||
const auto trackingTransform = [viewportId = m_viewportId]
|
||||
{
|
||||
bool tracking = false;
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult(
|
||||
tracking, viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::IsTrackingTransform);
|
||||
|
||||
return tracking;
|
||||
};
|
||||
|
||||
m_firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(SandboxEditor::CameraFreeLookChannelId());
|
||||
|
||||
m_firstPersonRotateCamera->m_rotateSpeedFn = []
|
||||
@@ -152,6 +161,11 @@ namespace SandboxEditor
|
||||
return SandboxEditor::CameraRotateSpeed();
|
||||
};
|
||||
|
||||
m_firstPersonRotateCamera->m_constrainPitch = [trackingTransform]
|
||||
{
|
||||
return !trackingTransform();
|
||||
};
|
||||
|
||||
// default behavior is to hide the cursor but this can be disabled (useful for remote desktop)
|
||||
// note: See CaptureCursorLook in the Settings Registry
|
||||
m_firstPersonRotateCamera->SetActivationBeganFn(hideCursor);
|
||||
@@ -255,6 +269,11 @@ namespace SandboxEditor
|
||||
return SandboxEditor::CameraOrbitYawRotationInverted();
|
||||
};
|
||||
|
||||
m_orbitRotateCamera->m_constrainPitch = [trackingTransform]
|
||||
{
|
||||
return !trackingTransform();
|
||||
};
|
||||
|
||||
m_orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffsetOrbit);
|
||||
|
||||
@@ -337,12 +356,12 @@ namespace SandboxEditor
|
||||
AZ::TransformBus::EventResult(worldFromLocal, viewEntityId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
|
||||
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetReferenceFrame, worldFromLocal);
|
||||
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::StartTrackingTransform, worldFromLocal);
|
||||
}
|
||||
else
|
||||
{
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
|
||||
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::ClearReferenceFrame);
|
||||
m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::StopTrackingTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/HMDBus.h>
|
||||
#include <CryCommon/IRenderAuxGeom.h>
|
||||
|
||||
// AzFramework
|
||||
@@ -299,13 +298,9 @@ AzToolsFramework::ViewportInteraction::MousePick EditorViewportWidget::BuildMous
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::MousePick mousePick;
|
||||
mousePick.m_screenCoordinates = AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point);
|
||||
if (const auto& ray = m_renderViewport->ViewportScreenToWorldRay(mousePick.m_screenCoordinates);
|
||||
ray.has_value())
|
||||
{
|
||||
mousePick.m_rayOrigin = ray.value().origin;
|
||||
mousePick.m_rayDirection = ray.value().direction;
|
||||
}
|
||||
|
||||
const auto[origin, direction] = m_renderViewport->ViewportScreenToWorldRay(mousePick.m_screenCoordinates);
|
||||
mousePick.m_rayOrigin = origin;
|
||||
mousePick.m_rayDirection = direction;
|
||||
return mousePick;
|
||||
}
|
||||
|
||||
@@ -556,22 +551,6 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
// this should only occur for the main viewport and no others.
|
||||
ShowCursor();
|
||||
|
||||
// If the user has selected game mode, enable outputting to any attached HMD and properly size the context
|
||||
// to the resolution specified by the VR device.
|
||||
if (gSettings.bEnableGameModeVR)
|
||||
{
|
||||
const AZ::VR::HMDDeviceInfo* deviceInfo = nullptr;
|
||||
EBUS_EVENT_RESULT(deviceInfo, AZ::VR::HMDDeviceRequestBus, GetDeviceInfo);
|
||||
AZ_Warning("Render Viewport", deviceInfo, "No VR device detected");
|
||||
|
||||
if (deviceInfo)
|
||||
{
|
||||
// Note: This may also need to adjust the viewport size
|
||||
SetActiveWindow();
|
||||
SetFocus();
|
||||
SetSelected(true);
|
||||
}
|
||||
}
|
||||
SetCurrentCursor(STD_CURSOR_GAME);
|
||||
|
||||
if (ShouldPreviewFullscreen())
|
||||
@@ -912,23 +891,6 @@ AZ::Vector3 EditorViewportWidget::PickTerrain(const AzFramework::ScreenPoint& po
|
||||
return LYVec3ToAZVec3(ViewToWorld(AzToolsFramework::ViewportInteraction::QPointFromScreenPoint(point), nullptr, true));
|
||||
}
|
||||
|
||||
AZ::EntityId EditorViewportWidget::PickEntity(const AzFramework::ScreenPoint& point)
|
||||
{
|
||||
AZ::EntityId entityId;
|
||||
HitContext hitInfo;
|
||||
hitInfo.view = this;
|
||||
if (HitTest(AzToolsFramework::ViewportInteraction::QPointFromScreenPoint(point), hitInfo))
|
||||
{
|
||||
if (hitInfo.object && (hitInfo.object->GetType() == OBJTYPE_AZENTITY))
|
||||
{
|
||||
auto entityObject = static_cast<CComponentEntityObject*>(hitInfo.object);
|
||||
entityId = entityObject->GetAssociatedEntityId();
|
||||
}
|
||||
}
|
||||
|
||||
return entityId;
|
||||
}
|
||||
|
||||
float EditorViewportWidget::TerrainHeight(const AZ::Vector2& position)
|
||||
{
|
||||
return GetIEditor()->GetTerrainElevation(position.GetX(), position.GetY());
|
||||
@@ -1653,16 +1615,15 @@ void EditorViewportWidget::RenderSelectedRegion()
|
||||
Vec3 EditorViewportWidget::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) const
|
||||
{
|
||||
Vec3 out(0, 0, 0);
|
||||
float x, y, z;
|
||||
float x, y;
|
||||
|
||||
ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z);
|
||||
if (_finite(x) && _finite(y) && _finite(z))
|
||||
ProjectToScreen(wp.x, wp.y, wp.z, &x, &y);
|
||||
if (_finite(x) && _finite(y))
|
||||
{
|
||||
out.x = (x / 100) * m_rcClient.width();
|
||||
out.y = (y / 100) * m_rcClient.height();
|
||||
out.x /= static_cast<float>(QHighDpiScaling::factor(windowHandle()->screen()));
|
||||
out.y /= static_cast<float>(QHighDpiScaling::factor(windowHandle()->screen()));
|
||||
out.z = z;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -1672,24 +1633,6 @@ QPoint EditorViewportWidget::WorldToView(const Vec3& wp) const
|
||||
{
|
||||
return AzToolsFramework::ViewportInteraction::QPointFromScreenPoint(m_renderViewport->ViewportWorldToScreen(LYVec3ToAZVec3(wp)));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QPoint EditorViewportWidget::WorldToViewParticleEditor(const Vec3& wp, int width, int height) const
|
||||
{
|
||||
QPoint p;
|
||||
float x, y, z;
|
||||
|
||||
ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z);
|
||||
if (_finite(x) || _finite(y))
|
||||
{
|
||||
p.rx() = static_cast<int>((x / 100) * width);
|
||||
p.ry() = static_cast<int>((y / 100) * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPoint(0, 0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 EditorViewportWidget::ViewToWorld(
|
||||
@@ -1705,20 +1648,16 @@ Vec3 EditorViewportWidget::ViewToWorld(
|
||||
AZ_UNUSED(collideWithObject);
|
||||
|
||||
auto ray = m_renderViewport->ViewportScreenToWorldRay(AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(vp));
|
||||
if (!ray.has_value())
|
||||
{
|
||||
return Vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
const float maxDistance = 10000.f;
|
||||
Vec3 v = AZVec3ToLYVec3(ray.value().direction) * maxDistance;
|
||||
Vec3 v = AZVec3ToLYVec3(ray.direction) * maxDistance;
|
||||
|
||||
if (!_finite(v.x) || !_finite(v.y) || !_finite(v.z))
|
||||
{
|
||||
return Vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
Vec3 colp = AZVec3ToLYVec3(ray.value().origin) + 0.002f * v;
|
||||
Vec3 colp = AZVec3ToLYVec3(ray.origin) + 0.002f * v;
|
||||
|
||||
return colp;
|
||||
}
|
||||
@@ -1757,21 +1696,19 @@ bool EditorViewportWidget::RayRenderMeshIntersection(IRenderMesh* pRenderMesh, c
|
||||
return bRes;*/
|
||||
}
|
||||
|
||||
void EditorViewportWidget::UnProjectFromScreen(float sx, float sy, float sz, float* px, float* py, float* pz) const
|
||||
void EditorViewportWidget::UnProjectFromScreen(float sx, float sy, float* px, float* py, float* pz) const
|
||||
{
|
||||
AZ::Vector3 wp;
|
||||
wp = m_renderViewport->ViewportScreenToWorld(AzFramework::ScreenPoint{(int)sx, m_rcClient.bottom() - ((int)sy)}, sz).value_or(wp);
|
||||
const AZ::Vector3 wp = m_renderViewport->ViewportScreenToWorld(AzFramework::ScreenPoint{(int)sx, m_rcClient.bottom() - ((int)sy)});
|
||||
*px = wp.GetX();
|
||||
*py = wp.GetY();
|
||||
*pz = wp.GetZ();
|
||||
}
|
||||
|
||||
void EditorViewportWidget::ProjectToScreen(float ptx, float pty, float ptz, float* sx, float* sy, float* sz) const
|
||||
void EditorViewportWidget::ProjectToScreen(float ptx, float pty, float ptz, float* sx, float* sy) const
|
||||
{
|
||||
AzFramework::ScreenPoint screenPosition = m_renderViewport->ViewportWorldToScreen(AZ::Vector3{ptx, pty, ptz});
|
||||
*sx = static_cast<float>(screenPosition.m_x);
|
||||
*sy = static_cast<float>(screenPosition.m_y);
|
||||
*sz = 0.f;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1781,32 +1718,22 @@ void EditorViewportWidget::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3&
|
||||
|
||||
Vec3 pos0, pos1;
|
||||
float wx, wy, wz;
|
||||
UnProjectFromScreen(static_cast<float>(vp.x()), static_cast<float>(rc.bottom() - vp.y()), 0.0f, &wx, &wy, &wz);
|
||||
if (!_finite(wx) || !_finite(wy) || !_finite(wz))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fabs(wx) > 1000000 || fabs(wy) > 1000000 || fabs(wz) > 1000000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pos0(wx, wy, wz);
|
||||
UnProjectFromScreen(static_cast<float>(vp.x()), static_cast<float>(rc.bottom() - vp.y()), 1.0f, &wx, &wy, &wz);
|
||||
if (!_finite(wx) || !_finite(wy) || !_finite(wz))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fabs(wx) > 1000000 || fabs(wy) > 1000000 || fabs(wz) > 1000000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pos1(wx, wy, wz);
|
||||
UnProjectFromScreen(static_cast<float>(vp.x()), static_cast<float>(rc.bottom() - vp.y()), &wx, &wy, &wz);
|
||||
|
||||
Vec3 v = (pos1 - pos0);
|
||||
v = v.GetNormalized();
|
||||
if (!_finite(wx) || !_finite(wy) || !_finite(wz))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fabs(wx) > 1000000 || fabs(wy) > 1000000 || fabs(wz) > 1000000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pos0(wx, wy, wz);
|
||||
|
||||
raySrc = pos0;
|
||||
rayDir = v;
|
||||
rayDir = (pos0 - AZVec3ToLYVec3(m_renderViewport->GetCameraState().m_position)).GetNormalized();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1815,13 +1742,6 @@ float EditorViewportWidget::GetScreenScaleFactor([[maybe_unused]] const Vec3& wo
|
||||
AZ_Error("CryLegacy", false, "EditorViewportWidget::GetScreenScaleFactor not implemented");
|
||||
return 1.f;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float EditorViewportWidget::GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position)
|
||||
{
|
||||
Vec3 camPos = camera.GetPosition();
|
||||
float dist = camPos.GetDistance(object_position);
|
||||
return dist;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool EditorViewportWidget::CheckRespondToInput() const
|
||||
@@ -1842,7 +1762,6 @@ bool EditorViewportWidget::CheckRespondToInput() const
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool EditorViewportWidget::HitTest(const QPoint& point, HitContext& hitInfo)
|
||||
{
|
||||
hitInfo.camera = nullptr;
|
||||
hitInfo.pExcludedObject = GetCameraObject();
|
||||
return QtViewport::HitTest(point, hitInfo);
|
||||
}
|
||||
@@ -2363,10 +2282,10 @@ void* EditorViewportWidget::GetSystemCursorConstraintWindow() const
|
||||
return systemCursorConstrained ? renderOverlayHWND() : nullptr;
|
||||
}
|
||||
|
||||
void EditorViewportWidget::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt)
|
||||
void EditorViewportWidget::BuildDragDropContext(
|
||||
AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point)
|
||||
{
|
||||
const auto scaledPoint = WidgetToViewport(pt);
|
||||
QtViewport::BuildDragDropContext(context, scaledPoint);
|
||||
QtViewport::BuildDragDropContext(context, viewportId, point);
|
||||
}
|
||||
|
||||
void EditorViewportWidget::RestoreViewportAfterGameMode()
|
||||
@@ -2547,12 +2466,6 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not supported in VR
|
||||
if (gSettings.bEnableGameModeVR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If level not loaded, don't preview in fullscreen (preview shouldn't work at all without a level, but it does)
|
||||
if (auto ge = GetIEditor()->GetGameEngine())
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user