Merge branch 'main' into Prefab/RemoveUndoCacheDependency

main
srikappa 5 years ago
commit 7d3dcf85f6

@ -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)

@ -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 = [

@ -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,
)

@ -128,6 +128,10 @@ foreach(external_directory ${LY_EXTERNAL_SUBDIRS})
endforeach()
# The following steps have to be done after all targets are registered:
# Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic
# builds until after all the targets are known
ly_delayed_generate_static_modules_inl()
# 1. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
# to provide applications with the filenames of gem modules to load
# This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIES as MANUALLY_ADDED_DEPENDENCIES

@ -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;
}

@ -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) {}
//! Get the scale value in local space.
//! @return The scale value in local space.
virtual AZ::Vector3 GetLocalScale() { return AZ::Vector3(FLT_MAX); }
//! 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) {}
//! Get the scale value in world space.
//! @return The scale value in world space.
virtual AZ::Vector3 GetWorldScale() { return AZ::Vector3(FLT_MAX); }
//! 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) {}
//! Set the uniform scale value in local space.
virtual void SetLocalUniformScale([[maybe_unused]] float scale) {}
//! Get the scale value on each axis in local space
//! @return The scale value of type Vector3 along each axis in local space.
virtual AZ::Vector3 GetLocalScale() { return AZ::Vector3(FLT_MAX); }
//! Get the uniform scale value in local space.
//! @return The uniform scale value in local space.
virtual float GetLocalUniformScale() { return 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.
virtual AZ::Vector3 GetWorldScale() { return AZ::Vector3(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;
};
}

@ -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);
}

@ -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)
{
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)
TEST(MATH_Transform, CreateUniformScale)
{
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);

@ -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,41 +499,31 @@ namespace AzFramework
SetLocalTM(newLocalTM);
}
void TransformComponent::SetLocalScaleX(float scaleX)
AZ::Vector3 TransformComponent::GetLocalScale()
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetX(scaleX);
newLocalTM.SetScale(newScale);
SetLocalTM(newLocalTM);
return m_localTM.GetScale();
}
void TransformComponent::SetLocalScaleY(float scaleY)
AZ::Vector3 TransformComponent::GetWorldScale()
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetY(scaleY);
newLocalTM.SetScale(newScale);
SetLocalTM(newLocalTM);
return m_worldTM.GetScale();
}
void TransformComponent::SetLocalScaleZ(float scaleZ)
void TransformComponent::SetLocalUniformScale(float scale)
{
AZ::Transform newLocalTM = m_localTM;
AZ::Vector3 newScale = newLocalTM.GetScale();
newScale.SetZ(scaleZ);
newLocalTM.SetScale(newScale);
newLocalTM.SetUniformScale(scale);
SetLocalTM(newLocalTM);
}
AZ::Vector3 TransformComponent::GetLocalScale()
float TransformComponent::GetLocalUniformScale()
{
return m_localTM.GetScale();
return m_localTM.GetUniformScale();
}
AZ::Vector3 TransformComponent::GetWorldScale()
float TransformComponent::GetWorldUniformScale()
{
return m_worldTM.GetScale();
return m_worldTM.GetUniformScale();
}
AZStd::vector<AZ::EntityId> TransformComponent::GetChildren()
@ -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>

@ -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()});
AzToolsFramework::Prefab::PrefabDom dom;
bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom);
if (!success)
AZStd::string watchFolder;
AZ::Data::AssetInfo assetInfo;
bool sourceInfoFound = false;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, DefaultLevelTemplateName,
assetInfo, watchFolder);
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;
}
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));
}
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;
}

@ -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);

@ -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,108 +677,36 @@ 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)
AZ::Vector3 TransformComponent::GetLocalScale()
{
m_editorTransform.m_scale.SetX(scaleX);
TransformChanged();
return m_editorTransform.m_scale;
}
void TransformComponent::SetLocalScaleY(float scaleY)
AZ::Vector3 TransformComponent::GetWorldScale()
{
m_editorTransform.m_scale.SetY(scaleY);
TransformChanged();
return GetWorldTM().GetScale();
}
void TransformComponent::SetLocalScaleZ(float scaleZ)
void TransformComponent::SetLocalUniformScale(float scale)
{
m_editorTransform.m_scale.SetZ(scaleZ);
m_editorTransform.m_scale = AZ::Vector3(scale);
TransformChanged();
}
AZ::Vector3 TransformComponent::GetLocalScale()
float TransformComponent::GetLocalUniformScale()
{
return m_editorTransform.m_scale;
return m_editorTransform.m_scale.GetMaxElement();
}
AZ::Vector3 TransformComponent::GetWorldScale()
float TransformComponent::GetWorldUniformScale()
{
return GetWorldTM().GetScale();
return GetWorldTM().GetUniformScale();
}
const AZ::Transform& TransformComponent::GetParentWorldTM() const
@ -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;
};

