Merge branch 'main' into SpawnableIndexQuery

This commit is contained in:
AMZN-koppersr
2021-05-26 09:48:20 -07:00
411 changed files with 34696 additions and 4469 deletions
+666
View File
@@ -0,0 +1,666 @@
{
"Source": "Default_Level.prefab",
"ContainerEntity": {
"Id": "Entity_[1146574390643]",
"Name": "Level",
"Components": {
"Component_[10641544592923449938]": {
"$type": "EditorInspectorComponent",
"Id": 10641544592923449938
},
"Component_[12039882709170782873]": {
"$type": "EditorOnlyEntityComponent",
"Id": 12039882709170782873
},
"Component_[12265484671603697631]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12265484671603697631
},
"Component_[14126657869720434043]": {
"$type": "EditorEntitySortComponent",
"Id": 14126657869720434043
},
"Component_[15230859088967841193]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 15230859088967841193,
"Parent Entity": "",
"Cached World Transform Parent": ""
},
"Component_[16239496886950819870]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 16239496886950819870
},
"Component_[5688118765544765547]": {
"$type": "EditorEntityIconComponent",
"Id": 5688118765544765547
},
"Component_[6545738857812235305]": {
"$type": "SelectionComponent",
"Id": 6545738857812235305
},
"Component_[7247035804068349658]": {
"$type": "EditorPrefabComponent",
"Id": 7247035804068349658
},
"Component_[9307224322037797205]": {
"$type": "EditorLockComponent",
"Id": 9307224322037797205
},
"Component_[9562516168917670048]": {
"$type": "EditorVisibilityComponent",
"Id": 9562516168917670048
}
},
"IsDependencyReady": true
},
"Entities": {
"Entity_[1155164325235]": {
"Id": "Entity_[1155164325235]",
"Name": "Sun",
"Components": {
"Component_[10440557478882592717]": {
"$type": "SelectionComponent",
"Id": 10440557478882592717
},
"Component_[13620450453324765907]": {
"$type": "EditorLockComponent",
"Id": 13620450453324765907
},
"Component_[2134313378593666258]": {
"$type": "EditorInspectorComponent",
"Id": 2134313378593666258
},
"Component_[234010807770404186]": {
"$type": "EditorVisibilityComponent",
"Id": 234010807770404186
},
"Component_[2970359110423865725]": {
"$type": "EditorEntityIconComponent",
"Id": 2970359110423865725
},
"Component_[3722854130373041803]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3722854130373041803
},
"Component_[5992533738676323195]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5992533738676323195
},
"Component_[7378860763541895402]": {
"$type": "AZ::Render::EditorDirectionalLightComponent",
"Id": 7378860763541895402,
"Controller": {
"Configuration": {
"Intensity": 1.0,
"CameraEntityId": "",
"ShadowFilterMethod": 1,
"ShadowmapSize": "Size1024",
"Pcf Method": 1
}
}
},
"Component_[7892834440890947578]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 7892834440890947578,
"Parent Entity": "Entity_[1176639161715]",
"Transform Data": {
"Translate": [
0.0,
0.0,
13.487043380737305
],
"Rotate": [
-76.13099670410156,
-0.847000002861023,
-15.8100004196167
]
},
"Cached World Transform": {
"Translation": [
0.0,
0.0,
9.442070960998536
],
"Rotation": [
-0.6098860502243042,
-0.09055805951356888,
-0.10376212745904924,
0.7804304361343384
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[8599729549570828259]": {
"$type": "EditorEntitySortComponent",
"Id": 8599729549570828259
},
"Component_[952797371922080273]": {
"$type": "EditorPendingCompositionComponent",
"Id": 952797371922080273
}
},
"IsDependencyReady": true
},
"Entity_[1159459292531]": {
"Id": "Entity_[1159459292531]",
"Name": "Ground",
"Components": {
"Component_[11701138785793981042]": {
"$type": "SelectionComponent",
"Id": 11701138785793981042
},
"Component_[12260880513256986252]": {
"$type": "EditorEntityIconComponent",
"Id": 12260880513256986252
},
"Component_[13711420870643673468]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 13711420870643673468
},
"Component_[138002849734991713]": {
"$type": "EditorOnlyEntityComponent",
"Id": 138002849734991713
},
"Component_[16578565737331764849]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 16578565737331764849,
"Parent Entity": "Entity_[1176639161715]",
"Cached World Transform": {
"Translation": [
0.0,
0.0,
0.0
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[16919232076966545697]": {
"$type": "EditorInspectorComponent",
"Id": 16919232076966545697
},
"Component_[5182430712893438093]": {
"$type": "EditorMaterialComponent",
"Id": 5182430712893438093,
"materialSlots": [
{
"id": {
"materialAssetId": {
"guid": "{935F694A-8639-515B-8133-81CDC7948E5B}",
"subId": 803645540
}
}
}
],
"materialSlotsByLod": [
[
{
"id": {
"lodIndex": 0,
"materialAssetId": {
"guid": "{935F694A-8639-515B-8133-81CDC7948E5B}",
"subId": 803645540
}
}
}
]
]
},
"Component_[5675108321710651991]": {
"$type": "AZ::Render::EditorMeshComponent",
"Id": 5675108321710651991,
"Controller": {
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{935F694A-8639-515B-8133-81CDC7948E5B}",
"subId": 277333723
},
"assetHint": "objects/groudplane/groundplane_521x521m.azmodel"
}
}
}
},
"Component_[5681893399601237518]": {
"$type": "EditorEntitySortComponent",
"Id": 5681893399601237518
},
"Component_[592692962543397545]": {
"$type": "EditorPendingCompositionComponent",
"Id": 592692962543397545
},
"Component_[7090012899106946164]": {
"$type": "EditorLockComponent",
"Id": 7090012899106946164
},
"Component_[9410832619875640998]": {
"$type": "EditorVisibilityComponent",
"Id": 9410832619875640998
}
},
"IsDependencyReady": true
},
"Entity_[1163754259827]": {
"Id": "Entity_[1163754259827]",
"Name": "Camera",
"Components": {
"Component_[11895140916889160460]": {
"$type": "EditorEntityIconComponent",
"Id": 11895140916889160460
},
"Component_[16880285896855930892]": {
"$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent",
"Id": 16880285896855930892,
"Controller": {
"Configuration": {
"Field of View": 55.0,
"EditorEntityId": 8929576024571800510
}
}
},
"Component_[17187464423780271193]": {
"$type": "EditorLockComponent",
"Id": 17187464423780271193
},
"Component_[17495696818315413311]": {
"$type": "EditorEntitySortComponent",
"Id": 17495696818315413311
},
"Component_[18086214374043522055]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 18086214374043522055,
"Parent Entity": "Entity_[1176639161715]",
"Transform Data": {
"Translate": [
-2.300000190734864,
-3.9368600845336916,
1.0
],
"Rotate": [
-2.050307512283325,
1.9552897214889529,
-43.62335586547852
]
},
"Cached World Transform": {
"Translation": [
-11.904647827148438,
13.392678260803223,
-3.0449724197387697
],
"Rotation": [
-0.02294669672846794,
0.00919158011674881,
-0.37172695994377139,
0.9280129671096802
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[18387556550380114975]": {
"$type": "SelectionComponent",
"Id": 18387556550380114975
},
"Component_[2654521436129313160]": {
"$type": "EditorVisibilityComponent",
"Id": 2654521436129313160
},
"Component_[5265045084611556958]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5265045084611556958
},
"Component_[7169798125182238623]": {
"$type": "EditorPendingCompositionComponent",
"Id": 7169798125182238623
},
"Component_[8866210352157164042]": {
"$type": "EditorInspectorComponent",
"Id": 8866210352157164042
},
"Component_[9129253381063760879]": {
"$type": "EditorOnlyEntityComponent",
"Id": 9129253381063760879
}
},
"IsDependencyReady": true
},
"Entity_[1168049227123]": {
"Id": "Entity_[1168049227123]",
"Name": "Grid",
"Components": {
"Component_[11443347433215807130]": {
"$type": "EditorEntityIconComponent",
"Id": 11443347433215807130
},
"Component_[11779275529534764488]": {
"$type": "SelectionComponent",
"Id": 11779275529534764488
},
"Component_[14249419413039427459]": {
"$type": "EditorInspectorComponent",
"Id": 14249419413039427459
},
"Component_[15448581635946161318]": {
"$type": "AZ::Render::EditorGridComponent",
"Id": 15448581635946161318,
"Controller": {
"Configuration": {
"primarySpacing": 4.0,
"primaryColor": [
0.501960813999176,
0.501960813999176,
0.501960813999176
],
"secondarySpacing": 0.5,
"secondaryColor": [
0.250980406999588,
0.250980406999588,
0.250980406999588
]
}
}
},
"Component_[1843303322527297409]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 1843303322527297409
},
"Component_[380249072065273654]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 380249072065273654,
"Parent Entity": "Entity_[1176639161715]",
"Cached World Transform": {
"Translation": [
0.0,
0.0,
0.0
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[7476660583684339787]": {
"$type": "EditorPendingCompositionComponent",
"Id": 7476660583684339787
},
"Component_[7557626501215118375]": {
"$type": "EditorEntitySortComponent",
"Id": 7557626501215118375
},
"Component_[7984048488947365511]": {
"$type": "EditorVisibilityComponent",
"Id": 7984048488947365511
},
"Component_[8118181039276487398]": {
"$type": "EditorOnlyEntityComponent",
"Id": 8118181039276487398
},
"Component_[9189909764215270515]": {
"$type": "EditorLockComponent",
"Id": 9189909764215270515
}
},
"IsDependencyReady": true
},
"Entity_[1172344194419]": {
"Id": "Entity_[1172344194419]",
"Name": "Shader Ball",
"Components": {
"Component_[10789351944715265527]": {
"$type": "EditorOnlyEntityComponent",
"Id": 10789351944715265527
},
"Component_[12037033284781049225]": {
"$type": "EditorEntitySortComponent",
"Id": 12037033284781049225
},
"Component_[13759153306105970079]": {
"$type": "EditorPendingCompositionComponent",
"Id": 13759153306105970079
},
"Component_[14135560884830586279]": {
"$type": "EditorInspectorComponent",
"Id": 14135560884830586279
},
"Component_[16247165675903986673]": {
"$type": "EditorVisibilityComponent",
"Id": 16247165675903986673
},
"Component_[18082433625958885247]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 18082433625958885247
},
"Component_[6472623349872972660]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6472623349872972660,
"Parent Entity": "Entity_[1176639161715]",
"Transform Data": {
"Rotate": [
0.0,
0.10000000149011612,
180.0
]
},
"Cached World Transform": {
"Translation": [
0.0,
0.0,
0.0
],
"Rotation": [
0.0008726645028218627,
0.0,
0.9999996423721314,
0.0
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[6495255223970673916]": {
"$type": "AZ::Render::EditorMeshComponent",
"Id": 6495255223970673916,
"Controller": {
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
}
}
}
},
"Component_[8056625192494070973]": {
"$type": "SelectionComponent",
"Id": 8056625192494070973
},
"Component_[8550141614185782969]": {
"$type": "EditorEntityIconComponent",
"Id": 8550141614185782969
},
"Component_[9439770997198325425]": {
"$type": "EditorLockComponent",
"Id": 9439770997198325425
}
},
"IsDependencyReady": true
},
"Entity_[1176639161715]": {
"Id": "Entity_[1176639161715]",
"Name": "Atom Default Environment",
"Components": {
"Component_[10757302973393310045]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 10757302973393310045,
"Parent Entity": "Entity_[1146574390643]",
"Cached World Transform": {
"Translation": [
0.0,
0.0,
0.0
]
},
"Cached World Transform Parent": "Entity_[1146574390643]"
},
"Component_[14505817420424255464]": {
"$type": "EditorInspectorComponent",
"Id": 14505817420424255464,
"ComponentOrderEntryArray": [
{
"ComponentId": 10757302973393310045
}
]
},
"Component_[14988041764659020032]": {
"$type": "EditorLockComponent",
"Id": 14988041764659020032
},
"Component_[15808690248755038124]": {
"$type": "SelectionComponent",
"Id": 15808690248755038124
},
"Component_[15900837685796817138]": {
"$type": "EditorVisibilityComponent",
"Id": 15900837685796817138
},
"Component_[3298767348226484884]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3298767348226484884
},
"Component_[4076975109609220594]": {
"$type": "EditorPendingCompositionComponent",
"Id": 4076975109609220594
},
"Component_[5679760548946028854]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5679760548946028854
},
"Component_[5855590796136709437]": {
"$type": "EditorEntitySortComponent",
"Id": 5855590796136709437,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[1155164325235]"
},
{
"EntityId": "Entity_[1180934129011]",
"SortIndex": 1
},
{
"EntityId": "Entity_[1172344194419]",
"SortIndex": 2
},
{
"EntityId": "Entity_[1168049227123]",
"SortIndex": 3
},
{
"EntityId": "Entity_[1163754259827]",
"SortIndex": 4
},
{
"EntityId": "Entity_[1159459292531]",
"SortIndex": 5
}
]
},
"Component_[9277695270015777859]": {
"$type": "EditorEntityIconComponent",
"Id": 9277695270015777859
}
},
"IsDependencyReady": true
},
"Entity_[1180934129011]": {
"Id": "Entity_[1180934129011]",
"Name": "Global Sky",
"Components": {
"Component_[11231930600558681245]": {
"$type": "AZ::Render::EditorHDRiSkyboxComponent",
"Id": 11231930600558681245,
"Controller": {
"Configuration": {
"CubemapAsset": {
"assetId": {
"guid": "{215E47FD-D181-5832-B1AB-91673ABF6399}",
"subId": 1000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_skyboxcm.exr.streamingimage"
}
}
}
},
"Component_[11980494120202836095]": {
"$type": "SelectionComponent",
"Id": 11980494120202836095
},
"Component_[1428633914413949476]": {
"$type": "EditorLockComponent",
"Id": 1428633914413949476
},
"Component_[14936200426671614999]": {
"$type": "AZ::Render::EditorImageBasedLightComponent",
"Id": 14936200426671614999,
"Controller": {
"Configuration": {
"diffuseImageAsset": {
"assetId": {
"guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
"subId": 3000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_ibldiffuse.exr.streamingimage"
},
"specularImageAsset": {
"assetId": {
"guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
"subId": 2000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_iblspecular.exr.streamingimage"
}
}
}
},
"Component_[14994774102579326069]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 14994774102579326069
},
"Component_[15417479889044493340]": {
"$type": "EditorPendingCompositionComponent",
"Id": 15417479889044493340
},
"Component_[15826613364991382688]": {
"$type": "EditorEntitySortComponent",
"Id": 15826613364991382688
},
"Component_[1665003113283562343]": {
"$type": "EditorOnlyEntityComponent",
"Id": 1665003113283562343
},
"Component_[3704934735944502280]": {
"$type": "EditorEntityIconComponent",
"Id": 3704934735944502280
},
"Component_[5698542331457326479]": {
"$type": "EditorVisibilityComponent",
"Id": 5698542331457326479
},
"Component_[6644513399057217122]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6644513399057217122,
"Parent Entity": "Entity_[1176639161715]",
"Cached World Transform": {
"Translation": [
0.0,
0.0,
0.0
]
},
"Cached World Transform Parent": "Entity_[1176639161715]"
},
"Component_[931091830724002070]": {
"$type": "EditorInspectorComponent",
"Id": 931091830724002070
}
},
"IsDependencyReady": true
}
}
}
@@ -12,7 +12,7 @@
# Extracted from Editor.xml
set(GEM_DEPENDENCIES
Gem::Maestro.Editor
Gem::TextureAtlas
Gem::TextureAtlas.Editor
Gem::LmbrCentral.Editor
Gem::LyShine.Editor
Gem::HttpRequestor
@@ -16,16 +16,16 @@
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
# Enable after installing NodeJS and CDK on jenkins Windows AMI.
#ly_add_pytest(
# NAME AutomatedTesting::AWSTests
# TEST_SUITE periodic
# TEST_SERIAL
# PATH ${CMAKE_CURRENT_LIST_DIR}/AWS/${PAL_PLATFORM_NAME}/
# RUNTIME_DEPENDENCIES
# Legacy::Editor
# AZ::AssetProcessor
# AutomatedTesting.Assets
# COMPONENT
# AWS
#)
ly_add_pytest(
NAME AutomatedTesting::AWSTests
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/${PAL_PLATFORM_NAME}/
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT
AWS
)
endif()
@@ -0,0 +1,11 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
@@ -0,0 +1,11 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
@@ -0,0 +1,11 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
@@ -68,6 +68,7 @@ class TestAWSClientAuthAnonymousCredentials(object):
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(
@@ -67,6 +67,7 @@ class TestAWSClientAuthPasswordSignIn(object):
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', 'AWS/ClientAuthPasswordSignUp']
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(
@@ -87,6 +88,7 @@ class TestAWSClientAuthPasswordSignIn(object):
)
launcher.args = ['+LoadLevel', 'AWS/ClientAuthPasswordSignIn']
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(
@@ -10,8 +10,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import os
from os.path import abspath
import pytest
import json
import logging
logger = logging.getLogger(__name__)
AWS_RESOURCE_MAPPINGS_KEY = 'AWSResourceMappings'
AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY = 'AccountId'
@@ -57,9 +61,9 @@ class ResourceMappings:
stacks = response.get('Stacks', [])
assert len(stacks) == 1, f'{stack_name} is invalid.'
self.__write_resource_mappings(stacks[0].get('Outputs', []))
self._write_resource_mappings(stacks[0].get('Outputs', []))
def __write_resource_mappings(self, outputs, append_feature_name = True) -> None:
def _write_resource_mappings(self, outputs, append_feature_name = True) -> None:
with open(self._resource_mapping_file_path) as file_content:
resource_mappings = json.load(file_content)
@@ -129,8 +133,10 @@ def resource_mappings(
:return: ResourceMappings class object.
"""
path = f'{workspace.paths.engine_root()}\\{project}\\Config\\{resource_mappings_filename}'
resource_mappings_obj = ResourceMappings(path, aws_utils.assume_session().region_name, feature_name,
path = f'{workspace.paths.engine_root()}/{project}/Config/{resource_mappings_filename}'
logger.info(f'Resource mapping path : {path}')
logger.info(f'Resource mapping resolved path : {abspath(path)}')
resource_mappings_obj = ResourceMappings(abspath(path), aws_utils.assume_session().region_name, feature_name,
aws_utils.assume_account_id(), workspace,
aws_utils.client('cloudformation'))
@@ -0,0 +1,11 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
@@ -74,15 +74,23 @@ def add_component(componentName, entityId):
typeIdsList = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', [componentName],
entity.EntityType().Game)
typeNamesList = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeNames', typeIdsList)
# If the type name comes back as empty, then it means componentName is invalid
if len(typeNamesList) != 1 or not typeNamesList[0]:
print('Unable to find component TypeId for {}'.format(componentName))
return None
componentOutcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', entityId, typeIdsList)
if not componentOutcome.IsSuccess():
print('Failed to add {} component to entity'.format(typeNamesList[0]))
return None
isActive = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', componentOutcome.GetValue()[0])
hasComponent = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', entityId, typeIdsList[0])
if componentOutcome.IsSuccess() and isActive:
if isActive:
print('{} component was added to entity'.format(typeNamesList[0]))
elif componentOutcome.IsSuccess() and not isActive:
else:
print('{} component was added to entity, but the component is disabled'.format(typeNamesList[0]))
elif not componentOutcome.IsSuccess():
print('Failed to add {} component to entity'.format(typeNamesList[0]))
if hasComponent:
print('Entity has a {} component'.format(typeNamesList[0]))
return componentOutcome.GetValue()[0]
@@ -218,7 +226,8 @@ class Entity:
def add_component(self, component):
new_component = add_component(component, self.id)
self.components.append(new_component)
if new_component:
self.components.append(new_component)
def add_component_of_type(self, componentTypeId):
new_component = add_component_of_type(componentTypeId, self.id)
@@ -84,10 +84,11 @@ class TestsMissingDependencies_WindowsAndMac(object):
"""Run a single test"""
for asset_platform in platforms:
db_product = db_utils.get_product_id_from_relative(self._workspace, source_product, asset_platform)
db_product_path = db_utils.get_db_product_path(self._workspace, source_product, asset_platform)
db_product = db_utils.get_product_id(self._missing_dep_helper.asset_db, db_product_path)
if db_product:
db_utils.clear_missing_dependencies(self._missing_dep_helper.asset_db, db_product)
expected_product = os.path.join(self._workspace.project, source_product).lower()
expected_product = source_product.lower()
dependency_search_params = [f"--dsp={dsp_param}", "--zeroAnalysisMode"]
if max_iterations:
@@ -112,17 +113,26 @@ class TestsMissingDependencies_WindowsAndMac(object):
# Expected missing dependencies
expected_dependencies = [
# String Asset #
("06E9D6633C875400A532BCB2C0CA19D6", "{06E9D663-3C87-5400-A532-BCB2C0CA19D6}:0"),
("1CB10C43F3245B93A294C602ADEF95F9:[0", "{1CB10C43-F324-5B93-A294-C602ADEF95F9}:0"),
("58BE9DA51F1753B98CEEEEB10E63454D", "{58BE9DA5-1F17-53B9-8CEE-EEB10E63454D}:914f19b7"),
("6BDE282B49C957F7B0714B26579BCA9A", "{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0"),
("747D31D71E62553592226173C49CF97E", "{747D31D7-1E62-5535-9222-6173C49CF97E}:1"),
("747D31D71E62553592226173C49CF97E", "{747D31D7-1E62-5535-9222-6173C49CF97E}:2"),
("9886E132-572D-5746-9377-E629AB6C1981", "{9886E132-572D-5746-9377-E629AB6C1981}:0"),
("33bcee02F3225688ABEE534F6058593F", "{33BCEE02-F322-5688-ABEE-534F6058593F}:0"),
("B92667DC-9F5B-5D72-A29D-99219DD9B691", "{B92667DC-9F5B-5D72-A29D-99219DD9B691}:0"),
("D92C4661C8985E19BD3597CB2318CFA6:[0", "{D92C4661-C898-5E19-BD35-97CB2318CFA6}:0"),
("7364AB2B092F5B0B80601BBC6E53087C", "{7364AB2B-092F-5B0B-8060-1BBC6E53087C}:0"),
('1CB10C43F3245B93A294C602ADEF95F9:[0', '{1CB10C43-F324-5B93-A294-C602ADEF95F9}:0'),
('33bcee02F3225688ABEE534F6058593F', '{33BCEE02-F322-5688-ABEE-534F6058593F}:0'),
('345E5C660D6254FF8D0F7C8EE66A2249', '{345E5C66-0D62-54FF-8D0F-7C8EE66A2249}:3e8'),
('345E5C660D6254FF8D0F7C8EE66A2249', '{345E5C66-0D62-54FF-8D0F-7C8EE66A2249}:3ea'),
('345E5C660D6254FF8D0F7C8EE66A2249', '{345E5C66-0D62-54FF-8D0F-7C8EE66A2249}:3eb'),
('37108522F50459499CD6C8D47A960CF1', '{37108522-F504-5949-9CD6-C8D47A960CF1}:3e8'),
('37108522F50459499CD6C8D47A960CF1', '{37108522-F504-5949-9CD6-C8D47A960CF1}:3ea'),
('37108522F50459499CD6C8D47A960CF1', '{37108522-F504-5949-9CD6-C8D47A960CF1}:3eb'),
('6BDE282B49C957F7B0714B26579BCA9A', '{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0'),
('747D31D71E62553592226173C49CF97E', '{747D31D7-1E62-5535-9222-6173C49CF97E}:1'),
('747D31D71E62553592226173C49CF97E', '{747D31D7-1E62-5535-9222-6173C49CF97E}:2'),
('A26C73D1837E5AE59E68F916FA7C3699', '{A26C73D1-837E-5AE5-9E68-F916FA7C3699}:3e8'),
('A26C73D1837E5AE59E68F916FA7C3699', '{A26C73D1-837E-5AE5-9E68-F916FA7C3699}:3ea'),
('A26C73D1837E5AE59E68F916FA7C3699', '{A26C73D1-837E-5AE5-9E68-F916FA7C3699}:3eb'),
('B076CDDC-14DF-50F4-A5E9-7518ABB3E851', '{B076CDDC-14DF-50F4-A5E9-7518ABB3E851}:0'),
('C67BEA9F-09FF-59AA-A7F0-A52B8F987508', '{C67BEA9F-09FF-59AA-A7F0-A52B8F987508}:3e8'),
('C67BEA9F-09FF-59AA-A7F0-A52B8F987508', '{C67BEA9F-09FF-59AA-A7F0-A52B8F987508}:3ea'),
('C67BEA9F-09FF-59AA-A7F0-A52B8F987508', '{C67BEA9F-09FF-59AA-A7F0-A52B8F987508}:3eb'),
('C67BEA9F-09FF-59AA-A7F0-A52B8F987508', '{C67BEA9F-09FF-59AA-A7F0-A52B8F987508}:3ec'),
('D92C4661C8985E19BD3597CB2318CFA6:[0', '{D92C4661-C898-5E19-BD35-97CB2318CFA6}:0'),
]
self.do_missing_dependency_test(expected_product, expected_dependencies,
"%ValidUUIDsNotDependency.txt")
@@ -151,9 +161,9 @@ class TestsMissingDependencies_WindowsAndMac(object):
# Expected missing dependencies
expected_dependencies = [
# String Asset #
("2ef92b8D044E5C278E2BB1AC0374A4E7:131072", "{2EF92B8D-044E-5C27-8E2B-B1AC0374A4E7}:20000"),
("A2482826-053D-5634-A27B-084B1326AAE5}:[196608", "{A2482826-053D-5634-A27B-084B1326AAE5}:30000"),
("D83B36F1-61A6-5001-B191-4D0CE282E236}-327680", "{D83B36F1-61A6-5001-B191-4D0CE282E236}:50000"),
('2ef92b8D044E5C278E2BB1AC0374A4E7:1003', '{2EF92B8D-044E-5C27-8E2B-B1AC0374A4E7}:3eb'),
('A2482826-053D-5634-A27B-084B1326AAE5}:[1002', '{A2482826-053D-5634-A27B-084B1326AAE5}:3ea'),
('D83B36F1-61A6-5001-B191-4D0CE282E236}-1002', '{D83B36F1-61A6-5001-B191-4D0CE282E236}:3ea'),
]
self.do_missing_dependency_test(expected_product, expected_dependencies,
@@ -186,16 +196,13 @@ class TestsMissingDependencies_WindowsAndMac(object):
# Expected missing dependencies
expected_dependencies = [
# String Asset #
("Config/Editor.xml", "{06E9D663-3C87-5400-A532-BCB2C0CA19D6}:0"),
(r"TestAssets\WildcardScanTest1.txt", "{1CB10C43-F324-5B93-A294-C602ADEF95F9}:0"),
("TestAssets/RelativeProductPathsNotDependencies.txt", "{B772953C-A08A-5D20-9491-530E87D11504}:0"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:0"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:10000"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:20000"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:30000"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:40000"),
("textures/_dev_Purple.tif", "{A2482826-053D-5634-A27B-084B1326AAE5}:50000"),
("Config/gAME.XML", "{B92667DC-9F5B-5D72-A29D-99219DD9B691}:0"),
('TestAssets\\WildcardScanTest1.txt', '{1CB10C43-F324-5B93-A294-C602ADEF95F9}:0'),
('libs/particles/milestone2PARTICLES.XML', '{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0'),
('textures/_dev_Purple.tif', '{A2482826-053D-5634-A27B-084B1326AAE5}:3e8'),
('textures/_dev_Purple.tif', '{A2482826-053D-5634-A27B-084B1326AAE5}:3ea'),
('textures/_dev_Purple.tif', '{A2482826-053D-5634-A27B-084B1326AAE5}:3eb'),
('project.json', '{B076CDDC-14DF-50F4-A5E9-7518ABB3E851}:0'),
('TestAssets/RelativeProductPathsNotDependencies.txt', '{B772953C-A08A-5D20-9491-530E87D11504}:0'),
]
self.do_missing_dependency_test(expected_product, expected_dependencies,
@@ -228,24 +235,22 @@ class TestsMissingDependencies_WindowsAndMac(object):
expected_product = f"testassets\\relativeproductpathsnotdependencies.txt"
expected_dependencies = [
# String Asset #
("materials/floor_tile.mtl", "{0EFF5E4A-F544-5D87-8696-6DDFA62D6063}:0"),
("materials/am_grass1.mtl", "{1151F14D-38A6-5579-888A-BE3139882E68}:0"),
("2ef92b8D044E5C278E2BB1AC0374A4E7:131072", "{2EF92B8D-044E-5C27-8E2B-B1AC0374A4E7}:20000"),
("ui/milestone2menu.uicanvas", "{445D9AF3-6CA5-5281-82A9-5C570BCD1DB8}:0"),
("ui/fonts/lyshineexamples/vera.ttf", "{74F5C29E-4749-5EE8-AEC6-A1C540600CE7}:0"),
("materials/am_rockground.mtl", "{A1DA3D05-A020-5BB5-A608-C4812B7BD733}:0"),
("textures/_dev_yellow_light.dds.2", "{6C40868F-3FC1-5115-96EA-DD0A9E33DEE4}:20000"),
(r"automatedtesting\textures\_dev_stucco.dds", "{70114D85-D712-5AEB-A816-8FE3A37087AF}:0"),
("textures/milestone2/ama_grey_02.dds", "{3EE80AAD-EB9C-56BD-9E9C-65410578998C}:0"),
(r"textures\\_dev_tan.dds", "{8F2BCEF5-C8CE-5B80-8103-8C1D694D012C}:0"),
("textures/_dev_purple.dds", "{A2482826-053D-5634-A27B-084B1326AAE5}:0"),
("TEXTURES/_DEV_WHITE.dds", "{D83B36F1-61A6-5001-B191-4D0CE282E236}:0"),
("textures/_dev_woodland.dds", "{F3DD193C-5845-569C-A974-AA338B30CF86}:0"),
("A2482826-053D-5634-A27B-084B1326AAE5}:[196608", "{A2482826-053D-5634-A27B-084B1326AAE5}:30000"),
("B92667DC-9F5B-5D72-A29D-99219DD9B691", "{B92667DC-9F5B-5D72-A29D-99219DD9B691}:0"),
("CEAA362B4E505BCEB827CB92EF40A50E", "{CEAA362B-4E50-5BCE-B827-CB92EF40A50E}:1"),
("CEAA362B4E505BCEB827CB92EF40A50E", "{CEAA362B-4E50-5BCE-B827-CB92EF40A50E}:2"),
("ui/fonts/lyshineexamples/veramono.ttf", "{BAD7FDC5-7BA6-5490-95AA-89078E2FA876}:0"),
('materials/floor_tile.mtl', '{0EFF5E4A-F544-5D87-8696-6DDFA62D6063}:0'),
('materials/am_grass1.mtl', '{1151F14D-38A6-5579-888A-BE3139882E68}:0'),
('2ef92b8D044E5C278E2BB1AC0374A4E7:1002', '{2EF92B8D-044E-5C27-8E2B-B1AC0374A4E7}:3ea'),
('textures/milestone2/ama_grey_02.tif.streamingimage', '{3EE80AAD-EB9C-56BD-9E9C-65410578998C}:3e8'),
('ui/milestone2menu.uicanvas', '{445D9AF3-6CA5-5281-82A9-5C570BCD1DB8}:0'),
('libs/particles/milestone2particles.xml', '{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0'),
('textures/_dev_yellow_light.tif.1002.imagemipchain', '{6C40868F-3FC1-5115-96EA-DD0A9E33DEE4}:3ea'),
('textures\\\\_dev_tan.tif.streamingimage', '{8F2BCEF5-C8CE-5B80-8103-8C1D694D012C}:3e8'),
('materials/am_rockground.mtl', '{A1DA3D05-A020-5BB5-A608-C4812B7BD733}:0'),
('textures/_dev_purple.tif.streamingimage', '{A2482826-053D-5634-A27B-084B1326AAE5}:3e8'),
('A2482826-053D-5634-A27B-084B1326AAE5}:[1002', '{A2482826-053D-5634-A27B-084B1326AAE5}:3ea'),
('project.json', '{B076CDDC-14DF-50F4-A5E9-7518ABB3E851}:0'),
('CEAA362B4E505BCEB827CB92EF40A50E', '{CEAA362B-4E50-5BCE-B827-CB92EF40A50E}:1'),
('CEAA362B4E505BCEB827CB92EF40A50E', '{CEAA362B-4E50-5BCE-B827-CB92EF40A50E}:2'),
('TEXTURES/_DEV_WHITE.tif.streamingimage', '{D83B36F1-61A6-5001-B191-4D0CE282E236}:3e8'),
('textures/_dev_woodland.tif.streamingimage', '{F3DD193C-5845-569C-A974-AA338B30CF86}:3e8'),
]
self.do_missing_dependency_test(expected_product, expected_dependencies,
@@ -260,8 +265,8 @@ class TestsMissingDependencies_WindowsAndMac(object):
helper = self._missing_dep_helper
# Relative paths to the txt file with no missing dependencies
expected_product_1 = f"{self._workspace.project}\\testassets\\wildcardscantest1.txt"
expected_product_2 = f"{self._workspace.project}\\testassets\\wildcardscantest2.txt"
expected_product_1 = f"testassets\\wildcardscantest1.txt"
expected_product_2 = f"testassets\\wildcardscantest2.txt"
expected_dependencies = [] # Neither file has expected missing dependencies
# Run missing dependency scanner and validate results for both files
@@ -288,13 +293,13 @@ class TestsMissingDependencies_WindowsAndMac(object):
emitting missing dependencies.
"""
# Relative path to target test file
expected_product = f"testassets\\dependencyscannerasset.dynamicslice"
expected_product = f"testassets\\reportonemissingdependency.txt"
# The only expected missing dependency
expected_dependencies = [("Config/Game.xml", "{B92667DC-9F5B-5D72-A29D-99219DD9B691}:0")]
expected_dependencies = [('6BDE282B49C957F7B0714B26579BCA9A', '{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0'),]
self.do_missing_dependency_test(expected_product, expected_dependencies,
"%DependencyScannerAsset%.dynamicslice")
"%reportonemissingdependency.txt")
@pytest.mark.BAT
@pytest.mark.assetpipeline
@@ -366,7 +371,7 @@ class TestsMissingDependencies_WindowsAndMac(object):
# Expected missing dependency hiding 31 dependencies deep
expected_dependencies = [
# String Asset #
("B92667DC-9F5B-5D72-A29D-99219DD9B691", "{B92667DC-9F5B-5D72-A29D-99219DD9B691}:0")
("6BDE282B-49C9-57F7-B071-4B26579BCA9A", "{6BDE282B-49C9-57F7-B071-4B26579BCA9A}:0")
]
self.do_missing_dependency_test(expected_product, expected_dependencies,
@@ -386,11 +391,11 @@ class TestsMissingDependencies_WindowsAndMac(object):
# Expected dependencies with valid lengths from file
expected_dependencies = [
# String Asset #
("D92C4661C8985E19BD3597CB2318CFA6", "{D92C4661-C898-5E19-BD35-97CB2318CFA6}:0"),
("58BE9DA51F1753B98CEEEEB10E63454D", "{58BE9DA5-1F17-53B9-8CEE-EEB10E63454D}:914f19b7"),
("747D31D71E62553592226173C49CF97E", "{747D31D7-1E62-5535-9222-6173C49CF97E}:1"),
("747D31D71E62553592226173C49CF97E", "{747D31D7-1E62-5535-9222-6173C49CF97E}:2"),
("1CB10C43-F324-5B93-A294-C602ADEF95F9", "{1CB10C43-F324-5B93-A294-C602ADEF95F9}:0"),
('D1265251CC14584AB1CECB10746A2BA0', '{D1265251-CC14-584A-B1CE-CB10746A2BA0}:2'),
('D1265251CC14584AB1CECB10746A2BA0', '{D1265251-CC14-584A-B1CE-CB10746A2BA0}:1'),
('D92C4661C8985E19BD3597CB2318CFA6', '{D92C4661-C898-5E19-BD35-97CB2318CFA6}:0'),
('837412DFD05F576D81AAACF360463749', '{837412DF-D05F-576D-81AA-ACF360463749}:0'),
('785A05D2483E5B43A2B992ACDAE6E938', '{785A05D2-483E-5B43-A2B9-92ACDAE6E938}:0'),
]
self.do_missing_dependency_test( expected_product, expected_dependencies,
@@ -135,9 +135,7 @@ def run():
# Delete all existing entities initially
search_filter = azlmbr.entity.SearchFilter()
all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
general.idle_wait_frames(1)
editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities)
general.idle_wait_frames(1)
class ComponentTests:
"""Test launcher for each component."""
@@ -149,11 +147,9 @@ def run():
def run_component_tests(self):
# Run common and additional tests
entity_obj = create_entity_undo_redo_component_addition(self.component_name)
general.idle_wait(0.5)
# Enter/Exit game mode test
verify_enter_exit_game_mode(self.component_name)
general.idle_wait(0.5)
# Any additional tests are executed here
for test in self.additional_tests:
@@ -161,16 +157,13 @@ def run():
# Hide/Unhide entity test
verify_hide_unhide_entity(self.component_name, entity_obj)
general.idle_wait(0.5)
# Deletion/Undo/Redo test
verify_deletion_undo_redo(self.component_name, entity_obj)
general.idle_wait(0.5)
# DepthOfField Component
camera_entity = hydra.Entity("camera_entity")
camera_entity.create_entity(math.Vector3(512.0, 512.0, 34.0), ["Camera"])
general.idle_wait(0.5)
depth_of_field = "DepthOfField"
ComponentTests(
depth_of_field,
@@ -26,20 +26,23 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("level", ["auto_test"])
class TestAtomEditorComponentsMain(object):
"""Holds tests for Atom components."""
@pytest.mark.xfail(reason="Timing out sporadically, LYN-3956")
@pytest.mark.test_case_id(
"C32078130", # Display Mapper
"C32078129", # Light
"C32078131", # Radius Weight Modifier
"C32078127", # PostFX Layer
"C32078125", # Physical Sky
"C32078115", # Global Skylight (IBL)
"C32078121", # Exposure Control
"C32078120", # Directional Light
"C32078119", # DepthOfField
"C32078118") # Decal (Atom)
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
"""
Please review the hydra script run by this test for more specific test info.
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
1. Display Mapper
2. Light
3. Radius Weight Modifier
4. PostFX Layer
5. Physical Sky
6. Global Skylight (IBL)
7. Exposure Control
8. Directional Light
9. DepthOfField
10. Decal (Atom)
"""
cfg_args = [level]
expected_lines = [
@@ -47,7 +47,7 @@ def get_active_platforms_from_db(asset_db_path) -> List[str]:
# Convert a source product path into a db product path
# cache_platform/projectname/product_path
def get_db_product_path(workspace, source_path, cache_platform):
product_path = os.path.join(cache_platform, workspace.project, source_path)
product_path = os.path.join(cache_platform, source_path)
product_path = product_path.replace('\\', '/')
return product_path
@@ -10,11 +10,27 @@
#
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_FOUNDATION_TEST_SUPPORTED)
ly_add_pytest(
NAME AutomatedTesting::EditorTests_Main
TEST_SUITE main
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT
Editor
)
ly_add_pytest(
NAME AutomatedTesting::EditorTests_Periodic
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_periodic"
TIMEOUT 1500
RUNTIME_DEPENDENCIES
Legacy::Editor
@@ -0,0 +1,160 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
"""
C6351273: Create a new level
C6384955: Basic Workflow: Entity Manipulation in the Outliner
C16929880: Add Delete Components
C15167490: Save a level
C15167491: Export a level
"""
import os
import sys
from PySide2 import QtWidgets
import azlmbr.bus as bus
import azlmbr.editor as editor
import azlmbr.entity as entity
import azlmbr.math as math
import azlmbr.paths
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
from editor_python_test_tools.editor_test_helper import EditorTestHelper
import editor_python_test_tools.pyside_utils as pyside_utils
import editor_python_test_tools.hydra_editor_utils as hydra
class TestBasicEditorWorkflows(EditorTestHelper):
def __init__(self):
EditorTestHelper.__init__(self, log_prefix="BasicEditorWorkflows_LevelEntityComponent", args=["level"])
@pyside_utils.wrap_async
async def run_test(self):
"""
Summary:
Open Lumberyard editor and check if basic Editor workflows are completable.
Expected Behavior:
- A new level can be created
- A new entity can be created
- Entity hierarchy can be adjusted
- Components can be added/removed/updated
- Level can be saved
- Level can be exported
Note:
- This test file must be called from the Lumberyard Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def find_entity_by_name(entity_name):
search_filter = entity.SearchFilter()
search_filter.names = [entity_name]
results = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
if len(results) > 0:
return results[0]
return None
# 1) Create a new level
editor_window = pyside_utils.get_editor_main_window()
new_level_action = pyside_utils.get_action_for_menu_path(editor_window, "File", "New Level")
pyside_utils.trigger_action_async(new_level_action)
active_modal_widget = await pyside_utils.wait_for_modal_widget()
new_level_dlg = active_modal_widget.findChild(QtWidgets.QWidget, "CNewLevelDialog")
if new_level_dlg:
if new_level_dlg.windowTitle() == "New Level":
self.log("New Level dialog opened")
grp_box = new_level_dlg.findChild(QtWidgets.QGroupBox, "STATIC_GROUP1")
level_name = grp_box.findChild(QtWidgets.QLineEdit, "LEVEL")
level_name.setText(self.args["level"])
level_folders = grp_box.findChild(QtWidgets.QComboBox, "LEVEL_FOLDERS")
level_folders.setCurrentText("Levels/")
button_box = new_level_dlg.findChild(QtWidgets.QDialogButtonBox, "buttonBox")
button_box.button(QtWidgets.QDialogButtonBox.Ok).click()
# Verify new level was created successfully
level_create_success = await pyside_utils.wait_for_condition(lambda: editor.EditorToolsApplicationRequestBus(
bus.Broadcast, "GetCurrentLevelName") == self.args["level"], 5.0)
self.test_success = level_create_success
self.log(f"Create and load new level: {level_create_success}")
# Execute EditorTestHelper setup since level was created outside of EditorTestHelper's methods
self.test_success = self.test_success and self.after_level_load()
# 2) Delete existing entities, and create and manipulate new entities via Entity Inspector
search_filter = azlmbr.entity.SearchFilter()
all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities)
entity_outliner_widget = editor_window.findChild(QtWidgets.QWidget, "OutlinerWidgetUI")
outliner_object_list = entity_outliner_widget.findChild(QtWidgets.QWidget, "m_objectList_Contents")
outliner_tree = outliner_object_list.findChild(QtWidgets.QWidget, "m_objectTree")
await pyside_utils.trigger_context_menu_entry(outliner_tree, "Create entity")
# Find the new entity
parent_entity_id = find_entity_by_name("Entity1")
parent_entity_success = await pyside_utils.wait_for_condition(lambda: parent_entity_id is not None, 5.0)
self.test_success = self.test_success and parent_entity_success
self.log(f"New entity creation: {parent_entity_success}")
# TODO: Replace Hydra call to creates child entity and add components with context menu triggering - LYN-3951
# Create a new child entity
child_entity = hydra.Entity("Child")
entity_position = math.Vector3(0.0, 0.0, 0.0)
components_to_add = []
child_entity.create_entity(entity_position, components_to_add, parent_entity_id)
# Verify entity hierarchy
child_entity.get_parent_info()
self.test_success = self.test_success and child_entity.parent_id == parent_entity_id
self.log(f"Create entity hierarchy: {child_entity.parent_id == parent_entity_id}")
# 3) Add/configure a component on an entity
# Add component and verify success
child_entity.add_component("Box Shape")
component_add_success = self.wait_for_condition(lambda: hydra.has_components(child_entity.id, ["Box Shape"]), 5.0)
self.test_success = self.test_success and component_add_success
self.log(f"Add component: {component_add_success}")
# Update the component
dimensions_to_set = math.Vector3(16.0, 16.0, 16.0)
child_entity.get_set_test(0, "Box Shape|Box Configuration|Dimensions", dimensions_to_set)
box_shape_dimensions = hydra.get_component_property_value(child_entity.components[0], "Box Shape|Box Configuration|Dimensions")
self.test_success = self.test_success and box_shape_dimensions == dimensions_to_set
self.log(f"Component update: {box_shape_dimensions == dimensions_to_set}")
# Remove the component
child_entity.remove_component("Box Shape")
component_rem_success = self.wait_for_condition(lambda: not hydra.has_components(child_entity.id, ["Box Shape"]),
5.0)
self.test_success = self.test_success and component_rem_success
self.log(f"Remove component: {component_rem_success}")
# 4) Save the level
save_level_action = pyside_utils.get_action_for_menu_path(editor_window, "File", "Save")
pyside_utils.trigger_action_async(save_level_action)
# 5) Export the level
export_action = pyside_utils.get_action_for_menu_path(editor_window, "Game", "Export to Engine")
pyside_utils.trigger_action_async(export_action)
level_pak_file = os.path.join(
"AutomatedTesting", "Levels", self.args["level"], "level.pak"
)
export_success = self.wait_for_condition(lambda: os.path.exists(level_pak_file), 5.0)
self.test_success = self.test_success and export_success
self.log(f"Save and Export: {export_success}")
test = TestBasicEditorWorkflows()
test.run()
@@ -0,0 +1,63 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import os
import pytest
# Bail on the test if ly_test_tools doesn't exist.
pytest.importorskip('ly_test_tools')
import ly_test_tools.environment.file_system as file_system
import editor_python_test_tools.hydra_test_utils as hydra
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
log_monitor_timeout = 180
@pytest.mark.parametrize('project', ['AutomatedTesting'])
@pytest.mark.parametrize('level', ['tmp_level'])
@pytest.mark.usefixtures("automatic_process_killer")
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestBasicEditorWorkflows(object):
@pytest.fixture(autouse=True)
def setup_teardown(self, request, workspace, project, level):
def teardown():
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
@pytest.mark.test_case_id("C6351273", "C6384955", "C16929880", "C15167490", "C15167491")
@pytest.mark.SUITE_main
def test_BasicEditorWorkflows_LevelEntityComponentCRUD(self, request, editor, level, launcher_platform):
expected_lines = [
"Create and load new level: True",
"New entity creation: True",
"Create entity hierarchy: True",
"Add component: True",
"Component update: True",
"Remove component: True",
"Save and Export: True",
"BasicEditorWorkflows_LevelEntityComponent: result=SUCCESS",
]
hydra.launch_and_validate_results(
request,
test_directory,
editor,
"BasicEditorWorkflows_LevelEntityComponentCRUD.py",
expected_lines,
cfg_args=[level],
timeout=log_monitor_timeout,
auto_test_mode=False
)
@@ -13,22 +13,21 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
## DynVeg ##
# Temporarily moving all tests to periodic suite - SPEC-6553
#ly_add_pytest(
# NAME AutomatedTesting::DynamicVegetationTests_Main
# TEST_SERIAL
# TEST_SUITE main
# PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
# PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
# TIMEOUT 1500
# RUNTIME_DEPENDENCIES
# AZ::AssetProcessor
# Legacy::Editor
# AutomatedTesting.GameLauncher
# AutomatedTesting.Assets
# COMPONENT
# LargeWorlds
#)
ly_add_pytest(
NAME AutomatedTesting::DynamicVegetationTests_Main
TEST_SERIAL
TEST_SUITE main
PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
COMPONENT
LargeWorlds
)
ly_add_pytest(
@@ -137,21 +136,21 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
LargeWorlds
)
## LandscapeCanvas ##
# Temporarily moving all tests to periodic suite - SPEC-6553
#ly_add_pytest(
# NAME AutomatedTesting::LandscapeCanvasTests_Main
# TEST_SERIAL
# TEST_SUITE main
# PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/landscape_canvas
# PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
# TIMEOUT 1500
# RUNTIME_DEPENDENCIES
# AZ::AssetProcessor
# Legacy::Editor
# AutomatedTesting.Assets
# COMPONENT
# LargeWorlds
#)
ly_add_pytest(
NAME AutomatedTesting::LandscapeCanvasTests_Main
TEST_SERIAL
TEST_SUITE main
PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas
PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark"
TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
AutomatedTesting.Assets
COMPONENT
LargeWorlds
)
ly_add_pytest(
NAME AutomatedTesting::LandscapeCanvasTests_Periodic
@@ -41,7 +41,7 @@ class TestDynamicSliceInstanceSpawner(object):
return console
@pytest.mark.test_case_id("C28851763")
@pytest.mark.SUITE_periodic
@pytest.mark.SUITE_main
@pytest.mark.dynveg_area
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
def test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(self, request, editor, level, workspace, project,
@@ -37,7 +37,7 @@ class TestEmptyInstanceSpawner(object):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
@pytest.mark.test_case_id("C28851762")
@pytest.mark.SUITE_periodic
@pytest.mark.SUITE_main
@pytest.mark.dynveg_area
def test_EmptyInstanceSpawner_EmptySpawnerWorks(self, request, editor, level, launcher_platform):
cfg_args = [level]
@@ -118,7 +118,7 @@ class TestGraphComponentSync(object):
@pytest.mark.test_case_id('C15987206')
@pytest.mark.SUITE_main
def test_LandscapeCanvas_GradientMixerNodeConstruction(self, request, editor, level, launcher_platform):
def test_LandscapeCanvas_GradientMixer_NodeConstruction(self, request, editor, level, launcher_platform):
"""
Verifies a Gradient Mixer can be setup in Landscape Canvas and all references are property set.
"""
@@ -141,7 +141,7 @@ class TestGraphComponentSync(object):
@pytest.mark.test_case_id('C21333743')
@pytest.mark.SUITE_periodic
def test_LandscapeCanvas_LayerBlenderNodeConstruction(self, request, editor, level, launcher_platform):
def test_LandscapeCanvas_LayerBlender_NodeConstruction(self, request, editor, level, launcher_platform):
"""
Verifies a Layer Blender can be setup in Landscape Canvas and all references are property set.
"""
@@ -0,0 +1,202 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
# fmt: off
class Tests():
new_event_created = ("New Script Event created", "New Script Event not created")
child_1_created = ("Initial Child Event created", "Initial Child Event not created")
child_2_created = ("Second Child Event created", "Second Child Event not created")
file_saved = ("Script event file saved", "Script event file did not save")
method_added = ("Method added to scriptevent file", "Method not added to scriptevent file")
method_removed = ("Method removed from scriptevent file", "Method not removed from scriptevent file")
# fmt: on
def ScriptEvent_AddRemoveMethod_UpdatesInSC():
"""
Summary:
Method can be added/removed to an existing .scriptevents file
Expected Behavior:
The Method is correctly added/removed to the asset, and Script Canvas nodes are updated accordingly.
Test Steps:
1) Open Asset Editor and Script Canvas windows
2) Initially create new Script Event file with one method
3) Verify if file is created and saved
4) Add a new child element
5) Update MethodNames and save file
6) Verify if the new node exist in SC (search in node palette)
7) Delete one method and save
8) Verify if the node is removed in SC
9) Close Asset Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
from utils import TestHelper as helper
import pyside_utils
# Open 3D Engine imports
import azlmbr.legacy.general as general
import azlmbr.editor as editor
import azlmbr.bus as bus
# Pyside imports
from PySide2 import QtWidgets, QtTest, QtCore
GENERAL_WAIT = 1.0 # seconds
FILE_PATH = os.path.join("AutomatedTesting", "TestAssets", "test_file.scriptevents")
METHOD_NAME = "test_method_name"
editor_window = pyside_utils.get_editor_main_window()
asset_editor = asset_editor_widget = container = menu_bar = None
sc = node_palette = tree = search_frame = search_box = None
def initialize_asset_editor_qt_objects():
nonlocal asset_editor, asset_editor_widget, container, menu_bar
asset_editor = editor_window.findChild(QtWidgets.QDockWidget, "Asset Editor")
asset_editor_widget = asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass")
container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
menu_bar = asset_editor_widget.findChild(QtWidgets.QMenuBar)
def initialize_sc_qt_objects():
nonlocal sc, node_palette, tree, search_frame, search_box
sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None:
action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction})
action.trigger()
node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette")
tree = node_palette.findChild(QtWidgets.QTreeView, "treeView")
search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame")
search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
def save_file():
editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "iconText": "Save"})
action.trigger()
# wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor,
# if there are no unsaved changes we will not have any * in the text
label = asset_editor.findChild(QtWidgets.QLabel, "textEdit")
return helper.wait_for_condition(lambda: "*" not in label.text(), 3.0)
def expand_container_rows(object_name):
children = container.findChildren(QtWidgets.QFrame, object_name)
for child in children:
check_box = child.findChild(QtWidgets.QCheckBox)
if check_box and not check_box.isChecked():
QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
def node_palette_search(node_name):
search_box.setText(node_name)
helper.wait_for_condition(lambda: search_box.text() == node_name, 1.0)
# Try clicking ENTER in search box multiple times
for _ in range(10):
QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier)
if pyside_utils.find_child_by_pattern(tree, {"text": node_name}) is not None:
break
# 1) Open Asset Editor
general.idle_enable(True)
# Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open
general.close_pane("Asset Editor")
general.open_pane("Asset Editor")
helper.wait_for_condition(lambda: general.is_pane_visible("Asset Editor"), 5.0)
# 2) Initially create new Script Event file with one method
initialize_asset_editor_qt_objects()
action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "text": "Script Events"})
action.trigger()
result = helper.wait_for_condition(
lambda: container.findChild(QtWidgets.QFrame, "Events") is not None
and container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") is not None,
3 * GENERAL_WAIT,
)
Report.result(Tests.new_event_created, result)
# Add new method
add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
add_event.click()
result = helper.wait_for_condition(
lambda: asset_editor_widget.findChild(QtWidgets.QFrame, "EventName") is not None, GENERAL_WAIT
)
Report.result(Tests.child_1_created, result)
editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
# 3) Verify if file is created and saved
result = helper.wait_for_condition(lambda: os.path.exists(FILE_PATH), 3 * GENERAL_WAIT)
Report.result(Tests.file_saved, result and save_file())
# 4) Add a new child element
add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
add_event.click()
result = helper.wait_for_condition(
lambda: len(asset_editor_widget.findChildren(QtWidgets.QFrame, "EventName")) == 2, 2 * GENERAL_WAIT
)
Report.result(Tests.child_2_created, result)
# 5) Update MethodNames and save file, (update all Method names to make it easier to search in SC later)
# Expand the EventName initially
expand_container_rows("EventName")
# Expand Name fields under it
expand_container_rows("Name")
count = 0 # 2 Method names will be updated Ex: test_method_name_0, test_method_name_1
container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
children = container.findChildren(QtWidgets.QFrame, "Name")
for child in children:
line_edit = child.findChild(QtWidgets.QLineEdit)
if line_edit and line_edit.text() == "MethodName":
line_edit.setText(f"{METHOD_NAME}_{count}")
count += 1
save_file()
# 6) Verify if the new node exist in SC (search in node palette)
general.open_pane("Script Canvas")
helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0)
initialize_sc_qt_objects()
node_palette_search(f"{METHOD_NAME}_1")
get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": f"{METHOD_NAME}_1"}) is not None
result = helper.wait_for_condition(get_node_index, GENERAL_WAIT)
Report.result(Tests.method_added, result)
# 7) Delete one method and save
initialize_asset_editor_qt_objects()
for child in container.findChildren(QtWidgets.QFrame, "EventName"):
if child.findChild(QtWidgets.QToolButton, ""):
child.findChild(QtWidgets.QToolButton, "").click()
break
save_file()
# 8) Verify if the node is removed in SC (search in node palette)
initialize_sc_qt_objects()
node_palette_search(f"{METHOD_NAME}_0")
get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": f"{METHOD_NAME}_0"}) is None
result = helper.wait_for_condition(get_node_index, GENERAL_WAIT)
Report.result(Tests.method_removed, result)
# 9) Close Asset Editor
general.close_pane("Asset Editor")
general.close_pane("Script Canvas")
if __name__ == "__main__":
import ImportPathHelper as imports
imports.init()
from utils import Report
Report.start_test(ScriptEvent_AddRemoveMethod_UpdatesInSC)
@@ -278,6 +278,7 @@ class TestScriptCanvasTests(object):
},
],
)
def test_Pane_PropertiesChanged_RetainsOnRestart(self, request, editor, config, project, launcher_platform):
hydra.launch_and_validate_results(
request,
@@ -289,3 +290,31 @@ class TestScriptCanvasTests(object):
auto_test_mode=False,
timeout=60,
)
def test_ScriptEvent_AddRemoveMethod_UpdatesInSC(self, request, workspace, editor, launcher_platform):
def teardown():
file_system.delete(
[os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
)
request.addfinalizer(teardown)
file_system.delete(
[os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
)
expected_lines = [
"Success: New Script Event created",
"Success: Initial Child Event created",
"Success: Second Child Event created",
"Success: Script event file saved",
"Success: Method added to scriptevent file",
"Success: Method removed from scriptevent file",
]
hydra.launch_and_validate_results(
request,
TEST_DIRECTORY,
editor,
"ScriptEvent_AddRemoveMethod_UpdatesInSC.py",
expected_lines,
auto_test_mode=False,
timeout=60,
)
@@ -1,3 +1,3 @@
The dependency scanner has a built in limit to how deep it will recurse when multiple results exist on the same line.
This file has a single line with 10 invalid UUIDs, and an 11th valid UUID.
1: 00000000-0000-0000-0000-000000000000, 2: 00000000-0000-0000-0000-000000000000, 3: 00000000-0000-0000-0000-000000000000, 4: 00000000-0000-0000-0000-000000000000, 5: 00000000-0000-0000-0000-000000000000, 6: 00000000-0000-0000-0000-000000000000, 7: 00000000-0000-0000-0000-000000000000, 8: 00000000-0000-0000-0000-000000000000, 9: 00000000-0000-0000-0000-000000000000, 10: 00000000-0000-0000-0000-000000000000, 11: 00000000-0000-0000-0000-000000000000, 12: 00000000-0000-0000-0000-000000000000, 13: 00000000-0000-0000-0000-000000000000, 14: 00000000-0000-0000-0000-000000000000, 15: 00000000-0000-0000-0000-000000000000, 16: 00000000-0000-0000-0000-000000000000, 17: 00000000-0000-0000-0000-000000000000, 18: 00000000-0000-0000-0000-000000000000, 19: 00000000-0000-0000-0000-000000000000, 20: 00000000-0000-0000-0000-000000000000, 21: 00000000-0000-0000-0000-000000000000, 22: 00000000-0000-0000-0000-000000000000, 23: 00000000-0000-0000-0000-000000000000, 24: 00000000-0000-0000-0000-000000000000, 25: 00000000-0000-0000-0000-000000000000, 26: 00000000-0000-0000-0000-000000000000, 27: 00000000-0000-0000-0000-000000000000, 28: 00000000-0000-0000-0000-000000000000, 29: 00000000-0000-0000-0000-000000000000, 30: 00000000-0000-0000-0000-000000000000, 31 (valid UUID, game . xml): B92667DC-9F5B-5D72-A29D-99219DD9B691
1: 00000000-0000-0000-0000-000000000000, 2: 00000000-0000-0000-0000-000000000000, 3: 00000000-0000-0000-0000-000000000000, 4: 00000000-0000-0000-0000-000000000000, 5: 00000000-0000-0000-0000-000000000000, 6: 00000000-0000-0000-0000-000000000000, 7: 00000000-0000-0000-0000-000000000000, 8: 00000000-0000-0000-0000-000000000000, 9: 00000000-0000-0000-0000-000000000000, 10: 00000000-0000-0000-0000-000000000000, 11: 00000000-0000-0000-0000-000000000000, 12: 00000000-0000-0000-0000-000000000000, 13: 00000000-0000-0000-0000-000000000000, 14: 00000000-0000-0000-0000-000000000000, 15: 00000000-0000-0000-0000-000000000000, 16: 00000000-0000-0000-0000-000000000000, 17: 00000000-0000-0000-0000-000000000000, 18: 00000000-0000-0000-0000-000000000000, 19: 00000000-0000-0000-0000-000000000000, 20: 00000000-0000-0000-0000-000000000000, 21: 00000000-0000-0000-0000-000000000000, 22: 00000000-0000-0000-0000-000000000000, 23: 00000000-0000-0000-0000-000000000000, 24: 00000000-0000-0000-0000-000000000000, 25: 00000000-0000-0000-0000-000000000000, 26: 00000000-0000-0000-0000-000000000000, 27: 00000000-0000-0000-0000-000000000000, 28: 00000000-0000-0000-0000-000000000000, 29: 00000000-0000-0000-0000-000000000000, 30: 00000000-0000-0000-0000-000000000000, 31 (valid UUID, libs / particles / milestone2particles . xml): 6BDE282B-49C9-57F7-B071-4B26579BCA9A
@@ -1,15 +1,15 @@
The missing dependency scanner was updated to only look for substrings that are the exact length of UUIDs, separated by word boundaries. This avoids problems with very long numbers causing the scan to stall out and take a long time.
This is the UUID for dev / AutomatedTesting / Config / Game . xml with an extra UUID character at the beginning. It should not show up in scan results.
aB92667DC-9F5B-5D72-A29D-99219DD9B691
This is the UUID for libs / particles / milestone2particles . xml with an extra UUID character at the beginning. It should not show up in scan results.
a6BDE282B49C957F7B0714B26579BCA9A
This is the UUID for dev / AutomatedTesting / Config / Editor . xml. It has an extra non-UUID character at the end. It should not show up in scan results.
06E9D6633C875400A532BCB2C0CA19D6t
This is the UUID for project . json. It has an extra non-UUID character at the end. It should not show up in scan results.
B076CDDC14DF50F4A5E97518ABB3E851t
Two UUIDs, the first invalid a6BDE282B49C957F7B0714B26579BCA9A mixed with a second valid one 58BE9DA51F1753B98CEEEEB10E63454D the same line. The second should show up in scan results.
Two UUIDs, the first invalid a1CB10C43F3245B93A294C602ADEF95F9 mixed with a second valid one D1265251CC14584AB1CECB10746A2BA0 the same line. The second should show up in scan results.
UUID for slices / MuzzleFlash . slice, after an equal sign should show up in scan results=747D31D71E62553592226173C49CF97E
UUID for TestAssets / DependencyScannerAsset . slice, after an equal sign should show up in scan results=837412DFD05F576D81AAACF360463749
UUID for TestsAssets / WildcardScanTest1 . txt in quotes, should show up in scan results"1CB10C43-F324-5B93-A294-C602ADEF95F9"
UUID for TestAssets / WildcardScanTest2 . txt in quotes, should show up in scan results"D92C4661C8985E19BD3597CB2318CFA6"
UUID for Objects / Lumbertank_turret . cgf in curly braces, should up show in scan results{D92C4661C8985E19BD3597CB2318CFA6}
UUID for TestAssets / SelfReferenceAssetID. txt in curly braces, should up show in scan results{785A05D2483E5B43A2B992ACDAE6E938}
@@ -1,25 +1,25 @@
These tests are mostly done with files that have a different extension between source and product.
The source scan is done first, and will catch files in the source path.
Product path searching is resolved using "endsWith" logic.
textures/_dev_purple.dds
textures/_dev_purple.tif.streamingimage
Back slashes, and project name in the path
automatedtesting\textures\_dev_stucco.dds
pc/textures/_dev_stucco.tif.streamingimage
Double back slashes
textures\\_dev_tan.dds
textures\\_dev_tan.tif.streamingimage
Casing doesn't match
TEXTURES/_DEV_WHITE.dds
TEXTURES/_DEV_WHITE.tif.streamingimage
Some files have multiple extensions, this verifies that won't trip up the scanner.
textures/_dev_yellow_light.dds.2
Path inline textures/milestone2/ama_grey_02.dds test
Path after=textures/_dev_woodland.dds equal sign
textures/_dev_yellow_light.tif.1002.imagemipchain
Path inline textures/milestone2/ama_grey_02.tif.streamingimage test
Path after=textures/_dev_woodland.tif.streamingimage equal sign
Multiple paths on one line
Multiple materials/am_grass1.mtl paths materials/am_rockground.mtl on one line
Path before a UUID
Path materials/floor_tile.mtl before B92667DC-9F5B-5D72-A29D-99219DD9B691 a UUID
Path before an asset ID
Path ui/milestone2menu.uicanvas before an 2ef92b8D044E5C278E2BB1AC0374A4E7:131072 asset ID
Path ui/milestone2menu.uicanvas before an 2ef92b8D044E5C278E2BB1AC0374A4E7:1002 asset ID
Path after a UUID
Path after CEAA362B4E505BCEB827CB92EF40A50E a ui/fonts/lyshineexamples/vera.ttf UUID
Path after CEAA362B4E505BCEB827CB92EF40A50E a project.json UUID
Path after an asset ID
Path after {A2482826-053D-5634-A27B-084B1326AAE5}:[196608] an ui/fonts/lyshineexamples/veramono.ttf asset ID
Path after {A2482826-053D-5634-A27B-084B1326AAE5}:[1002] an libs/particles/milestone2particles.xml asset ID
@@ -3,6 +3,6 @@ TestAssets/RelativeProductPathsNotDependencies.txt
Back slashes
TestAssets\WildcardScanTest1.txt
Casing doesn't match
Config/gAME.XML
Path inline Config/Editor.xml test
libs/particles/milestone2PARTICLES.XML
Path inline project.json test
Path after=textures/_dev_Purple.tif equal sign
@@ -1,5 +1,5 @@
dev/AutomatedTesting/textures/_dev_Purple.tif, the product ID is for one of the mips.
{A2482826-053D-5634-A27B-084B1326AAE5}:[196608]
_dev_Red.tif, another mip, different formatting.
2ef92b8D044E5C278E2BB1AC0374A4E7:131072
_dev_White.tif, {D83B36F1-61A6-5001-B191-4D0CE282E236}-327680 asset ID inline.
/textures /_dev_Purple . tif, the product ID is for one of the mips.
{A2482826-053D-5634-A27B-084B1326AAE5}:[1002]
_dev_Red . tif, another mip, different formatting.
2ef92b8D044E5C278E2BB1AC0374A4E7:1003
_dev_White.tif, {D83B36F1-61A6-5001-B191-4D0CE282E236}-1002 asset ID inline.
@@ -1,18 +1,18 @@
Paths are broken up to avoid having them show up as relative path results.
This is the UUID for dev / AutomatedTesting / Config / Game . xml
B92667DC-9F5B-5D72-A29D-99219DD9B691
This is the UUID for dev / AutomatedTesting / Config / Editor . xml. This tests UUIDs without separators.
06E9D6633C875400A532BCB2C0CA19D6
This is the UUID for Materials / Default / AM_UV_v1_1K_source . png
C67BEA9F-09FF-59AA-A7F0-A52B8F987508
This is the UUID for libs / particles / milestone2particles . xml. This tests UUIDs without separators.
6BDE282B49C957F7B0714B26579BCA9A
This is the UUID for SelfReferenceUUID.txt. This tests UUIDs with mixed casing.
33bcee02F3225688ABEE534F6058593F
This is a UUID mid-line 9886E132-572D-5746-9377-E629AB6C1981, for gems . json
This is a UUID mid-line B076CDDC-14DF-50F4-A5E9-7518ABB3E851, for project . json
Two UUIDs on the same line
Two UUIDs 6BDE282B49C957F7B0714B26579BCA9A mixed on 58BE9DA51F1753B98CEEEEB10E63454D the same line
Two UUIDs 345E5C660D6254FF8D0F7C8EE66A2249 mixed on A26C73D1837E5AE59E68F916FA7C3699 the same line
Test UUIDs and Asset IDs mixed on the same line. Relative paths are handled in the relative path tests.
UUID: slices / MuzzleFlash . slice, AssetID: TestsAssets / WildcardScanTest1 . txt
This 747D31D71E62553592226173C49CF97E uuid is on the line with 1CB10C43F3245B93A294C602ADEF95F9:[0] a valid asset ID
UUID: Objects / Lumbertank_turret . cgf, AssetID: TestsAssets / WildcardScanTest2 . txt
This D92C4661C8985E19BD3597CB2318CFA6:[0] uuid is on the line with 7364AB2B092F5B0B80601BBC6E53087C a valid asset ID
This D92C4661C8985E19BD3597CB2318CFA6:[0] uuid is on the line with 37108522F50459499CD6C8D47A960CF1 a valid asset ID
@@ -244,7 +244,7 @@ public class LumberyardActivity extends NativeActivity
boolean useMainObb = GetBooleanResource("use_main_obb");
boolean usePatchObb = GetBooleanResource("use_patch_obb");
if (IsBootstrapInAPK() && (useMainObb || usePatchObb))
if (AreAssetsInAPK() && (useMainObb || usePatchObb))
{
Log.d(TAG, "Using OBB expansion files for game assets");
@@ -421,12 +421,12 @@ public class LumberyardActivity extends NativeActivity
}
////////////////////////////////////////////////////////////////
private boolean IsBootstrapInAPK()
private boolean AreAssetsInAPK()
{
try
{
InputStream bootstrap = getAssets().open("bootstrap.cfg", AssetManager.ACCESS_UNKNOWN);
bootstrap.close();
InputStream engine = getAssets().open("engine.json", AssetManager.ACCESS_UNKNOWN);
engine.close();
return true;
}
catch (IOException exception)
@@ -148,7 +148,7 @@ namespace AZ
}
}
AZ_Assert(false, "Failed to locate the bootstrap.cfg path");
AZ_Assert(false, "Failed to locate the engine.json path");
return nullptr;
}
+2 -2
View File
@@ -73,8 +73,8 @@ namespace AZ
//! \return The pointer position of the relative asset path
AZ::IO::FixedMaxPath StripApkPrefix(const char* filePath);
//! Searches application storage and the APK for bootstrap.cfg. Will return nullptr
//! if bootstrap.cfg is not found.
//! Searches application storage and the APK for engine.json. Will return nullptr
//! if engine.json is not found.
const char* FindAssetsDirectory();
//! Calls into Java to show the splash screen on the main UI (Java) thread
@@ -462,8 +462,6 @@ namespace AZ
// for the application root.
CalculateAppRoot();
// Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
@@ -287,71 +287,28 @@ namespace AZ
//! Scale modifiers
//! @{
//! @deprecated Use SetLocalScale()
//! Scales the entity along the world's axes. The origin of the axes is the entity's position in the world.
//! @param scale A three-dimensional vector that represents the multipliers with which to scale the entity in world space.
virtual void SetScale([[maybe_unused]] const AZ::Vector3& scale) {}
//! @deprecated Use SetLocalScaleX()
//! Scales the entity along the world's X axis. The origin of the axis is the entity's position in the world.
//! @param scaleX The multiplier by which to scale the entity along the X axis in world space.
virtual void SetScaleX([[maybe_unused]] float scaleX) {}
//! @deprecated Use SetLocalScaleY()
//! Scales the entity along the world's Y axis. The origin of the axis is the entity's position in the world.
//! @param scaleY The multiplier by which to scale the entity along the Y axis in world space.
virtual void SetScaleY([[maybe_unused]] float scaleY) {}
//! @deprecated Use SetLocalScaleZ()
//! Scales the entity along the world's Z axis. The origin of the axis is the entity's position in the world.
//! @param scaleZ The multiplier by which to scale the entity along the Z axis in world space.
virtual void SetScaleZ([[maybe_unused]] float scaleZ) {}
//! @deprecated Use GetLocalScale()
//! Gets the scale of the entity in world space.
//! @return A three-dimensional vector that represents the scale of the entity in world space.
virtual AZ::Vector3 GetScale() { return AZ::Vector3(FLT_MAX); }
//! @deprecated Use GetLocalScale()
//! Gets the amount by which an entity is scaled along the world's X axis.
//! @return The amount by which an entity is scaled along the X axis in world space.
virtual float GetScaleX() { return FLT_MAX; }
//! @deprecated Use GetLocalScale()
//! Gets the amount by which an entity is scaled along the world's Y axis.
//! @return The amount by which an entity is scaled along the Y axis in world space.
virtual float GetScaleY() { return FLT_MAX; }
//! @deprecated Use GetLocalScale()
//! Gets the amount by which an entity is scaled along the world's Z axis.
//! @return The amount by which an entity is scaled along the Z axis in world space.
virtual float GetScaleZ() { return FLT_MAX; }
//! Set local scale of the transform.
//! @param scale The new scale to set along three local axes.
//! @param scale The new scale to set.
virtual void SetLocalScale([[maybe_unused]] const AZ::Vector3& scale) {}
//! Set local scale of the transform on x-axis.
//! @param scaleX The new x-axis scale to set.
virtual void SetLocalScaleX([[maybe_unused]] float scaleX) {}
//! Set local scale of the transform on y-axis.
//! @param scaleY The new y-axis scale to set.
virtual void SetLocalScaleY([[maybe_unused]] float scaleY) {}
//! Set local scale of the transform on z-axis.
//! @param scaleZ The new z-axis scale to set.
virtual void SetLocalScaleZ([[maybe_unused]] float scaleZ) {}
//! Get the scale value on each axis in local space
//! @return The scale value of type Vector3 along each axis in local space.
//! Get the scale value in local space.
//! @return The scale value in local space.
virtual AZ::Vector3 GetLocalScale() { return AZ::Vector3(FLT_MAX); }
//! Get the scale value on each axis in world space.
//! Note the transform will be skewed when it is rotated and has a parent transform scaled, in which
//! case the returned world-scale from this function will be inaccurate.
//! @return The scale value of type Vector3 along each axis in world space.
//! Get the scale value in world space.
//! @return The scale value in world space.
virtual AZ::Vector3 GetWorldScale() { return AZ::Vector3(FLT_MAX); }
//! Set the uniform scale value in local space.
virtual void SetLocalUniformScale([[maybe_unused]] float scale) {}
//! Get the uniform scale value in local space.
//! @return The uniform scale value in local space.
virtual float GetLocalUniformScale() { return FLT_MAX; }
//! Get the uniform scale value in world space.
//! @return The uniform scale value in world space.
virtual float GetWorldUniformScale() { return FLT_MAX; }
//! @}
//! Transform hierarchy
@@ -348,13 +348,20 @@ namespace AZ
return result.GetW() >= 0.0f ? result : -result;
}
const Quaternion Quaternion::CreateFromEulerAnglesDegrees(Vector3& anglesInDegrees)
const Quaternion Quaternion::CreateFromEulerAnglesDegrees(const Vector3& anglesInDegrees)
{
Quaternion result;
result.SetFromEulerDegrees(anglesInDegrees);
return result;
}
const Quaternion Quaternion::CreateFromEulerAnglesRadians(const Vector3& anglesInRadians)
{
Quaternion result;
result.SetFromEulerRadians(anglesInRadians);
return result;
}
Quaternion Quaternion::Slerp(const Quaternion& dest, float t) const
{
const float DestDot = Dot(dest);
@@ -83,8 +83,11 @@ namespace AZ
static Quaternion CreateShortestArc(const Vector3& v1, const Vector3& v2);
/// Creates a quaternion using rotation in degrees about the axes. First rotated about the X axis, followed by the Y axis, then the Z axis.
static const Quaternion CreateFromEulerAnglesDegrees(Vector3& anglesInDegrees);
//! Creates a quaternion using rotation in degrees about the axes. First rotated about the X axis, followed by the Y axis, then the Z axis.
static const Quaternion CreateFromEulerAnglesDegrees(const Vector3& anglesInDegrees);
//! Creates a quaternion using rotation in radians about the axes. First rotated about the X axis, followed by the Y axis, then the Z axis.
static const Quaternion CreateFromEulerAnglesRadians(const Vector3& anglesInRadians);
//! Stores the vector to an array of 4 floats. The floats need only be 4 byte aligned, 16 byte alignment is not required.
void StoreToFloat4(float* values) const;
@@ -86,4 +86,94 @@ namespace AZ
Normal,
UniformReal
};
//! Halton sequences are deterministic, quasi-random sequences with low discrepancy. They
//! are useful for generating evenly distributed points.
//! See https://en.wikipedia.org/wiki/Halton_sequence for more information.
//! Returns a single halton number.
//! @param index The index of the number. Indices start at 1. Using index 0 will return 0.
//! @param base The numerical base of the halton number.
inline float GetHaltonNumber(uint32_t index, uint32_t base)
{
float fraction = 1.0f;
float result = 0.0f;
while (index > 0)
{
fraction = fraction / base;
result += fraction * (index % base);
index = aznumeric_cast<uint32_t>(index / base);
}
return result;
}
//! A helper class for generating arrays of Halton sequences in n dimensions.
//! The class holds the state of which bases to use, the starting offset
//! of each dimension and how much to increment between each index for each
//! dimension.
template <uint8_t Dimensions>
class HaltonSequence
{
public:
//! Initializes a Halton sequence with some bases. By default there is no
//! offset and the index increments by 1 between each number.
HaltonSequence(AZStd::array<uint32_t, Dimensions> bases)
: m_bases(bases)
{
m_offsets.fill(1); // Halton sequences start at index 1.
m_increments.fill(1); // By default increment by 1 between each number.
}
//! Returns a Halton sequence in an array of N length
template<uint32_t N>
AZStd::array<AZStd::array<float, Dimensions>, N> GetHaltonSequence()
{
AZStd::array<AZStd::array<float, Dimensions>, N> result;
AZStd::array<uint32_t, Dimensions> indices = m_offsets;
// Generator that returns the Halton number for all bases for a single entry.
auto f = [&] ()
{
AZStd::array<float, Dimensions> item;
for (auto d = 0; d < Dimensions; ++d)
{
item[d] = GetHaltonNumber(indices[d], m_bases[d]);
indices[d] += m_increments[d];
}
return item;
};
AZStd::generate(result.begin(), result.end(), f);
return result;
}
//! Sets the offsets per dimension to start generating a sequence from.
//! By default, there is no offset (offset of 0 corresponds to starting at index 1)
void SetOffsets(AZStd::array<uint32_t, Dimensions> offsets)
{
m_offsets = offsets;
// Halton sequences start at index 1, so increment all the indices.
AZStd::for_each(m_offsets.begin(), m_offsets.end(), [](uint32_t &n){ n++; });
}
//! Sets the increment between numbers in the halton sequence per dimension
//! By default this is 1, meaning that no numbers are skipped. Can be negative
//! to generate numbers in reverse order.
void SetIncrements(AZStd::array<int32_t, Dimensions> increments)
{
m_increments = increments;
}
private:
AZStd::array<uint32_t, Dimensions> m_bases;
AZStd::array<uint32_t, Dimensions> m_offsets;
AZStd::array<int32_t, Dimensions> m_increments;
};
}
+2 -2
View File
@@ -441,10 +441,10 @@ namespace AZ
const Transform& worldFromLocal, const Vector3& src, const Vector3& dir, const Spline& spline)
{
Transform worldFromLocalNormalized = worldFromLocal;
const Vector3 scale = worldFromLocalNormalized.ExtractScale();
const float scale = worldFromLocalNormalized.ExtractUniformScale();
const Transform localFromWorldNormalized = worldFromLocalNormalized.GetInverse();
const Vector3 localRayOrigin = localFromWorldNormalized.TransformPoint(src) * scale.GetReciprocal();
const Vector3 localRayOrigin = localFromWorldNormalized.TransformPoint(src) / scale;
const Vector3 localRayDirection = localFromWorldNormalized.TransformVector(dir);
return spline.GetNearestAddressRay(localRayOrigin, localRayDirection);
}
@@ -284,10 +284,15 @@ namespace AZ
Method("GetRotation", &Transform::GetRotation)->
Method<void (Transform::*)(const Quaternion&)>("SetRotation", &Transform::SetRotation)->
Method("GetScale", &Transform::GetScale)->
Method<void (Transform::*)(const Vector3&)>("SetScale", &Transform::SetScale)->
Method("GetUniformScale", &Transform::GetUniformScale)->
Method("SetScale", &Transform::SetScale)->
Method("SetUniformScale", &Transform::SetUniformScale)->
Method("ExtractScale", &Transform::ExtractScale)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("ExtractUniformScale", &Transform::ExtractUniformScale)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("MultiplyByScale", &Transform::MultiplyByScale)->
Method("MultiplyByUniformScale", &Transform::MultiplyByUniformScale)->
Method("GetInverse", &Transform::GetInverse)->
Method("Invert", &Transform::Invert)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
@@ -306,6 +311,7 @@ namespace AZ
Method("CreateFromMatrix3x3", &Transform::CreateFromMatrix3x3)->
Method("CreateFromMatrix3x3AndTranslation", &Transform::CreateFromMatrix3x3AndTranslation)->
Method("CreateScale", &Transform::CreateScale)->
Method("CreateUniformScale", &Transform::CreateUniformScale)->
Method("CreateTranslation", &Transform::CreateTranslation)->
Method("ConstructFromValuesNumeric", &Internal::ConstructTransformFromValues);
}
+14 -5
View File
@@ -89,8 +89,11 @@ namespace AZ
static Transform CreateFromMatrix3x4(const Matrix3x4& value);
//! Sets the matrix to be a scale matrix, translation is set to zero.
static Transform CreateScale(const Vector3& scale);
//! Sets the transform to apply scale only, no rotation or translation.
static Transform CreateScale(const AZ::Vector3& scale);
//! Sets the transform to apply (uniform) scale only, no rotation or translation.
static Transform CreateUniformScale(const float scale);
//! Sets the matrix to be a translation matrix, rotation part is set to identity.
static Transform CreateTranslation(const Vector3& translation);
@@ -119,13 +122,19 @@ namespace AZ
const Quaternion& GetRotation() const;
void SetRotation(const Quaternion& rotation);
const Vector3& GetScale() const;
Vector3 GetScale() const;
float GetUniformScale() const;
void SetScale(const Vector3& v);
void SetUniformScale(const float scale);
//! Sets the transforms scale to a unit value and returns the previous scale value.
//! Sets the transform's scale to a unit value and returns the previous scale value.
Vector3 ExtractScale();
void MultiplyByScale(const Vector3& scale);
//! Sets the transform's scale to a unit value and returns the previous scale value.
float ExtractUniformScale();
void MultiplyByScale(const AZ::Vector3& scale);
void MultiplyByUniformScale(float scale);
Transform operator*(const Transform& rhs) const;
Transform& operator*=(const Transform& rhs);
@@ -65,6 +65,7 @@ namespace AZ
AZ_MATH_INLINE Transform Transform::CreateScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "CreateScale is deprecated, please use CreateUniformScale instead.");
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = scale;
@@ -72,6 +73,15 @@ namespace AZ
return result;
}
AZ_MATH_INLINE Transform Transform::CreateUniformScale(float scale)
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
result.m_scale = Vector3(scale);
result.m_translation = Vector3::CreateZero();
return result;
}
AZ_MATH_INLINE Transform Transform::CreateTranslation(const Vector3& translation)
{
Transform result;
@@ -150,24 +160,50 @@ namespace AZ
m_rotation = rotation;
}
AZ_MATH_INLINE const Vector3& Transform::GetScale() const
AZ_MATH_INLINE Vector3 Transform::GetScale() const
{
AZ_WarningOnce("Transform", false, "GetScale is deprecated, please use GetUniformScale instead.");
return m_scale;
}
AZ_MATH_INLINE float Transform::GetUniformScale() const
{
return m_scale.GetMaxElement();
}
AZ_MATH_INLINE void Transform::SetScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "SetScale is deprecated, please use SetUniformScale instead.");
m_scale = scale;
}
AZ_MATH_INLINE void Transform::SetUniformScale(const float scale)
{
m_scale = Vector3(scale);
}
AZ_MATH_INLINE Vector3 Transform::ExtractScale()
{
AZ_WarningOnce("Transform", false, "ExtractScale is deprecated, please use ExtractUniformScale instead.");
const Vector3 scale = m_scale;
m_scale = Vector3::CreateOne();
return scale;
}
AZ_MATH_INLINE float Transform::ExtractUniformScale()
{
const float scale = m_scale.GetMaxElement();
m_scale = Vector3::CreateOne();
return scale;
}
AZ_MATH_INLINE void Transform::MultiplyByScale(const Vector3& scale)
{
AZ_WarningOnce("Transform", false, "MultiplyByScale is deprecated, please use MultiplyByUniformScale instead.");
m_scale *= scale;
}
AZ_MATH_INLINE void Transform::MultiplyByUniformScale(float scale)
{
m_scale *= scale;
}
@@ -233,7 +269,7 @@ namespace AZ
AZ_MATH_INLINE void Transform::Orthogonalize()
{
*this = GetOrthogonalized();
m_scale = Vector3::CreateOne();
}
AZ_MATH_INLINE bool Transform::IsClose(const Transform& rhs, float tolerance) const
@@ -60,7 +60,7 @@ namespace AZ
{
// Scale is transitioning to a single uniform scale value, but since it's still internally represented as a Vector3,
// we need to pick one number to use for load/store operations.
float scale = transformInstance->GetScale().GetMaxElement();
float scale = transformInstance->GetUniformScale();
JSR::ResultCode loadResult =
ContinueLoadingFromJsonObjectField(&scale, azrtti_typeid<decltype(scale)>(), inputValue, ScaleTag, context);
@@ -124,8 +124,8 @@ namespace AZ
// Scale is transitioning to a single uniform scale value, but since it's still internally represented as a Vector3,
// we need to pick one number to use for load/store operations.
float scale = transformInstance->GetScale().GetMaxElement();
float defaultScale = defaultTransformInstance ? defaultTransformInstance->GetScale().GetMaxElement() : 0.0f;
float scale = transformInstance->GetUniformScale();
float defaultScale = defaultTransformInstance ? defaultTransformInstance->GetUniformScale() : 0.0f;
JSR::ResultCode storeResult = ContinueStoringToJsonObjectField(
outputValue, ScaleTag, &scale, defaultTransformInstance ? &defaultScale : nullptr, azrtti_typeid<decltype(scale)>(),
@@ -1020,29 +1020,60 @@ namespace AZ
}
};
/// OnDemand reflection for AZStd::set
template<class t_Key, class t_Hasher, class t_EqualKey, class t_Allocator>
class Iterator_VM<AZStd::unordered_set<t_Key, t_Hasher, t_EqualKey, t_Allocator>>
{
public:
using ContainerType = AZStd::unordered_set<t_Key, t_Hasher, t_EqualKey, t_Allocator>;
using IteratorType = typename ContainerType::iterator;
Iterator_VM(ContainerType& container)
: m_iterator(container.begin())
, m_end(container.end())
{}
const t_Key& GetKeyUnchecked() const
{
return *m_iterator;
}
bool IsNotAtEnd() const
{
return m_iterator != m_end;
}
t_Key& ModValueUnchecked()
{
return *m_iterator;
}
void Next()
{
++m_iterator;
}
private:
IteratorType m_iterator;
IteratorType m_end;
};
/// OnDemand reflection for AZStd::unordered_set
template<class Key, class Hasher, class EqualKey, class Allocator>
struct OnDemandReflection< AZStd::unordered_set<Key, Hasher, EqualKey, Allocator> >
{
using ContainerType = AZStd::unordered_set<Key, Hasher, EqualKey, Allocator>;
using KeyListType = AZStd::vector<Key, Allocator>;
static AZ::Outcome<void, void> Erase(ContainerType& thisMap, Key& key)
using ValueIteratorType = Iterator_VM<ContainerType>;
static bool EraseCheck_VM(ContainerType& thisSet, Key& key)
{
const auto result = thisMap.erase(key);
if (result)
{
return AZ::Success();
}
else
{
return AZ::Failure();
}
return thisSet.erase(key) != 0;
}
static void Insert(ContainerType& thisSet, Key& key)
static ContainerType& ErasePost_VM(ContainerType& thisSet, [[maybe_unused]] Key&)
{
thisSet.insert(key);
return thisSet;
}
static KeyListType GetKeys(ContainerType& thisSet)
@@ -1055,6 +1086,17 @@ namespace AZ
return keys;
}
static ContainerType& Insert(ContainerType& thisSet, Key& key)
{
thisSet.insert(key);
return thisSet;
}
static ValueIteratorType Iterate_VM(ContainerType& thisContainer)
{
return ValueIteratorType(thisContainer);
}
static void Swap(ContainerType& thisSet, ContainerType& otherSet)
{
thisSet.swap(otherSet);
@@ -1064,33 +1106,68 @@ namespace AZ
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
BranchOnResultInfo emptyBranchInfo;
emptyBranchInfo.m_returnResultInBranches = true;
emptyBranchInfo.m_trueToolTip = "The container is empty";
emptyBranchInfo.m_falseToolTip = "The container is not empty";
auto ContainsTransparent = [](const ContainerType& containerType, typename ContainerType::key_type& key)->bool
{
return containerType.contains(key);
};
ExplicitOverloadInfo explicitOverloadInfo;
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, ScriptCanvasOnDemandReflection::OnDemandPrettyName<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::ToolTip, ScriptCanvasOnDemandReflection::OnDemandToolTip<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::Category, ScriptCanvasOnDemandReflection::OnDemandCategoryName<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn)
->Method("BucketCount", static_cast<typename ContainerType::size_type(ContainerType::*)() const>(&ContainerType::bucket_count))
->Method("Erase", &Erase)
->Method("Empty", [](ContainerType& thisSet)->bool { return thisSet.empty(); })
->Method("Empty", static_cast<bool(ContainerType::*)() const>(&ContainerType::empty), { { { "Container", "The container to check if it is empty", nullptr, {} } } })
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Is Empty", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::BranchOnResult, emptyBranchInfo)
->Method("EraseCheck_VM", &EraseCheck_VM)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("Erase", &ErasePost_VM)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Erase", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::CheckedOperation, CheckedOperationInfo("EraseCheck_VM", {}, "Out", "Key Not Found", true))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "" }, { "ContainerGroup" }))
->Method("contains", ContainsTransparent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Has Key", "Containers"))
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Method("Insert", &Insert)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Insert", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "", "" }, { "ContainerGroup" }))
->Method(k_sizeName, [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); })
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("GetKeys", &GetKeys)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("GetSize", [](ContainerType& thisPtr) { return aznumeric_cast<int>(thisPtr.size()); })
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Get Size", "Containers"))
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Method("Reserve", static_cast<void(ContainerType::*)(typename ContainerType::size_type)>(&ContainerType::reserve))
->Method("Swap", &Swap)
->Method("Clear", [](ContainerType& thisContainer)->ContainerType& { thisContainer.clear(); return thisContainer; })
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Clear All Elements", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup" }, { "ContainerGroup" }))
->Method(k_iteratorConstructorName, &Iterate_VM)
;
behaviorContext->Class<ValueIteratorType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn)
->Method(k_iteratorGetKeyName, &ValueIteratorType::GetKeyUnchecked)
->Method(k_iteratorModValueName, &ValueIteratorType::ModValueUnchecked)
->Method(k_iteratorIsNotAtEndName, &ValueIteratorType::IsNotAtEnd)
->Method(k_iteratorNextName, &ValueIteratorType::Next)
;
}
}
};
template <>
@@ -165,7 +165,7 @@ namespace AZ
if (HasResult() != overload->HasResult())
{
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all");
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str());
return false;
}
@@ -176,7 +176,7 @@ namespace AZ
if (!(methodResult->m_typeId == overloadResult->m_typeId && methodResult->m_traits == overloadResult->m_traits))
{
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all");
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str());
return false;
}
}
@@ -575,7 +575,7 @@ namespace AZ
}
else
{
AZ_Error("BehaviorContext", false, "safety check declared for method %s but it was not found in the class");
AZ_Error("BehaviorContext", false, "Method: %s, declared safety check: %s, but it was not found in class: %s", method.m_name.c_str(), m_name.c_str(), checkedOperationInfo.m_safetyCheckName.c_str());
}
}
}
@@ -34,10 +34,17 @@ namespace BehaviorContextUtilitiesCPP
using argument_type = const BehaviorParameter*;
using result_type = size_t;
result_type operator()(const argument_type& value) const
{
result_type result = AZStd::hash<Uuid>()(value->m_typeId);
AZStd::hash_combine(result, CleanTraits(value->m_traits));
return result;
{
if (value)
{
result_type result = AZStd::hash<Uuid>()(value->m_typeId);
AZStd::hash_combine(result, CleanTraits(value->m_traits));
return result;
}
else
{
return 0;
}
}
};
@@ -45,7 +52,11 @@ namespace BehaviorContextUtilitiesCPP
{
bool operator()(const BehaviorParameter* left, const BehaviorParameter* right) const
{
return left->m_typeId == right->m_typeId && CleanTraits(left->m_traits) == CleanTraits(right->m_traits);
return (left == nullptr && right == nullptr)
|| (left != nullptr
&& right != nullptr
&& left->m_typeId == right->m_typeId
&& CleanTraits(left->m_traits) == CleanTraits(right->m_traits));
}
};
@@ -137,7 +148,7 @@ namespace AZ
for (size_t argIndex = 0, argSentinel = overload.GetNumArguments(); argIndex < argSentinel; ++argIndex)
{
auto overloadedArgIter = variance.m_input.find(argIndex);
if (overloadedArgIter != variance.m_input.end())
if (overloadedArgIter != variance.m_input.end() && overloadedArgIter->second[overloadIndex])
{
// if this doesn't work try the type name
overloadName += ReplaceCppArtifacts(overloadedArgIter->second[overloadIndex]->m_name);
@@ -185,16 +196,24 @@ namespace AZ
{
auto argument = overloads[overloadIndex].first->GetArgument(0);
const bool isThisPointer
= (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0
|| AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes);
if (argument)
{
const bool isThisPointer
= (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0
|| AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes);
oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer;
oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer;
}
types.insert(argument);
stripedArgs.emplace_back(argument);
}
if (types.size() == overloads.size())
{
variance.m_unambiguousInput.insert(0);
}
if (types.size() > 1 && (onThis == VariantOnThis::Yes || !oneArgIsThisPointer))
{
variance.m_input.insert(AZStd::make_pair(0, stripedArgs));
@@ -210,11 +229,15 @@ namespace AZ
for (size_t overloadIndex = 0, overloadSentinel = overloads.size(); overloadIndex < overloadSentinel; ++overloadIndex)
{
auto argument = overloads[overloadIndex].first->GetArgument(argIndex);
types.insert(argument);
stripedArgs.emplace_back(argument);
}
if (types.size() == overloads.size())
{
variance.m_unambiguousInput.insert(0);
}
if (types.size() > 1)
{
variance.m_input.insert(AZStd::make_pair(argIndex, stripedArgs));
@@ -27,6 +27,8 @@ namespace AZ
struct OverloadVariance
{
AZStd::unordered_map<size_t, AZStd::vector<const BehaviorParameter*>> m_input;
// the indices of inputs that make selection of overload unambiguous
AZStd::unordered_set<size_t> m_unambiguousInput;
AZStd::vector<const BehaviorParameter*> m_output;
};
@@ -2048,10 +2048,6 @@ LUA_API const Node* lua_getDummyNode()
return true;
}
else
{
AZ_Warning("Script", false, "Index %d is not a function!", functionIndex);
}
return false;
}
@@ -2078,7 +2074,6 @@ LUA_API const Node* lua_getDummyNode()
}
else
{
AZ_Warning("Script", lua_isnil(m_nativeContext, -1), "Name %s exists but is not a function!", functionName);
lua_pop(m_nativeContext, 1);
}
@@ -5888,7 +5883,6 @@ LUA_API const Node* lua_getDummyNode()
else
{
lua_pop(m_impl->m_lua, 1);
AZ_Warning("Script", false, "%s is not a function!", functionName);
}
return false;
}
@@ -5906,7 +5900,6 @@ LUA_API const Node* lua_getDummyNode()
else
{
lua_pop(m_impl->m_lua, 1);
AZ_Warning("Script", false, "CacheIndex %d is not a function!", cachedIndex);
}
return false;
}
@@ -10,6 +10,7 @@
*
*/
#include "AzCore/RTTI/TypeInfo.h"
#include <AzCore/Math/UuidSerializer.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/Serialization/Json/CastingHelpers.h>
@@ -61,6 +62,13 @@ namespace AZ
if (classData->m_azRtti && classData->m_azRtti->GetGenericTypeId() != typeId)
{
if (((classData->m_azRtti->GetTypeTraits() & (AZ::TypeTraits::is_signed | AZ::TypeTraits::is_unsigned)) != AZ::TypeTraits{0}) &&
context.GetSerializeContext()->GetUnderlyingTypeId(typeId) == classData->m_typeId)
{
// This value is from an enum, where a field has been reflected using ClassBuilder::Field, but the enum
// type itself has not been reflected using EnumBuilder. Treat it as an enum.
return LoadEnum(object, *classData, value, context);
}
serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId());
if (serializer)
{
@@ -77,21 +85,18 @@ namespace AZ
{
return LoadEnum(object, *classData, value, context);
}
else if (classData->m_container)
if (classData->m_container)
{
return context.Report(Tasks::ReadField, Outcomes::Unsupported,
"The Json Serializer uses custom serializers to load containers. If this message is encountered "
"then a serializer for the target containers is missing, isn't registered or doesn't exist.");
}
else if (value.IsObject())
if (value.IsObject())
{
return LoadClass(object, *classData, value, context);
}
else
{
return context.Report(Tasks::ReadField, Outcomes::Unsupported,
AZStd::string::format("Reading into targets of type '%s' is not supported.", classData->m_name));
}
return context.Report(Tasks::ReadField, Outcomes::Unsupported,
AZStd::string::format("Reading into targets of type '%s' is not supported.", classData->m_name));
}
JsonSerializationResult::ResultCode JsonDeserializer::LoadToPointer(void* object, const Uuid& typeId,
@@ -233,8 +238,16 @@ namespace AZ
AZ::TypeId underlyingTypeId = AZ::TypeId::CreateNull();
if (!attributeReader.Read<AZ::TypeId>(underlyingTypeId))
{
return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
"Unable to find underlying type of enum in class data.");
// for non-reflected enums, the passed-in classData already represents the enum's underlying type
if (context.GetSerializeContext()->GetUnderlyingTypeId(classData.m_typeId) == classData.m_typeId)
{
underlyingTypeId = classData.m_typeId;
}
else
{
return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
"Unable to find underlying type of enum in class data.");
}
}
const SerializeContext::ClassData* underlyingClassData = context.GetSerializeContext()->FindClassData(underlyingTypeId);
@@ -494,13 +494,6 @@ namespace AZ::SettingsRegistryMergeUtils
return configFileParsed;
}
void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry)
{
ConfigParserSettings parserSettings;
parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey;
MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings);
}
void MergeSettingsToRegistry_AddRuntimeFilePaths(SettingsRegistryInterface& registry)
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
@@ -172,9 +172,6 @@ namespace AZ::SettingsRegistryMergeUtils
bool MergeSettingsToRegistry_ConfigFile(SettingsRegistryInterface& registry, AZStd::string_view filePath,
const ConfigParserSettings& configParserSettings);
//! Loads bootstrap.cfg into the Settings Registry. This file does not support specializations.
void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry);
//! Extracts file path information from the environment and bootstrap to calculate the various file paths and adds those
//! to the Settings Registry under the FilePathsRootKey.
void MergeSettingsToRegistry_AddRuntimeFilePaths(SettingsRegistryInterface& registry);
@@ -31,6 +31,8 @@ namespace UnitTest
ErrorHandler::ErrorHandler(const char* errorPattern)
: m_errorCount(0)
, m_warningCount(0)
, m_expectedErrorCount(0)
, m_expectedWarningCount(0)
, m_errorPattern(errorPattern)
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
@@ -51,6 +53,16 @@ namespace UnitTest
return m_warningCount;
}
int ErrorHandler::GetExpectedErrorCount() const
{
return m_expectedErrorCount;
}
int ErrorHandler::GetExpectedWarningCount() const
{
return m_expectedWarningCount;
}
bool ErrorHandler::SuppressExpectedErrors([[maybe_unused]] const char* window, const char* message)
{
return AZStd::string(message).find(m_errorPattern) != AZStd::string::npos;
@@ -61,7 +73,9 @@ namespace UnitTest
[[maybe_unused]] const char* func, const char* message)
{
m_errorCount++;
return SuppressExpectedErrors(window, message);
bool suppress = SuppressExpectedErrors(window, message);
m_expectedErrorCount += suppress;
return suppress;
}
bool ErrorHandler::OnPreWarning(
@@ -69,7 +83,9 @@ namespace UnitTest
[[maybe_unused]] const char* func, const char* message)
{
m_warningCount++;
return SuppressExpectedErrors(window, message);
bool suppress = SuppressExpectedErrors(window, message);
m_expectedWarningCount += suppress;
return suppress;
}
bool ErrorHandler::OnPrintf(const char* window, const char* message)
@@ -30,8 +30,14 @@ namespace UnitTest
public:
explicit ErrorHandler(const char* errorPattern);
~ErrorHandler();
//! Returns the total number of errors encountered (including those which match the expected pattern).
int GetErrorCount() const;
//! Returns the total number of warnings encountered (including those which match the expected pattern).
int GetWarningCount() const;
//! Returns the number of errors encountered which matched the expected pattern.
int GetExpectedErrorCount() const;
//! Returns the number of warnings encountered which matched the expected pattern.
int GetExpectedWarningCount() const;
bool SuppressExpectedErrors(const char* window, const char* message);
// AZ::Debug::TraceMessageBus
@@ -44,6 +50,8 @@ namespace UnitTest
AZStd::string m_errorPattern;
int m_errorCount;
int m_warningCount;
int m_expectedErrorCount;
int m_expectedWarningCount;
};
}
@@ -61,8 +61,8 @@ namespace MathTestData
};
static const AZ::Transform NonOrthogonalTransforms[] = {
AZ::Transform::CreateScale(AZ::Vector3(2.4f, 0.3f, 1.7f)),
AZ::Transform::CreateRotationX(2.2f) * AZ::Transform::CreateScale(AZ::Vector3(0.2f, 0.8f, 1.4f))
AZ::Transform::CreateUniformScale(2.4f),
AZ::Transform::CreateRotationX(2.2f) * AZ::Transform::CreateUniformScale(0.8f)
};
static const AZ::Transform OrthogonalTransforms[] = {
@@ -59,11 +59,11 @@ namespace UnitTest
TEST(MATH_Obb, TestScaleTransform)
{
Obb obb = Obb::CreateFromPositionRotationAndHalfLengths(position, rotation, halfLengths);
Vector3 scaleFactors = Vector3(1.0f, 2.0f, 3.0f);
Transform transform = Transform::CreateScale(scaleFactors);
float scale = 3.0f;
Transform transform = Transform::CreateUniformScale(scale);
obb = transform * obb;
EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(1.0f, 4.0f, 9.0f)));
EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(0.5f, 1.0f, 1.5f)));
EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.0f, 6.0f, 9.0f)));
EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.5f, 1.5f, 1.5f)));
}
TEST(MATH_Obb, TestSetPosition)
@@ -0,0 +1,74 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Math/Random.h>
#include <AzCore/UnitTest/TestTypes.h>
using namespace AZ;
namespace UnitTest
{
TEST(MATH_Random, GetHaltonNumber)
{
EXPECT_FLOAT_EQ(0.5, GetHaltonNumber(1, 2));
EXPECT_FLOAT_EQ(898.0f / 2187.0f, GetHaltonNumber(1234, 3));
EXPECT_FLOAT_EQ(5981.0f / 15625.0f, GetHaltonNumber(4321, 5));
}
TEST(MATH_Random, HaltonSequence)
{
HaltonSequence<3> sequence({ 2, 3, 5 });
auto regularSequence = sequence.GetHaltonSequence<5>();
EXPECT_FLOAT_EQ(1.0f / 2.0f, regularSequence[0][0]);
EXPECT_FLOAT_EQ(1.0f / 3.0f, regularSequence[0][1]);
EXPECT_FLOAT_EQ(1.0f / 5.0f, regularSequence[0][2]);
EXPECT_FLOAT_EQ(1.0f / 4.0f, regularSequence[1][0]);
EXPECT_FLOAT_EQ(2.0f / 3.0f, regularSequence[1][1]);
EXPECT_FLOAT_EQ(2.0f / 5.0f, regularSequence[1][2]);
EXPECT_FLOAT_EQ(3.0f / 4.0f, regularSequence[2][0]);
EXPECT_FLOAT_EQ(1.0f / 9.0f, regularSequence[2][1]);
EXPECT_FLOAT_EQ(3.0f / 5.0f, regularSequence[2][2]);
EXPECT_FLOAT_EQ(1.0f / 8.0f, regularSequence[3][0]);
EXPECT_FLOAT_EQ(4.0f / 9.0f, regularSequence[3][1]);
EXPECT_FLOAT_EQ(4.0f / 5.0f, regularSequence[3][2]);
EXPECT_FLOAT_EQ(5.0f / 8.0f, regularSequence[4][0]);
EXPECT_FLOAT_EQ(7.0f / 9.0f, regularSequence[4][1]);
EXPECT_FLOAT_EQ(1.0f / 25.0f, regularSequence[4][2]);
sequence.SetOffsets({ 1, 2, 3 });
auto offsetSequence = sequence.GetHaltonSequence<2>();
EXPECT_FLOAT_EQ(1.0f / 4.0f, offsetSequence[0][0]);
EXPECT_FLOAT_EQ(1.0f / 9.0f, offsetSequence[0][1]);
EXPECT_FLOAT_EQ(4.0f / 5.0f, offsetSequence[0][2]);
EXPECT_FLOAT_EQ(3.0f / 4.0f, offsetSequence[1][0]);
EXPECT_FLOAT_EQ(4.0f / 9.0f, offsetSequence[1][1]);
EXPECT_FLOAT_EQ(1.0f / 25.0f, offsetSequence[1][2]);
sequence.SetIncrements({ 1, 2, 3 });
auto incrementedSequence = sequence.GetHaltonSequence<2>();
EXPECT_FLOAT_EQ(1.0f / 4.0f, incrementedSequence[0][0]);
EXPECT_FLOAT_EQ(1.0f / 9.0f, incrementedSequence[0][1]);
EXPECT_FLOAT_EQ(4.0f / 5.0f, incrementedSequence[0][2]);
EXPECT_FLOAT_EQ(3.0f / 4.0f, incrementedSequence[1][0]);
EXPECT_FLOAT_EQ(7.0f / 9.0f, incrementedSequence[1][1]);
EXPECT_FLOAT_EQ(11.0f / 25.0f, incrementedSequence[1][2]);
}
}
@@ -180,13 +180,13 @@ namespace Benchmark
}
}
BENCHMARK_F(BM_MathTransform, CreateScale)(benchmark::State& state)
BENCHMARK_F(BM_MathTransform, CreateUniformScale)(benchmark::State& state)
{
for (auto _ : state)
{
for (auto& testData : m_testDataArray)
{
AZ::Transform result = AZ::Transform::CreateScale(testData.v3);
AZ::Transform result = AZ::Transform::CreateUniformScale(testData.value[0]);
benchmark::DoNotOptimize(result);
}
}
@@ -344,39 +344,39 @@ namespace Benchmark
}
}
BENCHMARK_F(BM_MathTransform, GetScale)(benchmark::State& state)
BENCHMARK_F(BM_MathTransform, GetUniformScale)(benchmark::State& state)
{
for (auto _ : state)
{
for (auto& testData : m_testDataArray)
{
AZ::Vector3 result = testData.t1.GetScale();
float result = testData.t1.GetUniformScale();
benchmark::DoNotOptimize(result);
}
}
}
BENCHMARK_F(BM_MathTransform, SetScale)(benchmark::State& state)
BENCHMARK_F(BM_MathTransform, SetUniformScale)(benchmark::State& state)
{
for (auto _ : state)
{
for (auto& testData : m_testDataArray)
{
AZ::Transform testTransform = testData.t2;
testTransform.SetScale(testData.v3);
testTransform.SetUniformScale(testData.value[0]);
benchmark::DoNotOptimize(testTransform);
}
}
}
BENCHMARK_F(BM_MathTransform, ExtractScale)(benchmark::State& state)
BENCHMARK_F(BM_MathTransform, ExtractUniformScale)(benchmark::State& state)
{
for (auto _ : state)
{
for (auto& testData : m_testDataArray)
{
AZ::Transform testTransform = testData.t2;
AZ::Vector3 result = testTransform.ExtractScale();
float result = testTransform.ExtractUniformScale();
benchmark::DoNotOptimize(result);
}
}
@@ -159,37 +159,14 @@ namespace UnitTest
INSTANTIATE_TEST_CASE_P(MATH_Transform, TransformCreateFromQuaternionFixture, ::testing::ValuesIn(MathTestData::UnitQuaternions));
using TransformCreateFromMatrix3x3Fixture = ::testing::TestWithParam<AZ::Matrix3x3>;
TEST_P(TransformCreateFromMatrix3x3Fixture, CreateFromMatrix3x3)
TEST(MATH_Transform, CreateUniformScale)
{
const AZ::Matrix3x3 matrix3x3 = GetParam();
const AZ::Transform transform = AZ::Transform::CreateFromMatrix3x3(matrix3x3);
EXPECT_THAT(transform.GetTranslation(), IsClose(AZ::Vector3::CreateZero()));
const AZ::Vector3 vector(2.3f, -0.6, 1.8f);
EXPECT_THAT(transform.TransformPoint(vector), IsClose(matrix3x3 * vector));
}
TEST_P(TransformCreateFromMatrix3x3Fixture, CreateFromMatrix3x3AndTranslation)
{
const AZ::Matrix3x3 matrix3x3 = GetParam();
const AZ::Vector3 translation(-2.6f, 1.7f, 0.8f);
const AZ::Transform transform = AZ::Transform::CreateFromMatrix3x3AndTranslation(matrix3x3, translation);
EXPECT_THAT(transform.GetTranslation(), IsClose(translation));
const AZ::Vector3 vector(2.3f, -0.6, 1.8f);
EXPECT_THAT(transform.TransformPoint(vector), IsClose(matrix3x3 * vector + translation));
}
INSTANTIATE_TEST_CASE_P(MATH_Transform, TransformCreateFromMatrix3x3Fixture, ::testing::ValuesIn(MathTestData::Matrix3x3s));
TEST(MATH_Transform, CreateScale)
{
const AZ::Vector3 scale(1.7f, 0.3f, 2.4f);
const AZ::Transform transform = AZ::Transform::CreateScale(scale);
const float scale = 1.7f;
const AZ::Transform transform = AZ::Transform::CreateUniformScale(scale);
const AZ::Vector3 vector(0.2f, -1.6f, 0.4f);
EXPECT_THAT(transform.GetTranslation(), IsClose(AZ::Vector3::CreateZero()));
const AZ::Vector3 transformedVector = transform.TransformPoint(vector);
const AZ::Vector3 expected(0.34f, -0.48f, 0.96f);
const AZ::Vector3 expected(0.34f, -2.72f, 0.68f);
EXPECT_THAT(transformedVector, IsClose(expected));
}
@@ -237,10 +214,10 @@ namespace UnitTest
TEST(MATH_Transform, MultiplyByTransform)
{
const AZ::Transform transform1 = AZ::Transform::CreateRotationY(0.3f);
const AZ::Transform transform2 = AZ::Transform::CreateScale(AZ::Vector3(1.3f, 1.5f, 0.4f));
const AZ::Transform transform2 = AZ::Transform::CreateUniformScale(1.3f);
const AZ::Transform transform3 = AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion(0.42f, 0.46f, -0.66f, 0.42f), AZ::Vector3(2.8f, -3.7f, 1.6f));
const AZ::Transform transform4 = AZ::Transform::CreateRotationX(-0.7f) * AZ::Transform::CreateScale(AZ::Vector3(0.6f, 1.3f, 0.7f));
const AZ::Transform transform4 = AZ::Transform::CreateRotationX(-0.7f) * AZ::Transform::CreateUniformScale(0.6f);
AZ::Transform transform5 = transform1;
transform5 *= transform4;
const AZ::Vector3 vector(1.9f, 2.3f, 0.2f);
@@ -254,14 +231,14 @@ namespace UnitTest
TEST(MATH_Transform, TranslationCorrectInTransformHierarchy)
{
AZ::Transform parent = AZ::Transform::CreateRotationZ(AZ::DegToRad(45.0f));
parent.SetScale(AZ::Vector3(3.0f, 2.0f, 1.0f));
parent.SetUniformScale(3.0f);
parent.SetTranslation(AZ::Vector3(0.2f, 0.3f, 0.4f));
AZ::Transform child = AZ::Transform::CreateRotationZ(AZ::DegToRad(90.0f));
child.SetTranslation(AZ::Vector3(0.5f, 0.6f, 0.7f));
const AZ::Transform overallTransform = parent * child;
const AZ::Vector3 overallTranslation = overallTransform.GetTranslation();
const AZ::Vector3 expectedTranslation(0.412132f, 2.20919f, 1.1f);
EXPECT_THAT(overallTranslation, IsClose(AZ::Vector3(0.412132f, 2.20919f, 1.1f)));
const AZ::Vector3 expectedTranslation(-0.012132f, 2.633452f, 2.5f);
EXPECT_THAT(overallTranslation, IsClose(expectedTranslation));
}
TEST(MATH_Transform, TransformPointVector3)
@@ -337,14 +314,14 @@ namespace UnitTest
TEST_P(TransformScaleFixture, Scale)
{
const AZ::Transform orthogonalTransform = GetParam();
EXPECT_THAT(orthogonalTransform.GetScale(), IsClose(AZ::Vector3::CreateOne()));
EXPECT_NEAR(orthogonalTransform.GetUniformScale(), 1.0f, AZ::Constants::Tolerance);
AZ::Transform unscaledTransform = orthogonalTransform;
unscaledTransform.ExtractScale();
EXPECT_THAT(unscaledTransform.GetScale(), IsClose(AZ::Vector3::CreateOne()));
const AZ::Vector3 scale(2.8f, 0.7f, 1.3f);
unscaledTransform.ExtractUniformScale();
EXPECT_NEAR(unscaledTransform.GetUniformScale(), 1.0f, AZ::Constants::Tolerance);
const float scale = 2.8f;
AZ::Transform scaledTransform = orthogonalTransform;
scaledTransform.MultiplyByScale(scale);
EXPECT_THAT(scaledTransform.GetScale(), IsClose(scale));
scaledTransform.MultiplyByUniformScale(scale);
EXPECT_NEAR(scaledTransform.GetUniformScale(), scale, AZ::Constants::Tolerance);
}
INSTANTIATE_TEST_CASE_P(MATH_Transform, TransformScaleFixture, ::testing::ValuesIn(MathTestData::OrthogonalTransforms));
@@ -353,24 +330,11 @@ namespace UnitTest
{
EXPECT_TRUE(AZ::Transform::CreateIdentity().IsOrthogonal());
EXPECT_TRUE(AZ::Transform::CreateRotationZ(0.3f).IsOrthogonal());
EXPECT_FALSE(AZ::Transform::CreateScale(AZ::Vector3(0.8f, 0.3f, 1.2f)).IsOrthogonal());
EXPECT_FALSE(AZ::Transform::CreateUniformScale(0.8f).IsOrthogonal());
EXPECT_TRUE(AZ::Transform::CreateFromQuaternion(AZ::Quaternion(-0.52f, -0.08f, 0.56f, 0.64f)).IsOrthogonal());
AZ::Transform transform;
transform.SetFromEulerRadians(AZ::Vector3(0.2f, 0.4f, 0.1f));
EXPECT_TRUE(transform.IsOrthogonal());
// want to test each possible way the transform could fail to be orthogonal, which we can do by testing for one
// axis, then using a rotation which cycles the axes
const AZ::Transform axisCycle = AZ::Transform::CreateFromQuaternion(AZ::Quaternion(0.5f, 0.5f, 0.5f, 0.5f));
// a transform which is normalized in 2 axes, but not the third
AZ::Transform nonOrthogonalTransform1 = AZ::Transform::CreateScale(AZ::Vector3(1.0f, 1.0f, 2.0f));
for (int i = 0; i < 3; i++)
{
EXPECT_FALSE(nonOrthogonalTransform1.IsOrthogonal());
nonOrthogonalTransform1 = axisCycle * nonOrthogonalTransform1;
}
}
using TransformSetFromEulerDegreesFixture = ::testing::TestWithParam<AZ::Vector3>;
@@ -459,16 +423,17 @@ namespace UnitTest
{
const char* objectStreamBuffer =
R"DELIMITER(<ObjectStream version="3">
<Class name="Transform" field="m_data" value="0.79429845 0.8545947 -0.94273965 -0.05367075 0.3899708 0.30828915 1.0097652 -0.31084164 0.56899188 513.7845459 492.5420837 32.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
<Class name="Transform" field="m_data" value="0.79429845 0.8545947 -0.94273965 -0.1610121 1.1699124 0.92486745 1.2622065 -0.3885522 0.71123985 513.7845459 492.5420837 32.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
</ObjectStream>)DELIMITER";
AZ::Transform* deserializedTransform = AZ::Utils::LoadObjectFromBuffer<AZ::Transform>(objectStreamBuffer, strlen(objectStreamBuffer) + 1);
const AZ::Vector3 expectedTranslation(513.7845459f, 492.5420837f, 32.0000000f);
const AZ::Vector3 expectedScale(1.5f, 0.5f, 1.2f);
const float expectedScale = 1.5f;
const AZ::Quaternion expectedRotation(0.2624075f, 0.4405251f, 0.2029076f, 0.8342113f);
const AZ::Transform expectedTransform =
AZ::Transform::CreateFromQuaternionAndTranslation(expectedRotation, expectedTranslation) * AZ::Transform::CreateScale(expectedScale);
AZ::Transform::CreateFromQuaternionAndTranslation(expectedRotation, expectedTranslation) *
AZ::Transform::CreateUniformScale(expectedScale);
EXPECT_TRUE(deserializedTransform->IsClose(expectedTransform));
azfree(deserializedTransform);
+12 -12
View File
@@ -1275,10 +1275,10 @@ namespace UnitTest
script->Execute("AZTestAssert(t1:TransformVector(Vector3(1, 0, 0)):IsClose(Vector3(1, 0, 0)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 1, 0)):IsClose(Vector3(0, 0.866, 0.5)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 0, 1)):IsClose(Vector3(0, -0.5, 0.866)))");
script->Execute("t1 = Transform.CreateScale(Vector3(1, 2, 3))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(1, 0, 0)):IsClose(Vector3(1, 0, 0)))");
script->Execute("t1 = Transform.CreateUniformScale(2)");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(1, 0, 0)):IsClose(Vector3(2, 0, 0)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 1, 0)):IsClose(Vector3(0, 2, 0)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 0, 1)):IsClose(Vector3(0, 0, 3)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 0, 1)):IsClose(Vector3(0, 0, 2)))");
script->Execute("t1 = Transform.CreateTranslation(Vector3(1, 2, 3))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(1, 0, 0)):IsClose(Vector3(1, 0, 0)))");
script->Execute("AZTestAssert(t1:TransformVector(Vector3(0, 1, 0)):IsClose(Vector3(0, 1, 0)))");
@@ -1341,19 +1341,19 @@ namespace UnitTest
script->Execute("AZTestAssert(t3:GetTranslation():IsClose(Vector3(-5.90, 25.415, 19.645), 0.001))");
////test inverse, should handle non-orthogonal matrices
script->Execute("t1 = Transform.CreateRotationX(1) * Transform.CreateScale(Vector3(1, 2, 3))");
script->Execute("t1 = Transform.CreateRotationX(1) * Transform.CreateUniformScale(2)");
script->Execute("AZTestAssert((t1*t1:GetInverse()):IsClose(Transform.CreateIdentity()))");
////scale access
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(40)) * Transform.CreateScale(Vector3(2, 3, 4))");
script->Execute("AZTestAssert(t1:GetScale():IsClose(Vector3(2, 3, 4)))");
script->Execute("AZTestAssert(t1:ExtractScale():IsClose(Vector3(2, 3, 4)))");
script->Execute("AZTestAssert(t1:GetScale():IsClose(Vector3.CreateOne()))");
script->Execute("t1:MultiplyByScale(Vector3(3, 4, 5))");
script->Execute("AZTestAssert(t1:GetScale():IsClose(Vector3(3, 4, 5)))");
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(40)) * Transform.CreateUniformScale(3)");
script->Execute("AZTestAssertFloatClose(t1:GetUniformScale(), 3)");
script->Execute("AZTestAssertFloatClose(t1:ExtractUniformScale(), 3)");
script->Execute("AZTestAssertFloatClose(t1:GetUniformScale(), 1)");
script->Execute("t1:MultiplyByUniformScale(2)");
script->Execute("AZTestAssertFloatClose(t1:GetUniformScale(), 2)");
////orthogonalize
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(30)) * Transform.CreateScale(Vector3(2, 3, 4))");
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(30)) * Transform.CreateUniformScale(3)");
script->Execute("t1:SetTranslation(Vector3(1,2,3))");
script->Execute("t2 = t1:GetOrthogonalized()");
script->Execute("AZTestAssertFloatClose(t2:GetBasisX():GetLength(), 1)");
@@ -1372,7 +1372,7 @@ namespace UnitTest
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(30))");
script->Execute("t1:SetTranslation(Vector3(1, 2, 3))");
script->Execute("AZTestAssert(t1:IsOrthogonal(0.05))");
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(30)) * Transform.CreateScale(Vector3(2, 3, 4))");
script->Execute("t1 = Transform.CreateRotationX(Math.DegToRad(30)) * Transform.CreateUniformScale(2)");
script->Execute("AZTestAssert( not t1:IsOrthogonal(0.05))");
////IsClose
@@ -21,7 +21,7 @@ namespace JsonSerializationTests
{
using JsonSerializationTestCases = ::testing::Types<
// Structures
SimpleClass, SimpleInheritence, MultipleInheritence, SimpleNested, SimpleEnumWrapper,
SimpleClass, SimpleInheritence, MultipleInheritence, SimpleNested, SimpleEnumWrapper, NonReflectedEnumWrapper,
// Pointers
SimpleNullPointer, SimpleAssignedPointer, ComplexAssignedPointer, ComplexNullInheritedPointer,
ComplexAssignedDifferentInheritedPointer, ComplexAssignedSameInheritedPointer,
@@ -373,6 +373,57 @@ namespace JsonSerializationTests
return MakeInstanceWithoutDefaults(AZStd::move(instance), json);
}
// NonReflectedEnumWrapper
bool NonReflectedEnumWrapper::Equals(const NonReflectedEnumWrapper& rhs, bool fullReflection) const
{
return !fullReflection || (m_enumClass == rhs.m_enumClass && m_rawEnum== rhs.m_rawEnum);
}
void NonReflectedEnumWrapper::Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context, bool fullReflection)
{
if (fullReflection)
{
// Note that the enums are not reflected using context->Enum<>
context->Class<NonReflectedEnumWrapper>()
->Field("enumClass", &NonReflectedEnumWrapper::m_enumClass)
->Field("rawEnum", &NonReflectedEnumWrapper::m_rawEnum);
}
}
InstanceWithSomeDefaults<NonReflectedEnumWrapper> NonReflectedEnumWrapper::GetInstanceWithSomeDefaults()
{
auto instance = AZStd::make_unique<NonReflectedEnumWrapper>();
instance->m_enumClass = NonReflectedEnumWrapper::SimpleEnumClass::Option2;
const char* strippedDefaults = R"(
{
"enumClass": 2
})";
const char* keptDefaults = R"(
{
"enumClass": 2,
"rawEnum": 0
})";
return MakeInstanceWithSomeDefaults(AZStd::move(instance),
strippedDefaults, keptDefaults);
}
InstanceWithoutDefaults<NonReflectedEnumWrapper> NonReflectedEnumWrapper::GetInstanceWithoutDefaults()
{
auto instance = AZStd::make_unique<NonReflectedEnumWrapper>();
instance->m_enumClass = NonReflectedEnumWrapper::SimpleEnumClass::Option2;
instance->m_rawEnum = NonReflectedEnumWrapper::SimpleRawEnum::RawOption1;
const char* json = R"(
{
"enumClass": 2,
"rawEnum": 1
})";
return MakeInstanceWithoutDefaults(AZStd::move(instance), json);
}
// TemplatedClass<int>
bool TemplatedClass<int>::Equals(const TemplatedClass<int>& rhs, bool fullReflection) const
@@ -134,6 +134,35 @@ namespace JsonSerializationTests
SimpleRawEnum m_rawEnum{};
};
struct NonReflectedEnumWrapper
{
enum class SimpleEnumClass
{
Option1 = 1,
Option2,
};
enum SimpleRawEnum
{
RawOption1 = 1,
RawOption2,
};
AZ_CLASS_ALLOCATOR(NonReflectedEnumWrapper, AZ::SystemAllocator, 0);
AZ_RTTI(NonReflectedEnumWrapper, "{A80D5B6B-2FD1-46E9-A7A9-44C5E2650526}");
static constexpr bool SupportsPartialDefaults = true;
NonReflectedEnumWrapper() = default;
virtual ~NonReflectedEnumWrapper() = default;
bool Equals(const NonReflectedEnumWrapper& rhs, bool fullReflection) const;
static void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context, bool fullReflection);
static InstanceWithSomeDefaults<NonReflectedEnumWrapper> GetInstanceWithSomeDefaults();
static InstanceWithoutDefaults<NonReflectedEnumWrapper> GetInstanceWithoutDefaults();
SimpleEnumClass m_enumClass{};
SimpleRawEnum m_rawEnum{};
};
template<typename T>
struct TemplatedClass
{
@@ -158,5 +187,7 @@ namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::SimpleEnumWrapper::SimpleEnumClass, "{AF6F1964-5B20-4689-BF23-F36B9C9AAE6A}");
AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::SimpleEnumWrapper::SimpleRawEnum, "{EB24207F-B48F-4D8B-940D-3CD06A371739}");
AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::NonReflectedEnumWrapper::SimpleEnumClass, "{E80E4A41-B29E-4B7C-B630-3B599172C837}");
AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::NonReflectedEnumWrapper::SimpleRawEnum, "{C42AF28D-4F84-4540-972A-5B6EEFAB13FF}");
AZ_TYPE_INFO_TEMPLATE(JsonSerializationTests::TemplatedClass, "{CA4ADF74-66E7-4D16-B4AC-F71278C60EC7}", AZ_TYPE_INFO_TYPENAME);
}
@@ -112,7 +112,7 @@ namespace JsonSerializationTests
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
AZ::Transform expectedTransform =
AZ::Transform::CreateFromQuaternion(AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f));
expectedTransform.SetScale(AZ::Vector3(5.5f));
expectedTransform.SetUniformScale(5.5f);
rapidjson::Document json;
json.Parse(R"({ "Rotation": [ 0.25, 0.5, 0.75, 1.0 ], "Scale": 5.5 })");
@@ -128,7 +128,7 @@ namespace JsonSerializationTests
{
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
AZ::Transform expectedTransform = AZ::Transform::CreateTranslation(AZ::Vector3(2.25f, 3.5f, 4.75f));
expectedTransform.SetScale(AZ::Vector3(5.5f));
expectedTransform.SetUniformScale(5.5f);
rapidjson::Document json;
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Scale": 5.5 })");
@@ -189,7 +189,7 @@ namespace JsonSerializationTests
TEST_F(JsonTransformSerializerTests, Load_FullySetTransform_ReturnsSuccessWithOnlyScale)
{
AZ::Transform testTransform = AZ::Transform::CreateIdentity();
AZ::Transform expectedTransform = AZ::Transform::CreateScale(AZ::Vector3(5.5f));
AZ::Transform expectedTransform = AZ::Transform::CreateUniformScale(5.5f);
rapidjson::Document json;
json.Parse(R"({ "Scale" : 5.5 })");
@@ -152,6 +152,7 @@ set(FILES
Math/PlaneTests.cpp
Math/QuaternionPerformanceTests.cpp
Math/QuaternionTests.cpp
Math/RandomTests.cpp
Math/ShapeIntersectionPerformanceTests.cpp
Math/ShapeIntersectionTests.cpp
Math/SfmtTests.cpp
@@ -679,8 +679,6 @@ namespace AzFramework
{
auto fileIoBase = m_archiveFileIO.get();
// Set up the default file aliases based on the settings registry
fileIoBase->SetAlias("@assets@", "");
fileIoBase->SetAlias("@root@", GetEngineRoot());
fileIoBase->SetAlias("@engroot@", GetEngineRoot());
fileIoBase->SetAlias("@projectroot@", GetEngineRoot());
fileIoBase->SetAlias("@exefolder@", GetExecutableFolder());
@@ -694,8 +692,8 @@ namespace AzFramework
pathAliases.clear();
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
{
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
fileIoBase->SetAlias("@assets@", pathAliases.c_str());
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
fileIoBase->SetAlias("@root@", pathAliases.c_str()); // Deprecated Use @projectplatformcache@
}
pathAliases.clear();
@@ -432,46 +432,26 @@ namespace AzFramework
void TransformComponent::SetLocalRotation(const AZ::Vector3& eulerRadianAngles)
{
AZ::Transform newLocalTM = AZ::ConvertEulerRadiansToTransform(eulerRadianAngles);
newLocalTM.SetScale(m_localTM.GetScale());
newLocalTM.SetTranslation(m_localTM.GetTranslation());
AZ::Transform newLocalTM = m_localTM;
newLocalTM.SetRotation(AZ::Quaternion::CreateFromEulerAnglesRadians(eulerRadianAngles));
SetLocalTM(newLocalTM);
}
void TransformComponent::SetLocalRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ::Transform newLocalTM;
newLocalTM.SetScale(m_localTM.GetScale());
newLocalTM.SetTranslation(m_localTM.GetTranslation());
AZ::Transform newLocalTM = m_localTM;
newLocalTM.SetRotation(quaternion);
SetLocalTM(newLocalTM);
}
static AZ::Transform RotateAroundLocalHelper(float eulerAngleRadian, const AZ::Transform& localTM, AZ::Vector3 axis)
{
//get the existing translation and scale
AZ::Vector3 translation = localTM.GetTranslation();
AZ::Vector3 scale = localTM.GetScale();
//normalize the axis before creating rotation
axis.Normalize();
AZ::Quaternion rotate = AZ::Quaternion::CreateFromAxisAngle(axis, eulerAngleRadian);
//create new rotation transform
AZ::Quaternion currentRotate = localTM.GetRotation();
AZ::Quaternion newRotate = rotate * currentRotate;
newRotate.Normalize();
//scale
AZ::Transform newLocalTM = AZ::Transform::CreateScale(scale);
//rotate
AZ::Transform rotateLocalTM = AZ::Transform::CreateFromQuaternion(newRotate);
newLocalTM = rotateLocalTM * newLocalTM;
//translate
newLocalTM.SetTranslation(translation);
AZ::Transform newLocalTM = localTM;
newLocalTM.SetRotation((rotate * localTM.GetRotation()).GetNormalized());
return newLocalTM;
}
@@ -512,75 +492,6 @@ namespace AzFramework
return m_localTM.GetRotation();
}
void TransformComponent::SetScale(const AZ::Vector3& scale)
{
AZ_Warning("TransformComponent", false, "SetScale is deprecated, please use SetLocalScale");
if (!m_worldTM.GetScale().IsClose(scale))
{
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetScale(scale);
SetWorldTM(newWorldTransform);
}
}
void TransformComponent::SetScaleX(float scaleX)
{
AZ_Warning("TransformComponent", false, "SetScaleX is deprecated, please use SetLocalScaleX");
AZ::Vector3 newScale = m_worldTM.GetScale();
newScale.SetX(scaleX);
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetScale(newScale);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetScaleY(float scaleY)
{
AZ_Warning("TransformComponent", false, "SetScaleY is deprecated, please use SetLocalScaleY");
AZ::Vector3 newScale = m_worldTM.GetScale();
newScale.SetY(scaleY);
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetScale(newScale);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetScaleZ(float scaleZ)
{
AZ_Warning("TransformComponent", false, "SetScaleZ is deprecated, please use SetLocalScaleZ");
AZ::Vector3 newScale = m_worldTM.GetScale();
newScale.SetZ(scaleZ);
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetScale(newScale);
SetWorldTM(newWorldTransform);
}
AZ::Vector3 TransformComponent::GetScale()
{
AZ_Warning("TransformComponent", false, "GetScale is deprecated, please use GetLocalScale");
return m_worldTM.GetScale();
}
float TransformComponent::GetScaleX()
{
AZ_Warning("TransformComponent", false, "GetScaleX is deprecated, please use GetLocalScale");
return m_worldTM.GetScale().GetX();
}
float TransformComponent::GetScaleY()
{
AZ_Warning("TransformComponent", false, "GetScaleY is deprecated, please use GetLocalScale");
return m_worldTM.GetScale().GetY();
}
float TransformComponent::GetScaleZ()
{
AZ_Warning("TransformComponent", false, "GetScaleZ is deprecated, please use GetLocalScale");
return m_worldTM.GetScale().GetZ();
}
void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
{
AZ::Transform newLocalTM = m_localTM;
@@ -588,33 +499,6 @@ namespace AzFramework
SetLocalTM(newLocalTM);
}
void TransformComponent::SetLocalScaleX(float scaleX)
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetX(scaleX);
newLocalTM.SetScale(newScale);
SetLocalTM(newLocalTM);
}
void TransformComponent::SetLocalScaleY(float scaleY)
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetY(scaleY);
newLocalTM.SetScale(newScale);
SetLocalTM(newLocalTM);
}
void TransformComponent::SetLocalScaleZ(float scaleZ)
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetZ(scaleZ);
newLocalTM.SetScale(newScale);
SetLocalTM(newLocalTM);
}
AZ::Vector3 TransformComponent::GetLocalScale()
{
return m_localTM.GetScale();
@@ -625,6 +509,23 @@ namespace AzFramework
return m_worldTM.GetScale();
}
void TransformComponent::SetLocalUniformScale(float scale)
{
AZ::Transform newLocalTM = m_localTM;
newLocalTM.SetUniformScale(scale);
SetLocalTM(newLocalTM);
}
float TransformComponent::GetLocalUniformScale()
{
return m_localTM.GetUniformScale();
}
float TransformComponent::GetWorldUniformScale()
{
return m_worldTM.GetUniformScale();
}
AZStd::vector<AZ::EntityId> TransformComponent::GetChildren()
{
AZStd::vector<AZ::EntityId> children;
@@ -979,34 +880,7 @@ namespace AzFramework
->Event("GetLocalRotationQuaternion", &AZ::TransformBus::Events::GetLocalRotationQuaternion)
->Attribute("Rotation", AZ::Edit::Attributes::PropertyRotation)
->VirtualProperty("Rotation", "GetLocalRotationQuaternion", "SetLocalRotationQuaternion")
->Event("SetScale", &AZ::TransformBus::Events::SetScale)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetScaleX", &AZ::TransformBus::Events::SetScaleX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetScaleY", &AZ::TransformBus::Events::SetScaleY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetScaleZ", &AZ::TransformBus::Events::SetScaleZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetScale", &AZ::TransformBus::Events::GetScale)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetScaleX", &AZ::TransformBus::Events::GetScaleX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetScaleY", &AZ::TransformBus::Events::GetScaleY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetScaleZ", &AZ::TransformBus::Events::GetScaleZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetLocalScale", &AZ::TransformBus::Events::SetLocalScale)
->Event("SetLocalScaleX", &AZ::TransformBus::Events::SetLocalScaleX)
->Event("SetLocalScaleY", &AZ::TransformBus::Events::SetLocalScaleY)
->Event("SetLocalScaleZ", &AZ::TransformBus::Events::SetLocalScaleZ)
->Event("GetLocalScale", &AZ::TransformBus::Events::GetLocalScale)
->Attribute("Scale", AZ::Edit::Attributes::PropertyScale)
->VirtualProperty("Scale", "GetLocalScale", "SetLocalScale")
@@ -143,24 +143,14 @@ namespace AzFramework
AZ::Quaternion GetLocalRotationQuaternion() override;
// Scale Modifiers
void SetScale(const AZ::Vector3& scale) override;
void SetScaleX(float scaleX) override;
void SetScaleY(float scaleY) override;
void SetScaleZ(float scaleZ) override;
AZ::Vector3 GetScale() override;
float GetScaleX() override;
float GetScaleY() override;
float GetScaleZ() override;
void SetLocalScale(const AZ::Vector3& scale) override;
void SetLocalScaleX(float scaleX) override;
void SetLocalScaleY(float scaleY) override;
void SetLocalScaleZ(float scaleZ) override;
AZ::Vector3 GetLocalScale() override;
AZ::Vector3 GetWorldScale() override;
void SetLocalUniformScale(float scale) override;
float GetLocalUniformScale() override;
float GetWorldUniformScale() override;
// Transform hierarchy
AZStd::vector<AZ::EntityId> GetChildren() override;
AZStd::vector<AZ::EntityId> GetAllDescendants() override;
@@ -60,6 +60,7 @@ namespace AzFramework
virtual void DrawTrianglesIndexed(const AZStd::vector<AZ::Vector3>& vertices, const AZStd::vector<AZ::u32>& indices, const AZ::Color& color) { (void)vertices; (void)indices, (void)color; }
virtual void DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) { (void)min; (void)max; }
virtual void DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) { (void)min; (void)max; }
virtual void DrawWireOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) { (void)center; (void)axisX; (void)axisY; (void)axisZ; (void)halfExtents; }
virtual void DrawSolidOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) { (void)center; (void)axisX; (void)axisY; (void)axisZ; (void)halfExtents; }
virtual void DrawPoint(const AZ::Vector3& p, int nSize = 1) { (void)p; (void)nSize; }
virtual void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) { (void)p1; (void)p2; }
@@ -70,18 +71,15 @@ namespace AzFramework
virtual void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) { (void)p1; (void)p2; (void)z; }
virtual void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) { (void)p1; (void)p2; (void)z; (void)firstColor; (void)secondColor; }
virtual void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) { (void)center; (void)radius; (void)z; }
virtual void DrawTerrainCircle(const AZ::Vector3& worldPos, float radius, float height) { (void)worldPos; (void)radius; (void)height; }
virtual void DrawTerrainCircle(const AZ::Vector3& center, float radius, float angle1, float angle2, float height) { (void)center; (void)radius; (void)angle1; (void)angle2; (void)height; }
virtual void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2) { (void)pos; (void)radius; (void)startAngleDegrees; (void)sweepAngleDegrees; (void)angularStepDegrees; (void)referenceAxis; }
virtual void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) { (void)pos; (void)radius; (void)startAngleDegrees; (void)sweepAngleDegrees; (void)angularStepDegrees; (void)fixedAxis; }
virtual void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) { (void)pos; (void)radius; (void)nUnchangedAxis; }
virtual void DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis = 2 /*z axis*/) { (void)pos; (void)radius; (void)viewPos; (void)nUnchangedAxis; }
virtual void DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) { (void)pos; (void)dir; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height) { (void)pos; (void)dir; (void)radius; (void)height; }
virtual void DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) { (void)pos; (void)dir; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) { (void)center; (void)axis; (void)radius; (void)height; }
virtual void DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded = true) { (void)center; (void)axis; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float heightStraightSection) { (void)center; (void)axis; (void)radius; (void)heightStraightSection; }
virtual void DrawTerrainRect(float x1, float y1, float x2, float y2, float height) { (void)x1; (void)y1; (void)x2; (void)y2; (void)height; }
virtual void DrawTerrainLine(AZ::Vector3 worldPos1, AZ::Vector3 worldPos2) { (void)worldPos1; (void)worldPos2; }
virtual void DrawWireSphere(const AZ::Vector3& pos, float radius) { (void)pos; (void)radius; }
virtual void DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) { (void)pos; (void)radius; }
virtual void DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) { (void)pos; (void)dir; (void)radius; }
@@ -91,11 +89,8 @@ namespace AzFramework
virtual void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) { (void)pos; (void)size; (void)text; (void)bCenter; (void)srcOffsetX; (void)srcOffsetY; }
virtual void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) { (void)x; (void)y; (void)size; (void)text; (void)bCenter; }
virtual void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) { (void)pos; (void)text; (void)textScale; (void)TextColor; (void)TextBackColor; }
virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) { (void)texture; (void)pos; (void)sizeX; (void)sizeY; (void)texIconFlags; }
virtual void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) { (void)textureId; (void)pos; (void)sizeX; (void)sizeY; (void)texIconFlags; }
virtual void SetLineWidth(float width) { (void)width; }
virtual bool IsVisible(const AZ::Aabb& bounds) { (void)bounds; return false; }
virtual int SetFillMode(int nFillMode) { (void)nFillMode; return 0; }
virtual float GetLineWidth() { return 0.0f; }
virtual float GetAspectRatio() { return 0.0f; }
virtual void DepthTestOff() {}
@@ -46,7 +46,6 @@ namespace AzFramework::ProjectManager
// Store the Command line to the Setting Registry
AZ::SettingsRegistryImpl settingsRegistry;
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
// Retrieve Command Line from Settings Registry, it may have been updated by the call to FindEngineRoot()
// in MergeSettingstoRegistry_ConfigFile
@@ -99,51 +98,18 @@ namespace AzFramework::ProjectManager
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
}
{
const char projectsScript[] = "projects.py";
AZStd::string filename = "o3de";
AZ::IO::FixedMaxPath executablePath = AZ::Utils::GetExecutableDirectory();
executablePath /= filename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION;
AZ_Warning("ProjectManager", false, "No project provided - launching project selector.");
if (engineRootPath.empty())
if (!AZ::IO::SystemFile::Exists(executablePath.c_str()))
{
AZ_Error("ProjectManager", false, "Couldn't find engine root");
AZ_Error("ProjectManager", false, "%s not found", executablePath.c_str());
return false;
}
auto projectManagerPath = engineRootPath / "scripts" / "project_manager";
if (!AZ::IO::SystemFile::Exists((projectManagerPath / projectsScript).c_str()))
{
AZ_Error("ProjectManager", false, "%s not found at %s!", projectsScript, projectManagerPath.c_str());
return false;
}
AZ::IO::FixedMaxPathString executablePath;
AZ::Utils::GetExecutablePathReturnType result = AZ::Utils::GetExecutablePath(executablePath.data(), executablePath.capacity());
if (result.m_pathStored != AZ::Utils::ExecutablePathResult::Success)
{
AZ_Error("ProjectManager", false, "Could not determine executable path!");
return false;
}
AZ::IO::FixedMaxPath parentPath(executablePath.c_str());
auto exeFolder = parentPath.ParentPath();
AZStd::fixed_string<8> debugOption;
auto lastSep = exeFolder.Native().find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR);
if (lastSep != AZStd::string_view::npos)
{
exeFolder = exeFolder.Native().substr(lastSep + 1);
}
if (exeFolder == "debug")
{
// We need to use the debug version of the python interpreter to load up our debug version of our libraries which work with the debug version of QT living in this folder
debugOption = "debug ";
}
AZ::IO::FixedMaxPath pythonPath = engineRootPath / "python";
pythonPath /= AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL;
auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRIu32, pythonPath.Native().c_str(),
debugOption.c_str(), (projectManagerPath / projectsScript).c_str(), executablePath.c_str(), AZ::Platform::GetCurrentProcessId());
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = cmdPath;
processLaunchInfo.m_showWindow = false;
processLaunchInfo.m_commandlineParameters = executablePath.String();
launchSuccess = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
}
if (ownsSystemAllocator)
@@ -123,8 +123,9 @@ namespace AzFramework
OctreeNode* insertCheck = this;
while (insertCheck != nullptr)
{
if (AZ::ShapeIntersection::Contains(insertCheck->m_bounds, boundingVolume))
if (AZ::ShapeIntersection::Contains(insertCheck->m_bounds, boundingVolume) || !insertCheck->m_parent)
{
// Insert here if the entry is fully contained or if we've reached the root node
return insertCheck->Insert(octreeScene, entry);
}
insertCheck = insertCheck->m_parent;
@@ -65,5 +65,12 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_googletest(
NAME AZ::AzNetworking.Tests
)
ly_add_googletest(
NAME AZ::AzNetworking.Tests.Sandbox
TARGET AZ::AzNetworking.Tests
TEST_SUITE sandbox
)
endif()
@@ -129,7 +129,7 @@ namespace UnitTest
#if AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS
TEST_F(TcpTransportTests, DISABLED_TestSingleClient)
#else
TEST_F(TcpTransportTests, TestSingleClient)
TEST_F(TcpTransportTests, SUITE_sandbox_TestSingleClient)
#endif // AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS
{
TestTcpServer testServer;
@@ -157,7 +157,7 @@ namespace UnitTest
#if AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS
TEST_F(TcpTransportTests, DISABLED_TestMultipleClients)
#else
TEST_F(TcpTransportTests, TestMultipleClients)
TEST_F(TcpTransportTests, SUITE_sandbox_TestMultipleClients)
#endif // AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS
{
constexpr uint32_t NumTestClients = 50;
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / Local</title>
<g id="Icon-/-Local" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" x="0" y="0" width="24" height="24"></rect>
<polygon id="L" fill="#FFFFFF" fill-rule="nonzero" points="16.9658203 19 16.9658203 16.5 11.1748047 16.5 11.1748047 4.72265625 8.14746094 4.72265625 8.14746094 19"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 575 B

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / Parent</title>
<g id="Icon-/-Parent" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" x="0" y="0" width="24" height="24"></rect>
<path d="M10.5449219,19 L10.5449219,13.921875 L11.84375,13.921875 C13.6145833,13.921875 14.9801432,13.514974 15.9404297,12.7011719 C16.9007161,11.8873698 17.3808594,10.7122396 17.3808594,9.17578125 C17.3808594,7.69791667 16.930013,6.58626302 16.0283203,5.84082031 C15.1266276,5.0953776 13.8098958,4.72265625 12.078125,4.72265625 L12.078125,4.72265625 L7.51757812,4.72265625 L7.51757812,19 L10.5449219,19 Z M11.5410156,11.4414062 L10.5449219,11.4414062 L10.5449219,7.203125 L11.921875,7.203125 C12.7486979,7.203125 13.3557943,7.37239583 13.7431641,7.7109375 C14.1305339,8.04947917 14.3242188,8.57356771 14.3242188,9.28320312 C14.3242188,9.98632812 14.093099,10.5218099 13.6308594,10.8896484 C13.1686198,11.257487 12.4720052,11.4414062 11.5410156,11.4414062 L11.5410156,11.4414062 Z" id="P" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / World</title>
<g id="Icon-/-World" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" x="0" y="0" width="24" height="24"></rect>
<path d="M9.41210938,19 L11.3359375,11.5195312 C11.4205729,11.1875 11.5410156,10.632487 11.6972656,9.85449219 C11.8535156,9.0764974 11.9511719,8.51171875 11.9902344,8.16015625 C12.016276,8.44661458 12.1155599,9.00813802 12.2880859,9.84472656 C12.460612,10.6813151 12.5826823,11.2330729 12.6542969,11.5 L12.6542969,11.5 L14.5878906,19 L18.0351562,19 L21.6679688,4.72265625 L18.6894531,4.72265625 L16.8730469,12.515625 C16.7558594,12.984375 16.625651,13.5979818 16.4824219,14.3564453 C16.3391927,15.1149089 16.235026,15.7480469 16.1699219,16.2558594 C16.0983073,15.7285156 15.9941406,15.0970052 15.8574219,14.3613281 C15.7207031,13.625651 15.6067708,13.078776 15.515625,12.7207031 L15.515625,12.7207031 L13.4355469,4.72265625 L10.5742188,4.72265625 L8.49414062,12.7207031 C8.37044271,13.1503906 8.23860677,13.7542318 8.09863281,14.5322266 C7.95865885,15.3102214 7.86914062,15.8847656 7.83007812,16.2558594 C7.68684896,15.2011719 7.45572917,13.9544271 7.13671875,12.515625 L7.13671875,12.515625 L5.31054688,4.72265625 L2.33203125,4.72265625 L5.97460938,19 L9.41210938,19 Z" id="W" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -354,6 +354,7 @@
<file>img/UI20/toolbar/Grid.svg</file>
<file>img/UI20/toolbar/Lighting.svg</file>
<file>img/UI20/toolbar/Load.svg</file>
<file>img/UI20/toolbar/Local.svg</file>
<file>img/UI20/toolbar/Locked.svg</file>
<file>img/UI20/toolbar/LUA.svg</file>
<file>img/UI20/toolbar/Material.svg</file>
@@ -362,6 +363,7 @@
<file>img/UI20/toolbar/Object_follow_terrain.svg</file>
<file>img/UI20/toolbar/Object_height.svg</file>
<file>img/UI20/toolbar/Object_list.svg</file>
<file>img/UI20/toolbar/Parent.svg</file>
<file>img/UI20/toolbar/particle.svg</file>
<file>img/UI20/toolbar/Play.svg</file>
<file>img/UI20/toolbar/Redo.svg</file>
@@ -380,6 +382,7 @@
<file>img/UI20/toolbar/undo.svg</file>
<file>img/UI20/toolbar/Unlocked.svg</file>
<file>img/UI20/toolbar/Vertex_snapping.svg</file>
<file>img/UI20/toolbar/World.svg</file>
<file>img/UI20/toolbar/X_axis.svg</file>
<file>img/UI20/toolbar/Y_axis.svg</file>
<file>img/UI20/toolbar/Z_axis.svg</file>
@@ -52,6 +52,21 @@ namespace AzToolsFramework
* Deletes all entities in the provided list, as well as their transform descendants.
*/
virtual void DeleteEntitiesAndAllDescendants(const EntityIdList& entities) = 0;
/**
* Duplicate all currently-selected entities.
*/
virtual void DuplicateSelected() = 0;
/**
* Duplicates the specified entity.
*/
virtual void DuplicateEntityById(AZ::EntityId entityId) = 0;
/**
* Duplicates all specified entities.
*/
virtual void DuplicateEntities(const EntityIdList& entities) = 0;
};
} // namespace AzToolsFramework
@@ -43,7 +43,7 @@ namespace AzToolsFramework
void EditorEntityManager::DeleteEntityById(AZ::EntityId entityId)
{
DeleteEntities({entityId});
DeleteEntities(EntityIdList{ entityId });
}
void EditorEntityManager::DeleteEntities(const EntityIdList& entities)
@@ -53,12 +53,30 @@ namespace AzToolsFramework
void EditorEntityManager::DeleteEntityAndAllDescendants(AZ::EntityId entityId)
{
DeleteEntitiesAndAllDescendants({entityId});
DeleteEntitiesAndAllDescendants(EntityIdList{ entityId });
}
void EditorEntityManager::DeleteEntitiesAndAllDescendants(const EntityIdList& entities)
{
m_prefabPublicInterface->DeleteEntitiesAndAllDescendantsInInstance(entities);
}
void EditorEntityManager::DuplicateSelected()
{
EntityIdList selectedEntities;
ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &ToolsApplicationRequests::GetSelectedEntities);
m_prefabPublicInterface->DuplicateEntitiesInInstance(selectedEntities);
}
void EditorEntityManager::DuplicateEntityById(AZ::EntityId entityId)
{
DuplicateEntities(EntityIdList{ entityId });
}
void EditorEntityManager::DuplicateEntities(const EntityIdList& entities)
{
m_prefabPublicInterface->DuplicateEntitiesInInstance(entities);
}
}
@@ -31,6 +31,9 @@ namespace AzToolsFramework
void DeleteEntities(const EntityIdList& entities) override;
void DeleteEntityAndAllDescendants(AZ::EntityId entityId) override;
void DeleteEntitiesAndAllDescendants(const EntityIdList& entities) override;
void DuplicateSelected() override;
void DuplicateEntityById(AZ::EntityId entityId) override;
void DuplicateEntities(const EntityIdList& entities) override;
private:
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
@@ -81,9 +81,20 @@ namespace AzToolsFramework
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_" + name);
bool selectedAsset = false;
for (auto& assetId : selection.GetSelectedAssetIds())
{
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
if (assetId.IsValid())
{
selectedAsset = true;
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
}
}
if (!selectedAsset)
{
m_ui->m_assetBrowserTreeViewWidget->SelectFolder(selection.GetDefaultDirectory());
}
setWindowTitle(tr("Pick %1").arg(m_selection.GetTitle()));
@@ -93,6 +93,16 @@ namespace AzToolsFramework
m_selectedAssetIds.push_back(selectedAssetId);
}
void AssetSelectionModel::SetDefaultDirectory(AZStd::string_view defaultDirectory)
{
m_defaultDirectory = defaultDirectory;
}
AZStd::string_view AssetSelectionModel::GetDefaultDirectory() const
{
return m_defaultDirectory;
}
AZStd::vector<const AssetBrowserEntry*>& AssetSelectionModel::GetResults()
{
return m_results;
@@ -47,6 +47,9 @@ namespace AzToolsFramework
const AZStd::vector<AZ::Data::AssetId>& GetSelectedAssetIds() const;
void SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds);
void SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId);
void SetDefaultDirectory(AZStd::string_view defaultDirectory);
AZStd::string_view GetDefaultDirectory() const;
AZStd::vector<const AssetBrowserEntry*>& GetResults();
const AssetBrowserEntry* GetResult();
@@ -72,6 +75,7 @@ namespace AzToolsFramework
AZStd::vector<AZ::Data::AssetId> m_selectedAssetIds;
AZStd::vector<const AssetBrowserEntry*> m_results;
AZStd::string m_defaultDirectory;
QString m_title;
};
@@ -14,6 +14,7 @@
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -270,7 +271,20 @@ namespace AzToolsFramework
return false;
}
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex)
void AssetBrowserTreeView::SelectFolder(AZStd::string_view folderPath)
{
if (folderPath.size() == 0)
{
return;
}
AZStd::vector<AZStd::string> entries;
AZ::StringFunc::Tokenize(folderPath, entries, "/");
SelectEntry(QModelIndex(), entries, 0, true);
}
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex, bool useDisplayName)
{
if (entries.empty())
{
@@ -285,30 +299,43 @@ namespace AzToolsFramework
auto rowIdx = model()->index(idx, 0, idxParent);
auto rowEntry = GetEntryFromIndex<AssetBrowserEntry>(rowIdx);
// Check if this entry name matches the query
if (rowEntry && AzFramework::StringFunc::Equal(entry.c_str(), rowEntry->GetName().c_str(), true))
if (rowEntry)
{
// Final entry found - set it as the selected element
if (entryPathIndex == entries.size() - 1)
{
selectionModel()->clear();
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
setCurrentIndex(rowIdx);
return true;
}
// Check if this entry name matches the query
AZStd::string_view compareName = useDisplayName ? (const char*)(rowEntry->GetDisplayName().toUtf8()) : rowEntry->GetName().c_str();
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
if (AzFramework::StringFunc::Equal(entry.c_str(), compareName, true))
{
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset Browser (otherwise, early out)
if (SelectEntry(rowIdx, entries, entryPathIndex + 1))
// Final entry found - set it as the selected element
if (entryPathIndex == entries.size() - 1)
{
expand(rowIdx);
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
{
// Expand the item itself if it is a folder
expand(rowIdx);
}
selectionModel()->clear();
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
setCurrentIndex(rowIdx);
return true;
}
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
{
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset
// Browser (otherwise, early out)
if (SelectEntry(rowIdx, entries, entryPathIndex + 1, useDisplayName))
{
expand(rowIdx);
return true;
}
}
return false;
}
return false;
}
}
@@ -60,6 +60,8 @@ namespace AzToolsFramework
AZStd::vector<AssetBrowserEntry*> GetSelectedAssets() const;
void SelectFolder(AZStd::string_view folderPath);
//////////////////////////////////////////////////////////////////////////
// AssetBrowserViewRequestBus
void SelectProduct(AZ::Data::AssetId assetID) override;
@@ -67,6 +69,7 @@ namespace AzToolsFramework
void ClearFilter() override;
void Update() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -105,7 +108,7 @@ namespace AzToolsFramework
QString m_name;
bool SelectProduct(const QModelIndex& idxParent, AZ::Data::AssetId assetID);
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0);
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0, bool useDisplayName = false);
//! Grab one entry from the source thumbnail list and update it
void UpdateSCThumbnails();
@@ -14,9 +14,11 @@
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Script/ScriptSystemBus.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/Entity/GameEntityContextBus.h>
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
@@ -222,21 +224,52 @@ namespace AzToolsFramework
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
bool newLevelFromTemplate = false;
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
{
// This has not been loaded yet, this is the case of being saved with a different name.
// Create it
m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({m_rootInstance->m_containerEntity.get()});
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound = false;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, DefaultLevelTemplateName,
assetInfo, watchFolder);
AzToolsFramework::Prefab::PrefabDom dom;
bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom);
if (!success)
if (sourceInfoFound)
{
AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename));
return false;
AZStd::string fullPath;
AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath);
// Get the default prefab and copy the Dom over to the new template being saved
Prefab::TemplateId defaultId = m_loaderInterface->LoadTemplateFromFile(fullPath.c_str());
Prefab::PrefabDom& dom = m_prefabSystemComponent->FindTemplateDom(defaultId);
Prefab::PrefabDom levelDefaultDom;
levelDefaultDom.CopyFrom(dom, levelDefaultDom.GetAllocator());
Prefab::PrefabDomPath sourcePath("/Source");
sourcePath.Set(levelDefaultDom, relativePath.c_str());
templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(levelDefaultDom));
newLevelFromTemplate = true;
}
templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom));
else
{
// Create an empty level since we couldn't find the default template
m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() });
AzToolsFramework::Prefab::PrefabDom dom;
bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom);
if (!success)
{
AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename));
return false;
}
templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom));
}
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
{
AZ_Error("Prefab", false, "Couldn't add new template id '%i' when saving file '%.*s'", templateId, AZ_STRING_ARG(filename));
@@ -253,6 +286,13 @@ namespace AzToolsFramework
m_prefabSystemComponent->RemoveTemplate(prevTemplateId);
}
// If we have a new level from a template, we need to make sure to propagate the changes here otherwise
// the entities from the new template won't show up
if (newLevelFromTemplate)
{
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
}
AZStd::string out;
if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
{
@@ -216,5 +216,7 @@ namespace AzToolsFramework
Prefab::PrefabLoaderInterface* m_loaderInterface;
AzFramework::EntityContextId m_entityContextId;
AZ::SerializeContext m_serializeContext;
static inline constexpr const char* DefaultLevelTemplateName = "Prefabs/Default_Level.prefab";
};
}
@@ -447,17 +447,14 @@ namespace AzToolsFramework
m_radius * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
// show wireframe if the axis has been corrected/flipped
// note: please see IRenderAuxGeom.h for the definition of e_FillModeWireframe and e_FillModeSolid.
// it is not possible to include IRenderAuxGeom from here and we also don't want to introduce that dependency.
// these legacy enums should be wrapped so set SetFillMode can be used in a type safe way, until then,
// use the values directly until the API has been updated.
const AZ::u32 prevFillMode = debugDisplay.SetFillMode(
m_shouldCorrect ? /*e_FillModeWireframe =*/ 0x1 << 26 : /*e_FillModeSolid =*/ 0);
debugDisplay.DrawCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height, false);
debugDisplay.SetFillMode(prevFillMode);
if (m_shouldCorrect)
{
debugDisplay.DrawWireCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height);
}
else
{
debugDisplay.DrawSolidCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height, false);
}
RefreshBoundInternal(managerId, manipulatorId, coneBound);
}
@@ -82,9 +82,7 @@ namespace AzToolsFramework
m_uniformScaleManipulator->SetVisualOrientationOverride(
QuaternionFromTransformNoScaling(localTransform));
m_uniformScaleManipulator->SetLocalTransform(
AZ::Transform::CreateTranslation(localTransform.GetTranslation()) *
AZ::Transform::CreateScale(localTransform.GetScale()));
m_uniformScaleManipulator->SetLocalOrientation(AZ::Quaternion::CreateIdentity());
}
void ScaleManipulators::SetLocalPositionImpl(const AZ::Vector3& localPosition)
@@ -23,7 +23,7 @@ namespace AzToolsFramework
inline AZ::Transform TransformNormalizedScale(const AZ::Transform& transform)
{
AZ::Transform transformNormalizedScale = transform;
transformNormalizedScale.SetScale(AZ::Vector3::CreateOne());
transformNormalizedScale.SetUniformScale(1.0f);
return transformNormalizedScale;
}
@@ -33,8 +33,7 @@ namespace AzToolsFramework
inline AZ::Transform TransformUniformScale(const AZ::Transform& transform)
{
AZ::Transform transformUniformScale = transform;
const float maxScale = transformUniformScale.GetScale().GetMaxElement();
transformUniformScale.SetScale(AZ::Vector3(maxScale));
transformUniformScale.SetUniformScale(transformUniformScale.GetUniformScale());
return transformUniformScale;
}
@@ -28,6 +28,7 @@ namespace AzToolsFramework
inline static const char* PatchesName = "Patches";
inline static const char* SourceName = "Source";
inline static const char* LinkIdName = "LinkId";
inline static const char* EntityIdName = "Id";
inline static const char* EntitiesName = "Entities";
inline static const char* ContainerEntityName = "ContainerEntity";
@@ -41,7 +41,7 @@ namespace AzToolsFramework
[[maybe_unused]] bool result =
settingsRegistry->Get(m_projectPathWithOsSeparator.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath);
AZ_Assert(result, "Couldn't retrieve project root path");
AZ_Warning("Prefab", result, "Couldn't retrieve project root path");
m_projectPathWithSlashSeparator = AZ::IO::Path(m_projectPathWithOsSeparator.Native(), '/').MakePreferred();
AZ::Interface<PrefabLoaderInterface>::Register(this);
@@ -13,6 +13,8 @@
#include <AzToolsFramework/Prefab/PrefabPublicHandler.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/JSON/stringbuffer.h>
#include <AzCore/JSON/writer.h>
#include <AzCore/Utils/TypeHash.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
@@ -31,6 +33,8 @@
#include <AzToolsFramework/Prefab/PrefabUndoHelpers.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <QString>
namespace AzToolsFramework
{
namespace Prefab
@@ -83,7 +87,8 @@ namespace AzToolsFramework
commonRootInstanceDomBeforeCreate, commonRootEntityOwningInstance->get());
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
AZStd::vector<AZStd::unique_ptr<Instance>> instancePtrs;
AZStd::vector<Instance*> instances;
AZStd::unordered_map<Instance*, PrefabDom> nestedInstanceLinkPatchesMap;
// Retrieve all entities affected and identify Instances
@@ -93,10 +98,18 @@ namespace AzToolsFramework
AZStd::string("Could not create a new prefab out of the entities provided - invalid selection."));
}
// Detach the retrieved entities
for (AZ::Entity* entity : entities)
{
commonRootEntityOwningInstance->get().DetachEntity(entity->GetId()).release();
}
// When we create a prefab with other prefab instances, we have to remove the existing links between the source and
// target templates of the other instances.
for (auto& nestedInstance : instances)
{
AZStd::unique_ptr<Instance> outInstance = commonRootEntityOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias());
auto linkRef = m_prefabSystemComponentInterface->FindLink(nestedInstance->GetLinkId());
if (linkRef.has_value())
@@ -104,10 +117,12 @@ namespace AzToolsFramework
PrefabDom oldLinkPatches;
oldLinkPatches.CopyFrom(linkRef->get().GetLinkDom(), oldLinkPatches.GetAllocator());
nestedInstanceLinkPatchesMap.emplace(nestedInstance.get(), AZStd::move(oldLinkPatches));
nestedInstanceLinkPatchesMap.emplace(nestedInstance, AZStd::move(oldLinkPatches));
}
RemoveLink(nestedInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
RemoveLink(outInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
instancePtrs.emplace_back(AZStd::move(outInstance));
}
PrefabUndoHelpers::UpdatePrefabInstance(
@@ -123,7 +138,7 @@ namespace AzToolsFramework
// Create the Prefab
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
entities, AZStd::move(instancePtrs), filePath, commonRootEntityOwningInstance);
if (!instanceToCreate)
{
@@ -388,7 +403,7 @@ namespace AzToolsFramework
// Find common root and top level entities
bool entitiesHaveCommonRoot = false;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList,
commonRootEntityId, &topLevelEntities);
@@ -710,6 +725,151 @@ namespace AzToolsFramework
return DeleteFromInstance(entityIds, true);
}
PrefabOperationResult PrefabPublicHandler::DuplicateEntitiesInInstance(const EntityIdList& entityIds)
{
if (entityIds.empty())
{
return AZ::Failure(AZStd::string("No entities to duplicate."));
}
if (!EntitiesBelongToSameInstance(entityIds))
{
return AZ::Failure(AZStd::string("Cannot duplicate multiple "
"entities belonging to different instances with one operation."));
}
// We've already verified the entities are all owned by the same instance,
// so we can just retrieve our instance from the first entity in the list.
InstanceOptionalReference commonEntityOwningInstance = GetOwnerInstanceByEntityId(entityIds[0]);
AZ_Assert(
commonEntityOwningInstance.has_value(),
"Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided");
// This will cull out any entities that have ancestors in the list, since we will end up duplicating
// the full nested hierarchy with what is returned from RetrieveAndSortPrefabEntitiesAndInstances
AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entityIds);
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
ScopedUndoBatch undoBatch("Duplicate Entities");
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzToolsFramework, "DuplicateEntitiesInInstance::UndoCaptureAndDuplicateEntities");
// Take a snapshot of the instance DOM before we manipulate it
Prefab::PrefabDom instanceDomBefore;
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonEntityOwningInstance->get());
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<Instance*> instances;
// Gather all entities/instances in the hierarchy, but don't detach them because we are duplicating not deleting.
EntityList inputEntityList = EntityIdSetToEntityList(duplicationSet);
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonEntityOwningInstance->get(), entities, instances);
if (!success)
{
return AZ::Failure(AZStd::string("Failed to retrieve entities and instances from the given list of entity ids for duplication"));
}
// Make a copy of our before instance DOM where we will add our duplicated entities
Prefab::PrefabDom instanceDomAfter;
instanceDomAfter.CopyFrom(instanceDomBefore, instanceDomAfter.GetAllocator());
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
for (AZ::Entity* entity : entities)
{
EntityAliasOptionalReference oldAliasRef = commonEntityOwningInstance->get().GetEntityAlias(entity->GetId());
AZ_Assert(oldAliasRef.has_value(), "No alias found for Entity in the DOM");
EntityAlias oldAlias = oldAliasRef.value();
// Give this the outer allocator so that the memory reference will be valid when
// it gets used for AddMember
Prefab::PrefabDom entityDomBefore(&instanceDomAfter.GetAllocator());
m_instanceToTemplateInterface->GenerateDomForEntity(entityDomBefore, *entity);
// Keep track of the old alias <-> new alias mapping for this duplicated entity
// so we can fixup references later
EntityAlias newEntityAlias = Instance::GenerateEntityAlias();
oldAliasToNewAliasMap.insert(AZStd::make_pair(oldAlias, newEntityAlias));
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
entityDomBefore.Accept(writer);
// Store our duplicated Entity DOM with its new alias as a string
// so that we can fixup entity alias references before adding it
// to the Entities member of our instance DOM
QString entityDomString(buffer.GetString());
aliasToEntityDomMap.insert(AZStd::make_pair(newEntityAlias, entityDomString));
}
auto entitiesIter = instanceDomAfter.FindMember(PrefabDomUtils::EntitiesName);
AZ_Assert(entitiesIter != instanceDomAfter.MemberEnd(), "Instance DOM missing the Entities member.");
// Now that all the duplicated Entity DOMs have been created, we need to iterate
// through them and replace any previous EntityAlias references with the new ones.
// These are more than just parent entity references for nested entities, this will
// also cover any EntityId references that were made in the components between them.
for (auto aliasEntityPair : aliasToEntityDomMap)
{
EntityAlias newEntityAlias = aliasEntityPair.first;
QString newEntityDomString = aliasEntityPair.second;
// Replace all of the old alias references with the new ones
// We bookend the aliases with \" and also with a / as an extra precaution to prevent
// inadvertently replacing a matching string vs. where an actual EntityId is expected
// This will cover both cases where an alias could be used in a normal entity vs. an instance
for (auto aliasMapIter : oldAliasToNewAliasMap)
{
QString oldAliasQuotes = QString("\"%1\"").arg(aliasMapIter.first.c_str());
QString newAliasQuotes = QString("\"%1\"").arg(aliasMapIter.second.c_str());
newEntityDomString.replace(oldAliasQuotes, newAliasQuotes);
QString oldAliasPathRef = QString("/%1").arg(aliasMapIter.first.c_str());
QString newAliasPathRef = QString("/%1").arg(aliasMapIter.second.c_str());
newEntityDomString.replace(oldAliasPathRef, newAliasPathRef);
}
// Create the new Entity DOM from parsing the JSON string
Prefab::PrefabDom entityDomAfter(&instanceDomAfter.GetAllocator());
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
// Add the new Entity DOM to the Entities member of the instance
rapidjson::Value aliasName(newEntityAlias.c_str(), newEntityAlias.length(), instanceDomAfter.GetAllocator());
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, instanceDomAfter.GetAllocator());
}
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity duplication");
command->SetParent(undoBatch.GetUndoBatch());
command->Capture(instanceDomBefore, instanceDomAfter, commonEntityOwningInstance->get().GetTemplateId());
command->RunRedo();
EntityIdList duplicatedEntityIds;
for (auto aliasMapIter : oldAliasToNewAliasMap)
{
EntityAlias newEntityAlias = aliasMapIter.second;
AliasPath absoluteEntityPath = commonEntityOwningInstance->get().GetAbsoluteInstanceAliasPath();
absoluteEntityPath.Append(newEntityAlias);
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteEntityPath);
duplicatedEntityIds.push_back(newEntityId);
}
// Select the duplicated entities
auto selectionUndo = aznew SelectionCommand(duplicatedEntityIds, "Select Duplicated Entities");
selectionUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
}
return AZ::Success();
}
PrefabOperationResult PrefabPublicHandler::DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants)
{
if (entityIds.empty())
@@ -737,17 +897,7 @@ namespace AzToolsFramework
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
UndoSystem::URSequencePoint* currentUndoBatch = nullptr;
ToolsApplicationRequests::Bus::BroadcastResult(currentUndoBatch, &ToolsApplicationRequests::Bus::Events::GetCurrentUndoBatch);
bool createdUndo = false;
if (!currentUndoBatch)
{
createdUndo = true;
ToolsApplicationRequests::Bus::BroadcastResult(
currentUndoBatch, &ToolsApplicationRequests::Bus::Events::BeginUndoBatch, "Delete Selected");
AZ_Assert(currentUndoBatch, "Failed to create new undo batch.");
}
ScopedUndoBatch undoBatch("Delete Selected");
// In order to undo DeleteSelected, we have to create a selection command which selects the current selection
// and then add the deletion as children.
@@ -775,7 +925,7 @@ namespace AzToolsFramework
if (deleteDescendants)
{
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
AZStd::vector<Instance*> instances;
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
@@ -786,13 +936,15 @@ namespace AzToolsFramework
for (AZ::Entity* entity : entities)
{
commonOwningInstance->get().DetachEntity(entity->GetId()).release();
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, entity->GetId());
}
for (auto& nestedInstance : instances)
{
RemoveLink(nestedInstance, commonOwningInstance->get().GetTemplateId(), currentUndoBatch);
nestedInstance.reset();
AZStd::unique_ptr<Instance> outInstance = commonOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias());
RemoveLink(outInstance, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
outInstance.reset();
}
}
else
@@ -804,7 +956,7 @@ namespace AzToolsFramework
if (owningInstance->get().GetContainerEntityId() == entityId)
{
auto instancePtr = commonOwningInstance->get().DetachNestedInstance(owningInstance->get().GetInstanceAlias());
RemoveLink(instancePtr, commonOwningInstance->get().GetTemplateId(), currentUndoBatch);
RemoveLink(instancePtr, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
}
else
{
@@ -822,17 +974,12 @@ namespace AzToolsFramework
command->SetParent(selCommand);
}
selCommand->SetParent(currentUndoBatch);
selCommand->SetParent(undoBatch.GetUndoBatch());
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzToolsFramework, "Internal::DeleteEntities:RunRedo");
selCommand->RunRedo();
}
if (createdUndo)
{
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::EndUndoBatch);
}
return AZ::Success();
}
@@ -944,7 +1091,7 @@ namespace AzToolsFramework
bool PrefabPublicHandler::RetrieveAndSortPrefabEntitiesAndInstances(
const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<AZStd::unique_ptr<Instance>>& outInstances) const
EntityList& outEntities, AZStd::vector<Instance*>& outInstances) const
{
if (inputEntities.size() == 0)
{
@@ -1028,14 +1175,14 @@ namespace AzToolsFramework
for (AZ::Entity* entity : entities)
{
outEntities.emplace_back(commonRootEntityOwningInstance.DetachEntity(entity->GetId()).release());
outEntities.emplace_back(entity);
}
outInstances.clear();
outInstances.reserve(instances.size());
for (Instance* instancePtr : instances)
{
outInstances.push_back(AZStd::move(commonRootEntityOwningInstance.DetachNestedInstance(instancePtr->GetInstanceAlias())));
outInstances.push_back(instancePtr);
}
return (outEntities.size() + outInstances.size()) > 0;
@@ -60,11 +60,12 @@ namespace AzToolsFramework
PrefabOperationResult DeleteEntitiesInInstance(const EntityIdList& entityIds) override;
PrefabOperationResult DeleteEntitiesAndAllDescendantsInInstance(const EntityIdList& entityIds) override;
PrefabOperationResult DuplicateEntitiesInInstance(const EntityIdList& entityIds) override;
private:
PrefabOperationResult DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants);
bool RetrieveAndSortPrefabEntitiesAndInstances(const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<AZStd::unique_ptr<Instance>>& outInstances) const;
EntityList& outEntities, AZStd::vector<Instance*>& outInstances) const;
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
@@ -143,6 +143,13 @@ namespace AzToolsFramework
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
virtual PrefabOperationResult DeleteEntitiesAndAllDescendantsInInstance(const EntityIdList& entityIds) = 0;
/**
* Duplicates all entities in the owning instance. Bails if the entities don't all belong to the same instance.
* @param entities The entities to duplicate.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
virtual PrefabOperationResult DuplicateEntitiesInInstance(const EntityIdList& entityIds) = 0;
};
} // namespace Prefab
@@ -1475,10 +1475,8 @@ namespace AzToolsFramework
// to avoid pushing them to the slice.
// Only scale is preserved on the root entity of a slice.
transformComponent->SetParent(AZ::EntityId());
AZ::Vector3 scale = transformComponent->GetLocalScale();
transformComponent->SetWorldTranslation(AZ::Vector3::CreateZero());
transformComponent->SetLocalRotation(AZ::Vector3::CreateZero());
transformComponent->SetLocalScale(scale);
}
}
@@ -357,7 +357,7 @@ namespace AzToolsFramework
AZ::Transform TransformComponent::GetLocalScaleTM() const
{
return AZ::Transform::CreateScale(m_editorTransform.m_scale);
return AZ::Transform::CreateUniformScale(m_editorTransform.m_scale.GetMaxElement());
}
const AZ::Transform& TransformComponent::GetLocalTM()
@@ -677,100 +677,12 @@ namespace AzToolsFramework
return result;
}
void TransformComponent::SetScale(const AZ::Vector3& newScale)
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "SetScale is deprecated, please use SetLocalScale");
AZ::Transform newWorldTransform = GetWorldTM();
AZ::Vector3 prevScale = newWorldTransform.ExtractScale();
if (!prevScale.IsClose(newScale))
{
newWorldTransform.MultiplyByScale(newScale);
SetWorldTM(newWorldTransform);
}
}
void TransformComponent::SetScaleX(float newScale)
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "SetScaleX is deprecated, please use SetLocalScaleX");
AZ::Transform newWorldTransform = GetWorldTM();
AZ::Vector3 scale = newWorldTransform.ExtractScale();
scale.SetX(newScale);
newWorldTransform.MultiplyByScale(scale);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetScaleY(float newScale)
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "SetScaleY is deprecated, please use SetLocalScaleY");
AZ::Transform newWorldTransform = GetWorldTM();
AZ::Vector3 scale = newWorldTransform.ExtractScale();
scale.SetY(newScale);
newWorldTransform.MultiplyByScale(scale);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetScaleZ(float newScale)
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "SetScaleZ is deprecated, please use SetLocalScaleZ");
AZ::Transform newWorldTransform = GetWorldTM();
AZ::Vector3 scale = newWorldTransform.ExtractScale();
scale.SetZ(newScale);
newWorldTransform.MultiplyByScale(scale);
SetWorldTM(newWorldTransform);
}
AZ::Vector3 TransformComponent::GetScale()
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "GetScale is deprecated, please use GetLocalScale");
return GetWorldTM().GetScale();
}
float TransformComponent::GetScaleX()
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "GetScaleX is deprecated, please use GetLocalScale");
return GetWorldTM().GetScale().GetX();
}
float TransformComponent::GetScaleY()
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "GetScaleY is deprecated, please use GetLocalScale");
return GetWorldTM().GetScale().GetY();
}
float TransformComponent::GetScaleZ()
{
AZ_Warning("AzToolsFramework::TransformComponent", false, "GetScaleZ is deprecated, please use GetLocalScale");
return GetWorldTM().GetScale().GetZ();
}
void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
{
m_editorTransform.m_scale = scale;
TransformChanged();
}
void TransformComponent::SetLocalScaleX(float scaleX)
{
m_editorTransform.m_scale.SetX(scaleX);
TransformChanged();
}
void TransformComponent::SetLocalScaleY(float scaleY)
{
m_editorTransform.m_scale.SetY(scaleY);
TransformChanged();
}
void TransformComponent::SetLocalScaleZ(float scaleZ)
{
m_editorTransform.m_scale.SetZ(scaleZ);
TransformChanged();
}
AZ::Vector3 TransformComponent::GetLocalScale()
{
return m_editorTransform.m_scale;
@@ -781,6 +693,22 @@ namespace AzToolsFramework
return GetWorldTM().GetScale();
}
void TransformComponent::SetLocalUniformScale(float scale)
{
m_editorTransform.m_scale = AZ::Vector3(scale);
TransformChanged();
}
float TransformComponent::GetLocalUniformScale()
{
return m_editorTransform.m_scale.GetMaxElement();
}
float TransformComponent::GetWorldUniformScale()
{
return GetWorldTM().GetUniformScale();
}
const AZ::Transform& TransformComponent::GetParentWorldTM() const
{
auto parent = GetParentTransformComponent();
@@ -1183,12 +1111,6 @@ namespace AzToolsFramework
ModifyEditorTransform(m_editorTransform.m_rotate, data, parent);
}
void TransformComponent::ScaleBy(const AZ::Vector3& data)
{
//scale is always local
ModifyEditorTransform(m_editorTransform.m_scale, data, AZ::Transform::Identity());
}
AZ::EntityId TransformComponent::GetSliceEntityParentId()
{
return GetParentId();
@@ -130,24 +130,14 @@ namespace AzToolsFramework
AZ::Quaternion GetLocalRotationQuaternion() override;
// Scale Modifiers
void SetScale(const AZ::Vector3& newScale) override;
void SetScaleX(float newScale) override;
void SetScaleY(float newScale) override;
void SetScaleZ(float newScale) override;
AZ::Vector3 GetScale() override;
float GetScaleX() override;
float GetScaleY() override;
float GetScaleZ() override;
void SetLocalScale(const AZ::Vector3& scale) override;
void SetLocalScaleX(float scaleX) override;
void SetLocalScaleY(float scaleY) override;
void SetLocalScaleZ(float scaleZ) override;
AZ::Vector3 GetLocalScale() override;
AZ::Vector3 GetWorldScale() override;
void SetLocalUniformScale(float scale) override;
float GetLocalUniformScale() override;
float GetWorldUniformScale() override;
AZ::EntityId GetParentId() override;
AZ::TransformInterface* GetParent() override;
void SetParent(AZ::EntityId parentId) override;
@@ -161,7 +151,6 @@ namespace AzToolsFramework
// TransformComponentMessages::Bus
void TranslateBy(const AZ::Vector3&) override;
void RotateBy(const AZ::Vector3&) override; // euler in degrees
void ScaleBy(const AZ::Vector3&) override;
const EditorTransform& GetLocalEditorTransform() override;
void SetLocalEditorTransform(const EditorTransform& dest) override;
bool IsTransformLocked() override;
@@ -65,7 +65,6 @@ namespace AzToolsFramework
virtual void TranslateBy(const AZ::Vector3&) = 0;
virtual void RotateBy(const AZ::Vector3&) = 0;
virtual void ScaleBy(const AZ::Vector3&) = 0;
virtual bool IsTransformLocked() = 0;
};
@@ -63,6 +63,7 @@
#include <AzToolsFramework/UI/Outliner/EntityOutlinerDisplayOptionsMenu.h>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerSortFilterProxyModel.hxx>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerCacheBus.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
////////////////////////////////////////////////////////////////////////////
@@ -1409,6 +1410,16 @@ namespace AzToolsFramework
{
(void)name;
QueueEntityUpdate(entityId);
bool isSelected = false;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
isSelected, &AzToolsFramework::ToolsApplicationRequests::IsSelected, entityId);
if (isSelected)
{
// Ask the system to scroll to the entity in case it is off screen after the rename
EntityOutlinerModelNotificationBus::Broadcast(&EntityOutlinerModelNotifications::QueueScrollToNewContent, entityId);
}
}
void EntityOutlinerListModel::OnEntityInfoUpdatedUnsavedChanges(AZ::EntityId entityId)
@@ -83,7 +83,7 @@ namespace AzToolsFramework
protected:
QWidget* GetFirstInTabOrder() override;
QWidget* GetLastInTabOrder() override;
void UpdateTabOrder() override;
void UpdateTabOrder() override;
void onChildComboBoxValueChange(int comboBoxIndex) override;
@@ -93,7 +93,7 @@ namespace AzToolsFramework
void addElementImpl(const AZStd::pair<T, AZStd::string>& genericValue);
QLabel* m_warningLabel = nullptr;
QLabel* m_warningLabel = nullptr;
DHQComboBox* m_pComboBox;
AZStd::vector<AZStd::pair<T, AZStd::string>> m_values;
AZ::AttributeFunction <void(const T&)>* m_postChangeNotifyCB{};
@@ -131,6 +131,11 @@ namespace AzToolsFramework
template<typename T>
AzToolsFramework::PropertyHandlerBase* RegisterGenericComboBoxHandler()
{
if (!AzToolsFramework::PropertyTypeRegistrationMessages::Bus::FindFirstHandler())
{
return nullptr;
}
auto propertyHandler = aznew GenericComboBoxHandler<T>();
AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, propertyHandler);
return propertyHandler;

Some files were not shown because too many files have changed in this diff Show More