diff --git a/AutomatedTesting/EngineFinder.cmake b/AutomatedTesting/EngineFinder.cmake
index fbbe3d8cfe..eef3aa3cae 100644
--- a/AutomatedTesting/EngineFinder.cmake
+++ b/AutomatedTesting/EngineFinder.cmake
@@ -15,6 +15,8 @@ include_guard()
# Read the engine name from the project_json file
file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json)
+set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json)
+
string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine)
if(json_error)
message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}")
@@ -30,6 +32,7 @@ endif()
# Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path.
if(EXISTS ${manifest_path})
file(READ ${manifest_path} manifest_json)
+ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${manifest_path})
string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path)
if(json_error)
diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py b/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py
index 86bfc48636..aae01e4652 100755
--- a/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py
+++ b/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py
@@ -24,12 +24,11 @@ from base import TestAutomationBase
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(TestAutomationBase):
- @pytest.mark.xfail(reason="Running with atom null renderer is causing this test to fail")
+
def test_C18977329_NvCloth_AddClothSimulationToMesh(self, request, workspace, editor, launcher_platform):
from . import C18977329_NvCloth_AddClothSimulationToMesh as test_module
self._run_test(request, workspace, editor, test_module)
- @pytest.mark.xfail(reason="Running with atom null renderer is causing this test to fail")
def test_C18977330_NvCloth_AddClothSimulationToActor(self, request, workspace, editor, launcher_platform):
from . import C18977330_NvCloth_AddClothSimulationToActor as test_module
self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt
index f453a38486..f47d57b7bd 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt
@@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
## AP Python Tests ##
- ly_add_pytest(
- NAME AssetPipelineTests.AuxiliaryContent
- PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py
- EXCLUDE_TEST_RUN_TARGET_FROM_IDE
- TEST_SUITE periodic
- )
-
ly_add_pytest(
NAME AssetPipelineTests.BankInfoParser
PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py
deleted file mode 100755
index 452dc66352..0000000000
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py
+++ /dev/null
@@ -1,96 +0,0 @@
-"""
-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 pytest
-import ly_test_tools
-
-import os
-import sys
-import shutil
-import subprocess
-import glob
-from ly_test_tools.builtin.helpers import *
-from ly_test_tools.environment.process_utils import *
-from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
-
-logger = logging.getLogger(__name__)
-
-project_list = ['AutomatedTesting']
-
-@pytest.mark.system
-@pytest.mark.SUITE_periodic
-class TestAuxiliaryContent:
- @pytest.fixture(autouse=True)
- def setup_teardown(self, request, workspace, project):
- path_to_dev = workspace.paths.engine_root()
- os.chdir(path_to_dev)
- auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks"
- self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName)
-
- def teardown():
- if (os.path.exists(self.auxiliaryContentPath)):
- shutil.rmtree(self.auxiliaryContentPath)
-
- request.addfinalizer(teardown)
-
- @staticmethod
- def scanForLevelPak(path_toscan):
- files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True)
- return len(files)
-
- @pytest.mark.parametrize('level', ['alldependencies'])
- @pytest.mark.parametrize('project', project_list)
- def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level):
- """
- This test ensure that Auxiliary Content contain level.pak files
-
- Test Steps:
- 1. Run auxiliary content against project under test
- 2. Validate auxiliary content exists
- 3. Verifies that level.pak exists
- """
-
- path_to_dev = workspace.paths.engine_root()
- bin_path = workspace.paths.build_directory()
-
- auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
- subprocess.check_call(['python', auxiliaryContentScriptPath,
- "--buildFolder={0}".format(bin_path),
- "--platforms=pc",
- f"--project-path={workspace.project}"])
-
- assert os.path.exists(self.auxiliaryContentPath)
- assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0
-
- @pytest.mark.parametrize('level', ['alldependencies'])
- @pytest.mark.parametrize('project', project_list)
- def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level):
- """
- This test ensure that Auxiliary Content contain no level.pak file
-
- Test Steps:
- 1. Run auxiliary content against project under test with skiplevelPaks flag
- 2. Validate auxiliary content exists
- 3. Validate level.pak was added to auxiliary content
- """
-
- path_to_dev = workspace.paths.engine_root()
- bin_path = workspace.paths.build_directory()
-
- auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
- subprocess.check_call(['python', auxiliaryContentScriptPath,
- "--buildFolder={0}".format(bin_path),
- "--platforms=pc",
- "--skiplevelPaks",
- f"--project-path={workspace.project}"])
- assert os.path.exists(self.auxiliaryContentPath)
-
- assert self.scanForLevelPak(self.auxiliaryContentPath) == 0
diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py
index 57cdc8f9c5..40291b2114 100755
--- a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py
+++ b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py
@@ -102,7 +102,7 @@ def C4044695_PhysXCollider_AddMultipleSurfaceFbx():
# 6) Check if multiple material slots show up under Materials section in the PhysX Collider component
pte = collider_component.get_property_tree()
def get_surface_count():
- count = pte.get_container_count("Collider Configuration|Physics Material|Mesh Surfaces")
+ count = pte.get_container_count("Collider Configuration|Physics Materials|Slots")
return count.GetValue()
Report.result(
diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py
index 2b82c3e596..291bb96627 100755
--- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py
+++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py
@@ -93,11 +93,13 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C4044457_Material_RestitutionCombine.setreg_override', 'AutomatedTesting/Registry')
def test_C4044457_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform):
from . import C4044457_Material_RestitutionCombine as test_module
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C4044456_Material_FrictionCombine.setreg_override', 'AutomatedTesting/Registry')
def test_C4044456_Material_FrictionCombine(self, request, workspace, editor, launcher_platform):
from . import C4044456_Material_FrictionCombine as test_module
self._run_test(request, workspace, editor, test_module)
@@ -194,6 +196,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C18981526_Material_RestitutionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
def test_C18981526_Material_RestitutionCombinePriority(self, request, workspace, editor, launcher_platform):
from . import C18981526_Material_RestitutionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@@ -229,6 +232,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C18977601_Material_FrictionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
def test_C18977601_Material_FrictionCombinePriority(self, request, workspace, editor, launcher_platform):
from . import C18977601_Material_FrictionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@@ -250,6 +254,7 @@ class TestAutomation(TestAutomationBase):
@pytest.mark.xfail(
reason="This test needs new physics asset with multiple materials to be more stable.")
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C4044697_Material_PerfaceMaterialValidation.setreg_override', 'AutomatedTesting/Registry')
def test_C4044697_Material_PerfaceMaterialValidation(self, request, workspace, editor, launcher_platform):
from . import C4044697_Material_PerfaceMaterialValidation as test_module
self._run_test(request, workspace, editor, test_module)
@@ -282,6 +287,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override', 'AutomatedTesting/Registry')
def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform):
from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module
self._run_test(request, workspace, editor, test_module)
@@ -326,6 +332,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C4044461_Material_Restitution.setreg_override', 'AutomatedTesting/Registry')
def test_C4044461_Material_Restitution(self, request, workspace, editor, launcher_platform):
from . import C4044461_Material_Restitution as test_module
self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly
index 1afbf787db..9a1b1fe59a 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly
+++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e15d484113e8151072b410924747a8ad304f6f12457fad577308c0491693ab34
-size 5472
+oid sha256:6517300fb1ce70c4696286e14715c547cfd175eabbb2042f7f2a456b15054224
+size 5253
diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml
index 9775a35c53..2cf4d55bf0 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml
+++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak
index 08a775b6c8..954bb1912f 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak
+++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:64de37c805b0be77cdb7a85b5406af58b7f845e7d97fec1721ac5d789bb641db
-size 38856
+oid sha256:ce32a7cdf3ed37751385b3bb18f05206702978363f325d06727b5eb20d40b7eb
+size 38563
diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly
index 385027c479..9ef8bc0525 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly
+++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7b595323d4d51211463dea0338abb6ce2a4a0a8d41efb12ac3c9dccd1f972171
-size 5504
+oid sha256:89dbcec013cb819e52ec0f8fed0a9e417fd32eac8aeb67d3958266bb6089ec21
+size 5505
diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml
index 7ccc1d51eb..a7de99a91c 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml
+++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak
index 12ce03fa87..ad10c72b31 100644
--- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak
+++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:617c455668fc41cb7fd69de690e4aa3c80f2cb36deaa371902b79de18fcd1cb2
-size 39233
+oid sha256:622c2624b04e07b704520f32c458b50d5a50de1ef116b7bc9c3c0ccb6f4a4ecc
+size 3606
diff --git a/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly b/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly
index a649728997..87166a9d8d 100644
--- a/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly
+++ b/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b6e408095c15a388768b7f70b6049f33c894aab3e51f2d744bc1ae1d18668ee4
-size 9694
+oid sha256:824a51a375f19274d5698ff08af0fdc3dc18204505c73a943de748455d108b01
+size 6181
diff --git a/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override b/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override
new file mode 100644
index 0000000000..a329434623
--- /dev/null
+++ b/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{70D4A444-AFD4-57C4-9885-63F25AC3C281}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c15556261_physxmaterials_charactercontrollermaterialassignment/library.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override b/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override
new file mode 100644
index 0000000000..44a91c67cb
--- /dev/null
+++ b/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{B8749DAB-15DA-5A61-B565-C853673604CD}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c18977601_material_frictioncombinepriority/friction_combine.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override b/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override
new file mode 100644
index 0000000000..8de10787f1
--- /dev/null
+++ b/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{AED48B18-0F3F-5E59-A8FF-30DB134B307B}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c18981526_material_restitutioncombinepriority/restitution_combine.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override b/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override
new file mode 100644
index 0000000000..83f7079e1f
--- /dev/null
+++ b/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{8D2C4A29-E0FC-564F-82C9-24BBA30C5A90}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c4044456_material_frictioncombine/friction_combine.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override b/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override
new file mode 100644
index 0000000000..96836b6ae4
--- /dev/null
+++ b/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{D5D6A6DE-E636-5638-B30D-6CE2FDC321F8}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c4044457_material_restitutioncombine/restitution_combine.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override b/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override
new file mode 100644
index 0000000000..21b285506b
--- /dev/null
+++ b/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{E4117B5B-8D9A-5C1D-BA1E-C36542A6588D}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c4044461_material_restitution/restitution.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override b/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override
new file mode 100644
index 0000000000..d585a4c468
--- /dev/null
+++ b/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override
@@ -0,0 +1,115 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{2E85B457-ED19-5FE3-90B4-6EFFB4D0E682}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c4044697_material_perfacematerialvalidation/test_library.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas b/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas
index b24a477a2e..9b1357eebe 100644
--- a/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas
+++ b/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas
@@ -3,34 +3,34 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -39,77 +39,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -127,7 +73,7 @@
-
+
@@ -142,7 +88,7 @@
-
+
@@ -170,7 +116,7 @@
-
+
@@ -208,7 +154,7 @@
-
+
@@ -253,46 +199,58 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -307,7 +265,7 @@
-
+
@@ -335,7 +293,7 @@
-
+
@@ -350,7 +308,93 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -378,7 +422,7 @@
-
+
@@ -416,7 +460,7 @@
-
+
@@ -455,42 +499,64 @@
-
+
-
-
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
@@ -498,21 +564,21 @@
-
+
-
+
-
+
-
+
@@ -521,23 +587,18 @@
-
-
-
-
-
-
+
-
+
-
+
@@ -555,7 +616,7 @@
-
+
@@ -570,7 +631,7 @@
-
+
@@ -598,7 +659,7 @@
-
+
@@ -636,7 +697,215 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -713,21 +982,12 @@
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -1321,7 +1581,7 @@
-
+
@@ -1386,285 +1646,36 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
@@ -1692,7 +1703,7 @@
-
+
@@ -1707,7 +1718,7 @@
-
+
@@ -1735,7 +1746,7 @@
-
+
@@ -1744,13 +1755,8 @@
-
-
-
-
-
-
+
@@ -1761,13 +1767,13 @@
-
+
-
+
@@ -1778,7 +1784,7 @@
-
+
@@ -1787,89 +1793,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -1898,86 +1823,64 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -1986,14 +1889,9 @@
-
-
-
-
-
-
-
+
+
@@ -2002,211 +1900,304 @@
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2216,28 +2207,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2247,28 +2238,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2278,28 +2269,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2309,28 +2300,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2340,28 +2331,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2371,28 +2362,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2402,28 +2393,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2433,28 +2424,28 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2470,7 +2461,7 @@
-
+
@@ -2478,20 +2469,22 @@
-
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
@@ -2502,17 +2495,15 @@
-
-
-
-
+
+
+
-
-
-
-
+
+
+
@@ -2520,7 +2511,7 @@
-
+
@@ -2528,27 +2519,21 @@
-
+
-
+
-
-
-
-
-
-
-
+
@@ -2557,25 +2542,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -2583,7 +2553,7 @@
-
+
@@ -2591,27 +2561,21 @@
-
+
-
+
-
-
-
-
-
-
-
+
@@ -2620,12 +2584,18 @@
+
+
+
+
+
+
-
+
@@ -2633,27 +2603,21 @@
-
+
-
+
-
-
-
-
-
-
-
+
@@ -2662,46 +2626,52 @@
+
+
+
+
+
+
-
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
@@ -2709,7 +2679,7 @@
-
+
@@ -2717,7 +2687,7 @@
-
+
@@ -2734,24 +2704,24 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
+
@@ -2759,7 +2729,7 @@
-
+
@@ -2776,16 +2746,37 @@
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
@@ -2793,41 +2784,41 @@
-
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
@@ -2838,20 +2829,20 @@
-
-
+
+
-
+
-
+
-
-
+
+
@@ -2868,7 +2859,7 @@
-
+
diff --git a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp
index 3f7a3c3a5d..0d45a3fb6c 100644
--- a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp
@@ -36,6 +36,12 @@ namespace AZ
Color* color = reinterpret_cast(outputValue);
AZ_Assert(color, "Output value for JsonColorSerializer can't be null.");
+ if (IsExplicitDefault(inputValue))
+ {
+ *color = Color::CreateZero();
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Color value set to default of zero.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -43,10 +49,14 @@ namespace AZ
case rapidjson::kObjectType:
return LoadObject(*color, inputValue, context);
- case rapidjson::kStringType: // fall through
- case rapidjson::kNumberType: // fall through
- case rapidjson::kNullType: // fall through
- case rapidjson::kFalseType: // fall through
+ case rapidjson::kStringType:
+ [[fallthrough]];
+ case rapidjson::kNumberType:
+ [[fallthrough]];
+ case rapidjson::kNullType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
case rapidjson::kTrueType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Colors can only be read from arrays or objects.");
@@ -91,6 +101,11 @@ namespace AZ
}
}
+ auto JsonColorSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
JsonSerializationResult::Result JsonColorSerializer::LoadObject(Color& output, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
diff --git a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h
index b7b948a25a..cd16506b28 100644
--- a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h
@@ -28,6 +28,8 @@ namespace AZ
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
+
private:
enum class LoadAlpha
{
diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp
index 0b7e3300cf..7f412f68e6 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp
@@ -263,7 +263,7 @@ namespace AZ::JsonMathMatrixSerializerInternal
template
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId,
- const rapidjson::Value& inputValue, JsonDeserializerContext& context)
+ const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
@@ -279,6 +279,12 @@ namespace AZ::JsonMathMatrixSerializerInternal
MatrixType* matrix = reinterpret_cast(outputValue);
AZ_Assert(matrix, "Output value for JsonMatrix%zux%zuSerializer can't be null.", RowCount, ColumnCount);
+ if (isExplicitDefault)
+ {
+ *matrix = MatrixType::CreateIdentity();
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Matrix value set to identity matrix.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -381,6 +387,16 @@ namespace AZ::JsonMathMatrixSerializerInternal
namespace AZ
{
+ // BaseJsonMatrixSerializer
+
+ AZ_CLASS_ALLOCATOR_IMPL(BaseJsonMatrixSerializer, SystemAllocator, 0);
+
+ auto BaseJsonMatrixSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
+
// Matrix3x3
AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix3x3Serializer, SystemAllocator, 0);
@@ -389,10 +405,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load(
- outputValue,
- outputValueTypeId,
- inputValue,
- context);
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix3x3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -401,11 +414,7 @@ namespace AZ
outputValue.SetObject();
return JsonMathMatrixSerializerInternal::StoreRotationAndScale(
- outputValue,
- inputValue,
- defaultValue,
- valueTypeId,
- context);
+ outputValue, inputValue, defaultValue, valueTypeId, context);
}
@@ -417,10 +426,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load(
- outputValue,
- outputValueTypeId,
- inputValue,
- context);
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix3x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -428,19 +434,11 @@ namespace AZ
{
outputValue.SetObject();
- auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale(
- outputValue,
- inputValue,
- defaultValue,
- valueTypeId,
- context);
+ auto result =
+ JsonMathMatrixSerializerInternal::StoreRotationAndScale(outputValue, inputValue, defaultValue, valueTypeId, context);
- auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation(
- outputValue,
- inputValue,
- defaultValue,
- valueTypeId,
- context);
+ auto resultTranslation =
+ JsonMathMatrixSerializerInternal::StoreTranslation(outputValue, inputValue, defaultValue, valueTypeId, context);
result.GetResultCode().Combine(resultTranslation);
return result;
@@ -454,10 +452,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
return JsonMathMatrixSerializerInternal::Load(
- outputValue,
- outputValueTypeId,
- inputValue,
- context);
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonMatrix4x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -465,19 +460,11 @@ namespace AZ
{
outputValue.SetObject();
- auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale(
- outputValue,
- inputValue,
- defaultValue,
- valueTypeId,
- context);
-
- auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation(
- outputValue,
- inputValue,
- defaultValue,
- valueTypeId,
- context);
+ auto result =
+ JsonMathMatrixSerializerInternal::StoreRotationAndScale(outputValue, inputValue, defaultValue, valueTypeId, context);
+
+ auto resultTranslation =
+ JsonMathMatrixSerializerInternal::StoreTranslation(outputValue, inputValue, defaultValue, valueTypeId, context);
result.GetResultCode().Combine(resultTranslation);
return result;
diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h
index 81c9635a79..773859a2c8 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h
@@ -16,11 +16,18 @@
namespace AZ
{
- class JsonMatrix3x3Serializer
- : public BaseJsonSerializer
+ class BaseJsonMatrixSerializer : public BaseJsonSerializer
{
public:
- AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonSerializer);
+ AZ_RTTI(BaseJsonMatrixSerializer, "{18CA4637-C9B7-454B-9126-107E18A8C096}", BaseJsonSerializer);
+ AZ_CLASS_ALLOCATOR_DECL;
+ OperationFlags GetOperationsFlags() const override;
+ };
+
+ class JsonMatrix3x3Serializer : public BaseJsonMatrixSerializer
+ {
+ public:
+ AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -28,11 +35,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonMatrix3x4Serializer
- : public BaseJsonSerializer
+ class JsonMatrix3x4Serializer : public BaseJsonMatrixSerializer
{
public:
- AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonSerializer);
+ AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -40,11 +46,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonMatrix4x4Serializer
- : public BaseJsonSerializer
+ class JsonMatrix4x4Serializer : public BaseJsonMatrixSerializer
{
public:
- AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonSerializer);
+ AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonMatrixSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
index aa9686f709..7225f1713c 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
@@ -124,7 +124,7 @@ namespace AZ
template
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
- JsonDeserializerContext& context)
+ JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
@@ -138,6 +138,12 @@ namespace AZ
VectorType* vector = reinterpret_cast(outputValue);
AZ_Assert(vector, "Output value for JsonVector%iSerializer can't be null.", ElementCount);
+ if (isExplicitDefault)
+ {
+ *vector = VectorType::CreateZero();
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Math vector value set to default of zero.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
@@ -145,10 +151,14 @@ namespace AZ
case rapidjson::kObjectType:
return LoadObject(*vector, inputValue, context);
- case rapidjson::kStringType: // fall through
- case rapidjson::kNumberType: // fall through
- case rapidjson::kNullType: // fall through
- case rapidjson::kFalseType: // fall through
+ case rapidjson::kStringType:
+ [[fallthrough]];
+ case rapidjson::kNumberType:
+ [[fallthrough]];
+ case rapidjson::kNullType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
case rapidjson::kTrueType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Math vectors can only be read from arrays or objects.");
@@ -189,6 +199,16 @@ namespace AZ
}
}
+
+ // BaseJsonVectorSerializer
+
+ AZ_CLASS_ALLOCATOR_IMPL(BaseJsonVectorSerializer, SystemAllocator, 0);
+
+ auto BaseJsonVectorSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
// Vector2
@@ -197,7 +217,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector2Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
- return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context);
+ return JsonMathVectorSerializerInternal::Load(
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector2Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -214,7 +235,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector3Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
- return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context);
+ return JsonMathVectorSerializerInternal::Load(
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -231,7 +253,8 @@ namespace AZ
JsonSerializationResult::Result JsonVector4Serializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
- return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context);
+ return JsonMathVectorSerializerInternal::Load(
+ outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonVector4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -252,7 +275,7 @@ namespace AZ
// check for "yaw, pitch, roll" object
if (inputValue.IsObject())
{
- if (inputValue.GetObject().ObjectEmpty())
+ if (IsExplicitDefault(inputValue))
{
Quaternion* outQuaternion = reinterpret_cast(outputValue);
*outQuaternion = Quaternion::CreateIdentity();
@@ -283,7 +306,7 @@ namespace AZ
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read quaternion.");
}
- return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context);
+ return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context, false);
}
JsonSerializationResult::Result JsonQuaternionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
index 9c2606b932..0f81709c17 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
@@ -16,11 +16,18 @@
namespace AZ
{
- class JsonVector2Serializer
- : public BaseJsonSerializer
+ class BaseJsonVectorSerializer : public BaseJsonSerializer
{
public:
- AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonSerializer);
+ AZ_RTTI(BaseJsonVectorSerializer, "{C188D355-E6DF-4590-8B31-F40591F48A8E}", BaseJsonSerializer);
+ AZ_CLASS_ALLOCATOR_DECL;
+ OperationFlags GetOperationsFlags() const override;
+ };
+
+ class JsonVector2Serializer : public BaseJsonVectorSerializer
+ {
+ public:
+ AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -28,11 +35,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonVector3Serializer
- : public BaseJsonSerializer
+ class JsonVector3Serializer : public BaseJsonVectorSerializer
{
public:
- AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonSerializer);
+ AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -40,11 +46,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonVector4Serializer
- : public BaseJsonSerializer
+ class JsonVector4Serializer : public BaseJsonVectorSerializer
{
public:
- AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonSerializer);
+ AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -52,11 +57,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonQuaternionSerializer
- : public BaseJsonSerializer
+ class JsonQuaternionSerializer : public BaseJsonVectorSerializer
{
public:
- AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonSerializer);
+ AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonVectorSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
index 36c40265af..b3c9ea3b7c 100644
--- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
@@ -33,6 +33,12 @@ namespace AZ
AZ::Transform* transformInstance = reinterpret_cast(outputValue);
AZ_Assert(transformInstance, "Output value for JsonTransformSerializer can't be null.");
+ if (IsExplicitDefault(inputValue))
+ {
+ *transformInstance = AZ::Transform::CreateIdentity();
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Transform value set to identity.");
+ }
+
JSR::ResultCode result(JSR::Tasks::ReadField);
{
@@ -72,7 +78,7 @@ namespace AZ
return context.Report(
result,
- result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Transform information."
+ result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded Transform information."
: "Failed to load Transform information.");
}
@@ -140,4 +146,9 @@ namespace AZ
: "Failed to store Transform information.");
}
+ auto JsonTransformSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h
index e03c41e31d..ef277f831a 100644
--- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h
@@ -30,6 +30,8 @@ namespace AZ
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
+
private:
// Note: These need to be defined as "const char[]" instead of "const char*" so that they can be implicitly converted
// to a rapidjson::GenericStringRef<>. (This also lets rapidjson get the string length at compile time)
diff --git a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp
index 9da7b11805..458744d5b2 100644
--- a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp
@@ -33,6 +33,11 @@ namespace AZ
AZStd::regex_constants::icase | AZStd::regex_constants::optimize);
}
+ auto JsonUuidSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
JsonSerializationResult::Result JsonUuidSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
@@ -53,13 +58,24 @@ namespace AZ
Uuid* valAsUuid = reinterpret_cast(outputValue);
+ if (IsExplicitDefault(inputValue))
+ {
+ *valAsUuid = AZ::Uuid::CreateNull();
+ return MessageResult("Uuid value set to default of null.", JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed));
+ }
+
switch (inputValue.GetType())
{
- case rapidjson::kArrayType: // fallthrough
- case rapidjson::kObjectType:// fallthrough
- case rapidjson::kFalseType: // fallthrough
- case rapidjson::kTrueType: // fallthrough
- case rapidjson::kNumberType:// fallthrough
+ case rapidjson::kArrayType:
+ [[fallthrough]];
+ case rapidjson::kObjectType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
+ case rapidjson::kTrueType:
+ [[fallthrough]];
+ case rapidjson::kNumberType:
+ [[fallthrough]];
case rapidjson::kNullType:
return MessageResult("Unsupported type. Uuids can only be read from strings.",
JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported));
diff --git a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h
index 1c350a2fcd..43487dcc10 100644
--- a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h
@@ -41,6 +41,8 @@ namespace AZ
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
+
//! Does the same as load, but doesn't report through the provided callback in the settings. Instead the final
//! ResultCode and message are returned and it's up to the caller to report if need needed.
MessageResult UnreportedLoad(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue);
diff --git a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl
index 9bda5cdcce..ebe7d27a8e 100644
--- a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl
+++ b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl
@@ -406,6 +406,7 @@ namespace AZ
AZStd::vector eventParamsTypes{ AZStd::initializer_list{
CreateBehaviorEventParameter>()... } };
behaviorContext->Class>()
+ ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::Script::Attributes::EventHandlerCreationFunction, createHandlerHolder)
->Attribute(AZ::Script::Attributes::EventParameterTypes, eventParamsTypes)
->Method("HasHandlerConnected", &AZ::Event::HasHandlerConnected)
@@ -413,6 +414,7 @@ namespace AZ
behaviorContext->Class>()
->Method("Disconnect", &AZ::EventHandler::Disconnect)
+ ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
;
}
}
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp
index d5a1730364..2e53eb5697 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp
@@ -32,13 +32,24 @@ namespace AZ
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
- return LoadContainer(outputValue, outputValueTypeId, inputValue, context);
+ return LoadContainer(outputValue, outputValueTypeId, inputValue, false, context);
- case rapidjson::kObjectType: // fall through
- case rapidjson::kNullType: // fall through
- case rapidjson::kStringType: // fall through
- case rapidjson::kFalseType: // fall through
- case rapidjson::kTrueType: // fall through
+ case rapidjson::kObjectType:
+ if (IsExplicitDefault(inputValue))
+ {
+ // Because this serializer has only the operation flag "InitializeNewInstance" set, the only time this will be called with
+ // an explicit default is when a new instance has been created.
+ return LoadContainer(outputValue, outputValueTypeId, inputValue, true, context);
+ }
+ [[fallthrough]];
+ case rapidjson::kNullType:
+ [[fallthrough]];
+ case rapidjson::kStringType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
+ case rapidjson::kTrueType:
+ [[fallthrough]];
case rapidjson::kNumberType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. AZStd::array entries can only be read from an array.");
@@ -129,7 +140,16 @@ namespace AZ
}
}
- JsonSerializationResult::Result JsonArraySerializer::LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
+ auto JsonArraySerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
+ JsonSerializationResult::Result JsonArraySerializer::LoadContainer(
+ void* outputValue,
+ const Uuid& outputValueTypeId,
+ const rapidjson::Value& inputValue,
+ bool isNewInstance,
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult; // Used to remove name conflicts in AzCore in uber builds.
@@ -154,14 +174,7 @@ namespace AZ
"Unable to retrieve the correct container information for AZStd::array instance.");
}
- const size_t size = container->Size(outputValue);
- if (inputValue.Size() < size)
- {
- return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
- "Not enough entries in JSON array to load an AZStd::array from.");
- }
-
- ContinuationFlags flags = ContinuationFlags::None;
+ ContinuationFlags flags = isNewInstance ? ContinuationFlags::LoadAsNewInstance : ContinuationFlags::None;
Uuid elementTypeId = Uuid::CreateNull();
auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement)
{
@@ -175,13 +188,23 @@ namespace AZ
};
container->EnumTypes(typeEnumCallback);
+ const size_t size = container->Size(outputValue);
+ if (!isNewInstance && inputValue.Size() < size)
+ {
+ return context.Report(
+ JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Not enough entries in JSON array to load an AZStd::array from.");
+ }
+
+ rapidjson::Value explicitDefaultValue = GetExplicitDefault();
+
JSR::ResultCode retVal(JSR::Tasks::ReadField);
for (size_t i = 0; i < size; ++i)
{
ScopedContextPath subPath(context, i);
void* element = container->GetElementByIndex(outputValue, nullptr, i);
- JSR::ResultCode result = ContinueLoading(element, elementTypeId, inputValue[aznumeric_caster(i)], context, flags);
+ JSR::ResultCode result = ContinueLoading(
+ element, elementTypeId, isNewInstance ? explicitDefaultValue : inputValue[aznumeric_caster(i)], context, flags);
if (result.GetProcessing() == JSR::Processing::Halted)
{
return context.Report(result, "Failed to load data to element in AZStd::array.");
@@ -189,15 +212,19 @@ namespace AZ
retVal.Combine(result);
}
- if (container->Size(outputValue) == inputValue.Size())
+ if (isNewInstance)
+ {
+ return context.Report(retVal, "Filled new instance of AZStd::array with defaults.");
+ }
+ else if (container->Size(outputValue) == inputValue.Size())
{
return context.Report(retVal, "Successfully read entries into AZStd::array.");
}
else
{
retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Skipped));
- return context.Report(retVal,
- "Successfully read available entries into AZStd::array, but there were still values left in the JSON array.");
+ return context.Report(
+ retVal, "Successfully read available entries into AZStd::array, but there were still values left in the JSON array.");
}
}
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h
index 11edc87139..a6d8dd37e3 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h
@@ -30,8 +30,14 @@ namespace AZ
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
+
protected:
- JsonSerializationResult::Result LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
+ JsonSerializationResult::Result LoadContainer(
+ void* outputValue,
+ const Uuid& outputValueTypeId,
+ const rapidjson::Value& inputValue,
+ bool isNewInstance,
JsonDeserializerContext& context);
};
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp
index 9a426a1e59..666fa0f96a 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp
@@ -216,9 +216,10 @@ namespace AZ
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading(
void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags)
{
+ bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance;
return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer
? JsonDeserializer::LoadToPointer(object, typeId, value, context)
- : JsonDeserializer::Load(object, typeId, value, context);
+ : JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, context);
}
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring(
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h
index 06c5eda6de..99b63bf4de 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h
@@ -163,15 +163,20 @@ namespace AZ
enum class ContinuationFlags
{
- None = 0, //! No extra flags.
- ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance.
- ReplaceDefault = 1 << 1 //! The default value provided for storing will be replaced with a newly created one.
+ None = 0, //! No extra flags.
+ ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance.
+ ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one.
+ LoadAsNewInstance = 1 << 2 //! Treats the value as if it's a newly created instance. This may trigger serializers marked with
+ //! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to
+ //! an array.
};
enum class OperationFlags
{
- None = 0, //! No flags that control how the custom json serializer is used.
- ManualDefault = 1 << 0 //! Even if an (explicit) default is found the custom json serializer will still be called.
+ None = 0, //! No flags that control how the custom json serializer is used.
+ ManualDefault = 1 << 0, //! Even if an (explicit) default is found the custom json serializer will still be called.
+ InitializeNewInstance = 1 << 1 //! If set, the custom json serializer will be called with an explicit default if a new
+ //! instance of its target type is created.
};
virtual ~BaseJsonSerializer() = default;
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp
index 400a3b7949..d61366413f 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp
@@ -34,11 +34,16 @@ namespace AZ
case rapidjson::kArrayType:
return LoadContainer(outputValue, outputValueTypeId, inputValue, context);
- case rapidjson::kObjectType: // fall through
- case rapidjson::kNullType: // fall through
- case rapidjson::kStringType: // fall through
- case rapidjson::kFalseType: // fall through
- case rapidjson::kTrueType: // fall through
+ case rapidjson::kObjectType:
+ [[fallthrough]];
+ case rapidjson::kNullType:
+ [[fallthrough]];
+ case rapidjson::kStringType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
+ case rapidjson::kTrueType:
+ [[fallthrough]];
case rapidjson::kNumberType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Basic containers can only be read from an array.");
@@ -123,6 +128,10 @@ namespace AZ
{
if (retVal.HasDoneWork())
{
+ // If at least one value was written, even if it has all defaults, then the array has
+ // a value written to it and is therefore not in a default state anymore.
+ retVal.Combine(JSR::ResultCode(JSR::Tasks::WriteValue, JSR::Outcomes::Success));
+
outputValue = AZStd::move(array);
return context.Report(retVal, "Content written to basic container.");
}
@@ -165,6 +174,7 @@ namespace AZ
ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
? ContinuationFlags::ResolvePointer
: ContinuationFlags::None;
+ flags |= ContinuationFlags::LoadAsNewInstance;
const size_t capacity = container->IsFixedCapacity() ? container->Capacity(outputValue) : std::numeric_limits::max();
@@ -243,6 +253,11 @@ namespace AZ
}
size_t addedCount = container->Size(outputValue) - containerSize;
+ if (addedCount > 0)
+ {
+ // Values were added which means the container is no longer in its default state of being empty.
+ retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success));
+ }
AZStd::string_view message =
addedCount >= arraySize ? "Successfully read basic container.":
addedCount == 0 ? "Unable to read data for basic container." :
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp
index d37e512ac2..3a9b5323b0 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp
@@ -82,12 +82,18 @@ namespace AZ
bool* valAsBool = reinterpret_cast(outputValue);
+ if (IsExplicitDefault(inputValue))
+ {
+ *valAsBool = {};
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Boolean value set to default of 'false'.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kObjectType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Booleans can't be read from arrays, objects or null.");
@@ -96,7 +102,7 @@ namespace AZ
return SerializerInternal::TextToValue(valAsBool, inputValue.GetString(), inputValue.GetStringLength(), context);
case rapidjson::kFalseType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kTrueType:
*valAsBool = inputValue.GetBool();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read boolean.");
@@ -145,4 +151,9 @@ namespace AZ
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "Default boolean used.");
}
+
+ auto JsonBoolSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h
index ac288c73ed..f000a03317 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h
@@ -27,5 +27,6 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
};
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp
index 9140be7fcd..0921587041 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp
@@ -62,19 +62,26 @@ namespace AZ
}
template
- static JsonSerializationResult::Result Load(T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
+ static JsonSerializationResult::Result Load(
+ T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
static_assert(AZStd::is_floating_point::value, "Expected T to be a floating point type");
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
+ if (isExplicitDefault)
+ {
+ *outputValue = {};
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Floating point value set to default of 0.0.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kObjectType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Floating point values can't be read from arrays, objects or null.");
@@ -83,7 +90,7 @@ namespace AZ
return TextToValue(outputValue, inputValue.GetString(), context);
case rapidjson::kFalseType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kTrueType:
*outputValue = inputValue.GetBool() ? 1.0f : 0.0f;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success,
@@ -144,7 +151,8 @@ namespace AZ
"Unable to deserialize double to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerFloatingPointInternal::Load(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerFloatingPointInternal::Load(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonDoubleSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -156,6 +164,11 @@ namespace AZ
return SerializerFloatingPointInternal::Store(outputValue, inputValue, defaultValue, context);
}
+ auto JsonDoubleSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
JsonSerializationResult::Result JsonFloatSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
@@ -163,7 +176,8 @@ namespace AZ
"Unable to deserialize float to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerFloatingPointInternal::Load(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerFloatingPointInternal::Load(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonFloatSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -174,4 +188,9 @@ namespace AZ
AZ_UNUSED(valueTypeId);
return SerializerFloatingPointInternal::Store(outputValue, inputValue, defaultValue, context);
}
+
+ auto JsonFloatSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h
index 81e631d9ab..a8c37316f0 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h
@@ -28,6 +28,7 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
};
class JsonFloatSerializer
@@ -40,5 +41,6 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
};
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp
index cc365da4f7..a6b1118ac1 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp
@@ -25,6 +25,8 @@
namespace AZ
{
+ AZ_CLASS_ALLOCATOR_IMPL(BaseJsonIntegerSerializer, SystemAllocator, 0);
+
AZ_CLASS_ALLOCATOR_IMPL(JsonCharSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonShortSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonIntSerializer, SystemAllocator, 0);
@@ -56,19 +58,25 @@ namespace AZ
template
static JsonSerializationResult::Result LoadInt(T* outputValue, const rapidjson::Value& inputValue,
- JsonDeserializerContext& context)
+ JsonDeserializerContext& context, bool isDefaultValue)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
static_assert(AZStd::is_integral(), "Expected T to be a signed or unsigned type");
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
+ if (isDefaultValue)
+ {
+ *outputValue = {};
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Integer value set to default of zero.");
+ }
+
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kObjectType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Integers can't be read from arrays, objects or null.");
@@ -77,7 +85,7 @@ namespace AZ
return TextToValue(outputValue, inputValue.GetString(), context);
case rapidjson::kFalseType:
- // fallthrough
+ [[fallthrough]];
case rapidjson::kTrueType:
*outputValue = inputValue.GetBool() ? 1 : 0;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success,
@@ -125,6 +133,11 @@ namespace AZ
}
} // namespace SerializerInternal
+ auto BaseJsonIntegerSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
JsonSerializationResult::Result JsonCharSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
@@ -132,7 +145,7 @@ namespace AZ
"Unable to deserialize char to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -151,7 +164,7 @@ namespace AZ
"Unable to deserialize short to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -170,7 +183,7 @@ namespace AZ
"Unable to deserialize int to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -189,7 +202,7 @@ namespace AZ
"Unable to deserialize long to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -208,7 +221,7 @@ namespace AZ
"Unable to deserialize long long to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -227,7 +240,8 @@ namespace AZ
"Unable to deserialize unsigned char to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -246,7 +260,8 @@ namespace AZ
"Unable to deserialize unsigned short to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -265,7 +280,8 @@ namespace AZ
"Unable to deserialize unsigned int to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -284,7 +300,8 @@ namespace AZ
"Unable to deserialize unsigned long to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -303,7 +320,8 @@ namespace AZ
"Unable to deserialize unsigned long long to json because the provided type is %s",
outputValueTypeId.ToString().c_str());
AZ_UNUSED(outputValueTypeId);
- return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context);
+ return SerializerInternal::LoadInt(
+ reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h
index 9f522619ae..31d5a4164a 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h
@@ -18,11 +18,18 @@
namespace AZ
{
- class JsonCharSerializer
- : public BaseJsonSerializer
+ class BaseJsonIntegerSerializer : public BaseJsonSerializer
{
public:
- AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonSerializer);
+ AZ_RTTI(BaseJsonIntegerSerializer, "{FD060F54-D3B5-4D5B-B64A-AFE371CD6F20}", BaseJsonSerializer);
+ AZ_CLASS_ALLOCATOR_DECL;
+ OperationFlags GetOperationsFlags() const override;
+ };
+
+ class JsonCharSerializer : public BaseJsonIntegerSerializer
+ {
+ public:
+ AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -30,11 +37,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonShortSerializer
- : public BaseJsonSerializer
+ class JsonShortSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonSerializer);
+ AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -42,11 +48,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonIntSerializer
- : public BaseJsonSerializer
+ class JsonIntSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonSerializer);
+ AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -54,11 +59,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonLongSerializer
- : public BaseJsonSerializer
+ class JsonLongSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonSerializer);
+ AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -66,11 +70,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonLongLongSerializer
- : public BaseJsonSerializer
+ class JsonLongLongSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonSerializer);
+ AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -78,11 +81,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonUnsignedCharSerializer
- : public BaseJsonSerializer
+ class JsonUnsignedCharSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonSerializer);
+ AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -90,11 +92,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonUnsignedShortSerializer
- : public BaseJsonSerializer
+ class JsonUnsignedShortSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonSerializer);
+ AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -102,11 +103,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonUnsignedIntSerializer
- : public BaseJsonSerializer
+ class JsonUnsignedIntSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonSerializer);
+ AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -114,11 +114,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonUnsignedLongSerializer
- : public BaseJsonSerializer
+ class JsonUnsignedLongSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonSerializer);
+ AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -126,11 +125,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
- class JsonUnsignedLongLongSerializer
- : public BaseJsonSerializer
+ class JsonUnsignedLongLongSerializer : public BaseJsonIntegerSerializer
{
public:
- AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonSerializer);
+ AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp
index 9c4641741e..a0a2ea6c37 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp
@@ -19,25 +19,30 @@
#include
#include
#include
+#include
#include
namespace AZ
{
JsonSerializationResult::ResultCode JsonDeserializer::DeserializerDefaultCheck(BaseJsonSerializer* serializer, void* object,
- const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context)
+ const Uuid& typeId,const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context)
{
using namespace AZ::JsonSerializationResult;
bool isExplicitDefault = IsExplicitDefault(value);
bool manuallyDefaults = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::ManualDefault) ==
BaseJsonSerializer::OperationFlags::ManualDefault;
- return !isExplicitDefault || (isExplicitDefault && manuallyDefaults)
+ bool initializeNewInstance = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::InitializeNewInstance) ==
+ BaseJsonSerializer::OperationFlags::InitializeNewInstance;
+
+ return
+ !isExplicitDefault || (isExplicitDefault && manuallyDefaults) || (isExplicitDefault && isNewInstance && initializeNewInstance)
? serializer->Load(object, typeId, value, context)
: context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default.");
}
- JsonSerializationResult::ResultCode JsonDeserializer::Load(void* object, const Uuid& typeId, const rapidjson::Value& value,
- JsonDeserializerContext& context)
+ JsonSerializationResult::ResultCode JsonDeserializer::Load(
+ void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context)
{
using namespace AZ::JsonSerializationResult;
@@ -50,7 +55,7 @@ namespace AZ
BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId);
if (serializer)
{
- return DeserializerDefaultCheck(serializer, object, typeId, value, context);
+ return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context);
}
const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId);
@@ -72,7 +77,7 @@ namespace AZ
serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId());
if (serializer)
{
- return DeserializerDefaultCheck(serializer, object, typeId, value, context);
+ return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context);
}
}
@@ -133,7 +138,7 @@ namespace AZ
const SerializeContext::ClassData* resolvedClassData = context.GetSerializeContext()->FindClassData(resolvedTypeId);
if (resolvedClassData)
{
- status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, context);
+ status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, context);
*objectPtr = resolvedClassData->m_azRtti->Cast(*objectPtr, typeId);
@@ -174,7 +179,7 @@ namespace AZ
}
else
{
- return Load(object, classElement.m_typeId, value, context);
+ return Load(object, classElement.m_typeId, value, false, context);
}
}
@@ -591,7 +596,9 @@ namespace AZ
}
else
{
- status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, "Serialization information for target type not found.");
+ using ReporterString = AZStd::fixed_string<1024>;
+ status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
+ ReporterString::format("Serialization information for target type %s not found.", loadedTypeId.m_typeId.ToString().c_str()));
return ResolvePointerResult::FullyProcessed;
}
objectType = loadedTypeId.m_typeId;
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h
index 5954082ee0..1d16b49e39 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h
@@ -58,8 +58,8 @@ namespace AZ
JsonDeserializer(const JsonDeserializer& rhs) = delete;
JsonDeserializer(JsonDeserializer&& rhs) = delete;
- static JsonSerializationResult::ResultCode Load(void* object, const Uuid& typeId, const rapidjson::Value& value,
- JsonDeserializerContext& context);
+ static JsonSerializationResult::ResultCode Load(
+ void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context);
static JsonSerializationResult::ResultCode LoadToPointer(void* object, const Uuid& typeId, const rapidjson::Value& value,
JsonDeserializerContext& context);
@@ -120,6 +120,7 @@ namespace AZ
void* object,
const Uuid& typeId,
const rapidjson::Value& value,
+ bool isNewInstance,
JsonDeserializerContext& context);
};
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp
index de9aa70362..db1172d245 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp
@@ -607,10 +607,12 @@ namespace AZ
}
else if (source.Size() > target.Size())
{
- rapidjson::SizeType sourceCount = source.Size();
- for (rapidjson::SizeType i = count; i < sourceCount; ++i)
+ // Loop backwards through the removals so that each removal has a valid index when processing in order.
+ for (rapidjson::SizeType i = source.Size(); i > count; --i)
{
- ScopedStackedString entryName(element, i);
+ // (We use "i - 1" here instead of in the loop to ensure we don't wrap around our unsigned numbers in the case
+ // where count is 0.)
+ ScopedStackedString entryName(element, i - 1);
patch.PushBack(CreatePatchInternal_Remove(allocator, element), allocator);
resultCode.Combine(settings.m_reporting("Removed member from array in JSON Patch.",
ResultCode(Tasks::CreatePatch, Outcomes::Success), element));
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp
index 0629f1c32e..6fabf51237 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp
@@ -249,7 +249,7 @@ namespace AZ
{
StackedString path(StackedString::Format::JsonPointer);
JsonDeserializerContext context(settings);
- result = JsonDeserializer::Load(object, objectType, root, context);
+ result = JsonDeserializer::Load(object, objectType, root, false, context);
}
return result;
}
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
index 437a648e1e..4dc3c44834 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
@@ -190,6 +190,12 @@ namespace AZ
}
size_t addedCount = container->Size(outputValue) - containerSize;
+ if (addedCount > 0)
+ {
+ // If at least one entry was added then the map is no longer in it's default state so
+ // mark is with success so the result can at best be partial defaults.
+ retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success));
+ }
AZStd::string_view message =
addedCount >= maximumSize ? "Successfully read associative container." :
addedCount == 0 ? "Unable to read data for the associative container." :
@@ -215,10 +221,10 @@ namespace AZ
// Load key
void* keyAddress = pairContainer->GetElementByIndex(address, pairElement, 0);
AZ_Assert(keyAddress, "Element reserved for associative container, but unable to retrieve address of the key.");
- ContinuationFlags keyLoadFlags = ContinuationFlags::None;
+ ContinuationFlags keyLoadFlags = ContinuationFlags::LoadAsNewInstance;
if (keyElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
- keyLoadFlags = ContinuationFlags::ResolvePointer;
+ keyLoadFlags |= ContinuationFlags::ResolvePointer;
*reinterpret_cast(keyAddress) = nullptr;
}
JSR::ResultCode keyResult = ContinueLoading(keyAddress, keyElement->m_typeId, key, context, keyLoadFlags);
@@ -231,10 +237,10 @@ namespace AZ
// Load value
void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value.");
- ContinuationFlags valueLoadFlags = ContinuationFlags::None;
+ ContinuationFlags valueLoadFlags = ContinuationFlags::LoadAsNewInstance;
if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
- valueLoadFlags = ContinuationFlags::ResolvePointer;
+ valueLoadFlags |= ContinuationFlags::ResolvePointer;
*reinterpret_cast(valueAddress) = nullptr;
}
JSR::ResultCode valueResult = ContinueLoading(valueAddress, valueElement->m_typeId, value, context, valueLoadFlags);
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp
index 5b43cec817..e8a6f549a7 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp
@@ -34,13 +34,24 @@ namespace AZ
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
- return LoadContainer(outputValue, outputValueTypeId, inputValue, context);
+ return LoadContainer(outputValue, outputValueTypeId, inputValue, false, context);
- case rapidjson::kObjectType: // fall through
- case rapidjson::kNullType: // fall through
- case rapidjson::kStringType: // fall through
- case rapidjson::kFalseType: // fall through
- case rapidjson::kTrueType: // fall through
+ case rapidjson::kObjectType:
+ if (IsExplicitDefault(inputValue))
+ {
+ // Because this serializer has only the operation flag "InitializeNewInstance" set, the only time this will be called with
+ // an explicit default is when a new instance has been created.
+ return LoadContainer(outputValue, outputValueTypeId, inputValue, true, context);
+ }
+ [[fallthrough]];
+ case rapidjson::kNullType:
+ [[fallthrough]];
+ case rapidjson::kStringType:
+ [[fallthrough]];
+ case rapidjson::kFalseType:
+ [[fallthrough]];
+ case rapidjson::kTrueType:
+ [[fallthrough]];
case rapidjson::kNumberType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. AZStd::pair or AZStd::tuple can only be read from an array.");
@@ -127,8 +138,13 @@ namespace AZ
}
}
+ auto JsonTupleSerializer::GetOperationsFlags() const -> OperationFlags
+ {
+ return OperationFlags::InitializeNewInstance;
+ }
+
JsonSerializationResult::Result JsonTupleSerializer::LoadContainer(void* outputValue, const Uuid& outputValueTypeId,
- const rapidjson::Value& inputValue, JsonDeserializerContext& context)
+ const rapidjson::Value& inputValue, bool isNewInstance, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult; // Used to remove name conflicts in AzCore in uber builds.
@@ -154,13 +170,6 @@ namespace AZ
};
container->EnumTypes(typeCountCallback);
- rapidjson::SizeType arraySize = inputValue.Size();
- if (arraySize < typeCount)
- {
- return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
- "Not enough entries in array to load an AZStd::pair or AZStd::tuple from.");
- }
-
AZStd::vector classElements;
classElements.reserve(typeCount);
auto typeEnumCallback = [&classElements](const Uuid&, const SerializeContext::ClassElement* genericClassElement)
@@ -171,46 +180,80 @@ namespace AZ
container->EnumTypes(typeEnumCallback);
JSR::ResultCode retVal(JSR::Tasks::ReadField);
- rapidjson::SizeType arrayIndex = 0;
- size_t numElementsWritten = 0;
- for (size_t i = 0; i < typeCount; ++i)
+ if (isNewInstance)
{
- ScopedContextPath subPath(context, i);
-
- void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i);
- AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i);
-
- ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
- ? ContinuationFlags::ResolvePointer
- : ContinuationFlags::None;
+ rapidjson::Value explicitDefaultValue = GetExplicitDefault();
- while (arrayIndex < inputValue.Size())
+ for (size_t i = 0; i < typeCount; ++i)
{
- JSR::ResultCode result = ContinueLoading(elementAddress, classElements[i]->m_typeId, inputValue[arrayIndex], context, flags);
+ ScopedContextPath subPath(context, i);
+
+ void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i);
+ AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i);
+
+ ContinuationFlags flags = ContinuationFlags::LoadAsNewInstance;
+ flags |=
+ (classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? ContinuationFlags::ResolvePointer
+ : ContinuationFlags::None);
+ JSR::ResultCode result = ContinueLoading(elementAddress, classElements[i]->m_typeId, explicitDefaultValue, context, flags);
retVal.Combine(result);
- arrayIndex++;
if (result.GetProcessing() == JSR::Processing::Halted)
{
return context.Report(retVal, "Failed to read element for AZStd::pair or AZStd::tuple.");
}
- else if (result.GetProcessing() != JSR::Processing::Altered)
- {
- numElementsWritten++;
- break;
- }
}
- }
- if (numElementsWritten < typeCount)
- {
- AZStd::string_view message = numElementsWritten == 0 ?
- "Unable to read data for AZStd::pair or AZStd::tuple." :
- "Partially read data for AZStd::pair or AZStd::tuple.";
- return context.Report(retVal, message);
+ return context.Report(retVal, "Initialized AZStd::pair or AZStd::tuple to defaults.");
}
else
{
- return context.Report(retVal, "Successfully read AZStd::pair or AZStd::tuple.");
+ if (inputValue.Size() < typeCount)
+ {
+ return context.Report(
+ JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
+ "Not enough entries in array to load an AZStd::pair or AZStd::tuple from.");
+ }
+
+ rapidjson::SizeType arrayIndex = 0;
+ size_t numElementsWritten = 0;
+ for (size_t i = 0; i < typeCount; ++i)
+ {
+ ScopedContextPath subPath(context, i);
+
+ void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i);
+ AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i);
+
+ ContinuationFlags flags =
+ (classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? ContinuationFlags::ResolvePointer
+ : ContinuationFlags::None);
+ while (arrayIndex < inputValue.Size())
+ {
+ JSR::ResultCode result =
+ ContinueLoading(elementAddress, classElements[i]->m_typeId, inputValue[arrayIndex], context, flags);
+ retVal.Combine(result);
+ arrayIndex++;
+ if (result.GetProcessing() == JSR::Processing::Halted)
+ {
+ return context.Report(retVal, "Failed to read element for AZStd::pair or AZStd::tuple.");
+ }
+ else if (result.GetProcessing() != JSR::Processing::Altered)
+ {
+ numElementsWritten++;
+ break;
+ }
+ }
+ }
+
+ if (numElementsWritten < typeCount)
+ {
+ AZStd::string_view message = numElementsWritten == 0 ? "Unable to read data for AZStd::pair or AZStd::tuple."
+ : "Partially read data for AZStd::pair or AZStd::tuple.";
+ return context.Report(retVal, message);
+ }
+ else
+ {
+ return context.Report(retVal, "Successfully read AZStd::pair or AZStd::tuple.");
+ }
}
}
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h
index a105272811..70a506eb81 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h
@@ -23,13 +23,20 @@ namespace AZ
public:
AZ_RTTI(JsonTupleSerializer, "{1AA0ADC1-395A-4223-8A73-304ACDEE7793}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
+
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
+ OperationFlags GetOperationsFlags() const override;
+
private:
- JsonSerializationResult::Result LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
+ JsonSerializationResult::Result LoadContainer(
+ void* outputValue,
+ const Uuid& outputValueTypeId,
+ const rapidjson::Value& inputValue,
+ bool isNewInstance,
JsonDeserializerContext& context);
};
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
index 2d2acd9d44..172a3697e4 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
+++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
@@ -816,7 +816,11 @@ namespace AZ::SettingsRegistryMergeUtils
}
}
- void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands)
+ // This function intentionally copies `commandLine`. It looks like it only uses it as a const reference, but the
+ // code in the loop makes calls that mutates the `commandLine` instance, invalidating the iterators. Making a copy
+ // ensures that the iterators remain valid.
+ // NOLINTNEXTLINE(performance-unnecessary-value-param)
+ void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, AZ::CommandLine commandLine, bool executeCommands)
{
// Iterate over all the command line options in order to parse the --regset and --regremove
// arguments in the order they were supplied
@@ -831,7 +835,7 @@ namespace AZ::SettingsRegistryMergeUtils
continue;
}
}
- if (commandArgument.m_option == "regremove")
+ else if (commandArgument.m_option == "regremove")
{
if (!registry.Remove(commandArgument.m_value))
{
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
index b482530d24..dbeb1bfe24 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
+++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
@@ -15,11 +15,7 @@
#include
#include
#include
-
-namespace AZ
-{
- class CommandLine;
-}
+#include
namespace AZ::IO
{
@@ -217,7 +213,7 @@ namespace AZ::SettingsRegistryMergeUtils
//! example: --regdump /My/Array/With/Objects
//! --regdumpall Dumps the entire settings registry to output.
//! Note that this function is only called in development builds and is compiled out in release builds.
- void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands);
+ void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, AZ::CommandLine commandLine, bool executeCommands);
//! Stores the command line settings into the Setting Registry
//! The arguments can be used later anywhere the command line is needed
diff --git a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp
index 3e4ddac3af..47dba62ec8 100644
--- a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp
@@ -168,6 +168,10 @@ namespace JsonSerializationTests
{
features.EnableJsonType(rapidjson::kObjectType);
features.m_typeToInject = rapidjson::kNullType;
+ // Assets are not fully registered with the Serialize Context for historical reasons. Due to the missing
+ // information the Json Serializer Conformity Tests can't run the subsection of tests that explicitly
+ // require the missing information.
+ features.m_enableNewInstanceTests = false;
}
bool AreEqual(const Asset& lhs, const Asset& rhs) override
diff --git a/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp
index 4fa816cd4d..cb26937824 100644
--- a/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp
@@ -32,6 +32,11 @@ namespace JsonSerializationTests
AZ::NameDictionary::Destroy();
}
+ void Reflect(AZStd::unique_ptr& context)
+ {
+ AZ::Name::Reflect(context.get());
+ }
+
void Reflect(AZStd::unique_ptr& context)
{
AZ::Name::Reflect(context.get());
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp
index da66bdd0b5..f696a9d270 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp
@@ -126,9 +126,9 @@ namespace JsonSerializationTests
{
auto array = AZStd::shared_ptr(new Array(), Deleter);
(*array)[0] = nullptr;
- (*array)[1] = aznew MultipleInheritence();
+ (*array)[1] = nullptr;
(*array)[2] = nullptr;
- (*array)[3] = aznew MultipleInheritence();
+ (*array)[3] = nullptr;
return array;
}
@@ -154,6 +154,7 @@ namespace JsonSerializationTests
null,
null,
{
+ "$type": "MultipleInheritence",
"base_var": 242.0,
"var1" : 142
}
@@ -246,56 +247,21 @@ namespace JsonSerializationTests
])";
}
- AZStd::string_view GetJsonFor_Store_SerializeFullySetInstance() override
- {
- // This is a unique situation because the $type is determined separate from other values, so all
- // member values can be changed, but since the default type matches the stored type the $type
- // will only be written if default values are explicitly kept.
- return R"(
- [
- {
- "$type": "MultipleInheritence",
- "base_var": 1142.0,
- "base2_var1": 1242.0,
- "base2_var2": 1342.0,
- "base2_var3": 1442.0,
- "var1" : 1542,
- "var2" : 1642.0
- },
- {
- "base_var": 2142.0,
- "base2_var1": 2242.0,
- "base2_var2": 2342.0,
- "base2_var3": 2442.0,
- "var1" : 2542,
- "var2" : 2642.0
- },
- {
- "$type": "MultipleInheritence",
- "base_var": 3142.0,
- "base2_var1": 3242.0,
- "base2_var2": 3342.0,
- "base2_var3": 3442.0,
- "var1" : 3542,
- "var2" : 3642.0
- },
- {
- "base_var": 4142.0,
- "base2_var1": 4242.0,
- "base2_var2": 4342.0,
- "base2_var3": 4442.0,
- "var1" : 4542,
- "var2" : 4642.0
- }
- ])";
- }
-
void Reflect(AZStd::unique_ptr& context) override
{
Base::Reflect(context);
MultipleInheritence::Reflect(context, true);
}
+ void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
+ {
+ Base::ConfigureFeatures(features);
+ // These tests don't work with pointers because there'll be a random value in the pointer
+ // which the Json Serialization will try to delete. The POD version of these tests already cover
+ // these cases.
+ features.m_enableNewInstanceTests = false;
+ }
+
bool AreEqual(const Array& lhs, const Array& rhs) override
{
size_t size = lhs.size();
@@ -311,6 +277,11 @@ namespace JsonSerializationTests
return rhs[i] == nullptr;
}
+ if (rhs[i] == nullptr)
+ {
+ return false;
+ }
+
if (!static_cast(lhs[i])->Equals(*static_cast(rhs[i]), true))
{
return false;
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp
index 88e888743e..508658e2a5 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp
@@ -54,6 +54,11 @@ namespace JsonSerializationTests
return AZStd::make_shared(Container{ 188, 288, 388 });
}
+ AZStd::shared_ptr CreateSingleArrayDefaultInstance() override
+ {
+ return AZStd::make_shared(Container{ 0 });
+ }
+
AZStd::string_view GetJsonForFullySetInstance() override
{
return "[188, 288, 388]";
@@ -120,6 +125,13 @@ namespace JsonSerializationTests
&SimplePointerTestDescription::Delete);
}
+ AZStd::shared_ptr CreateSingleArrayDefaultInstance() override
+ {
+ int* value = reinterpret_cast(azmalloc(sizeof(int), alignof(int)));
+ *value = 0;
+ return AZStd::shared_ptr(new Container{ value }, &SimplePointerTestDescription::Delete);
+ }
+
AZStd::string_view GetJsonForFullySetInstance() override
{
return "[188, 288, 388]";
@@ -180,6 +192,13 @@ namespace JsonSerializationTests
return instance;
}
+ AZStd::shared_ptr CreateSingleArrayDefaultInstance() override
+ {
+ auto instance = AZStd::make_shared();
+ *instance = { SimpleClass{} };
+ return instance;
+ }
+
AZStd::string_view GetJsonForFullySetInstance() override
{
return R"([
@@ -301,7 +320,7 @@ namespace JsonSerializationTests
ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, &instance, azrtti_typeid(&instance), *m_jsonSerializationContext);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
- EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
+ EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome());
Expect_DocStrEq("[{}]");
}
@@ -315,7 +334,7 @@ namespace JsonSerializationTests
ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, nullptr, azrtti_typeid(&instance), *m_jsonSerializationContext);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
- EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
+ EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome());
Expect_DocStrEq("[{},{}]");
}
@@ -330,7 +349,6 @@ namespace JsonSerializationTests
ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, nullptr, azrtti_typeid(&instance), *m_jsonSerializationContext);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome());
- EXPECT_NE(Outcomes::DefaultsUsed, result.GetOutcome());
Expect_DocStrEq(R"([{"$type": "SimpleInheritence"},{"$type": "SimpleInheritence"}])");
}
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp
index cf9d76e79d..cd6fcef5c5 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp
@@ -63,6 +63,18 @@ namespace JsonSerializationTests
: public BaseJsonSerializerFixture
{
public:
+ struct BoolPointerWrapper
+ {
+ AZ_TYPE_INFO(BoolPointerWrapper, "{2E67C069-BB0F-4F00-A704-E964F5FE5ED2}");
+
+ bool* m_value{ nullptr };
+
+ ~BoolPointerWrapper()
+ {
+ azfree(m_value);
+ }
+ };
+
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
@@ -75,6 +87,12 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
+ void RegisterAdditional(AZStd::unique_ptr& serializeContext) override
+ {
+ serializeContext->Class()
+ ->Field("Value", &BoolPointerWrapper::m_value);
+ }
+
void Load(rapidjson::Value& testVal, bool expectedBool, AZ::JsonSerializationResult::Outcomes expectedOutcome)
{
using namespace AZ::JsonSerializationResult;
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp
index d19c38fcdc..1556318199 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp
@@ -32,7 +32,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr CreateDefaultInstance() override
{
- return AZStd::make_shared(-2.0f);
+ return AZStd::make_shared(0.0f);
}
AZStd::shared_ptr CreateFullySetInstance() override
@@ -71,6 +71,20 @@ namespace JsonSerializationTests
: public BaseJsonSerializerFixture
{
public:
+ struct DoublePointerWrapper
+ {
+ AZ_TYPE_INFO(DoublePointerWrapper, "{C2FD9E0B-2641-4D24-A3D9-A29FD1A21A81}");
+
+ double* m_double{ nullptr };
+ float* m_float{ nullptr };
+
+ ~DoublePointerWrapper()
+ {
+ azfree(m_float);
+ azfree(m_double);
+ }
+ };
+
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
@@ -85,6 +99,13 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
+ void RegisterAdditional(AZStd::unique_ptr& serializeContext) override
+ {
+ serializeContext->Class()
+ ->Field("Double", &DoublePointerWrapper::m_double)
+ ->Field("Float", &DoublePointerWrapper::m_float);
+ }
+
void TestSerializers(rapidjson::Value& testVal, double expectedValue, AZ::JsonSerializationResult::Outcomes expectedOutcome)
{
using namespace AZ::JsonSerializationResult;
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h
index c0f470378c..4931c203cf 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h
@@ -62,6 +62,14 @@ namespace JsonSerializationTests
//! can be used to manually create these documents. If that is also not an option the tests can be
//! disabled by setting this flag to false.
bool m_supportsInjection{ true };
+ //! Enables the check that tries to determine if variables are initialized and if not whether they have the
+ //! OperationFlags::ManualDefault set. This applies for instance to integers, which won't be initialized if
+ //! constructed a new instance is created for pointers.
+ bool m_enableInitializationTest{ true };
+ //! Enable the test that creates a new instance of the provided test type through the factory that's found in
+ //! the Serialize Context. This test is automatically disabled for classes that don't have a factory or
+ //! have a null factory as well as for classes that have mandatory fields.
+ bool m_enableNewInstanceTests{ true };
private:
// There's no way to retrieve the number of types from RapidJSON so they're hard-coded here.
@@ -87,6 +95,7 @@ namespace JsonSerializationTests
{
public:
using Type = T;
+
virtual ~JsonSerializerConformityTestDescriptor() = default;
virtual AZStd::shared_ptr CreateSerializer() = 0;
@@ -104,13 +113,21 @@ namespace JsonSerializationTests
virtual AZStd::shared_ptr CreatePartialDefaultInstance() { return nullptr; }
//! Create an instance where all values are set to non-default values.
virtual AZStd::shared_ptr CreateFullySetInstance() = 0;
+ //! Create an instance of the target array type with a single value that has all defaults.
+ //! If the target type doesn't support arrays or requires more than one entry this can be ignored and
+ //! tests using this value will be skipped.
+ virtual AZStd::shared_ptr CreateSingleArrayDefaultInstance() { return nullptr; }
//! Get the json that represents the default instance.
//! If the target type doesn't support partial specialization this can be ignored and
//! tests for partial support will be skipped.
- virtual AZStd::string_view GetJsonForPartialDefaultInstance() { return ""; }
+ virtual AZStd::string_view GetJsonForPartialDefaultInstance() { return ""; }
//! Get the json that represents the instance with all values set.
virtual AZStd::string_view GetJsonForFullySetInstance() = 0;
+ //! Get the json that represents an array with a single value that has only defaults.
+ //! If the target type doesn't support arrays or requires more than one entry this can be ignored and
+ //! tests using this value will be skipped.
+ virtual AZStd::string_view GetJsonForSingleArrayDefaultInstance() { return "[{}]"; }
//! Get the json where additional values are added to the json file.
//! If this function is not overloaded, but features.m_supportsInjection is enabled then
//! the Json Serializer Conformity Tests will inject extra values in the json for a fully.
@@ -138,12 +155,15 @@ namespace JsonSerializationTests
virtual AZStd::string_view GetJsonFor_Load_DeserializeUnreflectedType() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Load_DeserializeFullySetInstance() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Load_DeserializePartialInstance() { return this->GetJsonForPartialDefaultInstance(); }
+ virtual AZStd::string_view GetJsonFor_Load_DeserializeArrayWithDefaultValue() { return this->GetJsonForSingleArrayDefaultInstance(); }
+ virtual AZStd::string_view GetJsonFor_Load_DeserializeFullInstanceOnTopOfPartialDefaulted() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Load_HaltedThroughCallback() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Store_SerializeWithDefaultsKept() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Store_SerializeFullySetInstance() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Store_SerializeWithoutDefault() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Store_SerializeWithoutDefaultAndDefaultsKept() { return this->GetJsonForFullySetInstance(); }
virtual AZStd::string_view GetJsonFor_Store_SerializePartialInstance() { return this->GetJsonForPartialDefaultInstance(); }
+ virtual AZStd::string_view GetJsonFor_Store_SerializeArrayWithSingleDefaultValue() { return this->GetJsonForSingleArrayDefaultInstance(); }
};
template
@@ -154,6 +174,21 @@ namespace JsonSerializationTests
using Description = T;
using Type = typename T::Type;
+ struct PointerWrapper
+ {
+ AZ_TYPE_INFO(PointerWrapper, "{32FA6645-074A-458A-B79C-B173D0BD4B42}");
+ AZ_CLASS_ALLOCATOR(PointerWrapper, AZ::SystemAllocator, 0);
+
+ Type* m_value{ nullptr };
+
+ ~PointerWrapper()
+ {
+ // Using free because not all types can safely use delete. Since this just to clear the memory to satisfy the memory
+ // leak test, this is fine.
+ azfree(m_value);
+ }
+ };
+
void SetUp() override
{
using namespace AZ::JsonSerializationResult;
@@ -165,6 +200,7 @@ namespace JsonSerializationTests
descriptor->ConfigureFeatures(this->m_features);
descriptor->Reflect(this->m_serializeContext);
descriptor->Reflect(this->m_jsonRegistrationContext);
+ this->m_serializeContext->template Class()->Field("Value", &PointerWrapper::m_value);
this->m_deserializationSettings->m_reporting = &Internal::VerifyCallback;
this->m_serializationSettings->m_reporting = &Internal::VerifyCallback;
@@ -185,6 +221,7 @@ namespace JsonSerializationTests
this->m_jsonRegistrationContext->DisableRemoveReflection();
this->m_serializeContext->EnableRemoveReflection();
+ this->m_serializeContext->template Class()->Field("Value", &PointerWrapper::m_value);
descriptor->Reflect(this->m_serializeContext);
this->m_serializeContext->DisableRemoveReflection();
@@ -487,6 +524,41 @@ namespace JsonSerializationTests
}
}
+ TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeArrayWithDefaultValue_SucceedsAndReportPartialDefaults)
+ {
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.SupportsJsonType(rapidjson::kArrayType))
+ {
+ this->m_jsonDocument->Parse(this->m_description.GetJsonFor_Load_DeserializeArrayWithDefaultValue().data());
+ ASSERT_FALSE(this->m_jsonDocument->HasParseError());
+
+ auto serializer = this->m_description.CreateSerializer();
+ auto instance = this->m_description.CreateDefaultInstance();
+
+ this->m_jsonDeserializationContext->PushPath(DefaultPath);
+
+ ResultCode result =
+ serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext);
+
+ if (this->m_features.m_fixedSizeArray)
+ {
+ EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome());
+ EXPECT_EQ(Processing::Altered, result.GetProcessing());
+ }
+ else
+ {
+ EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+
+ auto compare = this->m_description.CreateSingleArrayDefaultInstance();
+ ASSERT_NE(nullptr, compare)
+ << "Conformity tests for variably sized arrays require an implementation of CreateSingleArrayDefaultInstance";
+ EXPECT_TRUE(this->m_description.AreEqual(*compare, *instance));
+ }
+ }
+ }
+
TYPED_TEST_P(JsonSerializerConformityTests, Load_InterruptClearingTarget_ContainerIsNotCleared)
{
using namespace AZ::JsonSerializationResult;
@@ -548,7 +620,6 @@ namespace JsonSerializationTests
this->m_jsonDocument->Parse(json.data());
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
- auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto compare = this->m_description.CreateFullySetInstance();
@@ -622,6 +693,94 @@ namespace JsonSerializationTests
}
}
+ TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeFullInstanceOnTopOfPartialDefaulted_SucceedsAndObjectMatchesParialInstance)
+ {
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.m_supportsPartialInitialization)
+ {
+ AZStd::string_view json = this->m_description.GetJsonFor_Load_DeserializeFullInstanceOnTopOfPartialDefaulted();
+ // If tests for partial initialization are enabled than json for the partial initialization is needed.
+ ASSERT_FALSE(json.empty());
+ this->m_jsonDocument->Parse(json.data());
+ ASSERT_FALSE(this->m_jsonDocument->HasParseError());
+
+ auto serializer = this->m_description.CreateSerializer();
+ auto instance = this->m_description.CreatePartialDefaultInstance();
+ auto compare = this->m_description.CreateFullySetInstance();
+ ASSERT_NE(nullptr, compare);
+
+ // Clear containers which should effectively turn them into default containers.
+ this->m_deserializationSettings->m_clearContainers = true;
+ this->ResetJsonContexts();
+ this->m_jsonDeserializationContext->PushPath(DefaultPath);
+
+ ResultCode result =
+ serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext);
+
+ EXPECT_EQ(Outcomes::Success, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare));
+ }
+ }
+
+ TYPED_TEST_P(JsonSerializerConformityTests, Load_DefaultToPointer_SucceedsAndValueIsInitialized)
+ {
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.m_enableNewInstanceTests && this->m_features.m_mandatoryFields.empty())
+ {
+ AZ::SerializeContext* serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
+ const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(azrtti_typeid());
+ ASSERT_NE(nullptr, classData);
+ // Skip this test if the target type doesn't have a factor to create a new instance with or if the factor explicit
+ // prohibits construction.
+ if (classData->m_factory && classData->m_factory != AZ::Internal::NullFactory::GetInstance())
+ {
+ typename JsonSerializerConformityTests::PointerWrapper instance;
+ auto compare = this->m_description.CreateDefaultInstance();
+
+ this->m_jsonDocument->Parse(R"({ "Value": {}})");
+ ASSERT_FALSE(this->m_jsonDocument->HasParseError());
+
+ AZ::JsonDeserializerSettings settings;
+ settings.m_serializeContext = serializeContext;
+ settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
+ ResultCode result = AZ::JsonSerialization::Load(instance, *this->m_jsonDocument, settings);
+
+ EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ ASSERT_NE(nullptr, instance.m_value);
+ EXPECT_TRUE(this->m_description.AreEqual(*instance.m_value, *compare));
+ }
+ }
+ }
+
+ TYPED_TEST_P(JsonSerializerConformityTests, Load_InitializeNewInstance_SucceedsAndValueIsInitialized)
+ {
+ using namespace AZ;
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.m_enableNewInstanceTests && this->m_features.m_mandatoryFields.empty())
+ {
+ auto serializer = this->m_description.CreateSerializer();
+ if ((serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::InitializeNewInstance) ==
+ BaseJsonSerializer::OperationFlags::InitializeNewInstance)
+ {
+ typename TypeParam::Type instance;
+ auto compare = this->m_description.CreateDefaultInstance();
+ this->m_jsonDocument->SetObject();
+
+ ResultCode result =
+ serializer->Load(&instance, azrtti_typeid(instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext);
+
+ EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ EXPECT_TRUE(this->m_description.AreEqual(instance, *compare));
+ }
+ }
+ }
+
TYPED_TEST_P(JsonSerializerConformityTests, Load_HaltedThroughCallback_LoadFailsAndHaltReported)
{
using namespace AZ::JsonSerializationResult;
@@ -909,6 +1068,28 @@ namespace JsonSerializationTests
}
}
+ TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeArrayWithSingleDefaultValue_StoredSuccessfullyAndJsonMatches)
+ {
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.SupportsJsonType(rapidjson::kArrayType) && !this->m_features.m_fixedSizeArray)
+ {
+ this->m_jsonSerializationContext->PushPath(DefaultPath);
+
+ auto serializer = this->m_description.CreateSerializer();
+ auto instance = this->m_description.CreateSingleArrayDefaultInstance();
+ ASSERT_NE(nullptr, instance)
+ << "Conformity tests for variably sized arrays require an implementation of CreateSingleArrayDefaultInstance";
+
+ ResultCode result = serializer->Store(
+ *this->m_jsonDocument, instance.get(), instance.get(), azrtti_typeid(*instance), *this->m_jsonSerializationContext);
+
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome());
+ this->Expect_DocStrEq(this->m_description.GetJsonFor_Store_SerializeArrayWithSingleDefaultValue());
+ }
+ }
+
TYPED_TEST_P(JsonSerializerConformityTests, Store_HaltedThroughCallback_StoreFailsAndHaltReported)
{
using namespace AZ::JsonSerializationResult;
@@ -1017,7 +1198,29 @@ namespace JsonSerializationTests
}
}
- TYPED_TEST_P(JsonSerializerConformityTests, GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared)
+ TYPED_TEST_P(JsonSerializerConformityTests, GetOperationFlags_RequiresExplicitInit_ObjectsThatDoNotConstructHaveExplicitInitOption)
+ {
+ using namespace AZ;
+ using namespace AZ::JsonSerializationResult;
+
+ if (this->m_features.m_enableInitializationTest)
+ {
+ auto instance = this->m_description.CreateDefaultInstance();
+ typename TypeParam::Type compare;
+ if (!this->m_description.AreEqual(*instance, compare))
+ {
+ auto serializer = this->m_description.CreateSerializer();
+ BaseJsonSerializer::OperationFlags flags = serializer->GetOperationsFlags();
+ bool hasManualDefaultSet =
+ (flags & BaseJsonSerializer::OperationFlags::ManualDefault) == BaseJsonSerializer::OperationFlags::ManualDefault ||
+ (flags & BaseJsonSerializer::OperationFlags::InitializeNewInstance) ==
+ BaseJsonSerializer::OperationFlags::InitializeNewInstance;
+ EXPECT_TRUE(hasManualDefaultSet);
+ }
+ }
+ }
+
+ TYPED_TEST_P(JsonSerializerConformityTests, GetOperationFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared)
{
if (this->m_features.SupportsJsonType(rapidjson::kObjectType))
{
@@ -1048,10 +1251,14 @@ namespace JsonSerializationTests
Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyArrayWithClearEnabled_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyArrayWithClearedTarget_SucceedsAndObjectMatchesDefaults,
+ Load_DeserializeArrayWithDefaultValue_SucceedsAndReportPartialDefaults,
Load_InterruptClearingTarget_ContainerIsNotCleared,
Load_DeserializeFullySetInstance_SucceedsAndObjectMatchesFullySetInstance,
Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance,
Load_DeserializePartialInstance_SucceedsAndObjectMatchesParialInstance,
+ Load_DeserializeFullInstanceOnTopOfPartialDefaulted_SucceedsAndObjectMatchesParialInstance,
+ Load_DefaultToPointer_SucceedsAndValueIsInitialized,
+ Load_InitializeNewInstance_SucceedsAndValueIsInitialized,
Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported,
Load_InsertAdditionalData_SucceedsAndObjectMatchesFullySetInstance,
Load_HaltedThroughCallback_LoadFailsAndHaltReported,
@@ -1066,13 +1273,15 @@ namespace JsonSerializationTests
Store_SerializeWithoutDefaultAndDefaultsKept_StoredSuccessfullyAndJsonMatches,
Store_SerializePartialInstance_StoredSuccessfullyAndJsonMatches,
Store_SerializeEmptyArray_StoredSuccessfullyAndJsonMatches,
+ Store_SerializeArrayWithSingleDefaultValue_StoredSuccessfullyAndJsonMatches,
Store_HaltedThroughCallback_StoreFailsAndHaltReported,
StoreLoad_RoundTripWithPartialDefault_IdenticalInstances,
StoreLoad_RoundTripWithFullSet_IdenticalInstances,
StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances,
- GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared);
+ GetOperationFlags_RequiresExplicitInit_ObjectsThatDoNotConstructHaveExplicitInitOption,
+ GetOperationFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared);
} // namespace JsonSerializationTests
namespace AZ
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
index 5dec394351..7ec5ca3b9a 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
@@ -35,6 +35,11 @@ namespace JsonSerializationTests
return AZStd::make_shared