@ -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;

@ -140,8 +140,7 @@ namespace AzToolsFramework
ProductAssetBrowserEntry* productEntry = static_cast<ProductAssetBrowserEntry*>(childEntry);
AZStd::string assetName;
AzFramework::StringFunc::Path::GetFileName(productEntry->GetFullPath().c_str(), assetName);
m_assets.push_back({
assetName, productEntry->GetFullPath(), productEntry->GetAssetId()
m_assets.push_back({ productEntry->GetName(), productEntry->GetFullPath(), productEntry->GetAssetId()
});
}

@ -769,6 +769,14 @@ namespace AzToolsFramework
// Request the AssetBrowser Dialog and set a type filter
AssetSelectionModel selection = GetAssetSelectionModel();
selection.SetSelectedAssetId(m_selectedAssetID);
AZStd::string defaultDirectory;
if (m_defaultDirectoryCallback)
{
m_defaultDirectoryCallback->Invoke(m_editNotifyTarget, defaultDirectory);
selection.SetDefaultDirectory(defaultDirectory);
}
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget());
if (selection.IsValid())
{
@ -1080,6 +1088,11 @@ namespace AzToolsFramework
m_editNotifyCallback = editNotifyCallback;
}
void PropertyAssetCtrl::SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback)
{
m_defaultDirectoryCallback = callback;
}
void PropertyAssetCtrl::SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback)
{
m_clearNotifyCallback = clearNotifyCallback;
@ -1214,6 +1227,11 @@ namespace AzToolsFramework
GUI->SetTitle(title.c_str());
}
}
else if (attrib == AZ_CRC_CE("DefaultStartingDirectoryCallback"))
{
// This is assumed to be an Asset Browser path to a specific folder to be used as a default by the asset picker if provided
GUI->SetDefaultDirectoryCallback(azdynamic_cast<PropertyAssetCtrl::DefaultDirectoryCallbackType*>(attrValue->GetAttribute()));
}
else if (attrib == AZ_CRC("EditCallback", 0xb74f2ee1))
{
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast<PropertyAssetCtrl::EditCallbackType*>(attrValue->GetAttribute());

@ -68,6 +68,7 @@ namespace AzToolsFramework
// This is meant to be used with the "EditCallback" Attribute
using EditCallbackType = AZ::Edit::AttributeFunction<void(const AZ::Data::AssetId&, const AZ::Data::AssetType&)>;
using ClearCallbackType = AZ::Edit::AttributeFunction<void()>;
using DefaultDirectoryCallbackType = AZ::Edit::AttributeFunction<void(AZStd::string&)>;
PropertyAssetCtrl(QWidget *pParent = NULL, QString optionalValidDragDropExtensions = QString());
virtual ~PropertyAssetCtrl();
@ -119,6 +120,7 @@ namespace AzToolsFramework
EditCallbackType* m_editNotifyCallback = nullptr;
ClearCallbackType* m_clearNotifyCallback = nullptr;
QString m_optionalValidDragDropExtensions;
DefaultDirectoryCallbackType* m_defaultDirectoryCallback = nullptr;
//! The number of characters after which the autocompleter dropdown will be shown.
// Prevents showing too many options.
@ -196,6 +198,7 @@ namespace AzToolsFramework
void SetEditNotifyTarget(void* editNotifyTarget);
void SetEditNotifyCallback(EditCallbackType* editNotifyCallback); // This is meant to be used with the "EditCallback" Attribute
void SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback); // This is meant to be used with the "ClearNotify" Attribute
void SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback); // This is meant to be used with the "DefaultStartingDirectoryCallback" Attribute
void SetEditButtonEnabled(bool enabled);
void SetEditButtonVisible(bool visible);
void SetEditButtonIcon(const QIcon& icon);

@ -233,9 +233,9 @@ namespace AzToolsFramework
}();
debugDisplay.SetColor(iconHighlight);
debugDisplay.DrawTextureLabel(
iconTextureId, entityPosition, iconSize, iconSize,
/*DisplayContext::ETextureIconFlags::TEXICON_ON_TOP=*/ 0x0008);
// debugDisplay.DrawTextureLabel(
// iconTextureId, entityPosition, iconSize, iconSize,
// /*DisplayContext::ETextureIconFlags::TEXICON_ON_TOP=*/ 0x0008);
}
}
}

@ -435,7 +435,7 @@ namespace AzToolsFramework
}
}
static void DestroyTransformModeSelectionCluster(const ViewportUi::ClusterId clusterId)
static void DestroyCluster(const ViewportUi::ClusterId clusterId)
{
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId,
@ -483,6 +483,26 @@ namespace AzToolsFramework
return worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, pivot));
}
void EditorTransformComponentSelection::UpdateSpaceCluster(const ReferenceFrame referenceFrame)
{
auto buttonIdFromFrameFn = [this](const ReferenceFrame referenceFrame) {
switch (referenceFrame)
{
case ReferenceFrame::Local:
return m_spaceCluster.m_localButtonId;
case ReferenceFrame::Parent:
return m_spaceCluster.m_parentButtonId;
case ReferenceFrame::World:
return m_spaceCluster.m_worldButtonId;
}
return m_spaceCluster.m_parentButtonId;
};
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, m_spaceCluster.m_spaceClusterId,
buttonIdFromFrameFn(referenceFrame));
}
namespace ETCS
{
PivotOrientationResult CalculatePivotOrientation(
@ -789,13 +809,13 @@ namespace AzToolsFramework
EntityIdManipulators& entityIdManipulators,
OptionalFrame& pivotOverrideFrame,
ViewportInteraction::KeyboardModifiers& prevModifiers,
bool& transformChangedInternally)
bool& transformChangedInternally, SpaceCluster spaceCluster)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
entityIdManipulators.m_manipulators->SetLocalPosition(action.LocalPosition());
const ReferenceFrame referenceFrame = ReferenceFrameFromModifiers(action.m_modifiers);
const ReferenceFrame referenceFrame = spaceCluster.m_spaceLock ? spaceCluster.m_currentSpace : ReferenceFrameFromModifiers(action.m_modifiers);
if (action.m_modifiers.Ctrl())
{
@ -1027,6 +1047,7 @@ namespace AzToolsFramework
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId);
CreateTransformModeSelectionCluster();
CreateSpaceSelectionCluster();
RegisterActions();
SetupBoxSelect();
RefreshSelectedEntityIdsAndRegenerateManipulators();
@ -1037,7 +1058,9 @@ namespace AzToolsFramework
m_selectedEntityIds.clear();
DestroyManipulators(m_entityIdManipulators);
DestroyTransformModeSelectionCluster(m_transformModeClusterId);
DestroyCluster(m_transformModeClusterId);
DestroyCluster(m_spaceCluster.m_spaceClusterId);
UnregisterActions();
m_pivotOverrideFrame.Reset();
@ -1274,8 +1297,8 @@ namespace AzToolsFramework
[this, prevModifiers, manipulatorEntityIds](const LinearManipulator::Action& action) mutable -> void
{
UpdateTranslationManipulator(
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators,
m_pivotOverrideFrame, prevModifiers, m_transformChangedInternally);
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers,
m_transformChangedInternally, m_spaceCluster);
});
translationManipulators->InstallLinearManipulatorMouseUpCallback(
@ -1305,8 +1328,8 @@ namespace AzToolsFramework
[this, prevModifiers, manipulatorEntityIds](const PlanarManipulator::Action& action) mutable -> void
{
UpdateTranslationManipulator(
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators,
m_pivotOverrideFrame, prevModifiers, m_transformChangedInternally);
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers,
m_transformChangedInternally, m_spaceCluster);
});
translationManipulators->InstallPlanarManipulatorMouseUpCallback(
@ -1335,8 +1358,8 @@ namespace AzToolsFramework
[this, prevModifiers, manipulatorEntityIds](const SurfaceManipulator::Action& action) mutable -> void
{
UpdateTranslationManipulator(
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators,
m_pivotOverrideFrame, prevModifiers, m_transformChangedInternally);
action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers,
m_transformChangedInternally, m_spaceCluster);
});
translationManipulators->InstallSurfaceManipulatorMouseUpCallback(
@ -1414,7 +1437,7 @@ namespace AzToolsFramework
[this, prevModifiers, sharedRotationState]
(const AngularManipulator::Action& action) mutable -> void
{
const ReferenceFrame referenceFrame = ReferenceFrameFromModifiers(action.m_modifiers);
const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock ? m_spaceCluster.m_currentSpace : ReferenceFrameFromModifiers(action.m_modifiers);
const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta;
// store the pivot override frame when positioning the manipulator manually (ctrl)
@ -1474,7 +1497,7 @@ namespace AzToolsFramework
{
const AZ::Quaternion rotation = entityIdLookupIt->second.m_initial.GetRotation().GetNormalized();
const AZ::Vector3 position = entityIdLookupIt->second.m_initial.GetTranslation();
const AZ::Vector3 scale = entityIdLookupIt->second.m_initial.GetScale();
const float scale = entityIdLookupIt->second.m_initial.GetUniformScale();
const AZ::Vector3 centerOffset = CalculateCenterOffset(entityId, m_pivotMode);
@ -1485,7 +1508,7 @@ namespace AzToolsFramework
AZ::Transform::CreateFromQuaternion(rotation) *
AZ::Transform::CreateTranslation(centerOffset) * offsetRotation *
AZ::Transform::CreateTranslation(-centerOffset) *
AZ::Transform::CreateScale(scale));
AZ::Transform::CreateUniformScale(scale));
}
break;
case ReferenceFrame::Parent:
@ -1597,16 +1620,15 @@ namespace AzToolsFramework
}
const AZ::Transform initial = entityIdLookupIt->second.m_initial;
const AZ::Vector3 initialScale = initial.GetScale();
const float initialScale = initial.GetUniformScale();
const auto sumVectorElements = [](const AZ::Vector3& vec) {
return vec.GetX() + vec.GetY() + vec.GetZ();
};
const AZ::Vector3 uniformScale = AZ::Vector3(action.m_start.m_sign * sumVectorElements(action.LocalScaleOffset()));
const AZ::Vector3 scale = (AZ::Vector3::CreateOne() +
(uniformScale / initialScale)).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale));
const AZ::Transform scaleTransform = AZ::Transform::CreateScale(scale);
const float uniformScale = action.m_start.m_sign * sumVectorElements(action.LocalScaleOffset());
const float scale = AZ::GetClamp(1.0f + uniformScale / initialScale, AZ::MinTransformScale, AZ::MaxTransformScale);
const AZ::Transform scaleTransform = AZ::Transform::CreateUniformScale(scale);
if (action.m_modifiers.Alt())
{
@ -1872,7 +1894,7 @@ namespace AzToolsFramework
CopyOrientationToSelectedEntitiesGroup(QuaternionFromTransformNoScaling(worldFromLocal));
break;
case Mode::Scale:
CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetScale());
CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale());
break;
case Mode::Translation:
CopyTranslationToSelectedEntitiesGroup(worldFromLocal.GetTranslation());
@ -1901,7 +1923,7 @@ namespace AzToolsFramework
CopyOrientationToSelectedEntitiesIndividual(QuaternionFromTransformNoScaling(worldFromLocal));
break;
case Mode::Scale:
CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetScale());
CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale());
break;
case Mode::Translation:
CopyTranslationToSelectedEntitiesIndividual(worldFromLocal.GetTranslation());
@ -2394,7 +2416,7 @@ namespace AzToolsFramework
ResetOrientationForSelectedEntitiesLocal();
break;
case Mode::Scale:
CopyScaleToSelectedEntitiesIndividualLocal(AZ::Vector3::CreateOne());
CopyScaleToSelectedEntitiesIndividualLocal(1.0f);
break;
case Mode::Translation:
ResetTranslationForSelectedEntitiesLocal();
@ -2420,7 +2442,7 @@ namespace AzToolsFramework
ResetOrientationForSelectedEntitiesLocal();
break;
case Mode::Scale:
CopyScaleToSelectedEntitiesIndividualWorld(AZ::Vector3::CreateOne());
CopyScaleToSelectedEntitiesIndividualWorld(1.0f);
break;
case Mode::Translation:
// do nothing
@ -2567,6 +2589,67 @@ namespace AzToolsFramework
m_transformModeSelectionHandler);
}
void EditorTransformComponentSelection::CreateSpaceSelectionCluster()
{
// create the cluster for switching spaces/reference frames
ViewportUi::ViewportUiRequestBus::EventResult(
m_spaceCluster.m_spaceClusterId, ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateCluster,
ViewportUi::Alignment::TopRight);
// create and register the buttons (strings correspond to icons even if the values appear different)
m_spaceCluster.m_worldButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "World");
m_spaceCluster.m_parentButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Parent");
m_spaceCluster.m_localButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Local");
auto onButtonClicked = [this](ViewportUi::ButtonId buttonId) {
if (buttonId == m_spaceCluster.m_localButtonId)
{
// Unlock
if (m_spaceCluster.m_spaceLock && m_spaceCluster.m_currentSpace == ReferenceFrame::Local)
{
m_spaceCluster.m_spaceLock = false;
}
else
{
m_spaceCluster.m_spaceLock = true;
m_spaceCluster.m_currentSpace = ReferenceFrame::Local;
}
}
else if (buttonId == m_spaceCluster.m_parentButtonId)
{
// Unlock
if (m_spaceCluster.m_spaceLock && m_spaceCluster.m_currentSpace == ReferenceFrame::Parent)
{
m_spaceCluster.m_spaceLock = false;
}
else
{
m_spaceCluster.m_spaceLock = true;
m_spaceCluster.m_currentSpace = ReferenceFrame::Parent;
}
}
else if (buttonId == m_spaceCluster.m_worldButtonId)
{
// Unlock
if (m_spaceCluster.m_spaceLock && m_spaceCluster.m_currentSpace == ReferenceFrame::World)
{
m_spaceCluster.m_spaceLock = false;
}
else
{
m_spaceCluster.m_spaceLock = true;
m_spaceCluster.m_currentSpace = ReferenceFrame::World;
}
}
};
m_spaceCluster.m_spaceSelectionHandler = AZ::Event<ViewportUi::ButtonId>::Handler(onButtonClicked);
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler,
m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_spaceSelectionHandler);
}
EditorTransformComponentSelectionRequests::Mode EditorTransformComponentSelection::GetTransformMode()
{
return m_mode;
@ -2940,7 +3023,7 @@ namespace AzToolsFramework
}
}
void EditorTransformComponentSelection::CopyScaleToSelectedEntitiesIndividualWorld(const AZ::Vector3& scale)
void EditorTransformComponentSelection::CopyScaleToSelectedEntitiesIndividualWorld(float scale)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@ -2955,7 +3038,7 @@ namespace AzToolsFramework
const auto transformsBefore = RecordTransformsBefore(manipulatorEntityIds.m_entityIds);
// update scale relative to initial
const AZ::Transform scaleTransform = AZ::Transform::CreateScale(scale);
const AZ::Transform scaleTransform = AZ::Transform::CreateUniformScale(scale);
for (AZ::EntityId entityId : manipulatorEntityIds.m_entityIds)
{
ScopedUndoBatch::MarkEntityDirty(entityId);
@ -2964,7 +3047,7 @@ namespace AzToolsFramework
if (transformIt != transformsBefore.end())
{
AZ::Transform transformBefore = transformIt->second;
transformBefore.ExtractScale();
transformBefore.ExtractUniformScale();
AZ::Transform newWorldFromLocal = transformBefore * scaleTransform;
SetEntityWorldTransform(entityId, newWorldFromLocal);
@ -2974,7 +3057,7 @@ namespace AzToolsFramework
RefreshUiAfterChange(manipulatorEntityIds.m_entityIds);
}
void EditorTransformComponentSelection::CopyScaleToSelectedEntitiesIndividualLocal(const AZ::Vector3& scale)
void EditorTransformComponentSelection::CopyScaleToSelectedEntitiesIndividualLocal(float scale)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@ -3020,9 +3103,9 @@ namespace AzToolsFramework
if (transformIt != transformsBefore.end())
{
AZ::Transform newWorldFromLocal = transformIt->second;
const AZ::Vector3 scale = newWorldFromLocal.GetScale();
const float scale = newWorldFromLocal.GetUniformScale();
newWorldFromLocal.SetRotation(orientation);
newWorldFromLocal *= AZ::Transform::CreateScale(scale);
newWorldFromLocal *= AZ::Transform::CreateUniformScale(scale);
SetEntityWorldTransform(entityId, newWorldFromLocal);
}
@ -3278,7 +3361,10 @@ namespace AzToolsFramework
ViewportInteraction::BuildMouseButtons(
QGuiApplication::mouseButtons()), m_boxSelect.Active());
const ReferenceFrame referenceFrame = ReferenceFrameFromModifiers(modifiers);
const ReferenceFrame referenceFrame =
m_spaceCluster.m_spaceLock ? m_spaceCluster.m_currentSpace : ReferenceFrameFromModifiers(modifiers);
UpdateSpaceCluster(referenceFrame);
bool refresh = false;
if (referenceFrame != m_referenceFrame)
@ -3669,7 +3755,7 @@ namespace AzToolsFramework
}
void EditorTransformComponentSelection::SetEntityLocalScale(
const AZ::EntityId entityId, const AZ::Vector3& localScale)
const AZ::EntityId entityId, const float localScale)
{
ETCS::SetEntityLocalScale(entityId, localScale, m_transformChangedInternally);
}
@ -3722,11 +3808,11 @@ namespace AzToolsFramework
entityId, &AZ::TransformBus::Events::SetWorldTM, worldTransform);
}
void SetEntityLocalScale(AZ::EntityId entityId, const AZ::Vector3& localScale, bool& internal)
void SetEntityLocalScale(AZ::EntityId entityId, float localScale, bool& internal)
{
ScopeSwitch sw(internal);
AZ::TransformBus::Event(
entityId, &AZ::TransformBus::Events::SetLocalScale, localScale);
entityId, &AZ::TransformBus::Events::SetLocalUniformScale, localScale);
}
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation, bool& internal)

@ -106,6 +106,17 @@ namespace AzToolsFramework
World, //!< World space (space aligned to world axes - identity).
};
struct SpaceCluster
{
ViewportUi::ClusterId m_spaceClusterId;
ViewportUi::ButtonId m_localButtonId;
ViewportUi::ButtonId m_parentButtonId;
ViewportUi::ButtonId m_worldButtonId;
AZ::Event<ViewportUi::ButtonId>::Handler m_spaceSelectionHandler;
ReferenceFrame m_currentSpace = ReferenceFrame::Parent;
bool m_spaceLock = false;
};
//! Entity selection/interaction handling.
//! Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
class EditorTransformComponentSelection
@ -160,6 +171,7 @@ namespace AzToolsFramework
void RegenerateManipulators();
void CreateTransformModeSelectionCluster();
void CreateSpaceSelectionCluster();
void ClearManipulatorTranslationOverride();
void ClearManipulatorOrientationOverride();
@ -214,8 +226,8 @@ namespace AzToolsFramework
void CopyOrientationToSelectedEntitiesIndividual(const AZ::Quaternion& orientation);
void CopyOrientationToSelectedEntitiesGroup(const AZ::Quaternion& orientation);
void ResetOrientationForSelectedEntitiesLocal();
void CopyScaleToSelectedEntitiesIndividualLocal(const AZ::Vector3& scale);
void CopyScaleToSelectedEntitiesIndividualWorld(const AZ::Vector3& scale);
void CopyScaleToSelectedEntitiesIndividualLocal(float scale);
void CopyScaleToSelectedEntitiesIndividualWorld(float scale);
// EditorManipulatorCommandUndoRedoRequestBus ...
void UndoRedoEntityManipulatorCommand(
@ -250,7 +262,7 @@ namespace AzToolsFramework
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation);
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation);
void SetEntityWorldTransform(AZ::EntityId entityId, const AZ::Transform& worldTransform);
void SetEntityLocalScale(AZ::EntityId entityId, const AZ::Vector3& localScale);
void SetEntityLocalScale(AZ::EntityId entityId, float localScale);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation);
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
@ -285,6 +297,9 @@ namespace AzToolsFramework
AZ::Event<ViewportUi::ButtonId>::Handler m_transformModeSelectionHandler; //!< Event handler for the Viewport UI cluster.
AzFramework::ClickDetector m_clickDetector; //!< Detect different types of mouse click.
AzFramework::CursorState m_cursorState; //!< Track the mouse position and delta movement each frame.
SpaceCluster m_spaceCluster;
void UpdateSpaceCluster(ReferenceFrame referenceFrame);
};
//! The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
@ -320,7 +335,7 @@ namespace AzToolsFramework
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation, bool& internal);
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation, bool& internal);
void SetEntityWorldTransform(AZ::EntityId entityId, const AZ::Transform& worldTransform, bool& internal);
void SetEntityLocalScale(AZ::EntityId entityId, const AZ::Vector3& localScale, bool& internal);
void SetEntityLocalScale(AZ::EntityId entityId, float localScale, bool& internal);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation, bool& internal);
} // namespace ETCS
} // namespace AzToolsFramework

@ -101,10 +101,10 @@ namespace AzToolsFramework
virtual void ResetOrientationForSelectedEntitiesLocal() = 0;
/// Copy scale to each individual entity in local space without moving position.
virtual void CopyScaleToSelectedEntitiesIndividualLocal(const AZ::Vector3& scale) = 0;
virtual void CopyScaleToSelectedEntitiesIndividualLocal(float scale) = 0;
/// Copy scale to to each individual entity in world (absolute) space.
virtual void CopyScaleToSelectedEntitiesIndividualWorld(const AZ::Vector3& scale) = 0;
virtual void CopyScaleToSelectedEntitiesIndividualWorld(float scale) = 0;
protected:
~EditorTransformComponentSelectionRequests() = default;

@ -15,6 +15,7 @@
#include <AzToolsFramework/Asset/AssetSeedManager.h>
#include <AzFramework/Asset/AssetRegistry.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/Asset/AssetCatalog.h>
#include <AzFramework/StringFunc/StringFunc.h>
@ -62,6 +63,12 @@ namespace UnitTest
m_assetSeedManager = new AzToolsFramework::AssetSeedManager();
m_assetRegistry = new AzFramework::AssetRegistry();
AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get();
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
registry->Set(projectPathKey, "AutomatedTesting");
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
m_application->Start(AzFramework::Application::Descriptor());
for (int idx = 0; idx < s_totalAssets; idx++)

@ -10,6 +10,8 @@
*
*/
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalogManager.h>
#include <AzFramework/Asset/AssetRegistry.h>
@ -49,6 +51,14 @@ namespace UnitTest
using namespace AZ::Data;
m_application = new ToolsTestApplication("AddressedAssetCatalogManager"); // Shorter name because Setting Registry
// specialization are 32 characters max.
AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get();
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
registry->Set(projectPathKey, "AutomatedTesting");
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
m_application->Start(AzFramework::Application::Descriptor());
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash

@ -483,6 +483,9 @@ namespace UnitTest
{
AUTO_RESULT_IF_SETTING_TRUE(UnitTest::prefabSystemSetting, true)
// Swallow deprecation warnings from the Transform component as they are not relevant to this test
UnitTest::ErrorHandler errorHandler("GetScale is deprecated");
// Create a parent entity with a transform component
AZ::Entity* parentEntity = aznew AZ::Entity("TestParentEntity");
parentEntity->CreateComponent<AzToolsFramework::Components::TransformComponent>();

@ -610,15 +610,15 @@ namespace AzToolsFramework
m_layerEntity.m_layer->ClearUnsavedChanges();
// Change the scale of the child entity so it registers as an unsaved change on the layer.
AZ::Vector3 scale(-1.0f,0.0f,0.0f);
float scale = 0.0f;
AZ::TransformBus::EventResult(
scale,
childEntity->GetId(),
&AZ::TransformBus::Events::GetLocalScale);
scale.SetX(scale.GetX() + 1.0f);
&AZ::TransformBus::Events::GetLocalUniformScale);
scale += 1.0f;
AZ::TransformBus::Event(
childEntity->GetId(),
&AZ::TransformBus::Events::SetLocalScale,
&AZ::TransformBus::Events::SetLocalUniformScale,
scale);
bool hasUnsavedChanges = false;

@ -52,19 +52,19 @@ namespace AzToolsFramework
TransformTestEntityHierarchy hierarchy = BuildTestHierarchy();
// Set scale to parent entity
const AZ::Vector3 parentScale(2.0f, 1.0f, 3.0f);
AZ::TransformBus::Event(hierarchy.m_parentId, &AZ::TransformInterface::SetLocalScale, parentScale);
const float parentScale = 2.0f;
AZ::TransformBus::Event(hierarchy.m_parentId, &AZ::TransformInterface::SetLocalUniformScale, parentScale);
// Set scale to child entity
const AZ::Vector3 childScale(5.0f, 6.0f, 10.0f);
AZ::TransformBus::Event(hierarchy.m_childId, &AZ::TransformInterface::SetLocalScale, childScale);
const float childScale = 5.0f;
AZ::TransformBus::Event(hierarchy.m_childId, &AZ::TransformInterface::SetLocalUniformScale, childScale);
const AZ::Vector3 expectedScale = childScale * parentScale;
const float expectedScale = childScale * parentScale;
AZ::Vector3 childWorldScale = AZ::Vector3::CreateOne();
AZ::TransformBus::EventResult(childWorldScale, hierarchy.m_childId, &AZ::TransformBus::Events::GetWorldScale);
float childWorldScale = 1.0f;
AZ::TransformBus::EventResult(childWorldScale, hierarchy.m_childId, &AZ::TransformBus::Events::GetWorldUniformScale);
EXPECT_THAT(childWorldScale, UnitTest::IsClose(expectedScale));
EXPECT_NEAR(childWorldScale, expectedScale, AZ::Constants::Tolerance);
}
TEST_F(EditorTransformComponentTest, TransformTests_GetChildren_DirectChildrenMatchHierarchy)

@ -488,18 +488,17 @@ void TransformCompressor::Marshal(WriteBuffer& wb, const AZ::Transform& value) c
{
AZ::u8 flags = 0;
auto flagsMarker = wb.InsertMarker(flags);
AZ::Matrix3x3 m33 = AZ::Matrix3x3::CreateFromTransform(value);
AZ::Vector3 scale = m33.ExtractScale();
AZ::Quaternion rot = AZ::Quaternion::CreateFromMatrix3x3(m33.GetOrthogonalized());
float scale = value.GetUniformScale();
AZ::Quaternion rot = value.GetRotation();
if (!rot.IsIdentity())
{
flags |= HAS_ROT;
wb.Write(rot, QuatCompMarshaler());
}
if (!scale.IsClose(AZ::Vector3::CreateOne()))
if (!AZ::IsClose(scale, 1.0f, AZ::Constants::Tolerance))
{
flags |= HAS_SCALE;
wb.Write(scale, Vec3CompMarshaler());
wb.Write(scale, HalfMarshaler());
}
AZ::Vector3 pos = value.GetTranslation();
if (!pos.IsZero())
@ -527,9 +526,9 @@ void TransformCompressor::Unmarshal(AZ::Transform& value, ReadBuffer& rb) const
}
if (flags & HAS_SCALE)
{
AZ::Vector3 scale;
rb.Read(scale, Vec3CompMarshaler());
xform.MultiplyByScale(scale);
float scale;
rb.Read(scale, HalfMarshaler());
xform.MultiplyByUniformScale(scale);
}
if (flags & HAS_POS)
{

@ -11,6 +11,7 @@
*/
#include <AzTest/AzTest.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
@ -40,6 +41,13 @@ namespace UnitTest
void SetUp() override
{
AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get();
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
registry->Set(projectPathKey, "AutomatedTesting");
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
m_application->Start({});
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash

@ -16,6 +16,7 @@
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/IO/SystemFile.h> // for max path decl
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/parallel/semaphore.h>
#include <AzCore/std/functional.h> // for function<> in the find files callback.
@ -42,6 +43,14 @@ namespace UnitTest
{
AZ::ComponentApplication::Descriptor descriptor;
descriptor.m_stackRecordLevels = 30;
AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get();
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
registry->Set(projectPathKey, "AutomatedTesting");
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
m_application->Start(descriptor);
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash

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

Loading…
Cancel
Save