Răsfoiți Sursa

SerializeContext header include dependency reduction (#14918)

* SerializeContext header include dependency reduction

The goal of changes in this commit is to remove unneccesary inclusion of SerializeContext.h from header files.

Whenever possible if a Reflect function was defined in header, it's
definition was moved to a cpp file and the header was replaced with a
forward declaration to ReflectContext.

The SerializeContext VersionConverter functions that were members of a class declaration were
instead moved to cpp files as static functions.
Declaring the SerializeContext VersionConverter functions in header
inhibits forward declaration of the SerializeContext due to the need to
access the local class of SerializeContext::DataElementNode

The AnimSplineTrack specializations for Vec2 for both the LyShine and
Maestro Gems were moved to a cpp file, with forward declarations for
the `TAnimSplineTrack<Vec2>` and `TUiAnimSplineTrack<Vec2>` member
functions added to remove the include of the
AnimSplineTrack_Vec2Specialization.cpp file

Finally the `AZ_TYPE_INFO_SPECIALIZE*` macros were moved from TypeInfo.h
to TypeInfoSimple.h which allows code to avoid including `TypeInfo.h`
when needing to use that macro.

The TypeInfo.h include specializes AZ TypeInfo for AZStd container
templates such as `AZStd::vector`, `AZStd::unordered_map`, etc...
So this should save a little bit of include time.

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Added non-template helper functions for the SerializeContext to reduce
compiling code code in frequently used templates.

The `SerializeContext::Class`, `SerializeContext::ClassBuilder::Class`
and `SerializeContext::ClassData::Create` functions have had
non-template helper functions added that encapsulates the non-template
logic in the SerializeContext.cpp file.

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Split the SerializeContext.h and Memory.h headers into forwarding
headers and class definitions headers

The `SerializeContext_fwd.h` allows access to the Serialization classes
without the need to include any other header files.
It provides access to the AZ_SERIALIZE_FRIEND macro as ell
It is useful for accessing SerializeContext structures within headers
without result in an over include exposure

The `Memory_fwd.h` header provides access to the macros previously
defined in Memory.h, but with a lot fewer includes.
This header only includes `AzCore/base.h` and the std library `<new>`
header.

Its primary uses is to allow a class to declare the AZ Class Allocator
functions while minimizing includes via the `AZ_CLASS_ALLOCATOR_DECL`
macro.

The biggest change within this commit is to remove several inner classes
from the SerializeContext class to be outside classes that are declared
in the `AZ::Serialize` namespace.

This allows those classes to be forward declared and referenced without
needing to include the `SerializeContext.h` header.

The normal classes that were moved outside of the SerializeContext class are
the following
* `AZ::Serialize::ClassData`
* `AZ::Serialize::EnumerateInstanceCallContext`
* `AZ::Serialize::ClassElement`
* `AZ::Serialize::DataElement`
* `AZ::Serialize::DataElementNode`
* `AZ::Serialize::IObjectFactory`
* `AZ::Serialize::IDataSerializer`
* `AZ::Serialize::IDataContainer`
* `AZ::Serialize::IEventHandler`
* `AZ::Serialize::IDataConverter`

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Updated the 2 remaining ObjectStream serialized files for the FBX
assetinfo that contains Version 1 PhysX MeshGroup data to JSON.

This conversion was done using the `SerializeContextTools` `convert`
function with a `--project-path` parameter pointing at the
AutomatedTesting project and a SettingsRegistry specialization tag set
to `--specializations=editor` so that the Editor gems were loaded in
order to load the old ObjectStream file and save it backout using JSON.

With that change the PhysX MeshGroup class Version Converter has been
removed from the codebase.

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Build fixes Adding missing includes to AssetBrowserThumbnailView.cpp

Add the `[[maybe_unused]]` to the AzPhysics SystemConfiguration struct
to fix the `-Wunused-private-field` warning.

Updated the member definition of Serialization classes defined in the
AZ::Serialize namespace to not prefix the function with the
SerializeContext alias.

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Removed more unused private variables which is now triggering warnings on clangRemoved more unused private variables which is now triggering warnings on clang

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Removed the preprocessor if block for the azcreate and azmalloc macros

The only differences was that the `defined(_RELEASE)` block had an implementation of the azcreate_1 macro.

Also replaced uses of AZStd::alignment_of with the builtin `alignof` keyword.
The `alignof` keyword doesn't require a header to be included, reducing the included dependencies even more.

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Simplified Remove Reflection logic for the SerializeContext ClassBuilder functions to reduce a `return this` statement

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Removed unused private member variables

The `-Wunused-private-field` warning is now triggering when using the clang compiler, so the unused private members have been removed.

There is two cases where the members are only used with the MSVC compiler and those variables have had the warning surpressed using [[maybe_unused]]

The ScriptCanvasDeveloperGem `EditorKeyActions.h` and `EditorMouseActions.h` are the cases where the private members are actually used.

Signed-off-by: lumberyard-employee-dm <[email protected]>

---------

Signed-off-by: lumberyard-employee-dm <[email protected]>
lumberyard-employee-dm 2 ani în urmă
părinte
comite
9b06340c6c
100 a modificat fișierele cu 3120 adăugiri și 3290 ștergeri
  1. 49 91
      AutomatedTesting/Assets/Physics/Collider_MultipleSurfaceSlots/test.fbx.assetinfo
  2. 49 91
      AutomatedTesting/Levels/Physics/Material_PerFaceMaterialGetsCorrectMaterial/test.fbx.assetinfo
  3. 2 2
      Code/Editor/DisplaySettingsPythonFuncs.cpp
  4. 1 0
      Code/Editor/EditorPreferencesPageAWS.cpp
  5. 8 3
      Code/Editor/EditorPreferencesPageAWS.h
  6. 6 2
      Code/Editor/EditorPreferencesPageExperimentalLighting.h
  7. 2 0
      Code/Editor/EditorPreferencesPageFiles.cpp
  8. 6 3
      Code/Editor/EditorPreferencesPageFiles.h
  9. 7 3
      Code/Editor/EditorPreferencesPageGeneral.h
  10. 7 3
      Code/Editor/EditorPreferencesPageViewportCamera.h
  11. 6 2
      Code/Editor/EditorPreferencesPageViewportDebug.h
  12. 3 1
      Code/Editor/EditorPreferencesPageViewportGeneral.cpp
  13. 7 3
      Code/Editor/EditorPreferencesPageViewportGeneral.h
  14. 2 0
      Code/Editor/EditorPreferencesPageViewportManipulator.cpp
  15. 7 3
      Code/Editor/EditorPreferencesPageViewportManipulator.h
  16. 1 0
      Code/Editor/Objects/ObjectManager.h
  17. 14 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp
  18. 8 13
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteSettings.h
  19. 0 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx
  20. 0 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp
  21. 0 2
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx
  22. 0 2
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentEntityEditorMainWindow.h
  23. 0 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentEntityEditorOutlinerWindow.h
  24. 0 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentLevelEntityEditorMainWindow.h
  25. 27 20
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
  26. 1 8
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
  27. 2 2
      Code/Framework/AzCore/AzCore/IO/Path/PathReflect.cpp
  28. 1 328
      Code/Framework/AzCore/AzCore/Memory/Memory.h
  29. 352 0
      Code/Framework/AzCore/AzCore/Memory/Memory_fwd.h
  30. 1 1
      Code/Framework/AzCore/AzCore/RTTI/BehaviorClassBuilder.inl
  31. 0 40
      Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h
  32. 41 0
      Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h
  33. 11 9
      Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp
  34. 0 5
      Code/Framework/AzCore/AzCore/Script/ScriptProperty.h
  35. 3 2
      Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp
  36. 0 1
      Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h
  37. 15 0
      Code/Framework/AzCore/AzCore/Serialization/EditContext.h
  38. 13 13
      Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp
  39. 3 4
      Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h
  40. 1980 1780
      Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp
  41. 233 722
      Code/Framework/AzCore/AzCore/Serialization/SerializeContext.h
  42. 2 2
      Code/Framework/AzCore/AzCore/Serialization/SerializeContextEnum.cpp
  43. 4 4
      Code/Framework/AzCore/AzCore/Serialization/SerializeContextEnum.inl
  44. 44 0
      Code/Framework/AzCore/AzCore/Serialization/SerializeContext_fwd.h
  45. 2 0
      Code/Framework/AzCore/AzCore/azcore_files.cmake
  46. 2 2
      Code/Framework/AzCore/Tests/Serialization.cpp
  47. 0 1
      Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.h
  48. 1 0
      Code/Framework/AzFramework/AzFramework/Asset/AssetRegistry.cpp
  49. 5 1
      Code/Framework/AzFramework/AzFramework/Asset/AssetRegistry.h
  50. 7 4
      Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h
  51. 1 0
      Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl
  52. 5 1
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/Reflection/LegacyReflectionBridge.h
  53. 0 1
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/ReflectionAdapter.h
  54. 6 0
      Code/Framework/AzFramework/AzFramework/Physics/Character.h
  55. 1 1
      Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h
  56. 6 6
      Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
  57. 2 0
      Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.cpp
  58. 5 1
      Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h
  59. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorEntityAPI.h
  60. 0 1
      Code/Framework/AzToolsFramework/AzToolsFramework/API/EntityCompositionNotificationBus.h
  61. 13 11
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManager.cpp
  62. 9 8
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManagerInterface.h
  63. 2 3
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManagerInternalInterface.h
  64. 3 1
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/EditorAction.cpp
  65. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/HotKey/HotKeyManagerInterface.h
  66. 2 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/HotKey/HotKeyManagerInternalInterface.h
  67. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/EditorMenu.cpp
  68. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/EditorMenuBar.cpp
  69. 5 3
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h
  70. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/MenuManagerInternalInterface.h
  71. 3 1
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/EditorToolBar.cpp
  72. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/EditorToolBarArea.cpp
  73. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInterface.h
  74. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInternalInterface.h
  75. 16 12
      Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSeedManager.h
  76. 3 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserThumbnailView.cpp
  77. 2 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp
  78. 0 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalogManager.h
  79. 1 0
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.cpp
  80. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
  81. 5 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EntityUtilityComponent.h
  82. 2 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h
  83. 0 2
      Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h
  84. 0 1
      Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/TranslationManipulators.cpp
  85. 0 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/TranslationManipulators.h
  86. 2 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/MetaUuidEntry.cpp
  87. 8 1
      Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/MetaUuidEntry.h
  88. 4 1
      Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/UuidUtils.h
  89. 5 1
      Code/Framework/AzToolsFramework/AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsSystemComponent.h
  90. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h
  91. 4 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
  92. 4 3
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
  93. 3 2
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderScriptingBus.h
  94. 5 6
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
  95. 1 1
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h
  96. 3 1
      Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/ScriptingPrefabLoader.h
  97. 3 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h
  98. 3 3
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.h
  99. 3 2
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorAssetMimeDataContainer.h
  100. 5 3
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h

+ 49 - 91
AutomatedTesting/Assets/Physics/Collider_MultipleSurfaceSlots/test.fbx.assetinfo

@@ -1,91 +1,49 @@
-<ObjectStream version="3">
-	<Class name="SceneManifest" version="1" type="{9274AD17-3212-4651-9F3B-7DCCB080E467}">
-		<Class name="AZStd::vector" field="values" type="{5D6A7C67-11CA-59A4-829B-0B20B781B292}">
-			<Class name="AZStd::shared_ptr" field="element" type="{EB7522F9-0E87-55A9-A191-E924DC5AE867}">
-				<Class name="MeshGroup" field="element" version="1" type="{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B}">
-					<Class name="ISceneNodeGroup" field="BaseClass1" version="1" type="{1D20FA11-B184-429E-8C86-745852234845}">
-						<Class name="IGroup" field="BaseClass1" version="1" type="{DE008E67-790D-4672-A73A-5CA0F31EDD2D}">
-							<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-						</Class>
-					</Class>
-					<Class name="AZStd::string" field="name" value="test" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="bool" field="export as convex" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="float" field="AreaTestEpsilon" value="0.0600000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="float" field="PlaneTolerance" value="0.0007000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="bool" field="Use16bitIndices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="CheckZeroAreaTriangles" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="QuantizeInput" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="UsePlaneShifting" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="ShiftVertices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="unsigned int" field="GaussMapLimit" value="32" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-					<Class name="bool" field="WeldVertices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="DisableCleanMesh" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="Force32BitIndices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="SuppressTriangleMeshRemapTable" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="BuildTriangleAdjacencies" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="float" field="MeshWeldTolerance" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="unsigned int" field="NumTrisPerLeaf" value="4" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-					<Class name="bool" field="BuildGPUData" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="SceneNodeSelectionList" field="NodeSelectionList" version="1" type="{D0CE66CE-1BAD-42F5-86ED-3923573B3A02}">
-						<Class name="ISceneNodeSelectionList" field="BaseClass1" version="1" type="{DC3F9996-E550-4780-A03B-80B0DDA1DA45}"/>
-						<Class name="AZStd::vector" field="selectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}">
-							<Class name="AZStd::string" field="element" value="RootNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pSphere1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						</Class>
-						<Class name="AZStd::vector" field="unselectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
-					</Class>
-					<Class name="AZ::Uuid" field="id" value="{41412636-5633-5803-972D-4BC87D362E4D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-					<Class name="RuleContainer" field="rules" version="1" type="{2C20D3DF-57FF-4A31-8680-A4D45302B9CF}">
-						<Class name="AZStd::vector" field="rules" type="{B5BDB053-178F-5D55-8663-70897A71B7C9}"/>
-					</Class>
-				</Class>
-			</Class>
-			<Class name="AZStd::shared_ptr" field="element" type="{EB7522F9-0E87-55A9-A191-E924DC5AE867}">
-				<Class name="MeshGroup" field="element" version="3" type="{07B356B7-3635-40B5-878A-FAC4EFD5AD86}">
-					<Class name="IMeshGroup" field="BaseClass1" version="2" type="{74D45E45-81EE-4AD4-83B5-F37EB98D847C}">
-						<Class name="ISceneNodeGroup" field="BaseClass1" version="1" type="{1D20FA11-B184-429E-8C86-745852234845}">
-							<Class name="IGroup" field="BaseClass1" version="1" type="{DE008E67-790D-4672-A73A-5CA0F31EDD2D}">
-								<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-							</Class>
-						</Class>
-					</Class>
-					<Class name="AZStd::string" field="name" value="test" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="SceneNodeSelectionList" field="nodeSelectionList" version="1" type="{D0CE66CE-1BAD-42F5-86ED-3923573B3A02}">
-						<Class name="ISceneNodeSelectionList" field="BaseClass1" version="1" type="{DC3F9996-E550-4780-A03B-80B0DDA1DA45}"/>
-						<Class name="AZStd::vector" field="selectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}">
-							<Class name="AZStd::string" field="element" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pSphere1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						</Class>
-						<Class name="AZStd::vector" field="unselectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
-					</Class>
-					<Class name="RuleContainer" field="rules" version="1" type="{2C20D3DF-57FF-4A31-8680-A4D45302B9CF}">
-						<Class name="AZStd::vector" field="rules" type="{B5BDB053-178F-5D55-8663-70897A71B7C9}">
-							<Class name="AZStd::shared_ptr" field="element" type="{0BB4AFBA-F087-55C7-95DF-01D71F6CB052}">
-								<Class name="MaterialRule" field="element" version="2" type="{35620013-A27C-4F6D-87BF-72F11688ACAD}">
-									<Class name="IMaterialRule" field="BaseClass1" version="1" type="{428C9752-6EDF-4FA2-9BDF-DBDFCEB4CC0F}">
-										<Class name="IRule" field="BaseClass1" version="1" type="{81267F8B-3963-423B-9FF7-D276D82CD110}">
-											<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-										</Class>
-									</Class>
-									<Class name="bool" field="updateMaterials" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="removeMaterials" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-							</Class>
-						</Class>
-					</Class>
-					<Class name="AZ::Uuid" field="id" value="{1624E866-D20F-5FBB-8982-2FA4392A588F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				</Class>
-			</Class>
-		</Class>
-	</Class>
-</ObjectStream>
-
+{
+    "values": [
+        {
+            "$type": "{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup",
+            "id": "{41412636-5633-5803-972D-4BC87D362E4D}",
+            "name": "test",
+            "NodeSelectionList": {
+                "selectedNodes": [
+                    "RootNode",
+                    "RootNode.group2",
+                    "RootNode.group2.pSphere1",
+                    "RootNode.group2.pCube1",
+                    "RootNode.group2.pCube2",
+                    "RootNode.group2.pCube3"
+                ]
+            },
+            "PhysicsMaterialSlots": {
+                "Slots": [
+                    {
+                        "Name": "Entire object"
+                    }
+                ]
+            }
+        },
+        {
+            "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup",
+            "name": "test",
+            "nodeSelectionList": {
+                "selectedNodes": [
+                    {},
+                    "RootNode",
+                    "RootNode.group2",
+                    "RootNode.group2.pSphere1",
+                    "RootNode.group2.pCube1",
+                    "RootNode.group2.pCube2",
+                    "RootNode.group2.pCube3"
+                ]
+            },
+            "rules": {
+                "rules": [
+                    {
+                        "$type": "MaterialRule"
+                    }
+                ]
+            },
+            "id": "{1624E866-D20F-5FBB-8982-2FA4392A588F}"
+        }
+    ]
+}

+ 49 - 91
AutomatedTesting/Levels/Physics/Material_PerFaceMaterialGetsCorrectMaterial/test.fbx.assetinfo

@@ -1,91 +1,49 @@
-<ObjectStream version="3">
-	<Class name="SceneManifest" version="1" type="{9274AD17-3212-4651-9F3B-7DCCB080E467}">
-		<Class name="AZStd::vector" field="values" type="{5D6A7C67-11CA-59A4-829B-0B20B781B292}">
-			<Class name="AZStd::shared_ptr" field="element" type="{EB7522F9-0E87-55A9-A191-E924DC5AE867}">
-				<Class name="MeshGroup" field="element" version="1" type="{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B}">
-					<Class name="ISceneNodeGroup" field="BaseClass1" version="1" type="{1D20FA11-B184-429E-8C86-745852234845}">
-						<Class name="IGroup" field="BaseClass1" version="1" type="{DE008E67-790D-4672-A73A-5CA0F31EDD2D}">
-							<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-						</Class>
-					</Class>
-					<Class name="AZStd::string" field="name" value="test" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="bool" field="export as convex" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="float" field="AreaTestEpsilon" value="0.0600000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="float" field="PlaneTolerance" value="0.0007000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="bool" field="Use16bitIndices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="CheckZeroAreaTriangles" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="QuantizeInput" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="UsePlaneShifting" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="ShiftVertices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="unsigned int" field="GaussMapLimit" value="32" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-					<Class name="bool" field="WeldVertices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="DisableCleanMesh" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="Force32BitIndices" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="SuppressTriangleMeshRemapTable" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="bool" field="BuildTriangleAdjacencies" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="float" field="MeshWeldTolerance" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-					<Class name="unsigned int" field="NumTrisPerLeaf" value="4" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-					<Class name="bool" field="BuildGPUData" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-					<Class name="SceneNodeSelectionList" field="NodeSelectionList" version="1" type="{D0CE66CE-1BAD-42F5-86ED-3923573B3A02}">
-						<Class name="ISceneNodeSelectionList" field="BaseClass1" version="1" type="{DC3F9996-E550-4780-A03B-80B0DDA1DA45}"/>
-						<Class name="AZStd::vector" field="selectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}">
-							<Class name="AZStd::string" field="element" value="RootNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pSphere1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						</Class>
-						<Class name="AZStd::vector" field="unselectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
-					</Class>
-					<Class name="AZ::Uuid" field="id" value="{5C756CD0-D832-5259-99F0-A1C8F6EFDC84}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-					<Class name="RuleContainer" field="rules" version="1" type="{2C20D3DF-57FF-4A31-8680-A4D45302B9CF}">
-						<Class name="AZStd::vector" field="rules" type="{B5BDB053-178F-5D55-8663-70897A71B7C9}"/>
-					</Class>
-				</Class>
-			</Class>
-			<Class name="AZStd::shared_ptr" field="element" type="{EB7522F9-0E87-55A9-A191-E924DC5AE867}">
-				<Class name="MeshGroup" field="element" version="3" type="{07B356B7-3635-40B5-878A-FAC4EFD5AD86}">
-					<Class name="IMeshGroup" field="BaseClass1" version="2" type="{74D45E45-81EE-4AD4-83B5-F37EB98D847C}">
-						<Class name="ISceneNodeGroup" field="BaseClass1" version="1" type="{1D20FA11-B184-429E-8C86-745852234845}">
-							<Class name="IGroup" field="BaseClass1" version="1" type="{DE008E67-790D-4672-A73A-5CA0F31EDD2D}">
-								<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-							</Class>
-						</Class>
-					</Class>
-					<Class name="AZStd::string" field="name" value="test" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="SceneNodeSelectionList" field="nodeSelectionList" version="1" type="{D0CE66CE-1BAD-42F5-86ED-3923573B3A02}">
-						<Class name="ISceneNodeSelectionList" field="BaseClass1" version="1" type="{DC3F9996-E550-4780-A03B-80B0DDA1DA45}"/>
-						<Class name="AZStd::vector" field="selectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}">
-							<Class name="AZStd::string" field="element" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pSphere1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-							<Class name="AZStd::string" field="element" value="RootNode.group2.pCube3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						</Class>
-						<Class name="AZStd::vector" field="unselectedNodes" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
-					</Class>
-					<Class name="RuleContainer" field="rules" version="1" type="{2C20D3DF-57FF-4A31-8680-A4D45302B9CF}">
-						<Class name="AZStd::vector" field="rules" type="{B5BDB053-178F-5D55-8663-70897A71B7C9}">
-							<Class name="AZStd::shared_ptr" field="element" type="{0BB4AFBA-F087-55C7-95DF-01D71F6CB052}">
-								<Class name="MaterialRule" field="element" version="2" type="{35620013-A27C-4F6D-87BF-72F11688ACAD}">
-									<Class name="IMaterialRule" field="BaseClass1" version="1" type="{428C9752-6EDF-4FA2-9BDF-DBDFCEB4CC0F}">
-										<Class name="IRule" field="BaseClass1" version="1" type="{81267F8B-3963-423B-9FF7-D276D82CD110}">
-											<Class name="IManifestObject" field="BaseClass1" type="{3B839407-1884-4FF4-ABEA-CA9D347E83F7}"/>
-										</Class>
-									</Class>
-									<Class name="bool" field="updateMaterials" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="removeMaterials" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-							</Class>
-						</Class>
-					</Class>
-					<Class name="AZ::Uuid" field="id" value="{75C73BDA-1256-53D6-B4ED-B4C9D53440EE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				</Class>
-			</Class>
-		</Class>
-	</Class>
-</ObjectStream>
-
+{
+    "values": [
+        {
+            "$type": "{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup",
+            "id": "{5C756CD0-D832-5259-99F0-A1C8F6EFDC84}",
+            "name": "test",
+            "NodeSelectionList": {
+                "selectedNodes": [
+                    "RootNode",
+                    "RootNode.group2",
+                    "RootNode.group2.pSphere1",
+                    "RootNode.group2.pCube1",
+                    "RootNode.group2.pCube2",
+                    "RootNode.group2.pCube3"
+                ]
+            },
+            "PhysicsMaterialSlots": {
+                "Slots": [
+                    {
+                        "Name": "Entire object"
+                    }
+                ]
+            }
+        },
+        {
+            "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup",
+            "name": "test",
+            "nodeSelectionList": {
+                "selectedNodes": [
+                    {},
+                    "RootNode",
+                    "RootNode.group2",
+                    "RootNode.group2.pSphere1",
+                    "RootNode.group2.pCube1",
+                    "RootNode.group2.pCube2",
+                    "RootNode.group2.pCube3"
+                ]
+            },
+            "rules": {
+                "rules": [
+                    {
+                        "$type": "MaterialRule"
+                    }
+                ]
+            },
+            "id": "{75C73BDA-1256-53D6-B4ED-B4C9D53440EE}"
+        }
+    ]
+}

+ 2 - 2
Code/Editor/DisplaySettingsPythonFuncs.cpp

@@ -11,8 +11,8 @@
 #include "DisplaySettingsPythonFuncs.h"
 
 // AzCore
-#include <AzCore/RTTI/ReflectContext.h>
 #include <AzCore/RTTI/BehaviorContext.h>
+#include <AzCore/Serialization/SerializeContext.h>
 
 // Editor
 #include "DisplaySettings.h"
@@ -74,7 +74,7 @@ namespace AzToolsFramework
             };
             addLegacyGeneral(behaviorContext->Method("get_misc_editor_settings", PyGetMiscDisplaySettings, nullptr, "Get miscellaneous Editor settings (camera collides with terrain, AI/Physics enabled, etc)."));
             addLegacyGeneral(behaviorContext->Method("set_misc_editor_settings", PySetMiscDisplaySettings, nullptr, "Set miscellaneous Editor settings (camera collides with terrain, AI/Physics enabled, etc)."));
-            
+
             behaviorContext->EnumProperty<EDisplaySettingsFlags::SETTINGS_NOCOLLISION>("DisplaySettings_NoCollision")
                 ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation);
             behaviorContext->EnumProperty<EDisplaySettingsFlags::SETTINGS_NOLABELS>("DisplaySettings_NoLabels")

+ 1 - 0
Code/Editor/EditorPreferencesPageAWS.cpp

@@ -11,6 +11,7 @@
 
 // AzCore
 #include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Settings/SettingsRegistryImpl.h>
 #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
 #include <AzCore/Jobs/JobFunction.h>
 

+ 8 - 3
Code/Editor/EditorPreferencesPageAWS.h

@@ -8,11 +8,16 @@
 #pragma once
 
 #include "Include/IPreferencesPage.h"
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Settings/SettingsRegistryImpl.h>
-#include <AzCore/RTTI/RTTI.h>
+
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+    class SettingsRegistryImpl;
+}
+
 class CEditorPreferencesPage_AWS
     : public IPreferencesPage
 {

+ 6 - 2
Code/Editor/EditorPreferencesPageExperimentalLighting.h

@@ -8,10 +8,14 @@
 #pragma once
 
 #include "Include/IPreferencesPage.h"
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+}
 
 class CEditorPreferencesPage_ExperimentalLighting
     : public IPreferencesPage

+ 2 - 0
Code/Editor/EditorPreferencesPageFiles.cpp

@@ -9,6 +9,8 @@
 
 #include "EditorPreferencesPageFiles.h"
 
+#include <AzCore/Serialization/EditContext.h>
+
 // AzToolsFramework
 #include <AzToolsFramework/Slice/SliceUtilities.h>
 

+ 6 - 3
Code/Editor/EditorPreferencesPageFiles.h

@@ -8,13 +8,16 @@
 #pragma once
 
 #include "Include/IPreferencesPage.h"
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <AzCore/Math/Vector3.h>
 #include <QIcon>
 
 
+namespace AZ
+{
+    class SerializeContext;
+}
 class CEditorPreferencesPage_Files
     : public IPreferencesPage
 {

+ 7 - 3
Code/Editor/EditorPreferencesPageGeneral.h

@@ -8,9 +8,8 @@
 #pragma once
 
 #include "Include/IPreferencesPage.h"
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <AzCore/Math/Vector3.h>
 #include <AzQtComponents/Components/Widgets/ToolBar.h>
 #include <AzToolsFramework/Editor/EditorSettingsAPIBus.h>
@@ -19,6 +18,11 @@
 
 #include "Settings.h"
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 class CEditorPreferencesPage_General
     : public IPreferencesPage
 {

+ 7 - 3
Code/Editor/EditorPreferencesPageViewportCamera.h

@@ -12,12 +12,16 @@
 
 #include <AzCore/Math/Vector2.h>
 #include <AzCore/Math/Vector3.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 class CEditorPreferencesPage_ViewportCamera : public IPreferencesPage
 {
 public:

+ 6 - 2
Code/Editor/EditorPreferencesPageViewportDebug.h

@@ -8,10 +8,14 @@
 #pragma once
 
 #include "Include/IPreferencesPage.h"
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/RTTI/RTTI.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+}
 
 class CEditorPreferencesPage_ViewportDebug
     : public IPreferencesPage

+ 3 - 1
Code/Editor/EditorPreferencesPageViewportGeneral.cpp

@@ -11,6 +11,8 @@
 #include "EditorPreferencesPageViewportGeneral.h"
 #include "EditorViewportSettings.h"
 
+#include <AzCore/Serialization/EditContext.h>
+
 #include <AzQtComponents/Components/StyleManager.h>
 
 // Editor
@@ -280,7 +282,7 @@ void CEditorPreferencesPage_ViewportGeneral::InitializeSettings()
     m_general.m_defaultNearPlane = SandboxEditor::CameraDefaultNearPlaneDistance();
     m_general.m_defaultFarPlane = SandboxEditor::CameraDefaultFarPlaneDistance();
     m_general.m_defaultFOV = SandboxEditor::CameraDefaultFovDegrees();
-    
+
     m_general.m_contextMenuEnabled = gSettings.viewports.bEnableContextMenu;
     m_general.m_sync2DViews = gSettings.viewports.bSync2DViews;
     m_general.m_stickySelectEnabled = SandboxEditor::StickySelectEnabled();

+ 7 - 3
Code/Editor/EditorPreferencesPageViewportGeneral.h

@@ -10,11 +10,15 @@
 
 #include "Include/IPreferencesPage.h"
 #include <AzCore/Math/Color.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 class CEditorPreferencesPage_ViewportGeneral : public IPreferencesPage
 {
 public:

+ 2 - 0
Code/Editor/EditorPreferencesPageViewportManipulator.cpp

@@ -10,6 +10,8 @@
 
 #include "EditorPreferencesPageViewportManipulator.h"
 
+#include <AzCore/Serialization/EditContext.h>
+
 #include <AzToolsFramework/Viewport/ViewportSettings.h>
 
 // Editor

+ 7 - 3
Code/Editor/EditorPreferencesPageViewportManipulator.h

@@ -10,11 +10,15 @@
 
 #include "Include/IPreferencesPage.h"
 #include <AzCore/Math/Vector3.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <QIcon>
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 class CEditorPreferencesPage_ViewportManipulator : public IPreferencesPage
 {
 public:

+ 1 - 0
Code/Editor/Objects/ObjectManager.h

@@ -15,6 +15,7 @@
 #include "SelectionGroup.h"
 #include "ObjectManagerEventBus.h"
 
+#include <AzCore/std/containers/map.h>
 #include <AzCore/std/smart_ptr/unique_ptr.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Component/Component.h>

+ 14 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp

@@ -29,6 +29,7 @@
 #include "SandboxIntegration.h"
 #include "Objects/ComponentEntityObject.h"
 
+
 namespace ComponentEntityEditorPluginInternal
 {
     void RegisterSandboxObjects()
@@ -102,13 +103,25 @@ namespace ComponentEntityEditorPluginInternal
                 "\nMake sure the Reflect function is called for all base classes as well.");
 
             // this happens during startup, and its a programmer error - so during startup, make it an error, so it shows as a pretty noisy
-            // popup box.  Its important that programmers fix this, before they submit their code, so that data corruption / data loss does 
+            // popup box.  Its important that programmers fix this, before they submit their code, so that data corruption / data loss does
             // not occur.
             AZ_Error("Serialize", false, message.c_str());
         }
     }
 } // end namespace ComponentEntityEditorPluginInternal
 
+void ComponentPaletteSettings::Reflect(AZ::ReflectContext* context)
+{
+    AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
+    if (serializeContext)
+    {
+        serializeContext->Class<ComponentPaletteSettings>()
+            ->Version(1)
+            ->Field("m_favorites", &ComponentPaletteSettings::m_favorites)
+            ;
+    }
+}
+
 ComponentEntityEditorPlugin::ComponentEntityEditorPlugin([[maybe_unused]] IEditor* editor)
     : m_registered(false)
 {

+ 8 - 13
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteSettings.h

@@ -11,11 +11,16 @@
 
 #include <AzCore/base.h>
 #include <AzCore/Memory/SystemAllocator.h>
-#include <AzCore/RTTI/ReflectContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+
 #include <AzCore/UserSettings/UserSettings.h>
 
 //=============================================================================
+namespace AZ
+{
+    class ReflectContext;
+}
 
 class ComponentPaletteSettings
     : public AZ::UserSettings
@@ -51,16 +56,6 @@ public:
         return settingsFile;
     }
 
-    static void Reflect(AZ::ReflectContext* context)
-    {
-        AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
-        if (serializeContext)
-        {
-            serializeContext->Class<ComponentPaletteSettings>()
-                ->Version(1)
-                ->Field("m_favorites", &ComponentPaletteSettings::m_favorites)
-                ;
-        }
-    }
+    static void Reflect(AZ::ReflectContext* context);
 };
 

+ 0 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx

@@ -376,7 +376,6 @@ private:
     mutable CheckboxGroup m_lockCheckBoxes;
 
     const int m_layerDividerLineHeight = 1;
-    const int m_lastEntityInLayerDividerLineHeight = 1;
     const int m_toggleColumnWidth = 16;
 
     // this is a cache, and is hence mutable

+ 0 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp

@@ -141,7 +141,6 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
     , m_gui(nullptr)
     , m_listModel(nullptr)
     , m_proxyModel(nullptr)
-    , m_selectionContextId(0)
     , m_selectedEntityIds()
     , m_inObjectPickMode(false)
     , m_scrollToNewContentQueued(false)

+ 0 - 2
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx

@@ -121,7 +121,6 @@ private:
     Ui::OutlinerWidgetUI* m_gui;
     OutlinerListModel* m_listModel;
     OutlinerSortFilterProxyModel* m_proxyModel;
-    AZ::u64 m_selectionContextId;
     AZStd::vector<AZ::EntityId> m_selectedEntityIds;
 
     void PrepareSelection();
@@ -154,7 +153,6 @@ private:
     QAction* m_actionToDeleteSelection;
     QAction* m_actionToDeleteSelectionAndDescendants;
     QAction* m_actionToRenameSelection;
-    QAction* m_actionToReparentSelection;
     QAction* m_actionToMoveEntityUp;
     QAction* m_actionToMoveEntityDown;
     QAction* m_actionGoToEntitiesInViewport;

+ 0 - 2
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentEntityEditorMainWindow.h

@@ -10,8 +10,6 @@
 #if !defined(Q_MOC_RUN)
 #include <QMainWindow>
 
-#include <AzCore/Serialization/SerializeContext.h>
-
 #include <CryCommon/ISystem.h>
 #endif
 

+ 0 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentEntityEditorOutlinerWindow.h

@@ -10,7 +10,6 @@
 #if !defined(Q_MOC_RUN)
 #include <QMainWindow>
 
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
 #endif
 

+ 0 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/QComponentLevelEntityEditorMainWindow.h

@@ -10,7 +10,6 @@
 #if !defined(Q_MOC_RUN)
 #include <QMainWindow>
 
-#include <AzCore/Serialization/SerializeContext.h>
 #include <Editor/IEditor.h>
 #include <AzToolsFramework/Slice/SliceMetadataEntityContextBus.h>
 #endif

+ 27 - 20
Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp

@@ -329,13 +329,38 @@ namespace AZ
     //=========================================================================
     // Reflect
     //=========================================================================
-    void  ComponentApplication::Descriptor::Reflect(ReflectContext* context, ComponentApplication* app)
+    void ComponentApplication::Descriptor::Reflect(ReflectContext* context, ComponentApplication* app)
     {
+        // Create a local ObjectFactory that passes the component application descriptor
+        // to the SerializeContext
+        struct DescriptorFactory
+            : public SerializeContext::IObjectFactory
+        {
+            DescriptorFactory(Descriptor* descriptor)
+                : m_descriptor(descriptor)
+            {}
+
+            void* Create(const char*) override
+            {
+                // Return a pointer to the component application descriptor
+                return m_descriptor;
+            }
+            void  Destroy(void*) override
+            {
+                // do nothing as descriptor is part of the component application
+            }
+
+        private:
+            Descriptor* m_descriptor;
+        };
+
+        static DescriptorFactory descriptorFactory(&app->GetDescriptor());
+
         DynamicModuleDescriptor::Reflect(context);
 
         if (auto serializeContext = azrtti_cast<SerializeContext*>(context))
         {
-            serializeContext->Class<Descriptor>(&app->GetDescriptor())
+            serializeContext->Class<Descriptor>(&descriptorFactory)
                 ->Version(2, AppDescriptorConverter)
                 ->Field("useExistingAllocator", &Descriptor::m_useExistingAllocator)
                 ->Field("allocationRecordsSaveNames", &Descriptor::m_allocationRecordsSaveNames)
@@ -386,24 +411,6 @@ namespace AZ
         }
     }
 
-    //=========================================================================
-    // Create
-    //=========================================================================
-    void* ComponentApplication::Descriptor::Create(const char* name)
-    {
-        (void)name;
-        return this; /// we the the factory and the object as we are part of the component application
-    }
-
-    //=========================================================================
-    // Destroy
-    //=========================================================================
-    void ComponentApplication::Descriptor::Destroy(void* data)
-    {
-        // do nothing as descriptor is part of the component application
-        (void)data;
-    }
-
     //=========================================================================
     // ComponentApplication
     // [5/30/2012]

+ 1 - 8
Code/Framework/AzCore/AzCore/Component/ComponentApplication.h

@@ -19,7 +19,6 @@
 #include <AzCore/Module/ModuleManager.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/SystemFile.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/RTTI/ReflectionManager.h>
 #include <AzCore/Settings/CommandLine.h>
 #include <AzCore/Settings/SettingsRegistry.h>
@@ -34,6 +33,7 @@
 namespace AZ
 {
     class BehaviorContext;
+    class SerializeContext;
     class IConsole;
     class Module;
     class ModuleManager;
@@ -99,17 +99,10 @@ namespace AZ
          *       Use the OSAllocator only.
          */
         struct Descriptor
-            : public SerializeContext::IObjectFactory
         {
             AZ_TYPE_INFO(ComponentApplication::Descriptor, "{70277A3E-2AF5-4309-9BBF-6161AFBDE792}");
             AZ_CLASS_ALLOCATOR(ComponentApplication::Descriptor, SystemAllocator);
 
-            ///////////////////////////////////////////////
-            // SerializeContext::IObjectFactory
-            void* Create(const char* name) override;
-            void  Destroy(void* data) override;
-            ///////////////////////////////////////////////
-
             /// Reflect the descriptor data.
             static void     Reflect(ReflectContext* context, ComponentApplication* app);
 

+ 2 - 2
Code/Framework/AzCore/AzCore/IO/Path/PathReflect.cpp

@@ -289,12 +289,12 @@ namespace AZ::IO
         if (auto serializeContext = azrtti_cast<SerializeContext*>(context); serializeContext != nullptr)
         {
             serializeContext->Class<Path>()
-                ->Serializer(AZ::SerializeContext::IDataSerializerPtr{ new PathSerializer<Path>{},
+                ->Serializer(AZ::Serialize::IDataSerializerPtr{ new PathSerializer<Path>{},
                 AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() })
                 ;
 
             serializeContext->Class<FixedMaxPath>()
-                ->Serializer(AZ::SerializeContext::IDataSerializerPtr{ new PathSerializer<FixedMaxPath>{},
+                ->Serializer(AZ::Serialize::IDataSerializerPtr{ new PathSerializer<FixedMaxPath>{},
                 AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() })
                 ;
         }

+ 1 - 328
Code/Framework/AzCore/AzCore/Memory/Memory.h

@@ -8,6 +8,7 @@
 #pragma once
 
 #include <AzCore/base.h>
+#include <AzCore/Memory/Memory_fwd.h>
 #include <AzCore/Memory/AllocatorWrapper.h>
 #include <AzCore/Memory/Config.h>
 #include <AzCore/Memory/SimpleSchemaAllocator.h>
@@ -20,328 +21,6 @@
 #include <AzCore/Module/Environment.h>
 #include <AzCore/Memory/AllocatorInstance.h>
 
-
-/**
- * AZ Memory allocation supports all best know allocation schemes. Even though we highly recommend using the
- * class overriding of new/delete operators for which we provide \ref ClassAllocators. We don't restrict to
- * use whatever you need, each way has it's benefits and drawback. Each of those will be described as we go along.
- * In every macro that doesn't require to specify an allocator AZ::SystemAllocator is implied.
- */
-#if !defined(_RELEASE)
-    #define aznew                                                   new
-    #define aznewex(_Name)                                          new
-
-/// azmalloc(size)
-    #define azmalloc_1(_1)                                          AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1)
-/// azmalloc(size,alignment)
-    #define azmalloc_2(_1, _2)                                      AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1, _2)
-/// azmalloc(size,alignment,Allocator)
-    #define azmalloc_3(_1, _2, _3)                                  AZ::AllocatorInstance< _3 >::Get().allocate(_1, _2)
-
-/// azcreate(class,params)
-    #define azcreate_2(_1, _2)                                      new(azmalloc_3(sizeof(_1), AZStd::alignment_of< _1 >::value, AZ::SystemAllocator)) _1 _2
-/// azcreate(class,params,Allocator)
-    #define azcreate_3(_1, _2, _3)                                  new(azmalloc_3(sizeof(_1), AZStd::alignment_of< _1 >::value, _3)) _1 _2
-#else
-    #define aznew           new
-    #define aznewex(_Name)  new
-
-/// azmalloc(size)
-    #define azmalloc_1(_1)                                          AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1)
-/// azmalloc(size,alignment)
-    #define azmalloc_2(_1, _2)                                      AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1, _2)
-/// azmalloc(size,alignment,Allocator)
-    #define azmalloc_3(_1, _2, _3)                                  AZ::AllocatorInstance< _3 >::Get().allocate(_1, _2)
-
-/// azcreate(class)
-    #define azcreate_1(_1)                                          new(azmalloc_3(sizeof(_1), AZStd::alignment_of< _1 >::value, AZ::SystemAllocator)) _1()
-/// azcreate(class,params)
-    #define azcreate_2(_1, _2)                                      new(azmalloc_3(sizeof(_1), AZStd::alignment_of< _1 >::value, AZ::SystemAllocator)) _1 _2
-/// azcreate(class,params,Allocator)
-    #define azcreate_3(_1, _2, _3)                                  new(azmalloc_3(sizeof(_1), AZStd::alignment_of< _1 >::value, _3)) _1 _2
-#endif
-
-/**
-* azmalloc is equivalent to ::malloc(...). It should be used with corresponding azfree call.
-* macro signature: azmalloc(size_t byteSize, size_t alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator)
-*/
-#define azmalloc(...)       AZ_MACRO_SPECIALIZE(azmalloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/// azcalloc(size)
-#define azcalloc_1(_1)                  ::memset(azmalloc_1(_1), 0, _1)
-/// azcalloc(size, alignment)
-#define azcalloc_2(_1, _2)              ::memset(azmalloc_2(_1, _2), 0, _1);
-/// azcalloc(size, alignment, Allocator)
-#define azcalloc_3(_1, _2, _3)          ::memset(azmalloc_3(_1, _2, _3), 0, _1);
-
-/**
-* azcalloc is equivalent to ::memset(azmalloc(...), 0, size);
-* macro signature: azcalloc(size, alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator, const char* name = "Default Name", int flags = 0)
-*/
-#define azcalloc(...)       AZ_MACRO_SPECIALIZE(azcalloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/// azrealloc(ptr, size)
-#define azrealloc_2(_1, _2)             AZ::AllocatorInstance<AZ::SystemAllocator>::Get().reallocate(_1, _2)
-/// azrealloc(ptr, size, alignment)
-#define azrealloc_3(_1, _2, _3)         AZ::AllocatorInstance<AZ::SystemAllocator>::Get().reallocate(_1, _2, _3)
-/// azrealloc(ptr, size, alignment, Allocator)
-#define azrealloc_4(_1, _2, _3, _4)     AZ::AllocatorInstance<_4>::Get().reallocate(_1, _2, _3)
-
-/**
-* azrealloc is equivalent to ::realloc(...)
-* macro signature: azrealloc(void* ptr, size_t size, size_t alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator)
-*/
-#define azrealloc(...)      AZ_MACRO_SPECIALIZE(azrealloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/**
- * azcreate is customized aznew function call. aznew can be used anywhere where we use new, while azcreate has a function call signature.
- * azcreate allows you to override the operator new and by this you can override the allocator per object instance. It should
- * be used with corresponding azdestroy call.
- * macro signature: azcreate(ClassName, CtorParams = (), AllocatorType = AZ::SystemAllocator)
- */
-#define azcreate(...)       AZ_MACRO_SPECIALIZE(azcreate_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/// azfree(pointer)
-#define azfree_1(_1)                do { if (_1) { AZ::AllocatorInstance< AZ::SystemAllocator >::Get().deallocate(_1); } }   while (0)
-/// azfree(pointer,allocator)
-#define azfree_2(_1, _2)            do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1); } }                    while (0)
-/// azfree(pointer,allocator,size)
-#define azfree_3(_1, _2, _3)        do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1, _3); } }                while (0)
-/// azfree(pointer,allocator,size,alignment)
-#define azfree_4(_1, _2, _3, _4)    do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1, _3, _4); } }            while (0)
-
-/**
- * azfree is equivalent to ::free(...). Is should be used with corresponding azmalloc call.
- * macro signature: azfree(Pointer* ptr, AllocatorType = AZ::SystemAllocator, size_t byteSize = Unknown, size_t alignment = DefaultAlignment);
- * \note Providing allocation size (byteSize) and alignment is optional, but recommended when possible. It will generate faster code.
- */
-#define azfree(...)         AZ_MACRO_SPECIALIZE(azfree_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/// Returns allocation size, based on it's pointer \ref AZ::IAllocator::AllocationSize.
-#define azallocsize(_Ptr, _Allocator)    AZ::AllocatorInstance< _Allocator >::Get().AllocationSize(_Ptr)
-/// Returns the new expanded size or 0 if NOT supported by the allocator \ref AZ::IAllocator::Resize.
-#define azallocresize(_Ptr, _NewSize, _Allocator) AZ::AllocatorInstance< _Allocator >::Get().Resize(_Ptr, _NewSize)
-
-namespace AZ {
-    // \note we can use AZStd::Internal::destroy<pointer_type>::single(ptr) if we template the entire function.
-    namespace Memory {
-        namespace Internal {
-            template<class T>
-            AZ_FORCE_INLINE void call_dtor(T* ptr)          { (void)ptr; ptr->~T(); }
-        }
-    }
-}
-
-#define azdestroy_1(_1)         do { AZ::Memory::Internal::call_dtor(_1); azfree_1(_1); } while (0)
-#define azdestroy_2(_1, _2)      do { AZ::Memory::Internal::call_dtor(_1); azfree_2(_1, _2); } while (0)
-#define azdestroy_3(_1, _2, _3)     do { AZ::Memory::Internal::call_dtor(reinterpret_cast<_3*>(_1)); azfree_4(_1, _2, sizeof(_3), AZStd::alignment_of< _3 >::value); } while (0)
-
-/**
- * azdestroy should be used only with corresponding azcreate.
- * macro signature: azdestroy(Pointer*, AllocatorType = AZ::SystemAllocator, ClassName = Unknown)
- * \note Providing ClassName is optional, but recommended when possible. It will generate faster code.
- */
-#define azdestroy(...)      AZ_MACRO_SPECIALIZE(azdestroy_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
-
-/**
- * Class Allocator (override new/delete operators)
- *
- * use this macro inside your objects to define it's default allocation (ex.):
- * class MyObj
- * {
- *   public:
- *          AZ_CLASS_ALLOCATOR(MyObj,SystemAllocator,0) - inline version requires to include the allocator (in this case sysallocator.h)
- *      or
- *          AZ_CLASS_ALLOCATOR_DECL in the header and AZ_CLASS_ALLOCATOR_IMPL(MyObj,SystemAllocator,0) in the cpp file. This way you don't need
- *          to include the allocator header where you decl your class (MyObj).
- *      ...
- * };
- *
- * \note We don't support array operators [] because they insert a compiler/platform
- * dependent array header, which then breaks the alignment in some cases.
- * If you want to use dynamic array use AZStd::vector or AZStd::fixed_vector.
- * Of course you can use placement new and do the array allocation anyway if
- * it's really needed.
- */
-#if __cpp_aligned_new
-// C++17 aligned alloc overloads for types with an alignment greater than sizeof(max_align_t)
-#define _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)                                                                                                                          \
-    /* class-specific allocation functions */                                                                                                                                                \
-    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align) {                                                                                                             \
-        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));                    \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, static_cast<std::size_t>(align));                                                                                   \
-    }                                                                                                                                                                                        \
-    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                             \
-        return operator new(size, align);                                                                                                                               \
-    }                                                                                                                                                                                        \
-    [[nodiscard]] void* operator new[]([[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) {                                                                         \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                             \
-                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                   \
-                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                              \
-        return AZ_INVALID_POINTER;                                                                                                                                                           \
-    }                                                                                                                                                                                        \
-    [[nodiscard]] void* operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                           \
-        return operator new[](size, align);                                                                                                                                                  \
-    }                                                                                                                                                                                        \
-    void operator delete(void* p, std::size_t size, std::align_val_t align) noexcept {                                                                                                       \
-        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, static_cast<std::size_t>(align)); }                                                                          \
-    }                                                                                                                                                                                        \
-    void operator delete[]([[maybe_unused]] void* p, [[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) noexcept {                                                  \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                             \
-                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                   \
-                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                              \
-    }
-#else
-#define _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)
-#endif
-
-#define AZ_CLASS_ALLOCATOR(_Class, _Allocator, ...)                                                                                                                              \
-    /* ========== placement operators (default) ========== */                                                                                                                       \
-    AZ_FORCE_INLINE void* operator new(std::size_t, void* p)    { return p; }   /* placement new */                                                                                 \
-    AZ_FORCE_INLINE void* operator new[](std::size_t, void* p)  { return p; }   /* placement array new */                                                                           \
-    AZ_FORCE_INLINE void  operator delete(void*, void*)         { }             /* placement delete, called when placement new asserts */                                           \
-    AZ_FORCE_INLINE void  operator delete[](void*, void*)       { }             /* placement array delete */                                                                        \
-    /* ========== standard operator new/delete ========== */                                                                                                                        \
-    AZ_FORCE_INLINE void* operator new(std::size_t size) {                      /* default operator new (called with "new _Class()") */                                             \
-        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));           \
-        AZ_Warning(0, true/*false*/, "Make sure you use aznew, offers better tracking! (%s)", #_Class /*Warning temporarily disabled until engine is using AZ allocators.*/);       \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, AZStd::alignment_of< _Class >::value);                                                                     \
-    }                                                                                                                                                                               \
-    AZ_FORCE_INLINE void  operator delete(void* p, std::size_t size) {    /* default operator delete */                                                                             \
-        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, AZStd::alignment_of< _Class >::value); }                                                            \
-    }                                                                                                                                                                               \
-    /* ========== Unsupported operators ========== */                                                                                                                               \
-    AZ_FORCE_INLINE void* operator new[](std::size_t) {                                         /* default array operator new (called with "new _Class[x]") */                      \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                    \
-                         "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                           \
-                         "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                      \
-        return AZ_INVALID_POINTER;                                                                                                                                                  \
-    }                                                                                                                                                                               \
-    AZ_FORCE_INLINE void  operator delete[](void*) {                                            /* default array operator delete */                                                 \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                    \
-                         "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                           \
-                         "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                      \
-    }                                                                                                                                                                               \
-    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                                              \
-    AZ_FORCE_INLINE static void* AZ_CLASS_ALLOCATOR_Allocate() {                                                                                                                    \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(sizeof(_Class), AZStd::alignment_of< _Class >::value);                                                           \
-    }                                                                                                                                                                               \
-    AZ_FORCE_INLINE static void AZ_CLASS_ALLOCATOR_DeAllocate(void* object) {                                                                                                       \
-        AZ::AllocatorInstance< _Allocator >::Get().deallocate(object, sizeof(_Class), AZStd::alignment_of< _Class >::value);                                                        \
-    }                                                                                                                                                                               \
-    template<bool Placeholder = true> void AZ_CLASS_ALLOCATOR_DECLARED();                                                                                                           \
-    _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)
-
-// If you want to avoid including the memory manager class in the header file use the _DECL (declaration) and _IMPL (implementations/definition) macros
-#if __cpp_aligned_new
-// Declares the C++17 aligned_new operator new/operator delete overloads
-#define _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW                                                                                                                 \
-    /* class-specific allocation functions */                                                                                                                \
-    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align);                                                                              \
-    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept;                                              \
-    [[nodiscard]] void* operator new[](std::size_t, std::align_val_t);                                                                                       \
-    [[nodiscard]] void* operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept;                                            \
-    void operator delete(void* p, std::size_t size, std::align_val_t align) noexcept;                                                                        \
-    void operator delete[](void* p, std::size_t size, std::align_val_t align) noexcept;
-#else
-#define _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW
-#endif
-
-#define AZ_CLASS_ALLOCATOR_DECL                                                                                                                           \
-    /* ========== placement operators (default) ========== */                                                                                             \
-    AZ_FORCE_INLINE void* operator new(std::size_t, void* p)    { return p; }                                                                             \
-    AZ_FORCE_INLINE void* operator new[](std::size_t, void* p)  { return p; }                                                                             \
-    AZ_FORCE_INLINE void operator delete(void*, void*)          { }                                                                                       \
-    AZ_FORCE_INLINE void operator delete[](void*, void*)        { }                                                                                       \
-    /* ========== standard operator new/delete ========== */                                                                                              \
-    void* operator new(std::size_t size);                                                                                                                 \
-    void  operator delete(void* p, std::size_t size);                                                                                                     \
-    /* ========== Unsupported operators ========== */                                                                                                     \
-    AZ_FORCE_INLINE void* operator new[](std::size_t) {                                                                                                   \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"          \
-                        "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                  \
-                        "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                             \
-        return AZ_INVALID_POINTER;                                                                                                                        \
-    }                                                                                                                                                     \
-    AZ_FORCE_INLINE void  operator delete[](void*) {                                                                                                      \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"          \
-                        "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                  \
-                        "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                             \
-    }                                                                                                                                                     \
-    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                    \
-    static void* AZ_CLASS_ALLOCATOR_Allocate();                                                                                                           \
-    static void  AZ_CLASS_ALLOCATOR_DeAllocate(void* object);                                                                                             \
-    template<bool Placeholder = true> void AZ_CLASS_ALLOCATOR_DECLARED();                                                                                 \
-    _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW
-
-#if __cpp_aligned_new
-// Defines the C++17 aligned_new operator new/operator delete overloads
-#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)                                                                                                                     \
-    _Template [[nodiscard]] void* _Class::operator new(std::size_t size, std::align_val_t align) {                                                                                                      \
-        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));                               \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, static_cast<std::size_t>(align));                                                                                              \
-    }                                                                                                                                                                                                   \
-    _Template [[nodiscard]] void* _Class::operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                      \
-        return operator new(size, align);                                                                                                                                                               \
-    }                                                                                                                                                                                                   \
-    _Template [[nodiscard]] void* _Class::operator new[]([[maybe_unused]] std::size_t, [[maybe_unused]] std::align_val_t) {                                                                             \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                                        \
-                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                              \
-                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                                         \
-        return AZ_INVALID_POINTER;                                                                                                                                                                      \
-    }                                                                                                                                                                                                   \
-    _Template [[nodiscard]] void* _Class::operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                    \
-        return operator new[](size, align);                                                                                                                                                             \
-    }                                                                                                                                                                                                   \
-    _Template void _Class::operator delete(void* p, std::size_t size, std::align_val_t align) noexcept {                                                                                                \
-        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, static_cast<std::size_t>(align)); }                                                                                     \
-    }                                                                                                                                                                                                   \
-    _Template void _Class::operator delete[]([[maybe_unused]] void* p, [[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) noexcept {                                           \
-        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                                        \
-                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                              \
-                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                                         \
-    }
-#else
-#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)
-#endif
-#define AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, _Template)                                                                                                                                                                     \
-    /* ========== standard operator new/delete ========== */                                                                                                                                                                                        \
-    _Template                                                                                                                                                                                                                                       \
-    [[nodiscard]] void* _Class::operator new(std::size_t size)                                                                                                                                                                                      \
-    {                                                                                                                                                                                                                                               \
-        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(_Class): %d", size, sizeof(_Class));                                                                                \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, AZStd::alignment_of< _Class >::value);                                                                                                                     \
-    }                                                                                                                                                                                                                                               \
-    _Template                                                                                                                                                                                                                                       \
-    void _Class::operator delete(void* p, std::size_t size)  {                                                                                                                                                                                      \
-        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, AZStd::alignment_of< _Class >::value); }                                                                                                                            \
-    }                                                                                                                                                                                                                                               \
-    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                                                                                                              \
-    _Template                                                                                                                                                                                                                                       \
-    [[nodiscard]] void* _Class::AZ_CLASS_ALLOCATOR_Allocate() {                                                                                                                                                                                     \
-        return AZ::AllocatorInstance< _Allocator >::Get().allocate(sizeof(_Class), AZStd::alignment_of< _Class >::value);                                                                                                          \
-    }                                                                                                                                                                                                                                               \
-    _Template                                                                                                                                                                                                                                       \
-    void _Class::AZ_CLASS_ALLOCATOR_DeAllocate(void* object) {                                                                                                                                                                                      \
-        AZ::AllocatorInstance< _Allocator >::Get().deallocate(object, sizeof(_Class), AZStd::alignment_of< _Class >::value);                                                                                                                        \
-    }                                                                                                                                                                                                                                               \
-    _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)
-
-#define AZ_CLASS_ALLOCATOR_IMPL(_Class, _Allocator, ...)                                                                                                                                                                                         \
-    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, )
-
-#define AZ_CLASS_ALLOCATOR_IMPL_TEMPLATE(_Class, _Allocator, ...)                                                                                                                                                                                \
-    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, template<>)
-
-//////////////////////////////////////////////////////////////////////////
-// new operator overloads
-
-// you can redefine this macro to whatever suits you.
-#ifndef AZCORE_GLOBAL_NEW_ALIGNMENT
-#   define AZCORE_GLOBAL_NEW_ALIGNMENT 16
-#endif
-
-
 /**
  * By default AZCore doesn't overload operator new and delete. This is a no-no for middle-ware.
  * You are encouraged to do that in your executable. What you need to do is to pipe all allocation trough AZCore memory manager.
@@ -492,12 +171,6 @@ namespace AZ
         functor_type m_allocatorFunctor;
     };
 
-    /**
-    * Helper class to determine if type T has a AZ_CLASS_ALLOCATOR defined,
-    * so we can safely call aznew on it. -  AZClassAllocator<ClassType>....
-    */
-    AZ_HAS_MEMBER(AZClassAllocator, AZ_CLASS_ALLOCATOR_DECLARED, void, ());
-
     // {@ Global New/Delete Operators
     [[nodiscard]] void* OperatorNew(std::size_t size);
     void OperatorDelete(void* ptr);

+ 352 - 0
Code/Framework/AzCore/AzCore/Memory/Memory_fwd.h

@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include <AzCore/base.h>
+#include <new>
+
+/**
+ * AZ Memory allocation supports all best know allocation schemes. Even though we highly recommend using the
+ * class overriding of new/delete operators for which we provide \ref ClassAllocators. We don't restrict to
+ * use whatever you need, each way has it's benefits and drawback. Each of those will be described as we go along.
+ * In every macro that doesn't require to specify an allocator AZ::SystemAllocator is implied.
+ */
+#define aznew                                                   new
+#define aznewex(_Name)                                          new
+
+/// azmalloc(size)
+#define azmalloc_1(_1)                                          AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1)
+/// azmalloc(size,alignment)
+#define azmalloc_2(_1, _2)                                      AZ::AllocatorInstance< AZ::SystemAllocator >::Get().allocate(_1, _2)
+/// azmalloc(size,alignment,Allocator)
+#define azmalloc_3(_1, _2, _3)                                  AZ::AllocatorInstance< _3 >::Get().allocate(_1, _2)
+
+/// azcreate(class)
+#define azcreate_1(_1)                                          new(azmalloc_3(sizeof(_1), alignof( _1 ), AZ::SystemAllocator)) _1()
+/// azcreate(class,params)
+#define azcreate_2(_1, _2)                                      new(azmalloc_3(sizeof(_1), alignof( _1 ), AZ::SystemAllocator)) _1 _2
+/// azcreate(class,params,Allocator)
+#define azcreate_3(_1, _2, _3)                                  new(azmalloc_3(sizeof(_1), alignof( _1 ), _3)) _1 _2
+
+/**
+* azmalloc is equivalent to ::malloc(...). It should be used with corresponding azfree call.
+* macro signature: azmalloc(size_t byteSize, size_t alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator)
+*/
+#define azmalloc(...)       AZ_MACRO_SPECIALIZE(azmalloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/// azcalloc(size)
+#define azcalloc_1(_1)                  ::memset(azmalloc_1(_1), 0, _1)
+/// azcalloc(size, alignment)
+#define azcalloc_2(_1, _2)              ::memset(azmalloc_2(_1, _2), 0, _1);
+/// azcalloc(size, alignment, Allocator)
+#define azcalloc_3(_1, _2, _3)          ::memset(azmalloc_3(_1, _2, _3), 0, _1);
+
+/**
+* azcalloc is equivalent to ::memset(azmalloc(...), 0, size);
+* macro signature: azcalloc(size, alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator, const char* name = "Default Name", int flags = 0)
+*/
+#define azcalloc(...)       AZ_MACRO_SPECIALIZE(azcalloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/// azrealloc(ptr, size)
+#define azrealloc_2(_1, _2)             AZ::AllocatorInstance<AZ::SystemAllocator>::Get().reallocate(_1, _2)
+/// azrealloc(ptr, size, alignment)
+#define azrealloc_3(_1, _2, _3)         AZ::AllocatorInstance<AZ::SystemAllocator>::Get().reallocate(_1, _2, _3)
+/// azrealloc(ptr, size, alignment, Allocator)
+#define azrealloc_4(_1, _2, _3, _4)     AZ::AllocatorInstance<_4>::Get().reallocate(_1, _2, _3)
+
+/**
+* azrealloc is equivalent to ::realloc(...)
+* macro signature: azrealloc(void* ptr, size_t size, size_t alignment = DefaultAlignment, AllocatorType = AZ::SystemAllocator)
+*/
+#define azrealloc(...)      AZ_MACRO_SPECIALIZE(azrealloc_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/**
+ * azcreate is customized aznew function call. aznew can be used anywhere where we use new, while azcreate has a function call signature.
+ * azcreate allows you to override the operator new and by this you can override the allocator per object instance. It should
+ * be used with corresponding azdestroy call.
+ * macro signature: azcreate(ClassName, CtorParams = (), AllocatorType = AZ::SystemAllocator)
+ */
+#define azcreate(...)       AZ_MACRO_SPECIALIZE(azcreate_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/// azfree(pointer)
+#define azfree_1(_1)                do { if (_1) { AZ::AllocatorInstance< AZ::SystemAllocator >::Get().deallocate(_1); } }   while (0)
+/// azfree(pointer,allocator)
+#define azfree_2(_1, _2)            do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1); } }                    while (0)
+/// azfree(pointer,allocator,size)
+#define azfree_3(_1, _2, _3)        do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1, _3); } }                while (0)
+/// azfree(pointer,allocator,size,alignment)
+#define azfree_4(_1, _2, _3, _4)    do { if (_1) { AZ::AllocatorInstance< _2 >::Get().deallocate(_1, _3, _4); } }            while (0)
+
+/**
+ * azfree is equivalent to ::free(...). Is should be used with corresponding azmalloc call.
+ * macro signature: azfree(Pointer* ptr, AllocatorType = AZ::SystemAllocator, size_t byteSize = Unknown, size_t alignment = DefaultAlignment);
+ * \note Providing allocation size (byteSize) and alignment is optional, but recommended when possible. It will generate faster code.
+ */
+#define azfree(...)         AZ_MACRO_SPECIALIZE(azfree_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/// Returns allocation size, based on it's pointer \ref AZ::IAllocator::AllocationSize.
+#define azallocsize(_Ptr, _Allocator)    AZ::AllocatorInstance< _Allocator >::Get().AllocationSize(_Ptr)
+/// Returns the new expanded size or 0 if NOT supported by the allocator \ref AZ::IAllocator::Resize.
+#define azallocresize(_Ptr, _NewSize, _Allocator) AZ::AllocatorInstance< _Allocator >::Get().Resize(_Ptr, _NewSize)
+
+#define azdestroy_1(_1)         do { [](auto* ptr){ using T = AZStd::remove_cvref_t<decltype(*ptr)>; ptr->~T(); }(_1); azfree_1(_1); } while (0)
+#define azdestroy_2(_1, _2)      do { [](auto* ptr){ using T = AZStd::remove_cvref_t<decltype(*ptr)>; ptr->~T(); }(_1); azfree_2(_1, _2); } while (0)
+#define azdestroy_3(_1, _2, _3)     do { [](auto* ptr){ using T = AZStd::remove_cvref_t<decltype(*ptr)>; ptr->~T(); }(reinterpret_cast<_3*>(_1)); azfree_4(_1, _2, sizeof(_3), alignof( _3 )); } while (0)
+
+/**
+ * azdestroy should be used only with corresponding azcreate.
+ * macro signature: azdestroy(Pointer*, AllocatorType = AZ::SystemAllocator, ClassName = Unknown)
+ * \note Providing ClassName is optional, but recommended when possible. It will generate faster code.
+ */
+#define azdestroy(...)      AZ_MACRO_SPECIALIZE(azdestroy_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+/**
+ * Class Allocator (override new/delete operators)
+ *
+ * use this macro inside your objects to define it's default allocation (ex.):
+ * class MyObj
+ * {
+ *   public:
+ *          AZ_CLASS_ALLOCATOR(MyObj,SystemAllocator,0) - inline version requires to include the allocator (in this case sysallocator.h)
+ *      or
+ *          AZ_CLASS_ALLOCATOR_DECL in the header and AZ_CLASS_ALLOCATOR_IMPL(MyObj,SystemAllocator,0) in the cpp file. This way you don't need
+ *          to include the allocator header where you decl your class (MyObj).
+ *      ...
+ * };
+ *
+ * \note We don't support array operators [] because they insert a compiler/platform
+ * dependent array header, which then breaks the alignment in some cases.
+ * If you want to use dynamic array use AZStd::vector or AZStd::fixed_vector.
+ * Of course you can use placement new and do the array allocation anyway if
+ * it's really needed.
+ */
+#if __cpp_aligned_new
+// C++17 aligned alloc overloads for types with an alignment greater than sizeof(max_align_t)
+#define _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)                                                                                                                          \
+    /* class-specific allocation functions */                                                                                                                                                \
+    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align) {                                                                                                             \
+        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));                    \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, static_cast<std::size_t>(align));                                                                                   \
+    }                                                                                                                                                                                        \
+    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                             \
+        return operator new(size, align);                                                                                                                               \
+    }                                                                                                                                                                                        \
+    [[nodiscard]] void* operator new[]([[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) {                                                                         \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                             \
+                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                   \
+                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                              \
+        return AZ_INVALID_POINTER;                                                                                                                                                           \
+    }                                                                                                                                                                                        \
+    [[nodiscard]] void* operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                           \
+        return operator new[](size, align);                                                                                                                                                  \
+    }                                                                                                                                                                                        \
+    void operator delete(void* p, std::size_t size, std::align_val_t align) noexcept {                                                                                                       \
+        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, static_cast<std::size_t>(align)); }                                                                          \
+    }                                                                                                                                                                                        \
+    void operator delete[]([[maybe_unused]] void* p, [[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) noexcept {                                                  \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                             \
+                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                   \
+                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                              \
+    }
+#else
+#define _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)
+#endif
+
+#define AZ_CLASS_ALLOCATOR(_Class, _Allocator, ...)                                                                                                                              \
+    /* ========== placement operators (default) ========== */                                                                                                                       \
+    AZ_FORCE_INLINE void* operator new(std::size_t, void* p)    { return p; }   /* placement new */                                                                                 \
+    AZ_FORCE_INLINE void* operator new[](std::size_t, void* p)  { return p; }   /* placement array new */                                                                           \
+    AZ_FORCE_INLINE void  operator delete(void*, void*)         { }             /* placement delete, called when placement new asserts */                                           \
+    AZ_FORCE_INLINE void  operator delete[](void*, void*)       { }             /* placement array delete */                                                                        \
+    /* ========== standard operator new/delete ========== */                                                                                                                        \
+    AZ_FORCE_INLINE void* operator new(std::size_t size) {                      /* default operator new (called with "new _Class()") */                                             \
+        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));           \
+        AZ_Warning(0, true/*false*/, "Make sure you use aznew, offers better tracking! (%s)", #_Class /*Warning temporarily disabled until engine is using AZ allocators.*/);       \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, alignof( _Class ));                                                                                        \
+    }                                                                                                                                                                               \
+    AZ_FORCE_INLINE void  operator delete(void* p, std::size_t size) {    /* default operator delete */                                                                             \
+        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, alignof( _Class )); }                                                                               \
+    }                                                                                                                                                                               \
+    /* ========== Unsupported operators ========== */                                                                                                                               \
+    AZ_FORCE_INLINE void* operator new[](std::size_t) {                                         /* default array operator new (called with "new _Class[x]") */                      \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                    \
+                         "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                           \
+                         "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                      \
+        return AZ_INVALID_POINTER;                                                                                                                                                  \
+    }                                                                                                                                                                               \
+    AZ_FORCE_INLINE void  operator delete[](void*) {                                            /* default array operator delete */                                                 \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                    \
+                         "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                           \
+                         "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                      \
+    }                                                                                                                                                                               \
+    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                                              \
+    AZ_FORCE_INLINE static void* AZ_CLASS_ALLOCATOR_Allocate() {                                                                                                                    \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(sizeof(_Class), alignof( _Class ));                                                                              \
+    }                                                                                                                                                                               \
+    AZ_FORCE_INLINE static void AZ_CLASS_ALLOCATOR_DeAllocate(void* object) {                                                                                                       \
+        AZ::AllocatorInstance< _Allocator >::Get().deallocate(object, sizeof(_Class), alignof( _Class ));                                                                           \
+    }                                                                                                                                                                               \
+    _AZ_CLASS_ALLOCATOR_ALIGNED_NEW(_Class, _Allocator)
+
+// If you want to avoid including the memory manager class in the header file use the _DECL (declaration) and _IMPL (implementations/definition) macros
+#if __cpp_aligned_new
+// Declares the C++17 aligned_new operator new/operator delete overloads
+#define _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW                                                                                                                 \
+    /* class-specific allocation functions */                                                                                                                \
+    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align);                                                                              \
+    [[nodiscard]] void* operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept;                                              \
+    [[nodiscard]] void* operator new[](std::size_t, std::align_val_t);                                                                                       \
+    [[nodiscard]] void* operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept;                                            \
+    void operator delete(void* p, std::size_t size, std::align_val_t align) noexcept;                                                                        \
+    void operator delete[](void* p, std::size_t size, std::align_val_t align) noexcept;
+#else
+#define _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW
+#endif
+
+#define AZ_CLASS_ALLOCATOR_DECL                                                                                                                           \
+    /* ========== placement operators (default) ========== */                                                                                             \
+    AZ_FORCE_INLINE void* operator new(std::size_t, void* p)    { return p; }                                                                             \
+    AZ_FORCE_INLINE void* operator new[](std::size_t, void* p)  { return p; }                                                                             \
+    AZ_FORCE_INLINE void operator delete(void*, void*)          { }                                                                                       \
+    AZ_FORCE_INLINE void operator delete[](void*, void*)        { }                                                                                       \
+    /* ========== standard operator new/delete ========== */                                                                                              \
+    void* operator new(std::size_t size);                                                                                                                 \
+    void  operator delete(void* p, std::size_t size);                                                                                                     \
+    /* ========== Unsupported operators ========== */                                                                                                     \
+    AZ_FORCE_INLINE void* operator new[](std::size_t) {                                                                                                   \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"          \
+                        "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                  \
+                        "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                             \
+        return AZ_INVALID_POINTER;                                                                                                                        \
+    }                                                                                                                                                     \
+    AZ_FORCE_INLINE void  operator delete[](void*) {                                                                                                      \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"          \
+                        "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                  \
+                        "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                             \
+    }                                                                                                                                                     \
+    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                    \
+    static void* AZ_CLASS_ALLOCATOR_Allocate();                                                                                                           \
+    static void  AZ_CLASS_ALLOCATOR_DeAllocate(void* object);                                                                                             \
+    _AZ_CLASS_ALLOCATOR_DECL_ALIGNED_NEW
+
+#if __cpp_aligned_new
+// Defines the C++17 aligned_new operator new/operator delete overloads
+#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)                                                                                                                     \
+    _Template [[nodiscard]] void* _Class::operator new(std::size_t size, std::align_val_t align) {                                                                                                      \
+        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(%s): %d", size, #_Class, sizeof(_Class));                               \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, static_cast<std::size_t>(align));                                                                                              \
+    }                                                                                                                                                                                                   \
+    _Template [[nodiscard]] void* _Class::operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                      \
+        return operator new(size, align);                                                                                                                                                               \
+    }                                                                                                                                                                                                   \
+    _Template [[nodiscard]] void* _Class::operator new[]([[maybe_unused]] std::size_t, [[maybe_unused]] std::align_val_t) {                                                                             \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                                        \
+                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                              \
+                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                                         \
+        return AZ_INVALID_POINTER;                                                                                                                                                                      \
+    }                                                                                                                                                                                                   \
+    _Template [[nodiscard]] void* _Class::operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept {                                                                    \
+        return operator new[](size, align);                                                                                                                                                             \
+    }                                                                                                                                                                                                   \
+    _Template void _Class::operator delete(void* p, std::size_t size, std::align_val_t align) noexcept {                                                                                                \
+        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, static_cast<std::size_t>(align)); }                                                                                     \
+    }                                                                                                                                                                                                   \
+    _Template void _Class::operator delete[]([[maybe_unused]] void* p, [[maybe_unused]] std::size_t size, [[maybe_unused]] std::align_val_t align) noexcept {                                           \
+        AZ_Assert(false, "We DO NOT support array operators, because it's really hard/impossible to handle alignment without proper tracking!\n"                                                        \
+                          "new[] inserts a header (platform dependent) to keep track of the array size!\n"                                                                                              \
+                          "Use AZStd::vector,AZStd::array,AZStd::fixed_vector or placement new and it's your responsibility!");                                                                         \
+    }
+#else
+#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)
+#endif
+#define AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, _Template)                                                                                                                                                                     \
+    /* ========== standard operator new/delete ========== */                                                                                                                                                                                        \
+    _Template                                                                                                                                                                                                                                       \
+    [[nodiscard]] void* _Class::operator new(std::size_t size)                                                                                                                                                                                      \
+    {                                                                                                                                                                                                                                               \
+        AZ_Assert(size == sizeof(_Class), "Size mismatch! Did you forget to declare the macro in derived class? Size: %d sizeof(_Class): %d", size, sizeof(_Class));                                                                                \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(size, alignof( _Class ));                                                                                                                                                        \
+    }                                                                                                                                                                                                                                               \
+    _Template                                                                                                                                                                                                                                       \
+    void _Class::operator delete(void* p, std::size_t size)  {                                                                                                                                                                                      \
+        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, alignof( _Class )); }                                                                                                                                               \
+    }                                                                                                                                                                                                                                               \
+    /* ========== AZ_CLASS_ALLOCATOR API ========== */                                                                                                                                                                                              \
+    _Template                                                                                                                                                                                                                                       \
+    [[nodiscard]] void* _Class::AZ_CLASS_ALLOCATOR_Allocate() {                                                                                                                                                                                     \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(sizeof(_Class), alignof( _Class ));                                                                                                                                              \
+    }                                                                                                                                                                                                                                               \
+    _Template                                                                                                                                                                                                                                       \
+    void _Class::AZ_CLASS_ALLOCATOR_DeAllocate(void* object) {                                                                                                                                                                                      \
+        AZ::AllocatorInstance< _Allocator >::Get().deallocate(object, sizeof(_Class), alignof( _Class ));                                                                                                                                           \
+    }                                                                                                                                                                                                                                               \
+    _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)
+
+#define AZ_CLASS_ALLOCATOR_IMPL(_Class, _Allocator, ...)                                                                                                                                                                                         \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, )
+
+#define AZ_CLASS_ALLOCATOR_IMPL_TEMPLATE(_Class, _Allocator, ...)                                                                                                                                                                                \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, template<>)
+
+//////////////////////////////////////////////////////////////////////////
+// new operator overloads
+
+// you can redefine this macro to whatever suits you.
+#ifndef AZCORE_GLOBAL_NEW_ALIGNMENT
+#   define AZCORE_GLOBAL_NEW_ALIGNMENT 16
+#endif
+
+
+#define AZ_PAGE_SIZE AZ_TRAIT_OS_DEFAULT_PAGE_SIZE
+#define AZ_DEFAULT_ALIGNMENT (sizeof(void*))
+
+// define unlimited allocator limits (scaled to real number when we check if there is enough memory to allocate)
+#define AZ_CORE_MAX_ALLOCATOR_SIZE AZ_TRAIT_OS_MEMORY_MAX_ALLOCATOR_SIZE
+
+namespace AZ
+{
+    /**
+    * Helper class to determine if type T specializes AZ Allocators,
+    * so we can safely call aznew on it. -  HasAZClassAllocator<ClassType>...
+    * In order to avoid reduce include dependencies, constructs such as
+    * std::integral_constant, std::enable_if_t and std::is_same_v are not being used
+    * This allows this header to be used without the need to include <type_traits>
+    */
+    template<class T, class = void>
+    struct HasAZClassAllocator
+    {
+        using type = HasAZClassAllocator;
+        static constexpr bool value = false;
+        constexpr operator bool() const
+        {
+            return value;
+        }
+        constexpr bool operator()() const
+        {
+            return value;
+        }
+    };
+
+    template <class T>
+    inline constexpr bool HasAZClassAllocator_v = AZ::HasAZClassAllocator<T>::value;
+
+    template<class T>
+    struct HasAZClassAllocator<T, decltype(T::AZ_CLASS_ALLOCATOR_Allocate(), void())>
+    {
+        using type = HasAZClassAllocator;
+        static constexpr bool value = true;
+        constexpr operator bool() const
+        {
+            return value;
+        }
+        constexpr bool operator()() const
+        {
+            return value;
+        }
+    };
+}

+ 1 - 1
Code/Framework/AzCore/AzCore/RTTI/BehaviorClassBuilder.inl

@@ -670,7 +670,7 @@ namespace AZ
                     );
 
             SetClassHasher<T>(behaviorClass);
-            SetClassDefaultAllocator<T>(behaviorClass, typename HasAZClassAllocator<T>::type());
+            SetClassDefaultAllocator<T>(behaviorClass, AZStd::bool_constant<HasAZClassAllocator_v<T>>{});
             SetClassDefaultConstructor<T>(behaviorClass, typename AZStd::conditional< AZStd::is_constructible<T>::value && !AZStd::is_abstract<T>::value, AZStd::true_type, AZStd::false_type>::type());
             SetClassDefaultDestructor<T>(behaviorClass, typename AZStd::is_destructible<T>::type());
             SetClassDefaultCopyConstructor<T>(behaviorClass, typename AZStd::conditional< AZStd::is_copy_constructible<T>::value && !AZStd::is_abstract<T>::value, AZStd::true_type, AZStd::false_type>::type());

+ 0 - 40
Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h

@@ -465,46 +465,6 @@ namespace AZ
 
 namespace AZ
 {
-        /**
-    * Use this macro outside a class to allow it to be identified across modules and serialized (in different contexts).
-    * The expected input is the class and the assigned uuid as a string or an instance of a uuid.
-    * Note that the AZ_TYPE_INFO_SPECIALIZE does NOT need has to be declared in "namespace AZ".
-    * It can be declared outside the namespace as mechanism for adding TypeInfo uses function overloading
-    * instead of template specialization
-    * Example:
-    *   class MyClass
-    *   {
-    *   public:
-    *       ...
-    *   };
-    *
-    *   AZ_TYPE_INFO_SPECIALIZE(MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}");
-    */
-#define AZ_TYPE_INFO_SPECIALIZE(_ClassType, _ClassUuid) \
-    AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME(_ClassType, #_ClassType, _ClassUuid)
-
-    // Adds support for specifying a different display name for the Class type being specialized for TypeInfo
-    // This is useful when wanting to remove a namespace from the TypeInfo name such as when reflecting to scripting
-    // i.e AZ_TYPE_INFO_SPECIALIZE_WITH_NAME(AZ::Metrics::MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}", MyClass)
-#define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME(_ClassType, _ClassUuid, _DisplayName) \
-    AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME(_ClassType, _DisplayName, _ClassUuid)
-
-// Adds declaration TypeInfo function overloads for a type(class, enum or fundamental)
-#define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_DECL(_ClassName) \
-    AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_DECL(_ClassName)
-
-// Adds function definition for TypeInfo functions
-// NOTE: This needs to be in the same namespace as the declaration
-// The functions do not have the inline attached, so this macro is only suitable for use
-// in a single translation unit
-#define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_IMPL(_ClassName, _DisplayName, _ClassUuid) \
-    AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_IMPL(_ClassName, _DisplayName, _ClassUuid)
-
-// Adds inline function definition for TypeInfo functions
-// This macro can be used in a header or inline file and is suitable for use with class template types
-#define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_IMPL_INLINE(_ClassName, _DisplayName, _ClassUuid) \
-    AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_IMPL_INLINE(_ClassName, _DisplayName, _ClassUuid)
-
     //! Add GetO3deTypeName and GetO3deTypeId declarations for commonly used O3DE types
     AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_DECL(AZ::Uuid);
     AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_DECL(PlatformID);

+ 41 - 0
Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h

@@ -127,6 +127,47 @@ namespace AZ
     AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_DECL(double);
     AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_DECL(bool);
     AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_DECL(void);
+
+    /**
+    * Use this macro outside a class to allow it to be identified across modules and serialized (in different contexts).
+    * The expected input is the class and the assigned uuid as a string or an instance of a uuid.
+    * Note that the AZ_TYPE_INFO_SPECIALIZE does NOT need has to be declared in "namespace AZ".
+    * It can be declared outside the namespace as mechanism for adding TypeInfo uses function overloading
+    * instead of template specialization
+    * Example:
+    *   class MyClass
+    *   {
+    *   public:
+    *       ...
+    *   };
+    *
+    *   AZ_TYPE_INFO_SPECIALIZE(MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}");
+    */
+    #define AZ_TYPE_INFO_SPECIALIZE(_ClassType, _ClassUuid) \
+        AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME(_ClassType, #_ClassType, _ClassUuid)
+
+    // Adds support for specifying a different display name for the Class type being specialized for TypeInfo
+    // This is useful when wanting to remove a namespace from the TypeInfo name such as when reflecting to scripting
+    // i.e AZ_TYPE_INFO_SPECIALIZE_WITH_NAME(AZ::Metrics::MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}", MyClass)
+    #define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME(_ClassType, _ClassUuid, _DisplayName) \
+        AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME(_ClassType, _DisplayName, _ClassUuid)
+
+    // Adds declaration TypeInfo function overloads for a type(class, enum or fundamental)
+    #define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_DECL(_ClassName) \
+        AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_DECL(_ClassName)
+
+    // Adds function definition for TypeInfo functions
+    // NOTE: This needs to be in the same namespace as the declaration
+    // The functions do not have the inline attached, so this macro is only suitable for use
+    // in a single translation unit
+    #define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_IMPL(_ClassName, _DisplayName, _ClassUuid) \
+        AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_IMPL(_ClassName, _DisplayName, _ClassUuid)
+
+    // Adds inline function definition for TypeInfo functions
+    // This macro can be used in a header or inline file and is suitable for use with class template types
+    #define AZ_TYPE_INFO_SPECIALIZE_WITH_NAME_IMPL_INLINE(_ClassName, _DisplayName, _ClassUuid) \
+        AZ_TYPE_INFO_INTERNAL_SPECIALIZE_WITH_NAME_IMPL_INLINE(_ClassName, _DisplayName, _ClassUuid)
+
 }
 
 namespace AZ

+ 11 - 9
Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp

@@ -11,7 +11,6 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Script/lua/lua.h>
 #include <AzCore/Script/ScriptProperty.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 namespace AZ
 {
@@ -105,7 +104,7 @@ namespace AZ
     // ScriptProperty
     ///////////////////
 
-    bool ScriptProperty::VersionConverter(SerializeContext& context, SerializeContext::DataElementNode& classElement)
+    static bool ScriptPropertyVersionConverter(SerializeContext& context, SerializeContext::DataElementNode& classElement)
     {
         if (classElement.GetVersion() == 1)
         {
@@ -136,7 +135,7 @@ namespace AZ
         if (serializeContext)
         {
             serializeContext->Class<AZ::ScriptProperty>()->
-                Version(2, AZ::ScriptProperty::VersionConverter)->
+                Version(2, &AZ::ScriptPropertyVersionConverter)->
                     PersistentId([](const void* instance) -> AZ::u64 { return reinterpret_cast<const AZ::ScriptProperty*>(instance)->m_id; })->
                     Field("id", &AZ::ScriptProperty::m_id)->
                     Field("name", &AZ::ScriptProperty::m_name);
@@ -837,7 +836,7 @@ namespace AZ
         return AZ::SerializeGenericTypeInfo< AZStd::vector<bool> >::GetClassTypeId();
     }
 
-    bool ScriptPropertyBooleanArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const 
+    bool ScriptPropertyBooleanArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
     {
         return IsBooleanArray(context,valueIndex);
     }
@@ -963,7 +962,7 @@ namespace AZ
         return AZ::SerializeGenericTypeInfo< AZStd::vector<double> >::GetClassTypeId();
     }
 
-    bool ScriptPropertyNumberArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const 
+    bool ScriptPropertyNumberArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
     {
         return IsNumberArray(context,valueIndex);
     }
@@ -1089,7 +1088,7 @@ namespace AZ
         return AZ::SerializeGenericTypeInfo< AZStd::vector<AZStd::string> >::GetClassTypeId();
     }
 
-    bool ScriptPropertyStringArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const 
+    bool ScriptPropertyStringArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
     {
         return IsStringArray(context,valueIndex);
     }
@@ -1120,6 +1119,9 @@ namespace AZ
     ////////////////////////////////////
     // ScriptPropertyGenericClassArray
     ////////////////////////////////////
+    // The GenericClassArray version converter is defined later in this file
+    static bool ScriptPropertyGenericClassArrayVersionConverter(AZ::SerializeContext& context,
+        AZ::SerializeContext::DataElementNode& classElement);
     void ScriptPropertyGenericClassArray::Reflect(AZ::ReflectContext* reflection)
     {
         AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
@@ -1127,7 +1129,7 @@ namespace AZ
         if (serializeContext)
         {
             serializeContext->Class<ScriptPropertyGenericClassArray, ScriptProperty>()->
-                Version(2, &VersionConverter)->
+                Version(2, &ScriptPropertyGenericClassArrayVersionConverter)->
                 Field("values", &ScriptPropertyGenericClassArray::m_values)->
                 Field("elementType", &ScriptPropertyGenericClassArray::m_elementTypeId);
         }
@@ -1257,7 +1259,7 @@ namespace AZ
         m_elementTypeId = elementTypeId;
     }
 
-    bool ScriptPropertyGenericClassArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const 
+    bool ScriptPropertyGenericClassArray::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
     {
         return IsGenericClassArray(context,valueIndex);
     }
@@ -1309,7 +1311,7 @@ namespace AZ
         }
     }
 
-    bool ScriptPropertyGenericClassArray::VersionConverter(AZ::SerializeContext& context,
+    bool ScriptPropertyGenericClassArrayVersionConverter(AZ::SerializeContext& context,
         AZ::SerializeContext::DataElementNode& classElement)
     {
 

+ 0 - 5
Code/Framework/AzCore/AzCore/Script/ScriptProperty.h

@@ -14,7 +14,6 @@
 #include <AzCore/Script/ScriptContext.h>
 #include <AzCore/Script/ScriptPropertyWatcherBus.h>
 #include <AzCore/Serialization/DynamicSerializableField.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/containers/set.h>
 
 // Ideally, the properties would be able to marshal themselves
@@ -51,7 +50,6 @@ namespace AZ
         static void UpdateScriptProperty(AZ::ScriptDataContext& sdc, int valueIndex, ScriptProperty** targetProperty);
 
         static void Reflect(AZ::ReflectContext* reflection);
-        static bool VersionConverter(SerializeContext& context, SerializeContext::DataElementNode& classElement);
 
         virtual ~ScriptProperty() {}
         AZ_TYPE_INFO_WITH_NAME_DECL(ScriptProperty);
@@ -466,9 +464,6 @@ namespace AZ
     private: // static member functions
 
         AZ::Uuid m_elementTypeId = AZ::Uuid::CreateNull(); // Stores type wrapped by DynamicSerializableField values
-
-        static bool VersionConverter(AZ::SerializeContext& context,
-            AZ::SerializeContext::DataElementNode& classElement);
     };
 
     class ScriptPropertyAsset

+ 3 - 2
Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp

@@ -9,6 +9,7 @@
 #include <AzCore/Script/ScriptPropertySerializer.h>
 #include <AzCore/Serialization/DynamicSerializableField.h>
 #include <AzCore/Serialization/Json/JsonSerialization.h>
+#include <AzCore/Serialization/SerializeContext.h>
 
 namespace AZ
 {
@@ -51,7 +52,7 @@ namespace AZ
         storageField.m_data = AZStd::any_cast<void>(&storage);
         storageField.m_typeId = typeId;
         outputVariable->CopyDataFrom(storageField, context.GetSerializeContext());
-        
+
         result.Combine(ContinueLoadingFromJsonObjectField(outputVariable->m_data, typeId, inputValue, "value", context));
         return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
             ? "ScriptPropertySerializer Load finished loading DynamicSerializableField"
@@ -74,7 +75,7 @@ namespace AZ
         auto inputFieldPtr = inputScriptDataPtr->m_data;
         auto defaultScriptDataPtr = reinterpret_cast<const DynamicSerializableField*>(defaultValue);
         auto defaultFieldPtr = defaultScriptDataPtr ? &defaultScriptDataPtr->m_data : nullptr;
- 
+
         if (defaultScriptDataPtr && inputScriptDataPtr->IsEqualTo(*defaultScriptDataPtr, context.GetSerializeContext()))
         {
             return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptPropertySerializer Store used defaults for DynamicSerializableField");

+ 0 - 1
Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h

@@ -10,7 +10,6 @@
 
 #include <AzCore/Memory/Memory.h>
 #include <AzCore/Serialization/Json/BaseJsonSerializer.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 namespace AZ
 {

+ 15 - 0
Code/Framework/AzCore/AzCore/Serialization/EditContext.h

@@ -115,6 +115,21 @@ namespace AZ
         };
     }
 
+    namespace SerializeInternal
+    {
+        template<class T>
+        struct ElementInfo;
+
+        template<class T, class C>
+        struct ElementInfo<T C::*>
+        {
+            using ElementType = AZStd::RemoveEnumT<T>;
+            using ClassType = C;
+            using Type = T;
+            using ValueType = AZStd::remove_pointer_t<ElementType>;
+        };
+    }
+
     /**
      * EditContext is bound to serialize context. It uses it for data manipulation.
      * It's role is to be an abstract way to generate and describe how a class should

+ 13 - 13
Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp

@@ -72,7 +72,7 @@ namespace AZ
                 // type itself has not been reflected using EnumBuilder. Treat it as an enum.
                 return LoadEnum(object, *classData, value, context);
             }
-            
+
             if (BaseJsonSerializer* serializer
                 = (custom == UseTypeDeserializer::Yes)
                     ? context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId())
@@ -86,7 +86,7 @@ namespace AZ
         {
             return context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default.");
         }
-        
+
         if (classData->m_azRtti && (classData->m_azRtti->GetTypeTraits() & AZ::TypeTraits::is_enum) == AZ::TypeTraits::is_enum)
         {
             return LoadEnum(object, *classData, value, context);
@@ -113,7 +113,7 @@ namespace AZ
         const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId);
         if (!classData)
         {
-            return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, 
+            return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
                 AZStd::string::format("Failed to retrieve serialization information for %s.", typeId.ToString<AZStd::string>().c_str()));
         }
         if (!classData->m_azRtti)
@@ -570,7 +570,7 @@ namespace AZ
         }
         else
         {
-            // There's data stored in the JSON document so try to determine the type, create an instance of it and 
+            // There's data stored in the JSON document so try to determine the type, create an instance of it and
             // return the new object to continue loading.
             LoadTypeIdResult loadedTypeId = LoadTypeIdFromJsonObject(pointerData, rtti, context);
             if (loadedTypeId.m_determination == TypeIdDetermination::FailedToDetermine ||
@@ -580,9 +580,9 @@ namespace AZ
                     if (typeField != pointerData.MemberEnd() && typeField->value.IsString())
                     {
                         const char* format = loadedTypeId.m_determination == TypeIdDetermination::FailedToDetermine ?
-                            "Unable to resolve provided type: %.*s." : 
+                            "Unable to resolve provided type: %.*s." :
                             "Unable to resolve provided type %.*s because the same name points to multiple types.";
-                        status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, 
+                        status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
                             AZStd::string::format(format, typeField->value.GetStringLength(), typeField->value.GetString()));
                     }
                     else
@@ -629,7 +629,7 @@ namespace AZ
                         const SerializeContext::ClassData* actualClassData = context.GetSerializeContext()->FindClassData(actualClassId);
                         if (!actualClassData)
                         {
-                            status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, 
+                            status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
                                 AZStd::string::format("Unable to find serialization information for type %s.", actualClassId.ToString<AZStd::string>().c_str()));
                             return ResolvePointerResult::FullyProcessed;
                         }
@@ -710,7 +710,7 @@ namespace AZ
     {
         LoadTypeIdResult result;
 
-        // Node doesn't contain an object, so there's no room to store the type id field. In this case the element can't be 
+        // Node doesn't contain an object, so there's no room to store the type id field. In this case the element can't be
         // specialized, so return it's type.
         if (!node.IsObject())
         {
@@ -742,7 +742,7 @@ namespace AZ
     {
         using namespace JsonSerializationResult;
 
-        SerializeContext::IRttiHelper* baseClassRtti = nullptr;
+        AZ::IRttiHelper* baseClassRtti = nullptr;
         if (baseTypeId)
         {
             const SerializeContext::ClassData* baseClassData = context.GetSerializeContext()->FindClassData(*baseTypeId);
@@ -852,7 +852,7 @@ namespace AZ
                 for (const Uuid& typeId : typeIdCandidates)
                 {
                     const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId);
-                    if (context.GetSerializeContext()->CanDowncast(typeId, baseClassRtti->GetTypeId(), 
+                    if (context.GetSerializeContext()->CanDowncast(typeId, baseClassRtti->GetTypeId(),
                         classData ? classData->m_azRtti : nullptr, baseClassRtti))
                     {
                         ++numApplicableCandidates;
@@ -874,13 +874,13 @@ namespace AZ
             result.m_typeId = Uuid::CreateNull();
             return result;
         }
-        
+
         result.m_determination = TypeIdDetermination::FailedToDetermine;
         result.m_typeId = Uuid::CreateNull();
         return result;
     }
 
-    JsonDeserializer::ElementDataResult JsonDeserializer::FindElementByNameCrc(SerializeContext& serializeContext, 
+    JsonDeserializer::ElementDataResult JsonDeserializer::FindElementByNameCrc(SerializeContext& serializeContext,
         void* object, const SerializeContext::ClassData& classData, const Crc32 nameCrc)
     {
         // The class data stores base class element information first in the set of m_elements
@@ -896,7 +896,7 @@ namespace AZ
                 result.m_found = true;
                 return result;
             }
-                
+
             if (elementData->m_flags & SerializeContext::ClassElement::Flags::FLG_BASE_CLASS)
             {
                 const SerializeContext::ClassData* baseClassData = serializeContext.FindClassData(elementData->m_typeId);

+ 3 - 4
Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.h

@@ -11,7 +11,6 @@
 #include <AzCore/Math/Uuid.h>
 #include <AzCore/Memory/SystemAllocator.h>
 #include <AzCore/RTTI/ReflectContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/Json/BaseJsonSerializer.h>
 #include <AzCore/std/containers/unordered_map.h>
 #include <AzCore/std/smart_ptr/unique_ptr.h>
@@ -34,7 +33,7 @@ namespace AZ
         const HandledTypesMap& GetRegisteredSerializers() const;
         BaseJsonSerializer* GetSerializerForType(const Uuid& typeId) const;
         BaseJsonSerializer* GetSerializerForSerializerType(const Uuid& typeId) const;
-        
+
         template <typename T>
         SerializerBuilder Serializer()
         {
@@ -52,7 +51,7 @@ namespace AZ
                 return SerializerBuilder(this, m_jsonSerializers.end());
             }
         }
-        
+
         class SerializerBuilder
         {
             friend class JsonRegistrationContext;
@@ -73,7 +72,7 @@ namespace AZ
 
 #if defined(AZ_COMPILER_MSVC)
             // There is a bug with the MSVC compiler when using the 'auto' keyword here. It appears that MSVC is unable to distinguish between a template
-            // template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack. 
+            // template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack.
             template<template<AZStd::size_t...> class T>
 #else
             template<template<auto...> class T>

+ 1980 - 1780
Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp

@@ -51,16 +51,6 @@ namespace AZ
     // The first argument to RTTI is template name followed by any template placeholders for substituting the template type specifiers
     AZ_RTTI_NO_TYPE_INFO_IMPL((SerializeContext::DataPatchTypeUpgrade, AZ_TYPE_INFO_CLASS, AZ_TYPE_INFO_CLASS), DataPatchUpgrade);
 
-    AZ_TYPE_INFO_WITH_NAME_IMPL(SerializeContext::ClassElement, "ClassElement", "{7D386902-A1D9-4525-8284-F68435FE1D05}");
-
-    AZ_TYPE_INFO_WITH_NAME_IMPL(SerializeContext::ClassData, "ClassData", "{20EB8E2E-D807-4039-84E2-CE37D7647CD4}");
-
-    AZ_TYPE_INFO_WITH_NAME_IMPL(SerializeContext::IDataContainer, "IDataContainer", "{8565CBEA-C077-4A49-927B-314533A6EDB1}");
-
-    AZ_TYPE_INFO_WITH_NAME_IMPL(SerializeContext::IDataContainer::IAssociativeDataContainer, "IAssociativeDataContainer", "{58CF6250-6B0F-4A25-9864-25A64EB55DB1}");
-
-    AZ_TYPE_INFO_WITH_NAME_IMPL(SerializeContext::EnumerateInstanceCallContext, "EnumerateInstanceCallContext", "{FCC1DB4B-72BD-4D78-9C23-C84B91589D33}");
-
     AZ_THREAD_LOCAL void* Internal::AZStdArrayEvents::m_indices = nullptr;
 
     //////////////////////////////////////////////////////////////////////////
@@ -68,7 +58,7 @@ namespace AZ
 
     template<class T>
     class BinaryValueSerializer
-        : public SerializeContext::IDataSerializer
+        : public Serialize::IDataSerializer
     {
         /// Load the class data from a binary buffer.
         bool    Load(void* classPtr, IO::GenericStream& stream, unsigned int /*version*/, bool isDataBigEndian = false) override
@@ -373,7 +363,7 @@ namespace AZ
 
     // serializer without any data write
     class EmptySerializer
-        : public SerializeContext::IDataSerializer
+        : public Serialize::IDataSerializer
     {
     public:
         /// Store the class data into a stream.
@@ -553,7 +543,7 @@ namespace AZ
         return m_editContext;
     }
 
-    auto SerializeContext::RegisterType(const AZ::TypeId& typeId, AZ::SerializeContext::ClassData&& classData, CreateAnyFunc createAnyFunc) -> ClassBuilder
+    auto SerializeContext::RegisterType(const AZ::TypeId& typeId, AZ::Serialize::ClassData&& classData, CreateAnyFunc createAnyFunc) -> ClassBuilder
     {
         auto [typeToClassIter, inserted] = m_uuidMap.try_emplace(typeId, AZStd::move(classData));
         m_classNameToUuid.emplace(AZ::Crc32(typeToClassIter->second.m_name), typeId);
@@ -607,7 +597,7 @@ namespace AZ
         ClassData& cd = result.first->second;
         cd.m_name = name;
         cd.m_typeId = typeUuid;
-        cd.m_version = VersionClassDeprecated;
+        cd.m_version = Serialize::VersionClassDeprecated;
         cd.m_converter = converter;
         cd.m_serializer = nullptr;
         cd.m_factory = nullptr;
@@ -646,7 +636,7 @@ namespace AZ
     // [5/11/2012]
     //=========================================================================
     const SerializeContext::ClassData*
-    SerializeContext::FindClassData(const Uuid& classId, const SerializeContext::ClassData* parent, u32 elementNameCrc) const
+    SerializeContext::FindClassData(const Uuid& classId, const Serialize::ClassData* parent, u32 elementNameCrc) const
     {
         SerializeContext::UuidToClassMap::const_iterator it = m_uuidMap.find(classId);
         const SerializeContext::ClassData* cd = it != m_uuidMap.end() ? &it->second : nullptr;
@@ -888,2398 +878,2608 @@ namespace AZ
         return fromClassHelper->Cast(instance, toClassHelper->GetTypeId());
     }
 
-    //=========================================================================
-    // DataElement
-    // [5/22/2012]
-    //=========================================================================
-    SerializeContext::DataElement::DataElement()
-        : m_name(nullptr)
-        , m_nameCrc(0)
-        , m_dataSize(0)
-        , m_byteStream(&m_buffer)
-        , m_stream(nullptr)
+    // Create a class builder that that can reflect fields and attributes to SerializeContext ClassData
+    auto SerializeContext::ReflectClassInternal(const char* className, const AZ::TypeId& classTypeId,
+        IObjectFactory* factory, const DeprecatedNameVisitWrapper& callback,
+        IRttiHelper* rttiHelper, CreateAnyFunc createAnyFunc) -> ClassBuilder
     {
-    }
+        // Add any the deprecated type names to the deprecated type name to type id map
+        auto AddDeprecatedNames = [this, &typeUuid = classTypeId](AZStd::string_view deprecatedName)
+        {
+            m_deprecatedNameToTypeIdMap.emplace(deprecatedName, typeUuid);
+        };
+        callback(AddDeprecatedNames);
 
-    //=========================================================================
-    // ~DataElement
-    // [5/22/2012]
-    //=========================================================================
-    SerializeContext::DataElement::~DataElement()
-    {
-        m_buffer.clear();
+        m_classNameToUuid.emplace(AZ::Crc32(className), classTypeId);
+        auto result = m_uuidMap.emplace(classTypeId,
+            ClassData::CreateImpl(className, classTypeId, factory, nullptr, nullptr, rttiHelper));
+        AZ_Assert(result.second, "This class type %s could not be registered with duplicated Uuid: %s.",
+            className, classTypeId.ToString<AZStd::string>().c_str());
+        m_uuidAnyCreationMap.emplace(classTypeId, createAnyFunc);
+
+        return ClassBuilder(this, result.first);
     }
 
-    //=========================================================================
-    // DataElement
-    // [5/22/2012]
-    //=========================================================================
-    SerializeContext::DataElement::DataElement(const DataElement& rhs)
-        : m_name(rhs.m_name)
-        , m_nameCrc(rhs.m_nameCrc)
-        , m_dataSize(rhs.m_dataSize)
-        , m_byteStream(&m_buffer)
+    // Remove reflection of the class with the specified typeid from the SerializeContext
+    auto SerializeContext::UnreflectClassInternal(const char* className, const AZ::TypeId& classTypeId,
+        const DeprecatedNameVisitWrapper& callback) -> ClassBuilder
     {
-        m_id = rhs.m_id;
-        m_version = rhs.m_version;
-        m_dataType = rhs.m_dataType;
-
-        m_buffer = rhs.m_buffer;
-        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
-        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
-        if (rhs.m_stream == &rhs.m_byteStream)
+        auto mapIt = m_uuidMap.find(classTypeId);
+        if (mapIt != m_uuidMap.end())
         {
-            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
-            m_stream = &m_byteStream;
-        }
-        else
-        {
-            m_stream = rhs.m_stream;
+            RemoveClassData(&mapIt->second);
+
+            // Remove the deprecated type name -> typeid mapping
+            auto RemoveDeprecatedNames = [this, &typeUuid = classTypeId](AZStd::string_view deprecatedName)
+            {
+                auto deprecatedNameRange = m_deprecatedNameToTypeIdMap.equal_range(Crc32(deprecatedName));
+                for (auto classNameRangeIter = deprecatedNameRange.first; classNameRangeIter != deprecatedNameRange.second;)
+                {
+                    if (classNameRangeIter->second == typeUuid)
+                    {
+                        classNameRangeIter = m_deprecatedNameToTypeIdMap.erase(classNameRangeIter);
+                    }
+                    else
+                    {
+                        ++classNameRangeIter;
+                    }
+                }
+            };
+            callback(RemoveDeprecatedNames);
+
+            // Remove the current class name -> typeid mapping
+            auto classNameRange = m_classNameToUuid.equal_range(Crc32(className));
+            for (auto classNameRangeIter = classNameRange.first; classNameRangeIter != classNameRange.second;)
+            {
+                if (classNameRangeIter->second == classTypeId)
+                {
+                    classNameRangeIter = m_classNameToUuid.erase(classNameRangeIter);
+                }
+                else
+                {
+                    ++classNameRangeIter;
+                }
+            }
+            m_uuidAnyCreationMap.erase(classTypeId);
+            m_uuidMap.erase(mapIt);
         }
+        return ClassBuilder(this, m_uuidMap.end());
     }
 
-    //=========================================================================
-    // DataElement
-    // [5/22/2012]
-    //=========================================================================
-    SerializeContext::DataElement& SerializeContext::DataElement::operator= (const DataElement& rhs)
+    // Class Builder non-template definitions
+    SerializeContext::ClassBuilder::ClassBuilder(SerializeContext* context, const UuidToClassMap::iterator& classMapIter)
+        : m_context(context)
+        , m_classData(classMapIter)
     {
-        m_name = rhs.m_name;
-        m_nameCrc = rhs.m_nameCrc;
-        m_id = rhs.m_id;
-        m_version = rhs.m_version;
-        m_dataSize = rhs.m_dataSize;
-        m_dataType = rhs.m_dataType;
-
-        m_buffer = rhs.m_buffer;
-        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
-        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
-
-        if (rhs.m_stream == &rhs.m_byteStream)
-        {
-            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
-            m_stream = &m_byteStream;
-        }
-        else
+        if (!context->IsRemovingReflection())
         {
-            m_stream = rhs.m_stream;
+            m_currentAttributes = &classMapIter->second.m_attributes;
         }
-
-        return *this;
     }
 
     //=========================================================================
-    // DataElement
+    // ClassBuilder::~ClassBuilder
     //=========================================================================
-    SerializeContext::DataElement::DataElement(DataElement&& rhs)
-        : m_name(rhs.m_name)
-        , m_nameCrc(rhs.m_nameCrc)
-        , m_dataSize(rhs.m_dataSize)
-        , m_byteStream(&m_buffer)
+    SerializeContext::ClassBuilder::~ClassBuilder()
     {
-        m_id = rhs.m_id;
-        m_version = rhs.m_version;
-        m_dataType = rhs.m_dataType;
-        if (rhs.m_stream == &rhs.m_byteStream)
-        {
-            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
-            m_stream = &m_byteStream;
-        }
-        else
+#if defined(AZ_ENABLE_TRACING)
+        if (!m_context->IsRemovingReflection())
         {
-            m_stream = rhs.m_stream;
+            if (m_classData->second.m_serializer)
+            {
+                AZ_Assert(
+                    m_classData->second.m_elements.empty(),
+                    "Reflection error for class %s.\n"
+                    "Classes with custom serializers are not permitted to also declare serialized elements.\n"
+                    "This is often caused by calling SerializeWithNoData() or specifying a custom serializer on a class which \n"
+                    "is derived from a base class that has serialized elements.",
+                    m_classData->second.m_name ? m_classData->second.m_name : "<Unknown Class>");
+            }
         }
+#endif // AZ_ENABLE_TRACING
+    }
 
-        m_buffer = AZStd::move(rhs.m_buffer);
-        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
-        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
+    // Non templated Field reflection function for the SerializeContext
+    auto SerializeContext::ClassBuilder::FieldImpl(AZStd::initializer_list<AttributePair> attributes,
+        [[maybe_unused]] const char* className, [[maybe_unused]] const AZ::TypeId& classId,
+        const char* fieldName, const AZ::TypeId& fieldTypeId,
+        size_t fieldOffset, size_t fieldSize, bool fieldIsPointer, bool fieldIsEnum,
+        const AZ::TypeId& fieldUnderlyingTypeId, IRttiHelper* fieldRttiHelper,
+        GenericClassInfo* fieldGenericClassInfo, CreateAnyFunc fieldCreateAnyFunc)
+        -> ClassBuilder*
+    {
+        AZ_Assert(!m_classData->second.m_serializer,
+            "Class %s has a custom serializer, and can not have additional fields. Classes can either have a custom serializer or child fields.",
+            fieldName);
 
-        rhs.m_name = nullptr;
-        rhs.m_nameCrc = 0;
-        rhs.m_id = Uuid::CreateNull();
-        rhs.m_version = 0;
-        rhs.m_dataSize = 0;
-        rhs.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-        if (m_stream == &m_byteStream)
+        AZ_Assert(m_classData->second.m_typeId == classId,
+            "Field %s is serialized with class %s, but belongs to class %s. If you are trying to expose base class field use FieldFromBase",
+            fieldName,
+            m_classData->second.m_name,
+            className);
+
+
+        m_classData->second.m_elements.emplace_back();
+        ClassElement& ed = m_classData->second.m_elements.back();
+        ed.m_name = fieldName;
+        ed.m_nameCrc = AZ::Crc32(fieldName);
+        // Not really portable but works for the supported compilers. It will crash and not work if we have virtual inheritance. Detect and assert at compile time about it. (something like is_virtual_base_of)
+        ed.m_offset = fieldOffset;
+        //ed.m_offset = or pass it to the function with offsetof(typename ElementTypeInfo::ClassType,member);
+        ed.m_dataSize = fieldSize;
+        ed.m_flags = fieldIsPointer ? ClassElement::FLG_POINTER : 0;
+        ed.m_editData = nullptr;
+        ed.m_azRtti = fieldRttiHelper;
+
+        ed.m_genericClassInfo = fieldGenericClassInfo;
+        if (!fieldTypeId.IsNull())
         {
-            rhs.m_stream = &rhs.m_byteStream;
+            ed.m_typeId = fieldTypeId;
+            // If the field is an enum type add it to the map of enum types -> underlying types
+            if (fieldIsEnum)
+            {
+                m_context->m_enumTypeIdToUnderlyingTypeIdMap.emplace(fieldTypeId, fieldUnderlyingTypeId);
+                m_context->m_uuidAnyCreationMap.emplace(fieldTypeId, fieldCreateAnyFunc);
+            }
         }
         else
         {
-            rhs.m_stream = nullptr;
+            // If the Field typeid is null, fallback to using the Underlying typeid  in case the reflected field is an enum
+            // This allows reflected enum fields which doen't specialize AzTypeInfo using the AZ_TYPE_INFO_SPECIALIZE macro to still
+            // serialize out using  the underlying type for backwards compatibility
+            ed.m_typeId = fieldUnderlyingTypeId;
         }
-    }
-
-    //=========================================================================
-    // DataElement
-    //=========================================================================
-    SerializeContext::DataElement& SerializeContext::DataElement::operator= (DataElement&& rhs)
-    {
-        m_name = rhs.m_name;
-        m_nameCrc = rhs.m_nameCrc;
-        m_id = rhs.m_id;
-        m_version = rhs.m_version;
-        m_dataSize = rhs.m_dataSize;
-        m_dataType = rhs.m_dataType;
-        if (rhs.m_stream == &rhs.m_byteStream)
+        AZ_Assert(!ed.m_typeId.IsNull(), "You must provide a valid class id for field %s", fieldName);
+        for (const AttributePair& attributePair : attributes)
         {
-            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
-            m_stream = &m_byteStream;
+            ed.m_attributes.emplace_back(attributePair.first, attributePair.second);
         }
-        else
+
+        if (ed.m_genericClassInfo)
         {
-            m_stream = rhs.m_stream;
+            ed.m_genericClassInfo->Reflect(m_context);
         }
 
+        m_currentAttributes = &ed.m_attributes;
 
-        m_buffer = AZStd::move(rhs.m_buffer);
-        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
-        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
-
-        rhs.m_name = nullptr;
-        rhs.m_nameCrc = 0;
-        rhs.m_id = Uuid::CreateNull();
-        rhs.m_version = 0;
-        rhs.m_dataSize = 0;
-        rhs.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-        if (m_stream == &m_byteStream)
+        // Flag the field with the EnumType attribute if we're an enumeration type aliased by RemoveEnum
+        // We use Attribute here, so we have to do this after m_currentAttributes is assigned
+        const bool isSpecializedEnum = fieldIsEnum && !fieldTypeId.IsNull();
+        if (isSpecializedEnum)
         {
-            rhs.m_stream = &rhs.m_byteStream;
-        }
-        else
-        {
-            rhs.m_stream = nullptr;
+            Attribute(AZ_CRC_CE("EnumType"), fieldTypeId);
         }
 
-        return *this;
+        return this;
     }
 
     //=========================================================================
-    // Convert
+    // ClassBuilder::NameChange
+    // [4/10/2019]
     //=========================================================================
-    bool SerializeContext::DataElementNode::Convert(SerializeContext& sc, const Uuid& id)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::NameChange(unsigned int fromVersion, unsigned int toVersion, AZStd::string_view oldFieldName, AZStd::string_view newFieldName)
     {
-        // remove sub elements
-        while (!m_subElements.empty())
+        if (m_context->IsRemovingReflection())
         {
-            RemoveElement(static_cast<int>(m_subElements.size()) - 1);
+            return this; // we have already removed the class data for this class
         }
 
-        // replace element
-        m_element.m_id = id;
-        m_element.m_dataSize = 0;
-        m_element.m_buffer.clear();
-        m_element.m_stream = &m_element.m_byteStream;
+        AZ_Error("Serialize", !m_classData->second.m_serializer, "Class has a custom serializer, and can not have per-node version upgrades.");
+        AZ_Error("Serialize", !m_classData->second.m_elements.empty(), "Class has no defined elements to add per-node version upgrades to.");
 
-        m_classData = sc.FindClassData(m_element.m_id);
-        AZ_Assert(m_classData, "You are adding element to an unregistered class!");
-        m_element.m_version = m_classData->m_version;
+        if (m_classData->second.m_serializer || m_classData->second.m_elements.empty())
+        {
+            return this;
+        }
 
-        return true;
+        m_classData->second.m_dataPatchUpgrader.AddFieldUpgrade(aznew DataPatchNameUpgrade(fromVersion, toVersion, oldFieldName, newFieldName));
+
+        return this;
     }
 
     //=========================================================================
-    // Convert
+    // ClassBuilder::Version
+    // [10/05/2012]
     //=========================================================================
-    bool SerializeContext::DataElementNode::Convert(SerializeContext& sc, const char* name, const Uuid& id)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Version(unsigned int version, VersionConverter converter)
     {
-        AZ_Assert(name != nullptr && strlen(name) > 0, "Empty name is an INVALID element name!");
-        u32 nameCrc = Crc32(name);
-
-#if defined(AZ_ENABLE_TRACING)
-        if (FindElement(nameCrc) != -1)
+        if (m_context->IsRemovingReflection())
         {
-            AZ_Error("Serialize", false, "During reflection of class '%s' - member %s is declared more than once.", m_classData->m_name ? m_classData->m_name : "<unknown class>", name);
-            return false;
+            return this; // we have already removed the class data.
         }
-#endif // AZ_ENABLE_TRACING
+        AZ_Assert(version != Serialize::VersionClassDeprecated, "You cannot use %u as the version, it is reserved by the system!", version);
+        m_classData->second.m_version = version;
+        m_classData->second.m_converter = converter;
+        return this;
+    }
 
-        // remove sub elements
-        while (!m_subElements.empty())
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Serializer(Serialize::IDataSerializerPtr serializer)
+    {
+        if (m_context->IsRemovingReflection())
         {
-            RemoveElement(static_cast<int>(m_subElements.size()) - 1);
+            return this; // we have already removed the class data.
         }
 
-        // replace element
-        m_element.m_name = name;
-        m_element.m_nameCrc = nameCrc;
-        m_element.m_id = id;
-        m_element.m_dataSize = 0;
-        m_element.m_buffer.clear();
-        m_element.m_stream = &m_element.m_byteStream;
+        AZ_Assert(m_classData->second.m_elements.empty(),
+            "Class %s has a custom serializer, and can not have additional fields. Classes can either have a custom serializer or child fields.",
+            m_classData->second.m_name);
 
-        m_classData = sc.FindClassData(m_element.m_id);
-        AZ_Assert(m_classData, "You are adding element to an unregistered class!");
-        m_element.m_version = m_classData->m_version;
+        m_classData->second.m_serializer = AZStd::move(serializer);
+        return this;
 
-        return true;
     }
 
     //=========================================================================
-    // FindElement
-    // [5/22/2012]
+    // ClassBuilder::Serializer
+    // [10/05/2012]
     //=========================================================================
-    int SerializeContext::DataElementNode::FindElement(u32 crc)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Serializer(IDataSerializer* serializer)
     {
-        for (size_t i = 0; i < m_subElements.size(); ++i)
-        {
-            if (m_subElements[i].m_element.m_nameCrc == crc)
-            {
-                return static_cast<int>(i);
-            }
-        }
-        return -1;
+        return Serializer(Serialize::IDataSerializerPtr(serializer, IDataSerializer::CreateNoDeleteDeleter()));
     }
 
     //=========================================================================
-    // FindSubElement
-    //=========================================================================
-    SerializeContext::DataElementNode* SerializeContext::DataElementNode::FindSubElement(u32 crc)
-    {
-        int index = FindElement(crc);
-        return index >= 0 ? &m_subElements[index] : nullptr;
-    }
-
-    //=========================================================================
-    // RemoveElement
-    // [5/22/2012]
+    // ClassBuilder::Serializer
     //=========================================================================
-    void SerializeContext::DataElementNode::RemoveElement(int index)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::SerializeWithNoData()
     {
-        AZ_Assert(index >= 0 && index < static_cast<int>(m_subElements.size()), "Invalid index passed to RemoveElement");
-
-        DataElementNode& node = m_subElements[index];
-
-        node.m_element.m_dataSize = 0;
-        node.m_element.m_buffer.clear();
-        node.m_element.m_stream = nullptr;
-
-        while (!node.m_subElements.empty())
+        if (!m_context->IsRemovingReflection())
         {
-            node.RemoveElement(static_cast<int>(node.m_subElements.size()) - 1);
+            m_classData->second.m_serializer = Serialize::IDataSerializerPtr(&Serialize::StaticInstance<EmptySerializer>::s_instance, IDataSerializer::CreateNoDeleteDeleter());
         }
-
-        m_subElements.erase(m_subElements.begin() + index);
+        return this;
     }
 
     //=========================================================================
-    // RemoveElementByName
+    // ClassBuilder::EventHandler
+    // [10/05/2012]
     //=========================================================================
-    bool SerializeContext::DataElementNode::RemoveElementByName(u32 crc)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::EventHandler(IEventHandler* eventHandler)
     {
-        int index = FindElement(crc);
-        if (index >= 0)
+        if (!m_context->IsRemovingReflection())
         {
-            RemoveElement(index);
-            return true;
+            m_classData->second.m_eventHandler = eventHandler;
         }
-        return false;
-    }
-
-    //=========================================================================
-    // AddElement
-    // [5/22/2012]
-    //=========================================================================
-    int SerializeContext::DataElementNode::AddElement(const DataElementNode& elem)
-    {
-        m_subElements.push_back(elem);
-        return static_cast<int>(m_subElements.size() - 1);
-    }
-
-    //=========================================================================
-    // AddElement
-    // [5/22/2012]
-    //=========================================================================
-    int SerializeContext::DataElementNode::AddElement(SerializeContext& sc, const char* name, const Uuid& id)
-    {
-        const AZ::SerializeContext::ClassData* classData = sc.FindClassData(id);
-        AZ_Assert(classData, "You are adding element to an unregistered class!");
-        return AddElement(sc, name, *classData);
+        return this;
     }
 
     //=========================================================================
-    // AddElement
+    // ClassBuilder::DataContainer
     //=========================================================================
-    int SerializeContext::DataElementNode::AddElement(SerializeContext& sc, const char* name, const ClassData& classData)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::DataContainer(IDataContainer* dataContainer)
     {
-        (void)sc;
-        AZ_Assert(name != nullptr && strlen(name) > 0, "Empty name is an INVALID element name!");
-        u32 nameCrc = Crc32(name);
-
-    #if defined(AZ_ENABLE_TRACING)
-        if (!m_classData->m_container && FindElement(nameCrc) != -1)
+        if (!m_context->IsRemovingReflection())
         {
-            AZ_Error("Serialize", false, "During reflection of class '%s' - member %s is declared more than once.", classData.m_name ? classData.m_name : "<unknown class>", name);
-            return -1;
+            m_classData->second.m_container = dataContainer;
         }
-    #endif // AZ_ENABLE_TRACING
-
-        DataElementNode node;
-        node.m_element.m_name = name;
-        node.m_element.m_nameCrc = nameCrc;
-        node.m_element.m_id = classData.m_typeId;
-        node.m_classData = &classData;
-        node.m_element.m_version = classData.m_version;
-
-        m_subElements.push_back(node);
-        return static_cast<int>(m_subElements.size() - 1);
+        return this;
     }
 
-    int SerializeContext::DataElementNode::AddElement(SerializeContext& sc, AZStd::string_view name, GenericClassInfo* genericClassInfo)
+    //=========================================================================
+    // ClassBuilder::PersistentId
+    //=========================================================================
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::PersistentId(ClassPersistentId persistentId)
     {
-        (void)sc;
-        AZ_Assert(!name.empty(), "Empty name is an INVALID element name!");
-
-        if (!genericClassInfo)
+        if (!m_context->IsRemovingReflection())
         {
-            AZ_Assert(false, "Supplied GenericClassInfo is nullptr. ClassData cannot be retrieved.");
-            return -1;
+            m_classData->second.m_persistentId = persistentId;
         }
-
-        u32 nameCrc = Crc32(name.data());
-        DataElementNode node;
-        node.m_element.m_name = name.data();
-        node.m_element.m_nameCrc = nameCrc;
-        node.m_element.m_id = genericClassInfo->GetClassData()->m_typeId;
-        node.m_classData = genericClassInfo->GetClassData();
-        node.m_element.m_version = node.m_classData->m_version;
-
-        m_subElements.push_back(node);
-        return static_cast<int>(m_subElements.size() - 1);
+        return this;
     }
 
     //=========================================================================
-    // ReplaceElement
+    // ClassBuilder::SerializerDoSave
     //=========================================================================
-    int SerializeContext::DataElementNode::ReplaceElement(SerializeContext& sc, int index, const char* name, const Uuid& id)
+    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::SerializerDoSave(ClassDoSave doSave)
     {
-        DataElementNode& node = m_subElements[index];
-        if (node.Convert(sc, name, id))
-        {
-            return index;
-        }
-        else
+        if (m_context->IsRemovingReflection())
         {
-            return -1;
+            return this; // we have already removed the class data.
         }
+        m_classData->second.m_doSave = doSave;
+        return this;
     }
 
     //=========================================================================
-    // SetName
-    // [1/16/2013]
+    // EnumerateInstanceConst
+    // [10/31/2012]
     //=========================================================================
-    void SerializeContext::DataElementNode::SetName(const char* newName)
+    bool SerializeContext::EnumerateInstanceConst(SerializeContext::EnumerateInstanceCallContext* callContext, const void* ptr, const Uuid& classId, const ClassData* classData, const ClassElement* classElement) const
     {
-        m_element.m_name = newName;
-        m_element.m_nameCrc = Crc32(newName);
+        AZ_Assert((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == 0, "You are asking the serializer to lock the data for write but you only have a const pointer!");
+        return EnumerateInstance(callContext, const_cast<void*>(ptr), classId, classData, classElement);
     }
 
     //=========================================================================
-    // SetDataHierarchy
+    // EnumerateInstance
+    // [10/31/2012]
     //=========================================================================
-    bool SerializeContext::DataElementNode::SetDataHierarchy(SerializeContext& sc, const void* objectPtr, const Uuid& classId, ErrorHandler* errorHandler, const ClassData* classData)
+    bool SerializeContext::EnumerateInstance(SerializeContext::EnumerateInstanceCallContext* callContext, void* ptr, Uuid classId, const ClassData* classData, const ClassElement* classElement) const
     {
-        AZ_Assert(m_element.m_id == classId, "SetDataHierarchy called with mismatched class type {%s} for element %s",
-            classId.ToString<AZStd::string>().c_str(), m_element.m_name);
-
-        AZStd::vector<DataElementNode*> nodeStack;
-        DataElementNode* topNode = this;
-        bool success = false;
+        // if useClassData is provided, just use it, otherwise try to find it using the classId provided.
+        void* objectPtr = ptr;
+        const SerializeContext::ClassData* dataClassInfo = classData;
 
-        auto beginCB = [&sc, &nodeStack, topNode, &success, errorHandler](void* ptr, const SerializeContext::ClassData* elementClassData, const SerializeContext::ClassElement* elementData) -> bool
+        if (classElement)
+        {
+            // if we are a pointer, then we may be pointing to a derived type.
+            if (classElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
             {
-                if (nodeStack.empty())
-                {
-                    success = true;
-                    nodeStack.push_back(topNode);
-                    return true;
-                }
-
-                DataElementNode* parentNode = nodeStack.back();
-                parentNode->m_subElements.reserve(64);
-
-                AZ_Assert(elementData, "Missing element data");
-                AZ_Assert(elementClassData, "Missing class data for element %s", elementData ? elementData->m_name : "<unknown>");
+                // if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
+                objectPtr = *(void**)(ptr);
 
-                int elementIndex = -1;
-                if (elementData)
+                if (!objectPtr)
                 {
-                    elementIndex = elementData->m_genericClassInfo
-                        ? parentNode->AddElement(sc, elementData->m_name, elementData->m_genericClassInfo)
-                        : parentNode->AddElement(sc, elementData->m_name, *elementClassData);
+                    return true;    // nothing to serialize
                 }
-                if (elementIndex >= 0)
+                if (classElement->m_azRtti)
                 {
-                    DataElementNode& newNode = parentNode->GetSubElement(elementIndex);
-
-                    if (elementClassData->m_serializer)
+                    const AZ::Uuid actualClassId = classElement->m_azRtti->GetActualUuid(objectPtr);
+                    if (actualClassId != classId)
                     {
-                        void* resolvedObject = ptr;
-                        if (elementData && elementData->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                        // we are pointing to derived type, adjust class data, uuid and pointer.
+                        classId = AZStd::move(actualClassId);
+                        dataClassInfo = FindClassData(classId);
+                        if ( (dataClassInfo) && (dataClassInfo->m_azRtti) ) // it could be missing RTTI if its deprecated.
                         {
-                            resolvedObject = *(void**)(resolvedObject);
+                            objectPtr = classElement->m_azRtti->Cast(objectPtr, dataClassInfo->m_azRtti->GetTypeId());
 
-                            if (resolvedObject && elementData->m_azRtti)
+                            AZ_Assert(objectPtr, "Potential Data Loss: AZ_RTTI Cast to type %s Failed on element: %s", dataClassInfo->m_name, classElement->m_name);
+                            if (!objectPtr)
                             {
-                                AZ::Uuid actualClassId = elementData->m_azRtti->GetActualUuid(resolvedObject);
-                                if (actualClassId != elementData->m_typeId)
-                                {
-                                    const AZ::SerializeContext::ClassData* actualClassData = sc.FindClassData(actualClassId);
-                                    if (actualClassData)
-                                    {
-                                        resolvedObject = elementData->m_azRtti->Cast(resolvedObject, actualClassData->m_azRtti->GetTypeId());
-                                    }
-                                }
+                                #if defined (AZ_ENABLE_SERIALIZER_DEBUG)
+                                // Additional error information: Provide Type IDs and the serialization stack from our enumeration
+                                AZStd::string sourceTypeID = dataClassInfo->m_typeId.ToString<AZStd::string>();
+                                AZStd::string targetTypeID = classElement->m_typeId.ToString<AZStd::string>();
+                                AZStd::string error = AZStd::string::format("EnumerateElements RTTI Cast Error: %s -> %s", sourceTypeID.c_str(), targetTypeID.c_str());
+                                callContext->m_errorHandler->ReportError(error.c_str());
+                                #endif
+                                return true;    // RTTI Error. Continue serialization
                             }
                         }
-
-                        AZ_Assert(newNode.m_element.m_byteStream.GetCurPos() == 0, "This stream should be only for our data element");
-                        newNode.m_element.m_dataSize = elementClassData->m_serializer->Save(resolvedObject, newNode.m_element.m_byteStream);
-                        newNode.m_element.m_byteStream.Truncate();
-                        newNode.m_element.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN); // reset stream position
-                        newNode.m_element.m_stream = &newNode.m_element.m_byteStream;
-
-                        newNode.m_element.m_dataType = DataElement::DT_BINARY;
                     }
-
-                    nodeStack.push_back(&newNode);
-                    success = true;
                 }
-                else
-                {
-                    const AZStd::string error =
-                        AZStd::string::format("Failed to add sub-element \"%s\" to element \"%s\".",
-                            elementData ? elementData->m_name : "<unknown>",
-                            parentNode->m_element.m_name);
-
-                    if (errorHandler)
-                    {
-                        errorHandler->ReportError(error.c_str());
-                    }
-                    else
-                    {
-                        AZ_Error("Serialize", false, "%s", error.c_str());
-                    }
+            }
+        }
 
-                    success = false;
-                    return false; // Stop enumerating.
-                }
+        if (!dataClassInfo)
+        {
+            dataClassInfo = FindClassData(classId);
+        }
 
-                return true;
+    #if defined(AZ_ENABLE_SERIALIZER_DEBUG)
+        {
+            DbgStackEntry de{
+                /*.m_dataPtr =*/ objectPtr,
+                /*.m_uuid =*/ classId,
+                /*.m_classData =*/ dataClassInfo,
+                /*.m_elementName =*/ classElement ? classElement->m_name : nullptr,
+                /*.m_classElement =*/ classElement,
             };
+            callContext->m_errorHandler->Push(de);
+        }
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
 
-        auto endCB = [&nodeStack, &success]() -> bool
-            {
-                if (success)
-                {
-                    nodeStack.pop_back();
-                }
-
-                return true;
-            };
+        if (dataClassInfo == nullptr)
+        {
+    #if defined (AZ_ENABLE_SERIALIZER_DEBUG)
+            AZStd::string error;
 
-        EnumerateInstanceCallContext callContext(
-            beginCB,
-            endCB,
-            &sc,
-            SerializeContext::ENUM_ACCESS_FOR_READ,
-            errorHandler);
+            // output an error
+            if (classElement && classElement->m_flags & SerializeContext::ClassElement::FLG_BASE_CLASS)
+            {
+                error = AZStd::string::format("Element with class ID '%s' was declared as a base class of another type but is not registered with the serializer.  Either remove it from the Class<> call or reflect it.", classId.ToString<AZStd::string>().c_str());
+            }
+            else
+            {
+                error = AZStd::string::format("Element with class ID '%s' is not registered with the serializer!", classId.ToString<AZStd::string>().c_str());
+            }
 
-        sc.EnumerateInstanceConst(
-            &callContext,
-            objectPtr,
-            classId,
-            classData,
-            nullptr
-            );
+            callContext->m_errorHandler->ReportError(error.c_str());
 
-        return success;
-    }
+            callContext->m_errorHandler->Pop();
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
 
-    bool SerializeContext::DataElementNode::GetClassElement(ClassElement& classElement, const DataElementNode& parentDataElement, ErrorHandler* errorHandler) const
-    {
-        bool elementFound = false;
-        if (parentDataElement.m_classData)
+            return true;    // we errored, but return true to continue enumeration of our siblings and other unrelated hierarchies
+        }
+
+        if (dataClassInfo->m_eventHandler)
         {
-            const ClassData* parentClassData = parentDataElement.m_classData;
-            if (parentClassData->m_container)
+            if ((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == ENUM_ACCESS_FOR_WRITE)
             {
-                IDataContainer* classContainer = parentClassData->m_container;
-                // store the container element in classElementMetadata
-                ClassElement classElementMetadata;
-                bool classElementFound = classContainer->GetElement(classElementMetadata, m_element);
-                AZ_Assert(classElementFound, "'%s'(0x%x) is not a valid element name for container type %s", m_element.m_name ? m_element.m_name : "NULL", m_element.m_nameCrc, parentClassData->m_name);
-                if (classElementFound)
+                dataClassInfo->m_eventHandler->OnWriteBegin(objectPtr);
+            }
+            else
+            {
+                dataClassInfo->m_eventHandler->OnReadBegin(objectPtr);
+            }
+        }
+
+        bool keepEnumeratingSiblings = true;
+
+        // Call beginElemCB for this element if there is one. If the callback
+        // returns false, stop enumeration of this branch
+        // pass the original ptr to the user instead of objectPtr because
+        // he may want to replace the actual object.
+        if (!callContext->m_beginElemCB || callContext->m_beginElemCB(ptr, dataClassInfo, classElement))
+        {
+            if (dataClassInfo->m_container)
+            {
+                dataClassInfo->m_container->EnumElements(objectPtr, callContext->m_elementCallback);
+            }
+            else
+            {
+                for (size_t i = 0, n = dataClassInfo->m_elements.size(); i < n; ++i)
                 {
-                    // if the container contains pointers, then the elements could be a derived type,
-                    // otherwise we need the uuids to be exactly the same.
-                    if (classElementMetadata.m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                    const SerializeContext::ClassElement& ed = dataClassInfo->m_elements[i];
+                    void* dataAddress = (char*)(objectPtr) + ed.m_offset;
+                    if (dataAddress)
                     {
-                        bool downcastPossible = m_element.m_id == classElementMetadata.m_typeId;
-                        downcastPossible = downcastPossible || (m_classData->m_azRtti && classElementMetadata.m_azRtti && m_classData->m_azRtti->IsTypeOf(classElementMetadata.m_azRtti->GetTypeId()));
-                        if (!downcastPossible)
-                        {
-                            AZStd::string error = AZStd::string::format("Element of type %s cannot be added to container of pointers to type %s!"
-                                , m_element.m_id.ToString<AZStd::string>().c_str(), classElementMetadata.m_typeId.ToString<AZStd::string>().c_str());
-                            errorHandler->ReportError(error.c_str());
+                        const SerializeContext::ClassData* elemClassInfo = ed.m_genericClassInfo ? ed.m_genericClassInfo->GetClassData() : FindClassData(ed.m_typeId, dataClassInfo, ed.m_nameCrc);
 
-                            return false;
-                        }
-                    }
-                    else
-                    {
-                        if (m_element.m_id != classElementMetadata.m_typeId)
+                        keepEnumeratingSiblings = EnumerateInstance(callContext, dataAddress, ed.m_typeId, elemClassInfo, &ed);
+                        if (!keepEnumeratingSiblings)
                         {
-                            AZStd::string error = AZStd::string::format("Element of type %s cannot be added to container of type %s!"
-                                , m_element.m_id.ToString<AZStd::string>().c_str(), classElementMetadata.m_typeId.ToString<AZStd::string>().c_str());
-                            errorHandler->ReportError(error.c_str());
-
-                            return false;
+                            break;
                         }
                     }
-                    classElement = classElementMetadata;
-                    elementFound = true;
                 }
-            }
-            else
-            {
-                for (size_t i = 0; i < parentClassData->m_elements.size(); ++i)
+
+                if (dataClassInfo->m_typeId == SerializeTypeInfo<DynamicSerializableField>::GetUuid())
                 {
-                    const SerializeContext::ClassElement* childElement = &parentClassData->m_elements[i];
-                    if (childElement->m_nameCrc == m_element.m_nameCrc)
+                    AZ::DynamicSerializableField* dynamicFieldDesc = reinterpret_cast<AZ::DynamicSerializableField*>(objectPtr);
+                    if (dynamicFieldDesc->IsValid())
                     {
-                        // if the member is a pointer type, then the pointer could be a derived type,
-                        // otherwise we need the uuids to be exactly the same.
-                        if (childElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                        const AZ::SerializeContext::ClassData* dynamicTypeMetadata = FindClassData(dynamicFieldDesc->m_typeId);
+                        if (dynamicTypeMetadata)
                         {
-                            // Verify that a downcast is possible
-                            bool downcastPossible = m_element.m_id == childElement->m_typeId;
-                            downcastPossible = downcastPossible || (m_classData->m_azRtti && childElement->m_azRtti && m_classData->m_azRtti->IsTypeOf(childElement->m_azRtti->GetTypeId()));
-                            if (downcastPossible)
-                            {
-                                classElement = *childElement;
-                                elementFound = true;
-                            }
+                            AZ::SerializeContext::ClassElement dynamicElementData;
+                            dynamicElementData.m_name = "m_data";
+                            dynamicElementData.m_nameCrc = AZ_CRC("m_data", 0x335cc942);
+                            dynamicElementData.m_typeId = dynamicFieldDesc->m_typeId;
+                            dynamicElementData.m_dataSize = sizeof(void*);
+                            dynamicElementData.m_offset = reinterpret_cast<size_t>(&(reinterpret_cast<AZ::DynamicSerializableField const volatile*>(0)->m_data));
+                            dynamicElementData.m_azRtti = nullptr; // we won't need this because we always serialize top classes.
+                            dynamicElementData.m_genericClassInfo = FindGenericClassInfo(dynamicFieldDesc->m_typeId);
+                            dynamicElementData.m_editData = nullptr; // we cannot have element edit data for dynamic fields.
+                            dynamicElementData.m_flags = ClassElement::FLG_DYNAMIC_FIELD | ClassElement::FLG_POINTER;
+                            EnumerateInstance(callContext, &dynamicFieldDesc->m_data, dynamicTypeMetadata->m_typeId, dynamicTypeMetadata, &dynamicElementData);
                         }
                         else
                         {
-                            if (m_element.m_id == childElement->m_typeId)
-                            {
-                                classElement = *childElement;
-                                elementFound = true;
-                            }
+                            AZ_Error("Serialization", false, "Failed to find class data for 'Dynamic Serializable Field' with type=%s address=%p. Make sure this type is reflected,"
+                                " otherwise you will lose data during serialization!\n", dynamicFieldDesc->m_typeId.ToString<AZStd::string>().c_str(), dynamicFieldDesc->m_data);
                         }
-                        break;
                     }
                 }
             }
         }
-        return elementFound;
-    }
-
-    bool SerializeContext::DataElementNode::GetDataHierarchyEnumerate(ErrorHandler* errorHandler, NodeStack& nodeStack)
-    {
-        if (nodeStack.empty())
-        {
-            return true;
-        }
 
-        void* parentPtr = nodeStack.back().m_ptr;
-        DataElementNode* parentDataElement = nodeStack.back().m_dataElement;
-        AZ_Assert(parentDataElement, "parentDataElement is null, cannot enumerate data from data element (%s:%s)",
-            m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data());
-        if (!parentDataElement)
-        {
-            return false;
-        }
-
-        bool success = true;
-
-        if (!m_classData)
+        // call endElemCB
+        if (callContext->m_endElemCB)
         {
-            AZ_Error("Serialize", false, R"(Cannot enumerate data from data element (%s:%s) from parent data element (%s:%s) with class name "%s" because the ClassData does not exist.)"
-                " This can indicate that the class is not reflected at the point of this call. If this is class is reflected as part of a gem"
-                " check if that gem is loaded", m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data(),
-                parentDataElement->m_element.m_name ? parentDataElement->m_element.m_name : "", parentDataElement->m_element.m_id.ToString<AZStd::string>().data(), parentDataElement->m_classData->m_name);
-            return false;
+            keepEnumeratingSiblings = callContext->m_endElemCB();
         }
 
-        AZ::SerializeContext::ClassElement classElement;
-        bool classElementFound = parentDataElement && GetClassElement(classElement, *parentDataElement, errorHandler);
-        AZ_Warning("Serialize", classElementFound, R"(Unable to find class element for data element(%s:%s) with class name "%s" that is a child of parent data element(%s:%s) with class name "%s")",
-            m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data(), m_classData->m_name,
-            parentDataElement->m_element.m_name ? parentDataElement->m_element.m_name : "", parentDataElement->m_element.m_id.ToString<AZStd::string>().data(), parentDataElement->m_classData->m_name);
-
-        if (classElementFound)
+        if (dataClassInfo->m_eventHandler)
         {
-            void* dataAddress = nullptr;
-            IDataContainer* dataContainer = parentDataElement->m_classData->m_container;
-            if (dataContainer) // container elements
+            if ((callContext->m_accessFlags & ENUM_ACCESS_HOLD) == 0)
             {
-                int& parentCurrentContainerElementIndex = nodeStack.back().m_currentContainerElementIndex;
-                // add element to the array
-                if (dataContainer->CanAccessElementsByIndex() && dataContainer->Size(parentPtr) > parentCurrentContainerElementIndex)
+                if ((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == ENUM_ACCESS_FOR_WRITE)
                 {
-                    dataAddress = dataContainer->GetElementByIndex(parentPtr, &classElement, parentCurrentContainerElementIndex);
+                    dataClassInfo->m_eventHandler->OnWriteEnd(objectPtr);
                 }
                 else
                 {
-                    dataAddress = dataContainer->ReserveElement(parentPtr, &classElement);
-                }
-
-                if (dataAddress == nullptr)
-                {
-                    AZStd::string error = AZStd::string::format("Failed to reserve element in container. The container may be full. Element %u will not be added to container.", static_cast<unsigned int>(parentCurrentContainerElementIndex));
-                    errorHandler->ReportError(error.c_str());
+                    dataClassInfo->m_eventHandler->OnReadEnd(objectPtr);
                 }
-
-                parentCurrentContainerElementIndex++;
-            }
-            else
-            {   // normal elements
-                dataAddress = reinterpret_cast<char*>(parentPtr) + classElement.m_offset;
             }
+        }
 
-            void* reserveAddress = dataAddress;
+    #if defined(AZ_ENABLE_SERIALIZER_DEBUG)
+        callContext->m_errorHandler->Pop();
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
 
-            // create a new instance if needed
-            if (classElement.m_flags & SerializeContext::ClassElement::FLG_POINTER)
-            {
-                // create a new instance if we are referencing it by pointer
-                AZ_Assert(m_classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide factory or change data member '%s' to value not pointer!", m_classData->m_name, classElement.m_name);
-                void* newDataAddress = m_classData->m_factory->Create(m_classData->m_name);
+        return keepEnumeratingSiblings;
+    }
 
-                // we need to account for additional offsets if we have a pointer to
-                // a base class.
-                void* basePtr = nullptr;
-                if (m_element.m_id == classElement.m_typeId)
-                {
-                    basePtr = newDataAddress;
-                }
-                else if(m_classData->m_azRtti && classElement.m_azRtti)
-                {
-                    basePtr = m_classData->m_azRtti->Cast(newDataAddress, classElement.m_azRtti->GetTypeId());
-                }
-                AZ_Assert(basePtr != nullptr, dataContainer
-                    ? "Can't cast container element %s(0x%x) to %s, make sure classes are registered in the system and not generics!"
-                    : "Can't cast %s(0x%x) to %s, make sure classes are registered in the system and not generics!"
-                    , m_element.m_name ? m_element.m_name : "NULL"
-                    , m_element.m_nameCrc
-                    , m_classData->m_name);
+    //=========================================================================
+    // EnumerateInstanceConst (deprecated overload)
+    //=========================================================================
+    bool SerializeContext::EnumerateInstanceConst(const void* ptr, const Uuid& classId, const BeginElemEnumCB& beginElemCB, const EndElemEnumCB& endElemCB, unsigned int accessFlags, const ClassData* classData, const ClassElement* classElement, ErrorHandler* errorHandler /*= nullptr*/) const
+    {
+        EnumerateInstanceCallContext callContext(
+            beginElemCB,
+            endElemCB,
+            this,
+            accessFlags,
+            errorHandler);
 
-                *reinterpret_cast<void**>(dataAddress) = basePtr; // store the pointer in the class
-                dataAddress = newDataAddress;
-            }
+        return EnumerateInstanceConst(
+            &callContext,
+            ptr,
+            classId,
+            classData,
+            classElement
+        );
+    }
 
-            DataElement& rawElement = m_element;
-            if (m_classData->m_serializer && rawElement.m_dataSize != 0)
-            {
-                rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-                if (rawElement.m_dataType == DataElement::DT_TEXT)
-                {
-                    // convert to binary so we can load the data
-                    AZStd::string text;
-                    text.resize_no_construct(rawElement.m_dataSize);
-                    rawElement.m_byteStream.Read(text.size(), reinterpret_cast<void*>(text.data()));
-                    rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-                    rawElement.m_dataSize = m_classData->m_serializer->TextToData(text.c_str(), rawElement.m_version, rawElement.m_byteStream);
-                    rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-                    rawElement.m_dataType = DataElement::DT_BINARY;
-                }
+    //=========================================================================
+    // EnumerateInstance (deprecated overload)
+    //=========================================================================
+    bool SerializeContext::EnumerateInstance(void* ptr, const Uuid& classId, const BeginElemEnumCB& beginElemCB, const EndElemEnumCB& endElemCB, unsigned int accessFlags, const ClassData* classData, const ClassElement* classElement, ErrorHandler* errorHandler /*= nullptr*/) const
+    {
+        EnumerateInstanceCallContext callContext(
+            beginElemCB,
+            endElemCB,
+            this,
+            accessFlags,
+            errorHandler);
 
-                bool isLoaded = m_classData->m_serializer->Load(dataAddress, rawElement.m_byteStream, rawElement.m_version, rawElement.m_dataType == DataElement::DT_BINARY_BE);
-                rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN); // reset stream position
-                if (!isLoaded)
-                {
-                    const AZStd::string error =
-                        AZStd::string::format(R"(Failed to load rawElement "%s" for class "%s" with parent element "%s".)",
-                            rawElement.m_name ? rawElement.m_name : "<unknown>",
-                            m_classData->m_name,
-                            m_element.m_name);
+        return EnumerateInstance(
+            &callContext,
+            ptr,
+            classId,
+            classData,
+            classElement
+        );
+    }
 
-                    if (errorHandler)
-                    {
-                        errorHandler->ReportError(error.c_str());
-                    }
-                    else
-                    {
-                        AZ_Error("Serialize", false, "%s", error.c_str());
-                    }
+    struct ObjectCloneData
+    {
+        ObjectCloneData()
+        {
+            m_parentStack.reserve(10);
+        }
+        struct ParentInfo
+        {
+            void* m_ptr;
+            void* m_reservePtr; ///< Used for associative containers like set to store the original address returned by ReserveElement
+            const SerializeContext::ClassData* m_classData;
+            size_t m_containerIndexCounter; ///< Used for fixed containers like array, where the container doesn't store the size.
+        };
+        using ObjectParentStack = AZStd::vector<ParentInfo>;
 
-                    success = false;
-                }
-            }
+        void*               m_ptr;
+        ObjectParentStack   m_parentStack;
+    };
 
-            // Push current DataElementNode to stack
-            DataElementInstanceData node;
-            node.m_ptr = dataAddress;
-            node.m_dataElement = this;
-            nodeStack.push_back(node);
+    //=========================================================================
+    // CloneObject
+    //=========================================================================
+    void* SerializeContext::CloneObject(const void* ptr, const Uuid& classId)
+    {
+        AZStd::vector<char> scratchBuffer;
 
-            for (int dataElementIndex = 0; dataElementIndex < m_subElements.size(); ++dataElementIndex)
-            {
-                DataElementNode& subElement = m_subElements[dataElementIndex];
-                if (!subElement.GetDataHierarchyEnumerate(errorHandler, nodeStack))
-                {
-                    success = false;
-                    break;
-                }
-            }
+        ObjectCloneData cloneData;
+        ErrorHandler m_errorLogger;
 
-            // Pop stack
-            nodeStack.pop_back();
+        AZ_Assert(ptr, "SerializeContext::CloneObject - Attempt to clone a nullptr.");
 
-            if (dataContainer)
-            {
-                dataContainer->StoreElement(parentPtr, reserveAddress);
-            }
+        if (!ptr)
+        {
+            return nullptr;
         }
 
-        return success;
+        EnumerateInstanceCallContext callContext(
+            [&](void* ptr, const ClassData* classData, const ClassElement* elementData) -> bool
+            {
+                return BeginCloneElement(ptr, classData, elementData, &cloneData, &m_errorLogger, &scratchBuffer);
+            },
+            [&]() -> bool
+            {
+                return EndCloneElement(&cloneData);
+            },
+            this, SerializeContext::ENUM_ACCESS_FOR_READ, &m_errorLogger);
+
+        EnumerateInstance(
+            &callContext
+            , const_cast<void*>(ptr)
+            , classId
+            , nullptr
+            , nullptr
+            );
+
+        return cloneData.m_ptr;
     }
 
     //=========================================================================
-    // GetDataHierarchy
+    // CloneObjectInplace
     //=========================================================================
-    bool SerializeContext::DataElementNode::GetDataHierarchy(void* objectPtr, const Uuid& classId, ErrorHandler* errorHandler)
+    void SerializeContext::CloneObjectInplace(void* dest, const void* ptr, const Uuid& classId)
     {
-        (void)classId;
-        AZ_Assert(m_element.m_id == classId, "GetDataHierarchy called with mismatched class type {%s} for element %s",
-            classId.ToString<AZStd::string>().c_str(), m_element.m_name);
+        AZStd::vector<char> scratchBuffer;
 
-        NodeStack nodeStack;
-        DataElementInstanceData topNode;
-        topNode.m_ptr = objectPtr;
-        topNode.m_dataElement = this;
-        nodeStack.push_back(topNode);
+        ObjectCloneData cloneData;
+        cloneData.m_ptr = dest;
+        ErrorHandler m_errorLogger;
 
-        bool success = true;
-        for (size_t i = 0; i < m_subElements.size(); ++i)
+        AZ_Assert(ptr, "SerializeContext::CloneObjectInplace - Attempt to clone a nullptr.");
+
+        if (ptr)
         {
-            if (!m_subElements[i].GetDataHierarchyEnumerate(errorHandler, nodeStack))
-            {
-                success = false;
-                break;
-            }
-        }
+            EnumerateInstanceCallContext callContext(
+                [&](void* ptr, const ClassData* classData, const ClassElement* elementData) -> bool
+                {
+                    return BeginCloneElementInplace(dest, ptr, classData, elementData, &cloneData, &m_errorLogger, &scratchBuffer);
+                },
+                [&]() -> bool
+                {
+                    return EndCloneElement(&cloneData);
+                },
+                this, SerializeContext::ENUM_ACCESS_FOR_READ, &m_errorLogger);
 
-        return success;
+            EnumerateInstance(&callContext, const_cast<void*>(ptr), classId, nullptr, nullptr);
+        }
     }
 
-    //=========================================================================
-    // ClassBuilder::~ClassBuilder
-    //=========================================================================
-    SerializeContext::ClassBuilder::~ClassBuilder()
+    SerializeContext::DataPatchUpgrade::DataPatchUpgrade(AZStd::string_view fieldName, unsigned int fromVersion, unsigned int toVersion)
+        : m_targetFieldName(fieldName)
+        , m_targetFieldCRC(m_targetFieldName.data(), m_targetFieldName.size(), true)
+        , m_fromVersion(fromVersion)
+        , m_toVersion(toVersion)
+    {}
+
+    bool SerializeContext::DataPatchUpgrade::operator==(const DataPatchUpgrade& RHS) const
     {
-#if defined(AZ_ENABLE_TRACING)
-        if (!m_context->IsRemovingReflection())
-        {
-            if (m_classData->second.m_serializer)
-            {
-                AZ_Assert(
-                    m_classData->second.m_elements.empty(),
-                    "Reflection error for class %s.\n"
-                    "Classes with custom serializers are not permitted to also declare serialized elements.\n"
-                    "This is often caused by calling SerializeWithNoData() or specifying a custom serializer on a class which \n"
-                    "is derived from a base class that has serialized elements.",
-                    m_classData->second.m_name ? m_classData->second.m_name : "<Unknown Class>");
-            }
-        }
-#endif // AZ_ENABLE_TRACING
+        return m_upgradeType == RHS.m_upgradeType
+            && m_targetFieldCRC == RHS.m_targetFieldCRC
+            && m_fromVersion == RHS.m_fromVersion
+            && m_toVersion == RHS.m_toVersion;
     }
 
-    //=========================================================================
-    // ClassBuilder::NameChange
-    // [4/10/2019]
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::NameChange(unsigned int fromVersion, unsigned int toVersion, AZStd::string_view oldFieldName, AZStd::string_view newFieldName)
+    bool SerializeContext::DataPatchUpgrade::operator<(const DataPatchUpgrade& RHS) const
     {
-        if (m_context->IsRemovingReflection())
+        if (m_fromVersion < RHS.m_fromVersion)
         {
-            return this; // we have already removed the class data for this class
+            return true;
         }
 
-        AZ_Error("Serialize", !m_classData->second.m_serializer, "Class has a custom serializer, and can not have per-node version upgrades.");
-        AZ_Error("Serialize", !m_classData->second.m_elements.empty(), "Class has no defined elements to add per-node version upgrades to.");
+        if (m_fromVersion > RHS.m_fromVersion)
+        {
+            return false;
+        }
 
-        if (m_classData->second.m_serializer || m_classData->second.m_elements.empty())
+        // We sort on to version in reverse order
+        if (m_toVersion > RHS.m_toVersion)
         {
-            return this;
+            return true;
         }
 
-        m_classData->second.m_dataPatchUpgrader.AddFieldUpgrade(aznew DataPatchNameUpgrade(fromVersion, toVersion, oldFieldName, newFieldName));
+        if (m_toVersion < RHS.m_toVersion)
+        {
+            return false;
+        }
 
-        return this;
+        // When versions are equal, upgrades are prioritized by type in the
+        // order in which they appear in the DataPatchUpgradeType enum.
+        return m_upgradeType < RHS.m_upgradeType;
     }
 
-    //=========================================================================
-    // ClassBuilder::Version
-    // [10/05/2012]
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Version(unsigned int version, VersionConverter converter)
+    unsigned int SerializeContext::DataPatchUpgrade::FromVersion() const
     {
-        if (m_context->IsRemovingReflection())
-        {
-            return this; // we have already removed the class data.
-        }
-        AZ_Assert(version != VersionClassDeprecated, "You cannot use %u as the version, it is reserved by the system!", version);
-        m_classData->second.m_version = version;
-        m_classData->second.m_converter = converter;
-        return this;
+        return m_fromVersion;
     }
 
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Serializer(IDataSerializerPtr serializer)
+    unsigned int SerializeContext::DataPatchUpgrade::ToVersion() const
     {
-        if (m_context->IsRemovingReflection())
-        {
-            return this; // we have already removed the class data.
-        }
-
-        AZ_Assert(m_classData->second.m_elements.empty(),
-            "Class %s has a custom serializer, and can not have additional fields. Classes can either have a custom serializer or child fields.",
-            m_classData->second.m_name);
-
-        m_classData->second.m_serializer = AZStd::move(serializer);
-        return this;
+        return m_toVersion;
+    }
 
+    const AZStd::string& SerializeContext::DataPatchUpgrade::GetFieldName() const
+    {
+        return m_targetFieldName;
     }
 
-    //=========================================================================
-    // ClassBuilder::Serializer
-    // [10/05/2012]
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::Serializer(IDataSerializer* serializer)
+    AZ::Crc32 SerializeContext::DataPatchUpgrade::GetFieldCRC() const
     {
-        return Serializer(IDataSerializerPtr(serializer, IDataSerializer::CreateNoDeleteDeleter()));
+        return m_targetFieldCRC;
     }
 
-    //=========================================================================
-    // ClassBuilder::Serializer
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::SerializeWithNoData()
+    SerializeContext::DataPatchUpgradeType SerializeContext::DataPatchUpgrade::GetUpgradeType() const
     {
-        if (m_context->IsRemovingReflection())
-        {
-            return this; // we have already removed the class data.
-        }
-        m_classData->second.m_serializer = IDataSerializerPtr(&Serialize::StaticInstance<EmptySerializer>::s_instance, IDataSerializer::CreateNoDeleteDeleter());
-        return this;
+        return m_upgradeType;
     }
 
-    //=========================================================================
-    // ClassBuilder::EventHandler
-    // [10/05/2012]
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::EventHandler(IEventHandler* eventHandler)
+    SerializeContext::DataPatchUpgradeHandler::~DataPatchUpgradeHandler()
     {
-        if (m_context->IsRemovingReflection())
+        for (const auto& fieldUpgrades : m_upgrades)
         {
-            return this; // we have already removed the class data.
+            for (const auto& versionUpgrades : fieldUpgrades.second)
+            {
+                for (auto* upgrade : versionUpgrades.second)
+                {
+                    delete upgrade;
+                }
+            }
         }
-        m_classData->second.m_eventHandler = eventHandler;
-        return this;
     }
 
-    //=========================================================================
-    // ClassBuilder::DataContainer
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::DataContainer(IDataContainer* dataContainer)
+    void SerializeContext::DataPatchUpgradeHandler::AddFieldUpgrade(DataPatchUpgrade* upgrade)
     {
-        if (m_context->IsRemovingReflection())
+        // Find the field
+        auto fieldUpgrades = m_upgrades.find(upgrade->GetFieldCRC());
+
+        // If we don't have any upgrades for the field, add this item.
+        if (fieldUpgrades == m_upgrades.end())
         {
-            return this;
+            m_upgrades[upgrade->GetFieldCRC()][upgrade->FromVersion()].insert(upgrade);
+        }
+        else
+        {
+            auto versionUpgrades = fieldUpgrades->second.find(upgrade->FromVersion());
+            if (versionUpgrades == fieldUpgrades->second.end())
+            {
+                fieldUpgrades->second[upgrade->FromVersion()].insert(upgrade);
+            }
+            else
+            {
+                for (auto* existingUpgrade : versionUpgrades->second)
+                {
+                    if (*existingUpgrade == *upgrade)
+                    {
+                        AZ_Assert(false, "Duplicate upgrade to field %s from version %u to version %u", upgrade->GetFieldName().c_str(), upgrade->FromVersion(), upgrade->ToVersion());
+
+                        // In a failure case, delete the upgrade as we've assumed control of it.
+                        delete upgrade;
+                        return;
+                    }
+                }
+
+                m_upgrades[upgrade->GetFieldCRC()][upgrade->FromVersion()].insert(upgrade);
+            }
         }
-        m_classData->second.m_container = dataContainer;
-        return this;
     }
 
-    //=========================================================================
-    // ClassBuilder::PersistentId
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::PersistentId(ClassPersistentId persistentId)
+    const SerializeContext::DataPatchFieldUpgrades& SerializeContext::DataPatchUpgradeHandler::GetUpgrades() const
     {
-        if (m_context->IsRemovingReflection())
-        {
-            return this; // we have already removed the class data.
-        }
-        m_classData->second.m_persistentId = persistentId;
-        return this;
+        return m_upgrades;
     }
 
-    //=========================================================================
-    // ClassBuilder::SerializerDoSave
-    //=========================================================================
-    SerializeContext::ClassBuilder* SerializeContext::ClassBuilder::SerializerDoSave(ClassDoSave doSave)
+    bool SerializeContext::DataPatchNameUpgrade::operator<(const DataPatchUpgrade& RHS) const
     {
-        if (m_context->IsRemovingReflection())
+        // If the right side is also a Field Name Upgrade, forward this to the
+        // appropriate equivalence operator.
+        return DataPatchUpgrade::operator<(RHS);
+    }
+
+    bool SerializeContext::DataPatchNameUpgrade::operator<(const DataPatchNameUpgrade& RHS) const
+    {
+        // The default operator is fine for name upgrades
+        return DataPatchUpgrade::operator<(RHS);
+    }
+
+    void SerializeContext::DataPatchNameUpgrade::Apply(SerializeContext& context, SerializeContext::DataElementNode& node) const
+    {
+        AZ_UNUSED(context);
+
+        int targetElementIndex = node.FindElement(m_targetFieldCRC);
+
+        AZ_Assert(targetElementIndex >= 0, "Invalid node. Field %s is not a valid element of class %s (Version %u). Check your reflection function.", m_targetFieldName.c_str(), node.GetNameString(), node.GetVersion());
+
+        if (targetElementIndex >= 0)
         {
-            return this; // we have already removed the class data.
+            auto& targetElement = node.GetSubElement(targetElementIndex);
+            targetElement.SetName(m_newNodeName.c_str());
         }
-        m_classData->second.m_doSave = doSave;
-        return this;
+    }
+
+    AZStd::string SerializeContext::DataPatchNameUpgrade::GetNewName() const
+    {
+        return m_newNodeName;
     }
 
     //=========================================================================
-    // EnumerateInstanceConst
-    // [10/31/2012]
+    // BeginCloneElement (internal element clone callbacks)
     //=========================================================================
-    bool SerializeContext::EnumerateInstanceConst(SerializeContext::EnumerateInstanceCallContext* callContext, const void* ptr, const Uuid& classId, const ClassData* classData, const ClassElement* classElement) const
+    bool SerializeContext::BeginCloneElement(void* ptr, const ClassData* classData, const ClassElement* elementData, void* data, ErrorHandler* errorHandler, AZStd::vector<char>* scratchBuffer)
     {
-        AZ_Assert((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == 0, "You are asking the serializer to lock the data for write but you only have a const pointer!");
-        return EnumerateInstance(callContext, const_cast<void*>(ptr), classId, classData, classElement);
+        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
+
+        if (cloneData->m_parentStack.empty())
+        {
+            // Since this is the root element, we will need to allocate it using the creator provided
+            AZ_Assert(classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide factory or change data member '%s' to value not pointer!", classData->m_name, elementData->m_name);
+            cloneData->m_ptr = classData->m_factory->Create(classData->m_name);
+        }
+
+        return BeginCloneElementInplace(cloneData->m_ptr, ptr, classData, elementData, data, errorHandler, scratchBuffer);
     }
 
     //=========================================================================
-    // EnumerateInstance
-    // [10/31/2012]
+    // BeginCloneElementInplace (internal element clone callbacks)
     //=========================================================================
-    bool SerializeContext::EnumerateInstance(SerializeContext::EnumerateInstanceCallContext* callContext, void* ptr, Uuid classId, const ClassData* classData, const ClassElement* classElement) const
+    bool SerializeContext::BeginCloneElementInplace(void* rootDestPtr, void* ptr, const ClassData* classData, const ClassElement* elementData, void* data, ErrorHandler* errorHandler, AZStd::vector<char>* scratchBuffer)
     {
-        // if useClassData is provided, just use it, otherwise try to find it using the classId provided.
-        void* objectPtr = ptr;
-        const SerializeContext::ClassData* dataClassInfo = classData;
+        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
 
-        if (classElement)
+        void* srcPtr = ptr;
+        void* destPtr = nullptr;
+        void* reservePtr = nullptr;
+
+        if (classData->m_version == Serialize::VersionClassDeprecated)
         {
-            // if we are a pointer, then we may be pointing to a derived type.
-            if (classElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+            if (classData->m_converter)
             {
-                // if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
-                objectPtr = *(void**)(ptr);
+                AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.");
+            }
+            // push a dummy node in the stack
+            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
+            parentInfo.m_ptr = destPtr;
+            parentInfo.m_reservePtr = reservePtr;
+            parentInfo.m_classData = classData;
+            parentInfo.m_containerIndexCounter = 0;
+            return false;    // do not iterate further.
+        }
 
-                if (!objectPtr)
+
+        if (!cloneData->m_parentStack.empty())
+        {
+            AZ_Assert(elementData, "Non-root nodes need to have a valid elementData!");
+            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.back();
+            void* parentPtr = parentInfo.m_ptr;
+            const ClassData* parentClassData = parentInfo.m_classData;
+            if (parentClassData->m_container)
+            {
+                if (parentClassData->m_container->CanAccessElementsByIndex() && parentClassData->m_container->Size(parentPtr) > parentInfo.m_containerIndexCounter)
                 {
-                    return true;    // nothing to serialize
+                    destPtr = parentClassData->m_container->GetElementByIndex(parentPtr, elementData, parentInfo.m_containerIndexCounter);
                 }
-                if (classElement->m_azRtti)
+                else
                 {
-                    const AZ::Uuid actualClassId = classElement->m_azRtti->GetActualUuid(objectPtr);
-                    if (actualClassId != classId)
-                    {
-                        // we are pointing to derived type, adjust class data, uuid and pointer.
-                        classId = AZStd::move(actualClassId);
-                        dataClassInfo = FindClassData(classId);
-                        if ( (dataClassInfo) && (dataClassInfo->m_azRtti) ) // it could be missing RTTI if its deprecated.
-                        {
-                            objectPtr = classElement->m_azRtti->Cast(objectPtr, dataClassInfo->m_azRtti->GetTypeId());
-
-                            AZ_Assert(objectPtr, "Potential Data Loss: AZ_RTTI Cast to type %s Failed on element: %s", dataClassInfo->m_name, classElement->m_name);
-                            if (!objectPtr)
-                            {
-                                #if defined (AZ_ENABLE_SERIALIZER_DEBUG)
-                                // Additional error information: Provide Type IDs and the serialization stack from our enumeration
-                                AZStd::string sourceTypeID = dataClassInfo->m_typeId.ToString<AZStd::string>();
-                                AZStd::string targetTypeID = classElement->m_typeId.ToString<AZStd::string>();
-                                AZStd::string error = AZStd::string::format("EnumarateElements RTTI Cast Error: %s -> %s", sourceTypeID.c_str(), targetTypeID.c_str());
-                                callContext->m_errorHandler->ReportError(error.c_str());
-                                #endif
-                                return true;    // RTTI Error. Continue serialization
-                            }
-                        }
-                    }
+                    destPtr = parentClassData->m_container->ReserveElement(parentPtr, elementData);
                 }
+
+                ++parentInfo.m_containerIndexCounter;
+            }
+            else
+            {
+                // Allocate memory for our element using the creator provided
+                destPtr = reinterpret_cast<char*>(parentPtr) + elementData->m_offset;
+            }
+
+            reservePtr = destPtr;
+            if (elementData->m_flags & ClassElement::FLG_POINTER)
+            {
+                AZ_Assert(classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide a factory or change data member '%s' to value not pointer!", classData->m_name, elementData->m_name);
+                void* newElement = classData->m_factory->Create(classData->m_name);
+                void* basePtr = DownCast(newElement, classData->m_typeId, elementData->m_typeId, classData->m_azRtti, elementData->m_azRtti);
+                *reinterpret_cast<void**>(destPtr) = basePtr; // store the pointer in the class
+                destPtr = newElement;
+            }
+
+            if (!destPtr && errorHandler)
+            {
+                AZStd::string error = AZStd::string::format("Failed to reserve element in container. The container may be full. Element %u will not be added to container.", static_cast<unsigned int>(parentInfo.m_containerIndexCounter));
+                errorHandler->ReportError(error.c_str());
             }
         }
+        else
+        {
+            destPtr = rootDestPtr;
+            reservePtr = rootDestPtr;
+        }
 
-        if (!dataClassInfo)
+        if (!destPtr)
         {
-            dataClassInfo = FindClassData(classId);
+            // There is no valid destination pointer so a dummy node is added to the clone data parent stack
+            // and further descendent type iteration is halted
+            // An error has been reported to the supplied errorHandler in the code above
+            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
+            parentInfo.m_ptr = destPtr;
+            parentInfo.m_reservePtr = reservePtr;
+            parentInfo.m_classData = classData;
+            parentInfo.m_containerIndexCounter = 0;
+            return false;
         }
 
-    #if defined(AZ_ENABLE_SERIALIZER_DEBUG)
+        if (elementData && elementData->m_flags & ClassElement::FLG_POINTER)
         {
-            DbgStackEntry de{
-                /*.m_dataPtr =*/ objectPtr,
-                /*.m_uuid =*/ classId,
-                /*.m_classData =*/ dataClassInfo,
-                /*.m_elementName =*/ classElement ? classElement->m_name : nullptr,
-                /*.m_classElement =*/ classElement,
-            };
-            callContext->m_errorHandler->Push(de);
+            // if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
+            srcPtr = *(void**)(ptr);
+            if (elementData->m_azRtti)
+            {
+                srcPtr = elementData->m_azRtti->Cast(srcPtr, classData->m_azRtti->GetTypeId());
+            }
         }
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
 
-        if (dataClassInfo == nullptr)
+        if (classData->m_eventHandler)
         {
-    #if defined (AZ_ENABLE_SERIALIZER_DEBUG)
-            AZStd::string error;
+            classData->m_eventHandler->OnWriteBegin(destPtr);
+        }
 
-            // output an error
-            if (classElement && classElement->m_flags & SerializeContext::ClassElement::FLG_BASE_CLASS)
+        if (classData->m_serializer)
+        {
+            if (const auto* genericInfo = elementData ? elementData->m_genericClassInfo : FindGenericClassInfo(classData->m_typeId);
+                    genericInfo && genericInfo->GetGenericTypeId() == GetAssetClassId())
             {
-                error = AZStd::string::format("Element with class ID '%s' was declared as a base class of another type but is not registered with the serializer.  Either remove it from the Class<> call or reflect it.", classId.ToString<AZStd::string>().c_str());
+                // Optimized clone path for asset references.
+                static_cast<AssetSerializer*>(classData->m_serializer.get())->Clone(srcPtr, destPtr);
             }
             else
             {
-                error = AZStd::string::format("Element with class ID '%s' is not registered with the serializer!", classId.ToString<AZStd::string>().c_str());
-            }
+                scratchBuffer->clear();
+                IO::ByteContainerStream<AZStd::vector<char>> stream(scratchBuffer);
 
-            callContext->m_errorHandler->ReportError(error.c_str());
+                classData->m_serializer->Save(srcPtr, stream);
+                stream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
 
-            callContext->m_errorHandler->Pop();
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
+                classData->m_serializer->Load(destPtr, stream, classData->m_version);
+            }
+        }
 
-            return true;    // we errored, but return true to continue enumeration of our siblings and other unrelated hierarchies
+        // If it is a container, clear it before loading the child
+        // nodes, otherwise we end up with more elements than the ones
+        // we should have
+        if (classData->m_container)
+        {
+            classData->m_container->ClearElements(destPtr, this);
         }
 
-        if (dataClassInfo->m_eventHandler)
+        // push this node in the stack
+        ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
+        parentInfo.m_ptr = destPtr;
+        parentInfo.m_reservePtr = reservePtr;
+        parentInfo.m_classData = classData;
+        parentInfo.m_containerIndexCounter = 0;
+        return true;
+    }
+
+    //=========================================================================
+    // EndCloneElement (internal element clone callbacks)
+    //=========================================================================
+    bool SerializeContext::EndCloneElement(void* data)
+    {
+        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
+        void* dataPtr = cloneData->m_parentStack.back().m_ptr;
+        void* reservePtr = cloneData->m_parentStack.back().m_reservePtr;
+
+        if (!dataPtr)
         {
-            if ((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == ENUM_ACCESS_FOR_WRITE)
-            {
-                dataClassInfo->m_eventHandler->OnWriteBegin(objectPtr);
-            }
-            else
+            // we failed to clone an object - an assertion was already raised if it needed to be.
+            cloneData->m_parentStack.pop_back();
+            return true; // continue on to siblings.
+        }
+
+        const ClassData* classData = cloneData->m_parentStack.back().m_classData;
+        if (classData->m_eventHandler)
+        {
+            classData->m_eventHandler->OnWriteEnd(dataPtr);
+            classData->m_eventHandler->OnObjectCloned(dataPtr);
+        }
+
+        if (classData->m_serializer)
+        {
+            classData->m_serializer->PostClone(dataPtr);
+        }
+
+        cloneData->m_parentStack.pop_back();
+        if (!cloneData->m_parentStack.empty())
+        {
+            const ClassData* parentClassData = cloneData->m_parentStack.back().m_classData;
+            if (parentClassData->m_container)
             {
-                dataClassInfo->m_eventHandler->OnReadBegin(objectPtr);
+                // Pass in the address returned by IDataContainer::ReserveElement.
+                //AZStdAssociativeContainer is the only DataContainer that uses the second argument passed into IDataContainer::StoreElement
+                parentClassData->m_container->StoreElement(cloneData->m_parentStack.back().m_ptr, reservePtr);
             }
         }
+        return true;
+    }
 
-        bool keepEnumeratingSiblings = true;
-
-        // Call beginElemCB for this element if there is one. If the callback
-        // returns false, stop enumeration of this branch
-        // pass the original ptr to the user instead of objectPtr because
-        // he may want to replace the actual object.
-        if (!callContext->m_beginElemCB || callContext->m_beginElemCB(ptr, dataClassInfo, classElement))
+    //=========================================================================
+    // EnumerateDerived
+    // [11/13/2012]
+    //=========================================================================
+    void SerializeContext::EnumerateDerived(const TypeInfoCB& callback, const Uuid& classId, const Uuid& typeId) const
+    {
+        // right now this function is SLOW, traverses all serialized types. If we need faster
+        // we will need to cache/store derived type in the base type.
+        for (SerializeContext::UuidToClassMap::const_iterator it = m_uuidMap.begin(); it != m_uuidMap.end(); ++it)
         {
-            if (dataClassInfo->m_container)
+            const ClassData& cd = it->second;
+
+            if (cd.m_typeId == classId)
             {
-                dataClassInfo->m_container->EnumElements(objectPtr, callContext->m_elementCallback);
+                continue;
             }
-            else
+
+            if (cd.m_azRtti && typeId != Uuid::CreateNull())
             {
-                for (size_t i = 0, n = dataClassInfo->m_elements.size(); i < n; ++i)
+                if (cd.m_azRtti->IsTypeOf(typeId))
                 {
-                    const SerializeContext::ClassElement& ed = dataClassInfo->m_elements[i];
-                    void* dataAddress = (char*)(objectPtr) + ed.m_offset;
-                    if (dataAddress)
+                    if (!callback(&cd, {}))
                     {
-                        const SerializeContext::ClassData* elemClassInfo = ed.m_genericClassInfo ? ed.m_genericClassInfo->GetClassData() : FindClassData(ed.m_typeId, dataClassInfo, ed.m_nameCrc);
+                        return;
+                    }
+                }
+            }
 
-                        keepEnumeratingSiblings = EnumerateInstance(callContext, dataAddress, ed.m_typeId, elemClassInfo, &ed);
-                        if (!keepEnumeratingSiblings)
+            if (!classId.IsNull())
+            {
+                for (size_t i = 0; i < cd.m_elements.size(); ++i)
+                {
+                    if ((cd.m_elements[i].m_flags & ClassElement::FLG_BASE_CLASS) != 0)
+                    {
+                        if (cd.m_elements[i].m_typeId == classId)
                         {
-                            break;
+                            // if both classes have azRtti they will be enumerated already by the code above (azrtti)
+                            if (cd.m_azRtti == nullptr || cd.m_elements[i].m_azRtti == nullptr)
+                            {
+                                if (!callback(&cd, {}))
+                                {
+                                    return;
+                                }
+                            }
                         }
                     }
                 }
+            }
+        }
+    }
 
-                if (dataClassInfo->m_typeId == SerializeTypeInfo<DynamicSerializableField>::GetUuid())
+    //=========================================================================
+    // EnumerateBase
+    // [11/13/2012]
+    //=========================================================================
+    void SerializeContext::EnumerateBase(const TypeInfoCB& callback, const Uuid& classId)
+    {
+        const ClassData* cd = FindClassData(classId);
+        if (cd)
+        {
+            EnumerateBaseRTTIEnumCallbackData callbackData;
+            callbackData.m_callback = &callback;
+            callbackData.m_reportedTypes.push_back(cd->m_typeId);
+            for (size_t i = 0; i < cd->m_elements.size(); ++i)
+            {
+                if ((cd->m_elements[i].m_flags & ClassElement::FLG_BASE_CLASS) != 0)
                 {
-                    AZ::DynamicSerializableField* dynamicFieldDesc = reinterpret_cast<AZ::DynamicSerializableField*>(objectPtr);
-                    if (dynamicFieldDesc->IsValid())
+                    const ClassData* baseClassData = FindClassData(cd->m_elements[i].m_typeId);
+                    if (baseClassData)
                     {
-                        const AZ::SerializeContext::ClassData* dynamicTypeMetadata = FindClassData(dynamicFieldDesc->m_typeId);
-                        if (dynamicTypeMetadata)
-                        {
-                            AZ::SerializeContext::ClassElement dynamicElementData;
-                            dynamicElementData.m_name = "m_data";
-                            dynamicElementData.m_nameCrc = AZ_CRC("m_data", 0x335cc942);
-                            dynamicElementData.m_typeId = dynamicFieldDesc->m_typeId;
-                            dynamicElementData.m_dataSize = sizeof(void*);
-                            dynamicElementData.m_offset = reinterpret_cast<size_t>(&(reinterpret_cast<AZ::DynamicSerializableField const volatile*>(0)->m_data));
-                            dynamicElementData.m_azRtti = nullptr; // we won't need this because we always serialize top classes.
-                            dynamicElementData.m_genericClassInfo = FindGenericClassInfo(dynamicFieldDesc->m_typeId);
-                            dynamicElementData.m_editData = nullptr; // we cannot have element edit data for dynamic fields.
-                            dynamicElementData.m_flags = ClassElement::FLG_DYNAMIC_FIELD | ClassElement::FLG_POINTER;
-                            EnumerateInstance(callContext, &dynamicFieldDesc->m_data, dynamicTypeMetadata->m_typeId, dynamicTypeMetadata, &dynamicElementData);
-                        }
-                        else
+                        callbackData.m_reportedTypes.push_back(baseClassData->m_typeId);
+                        if (!callback(baseClassData, {}))
                         {
-                            AZ_Error("Serialization", false, "Failed to find class data for 'Dynamic Serializable Field' with type=%s address=%p. Make sure this type is reflected, \
-                                otherwise you will lose data during serialization!\n", dynamicFieldDesc->m_typeId.ToString<AZStd::string>().c_str(), dynamicFieldDesc->m_data);
+                            return;
                         }
                     }
                 }
             }
+            if (cd->m_azRtti)
+            {
+                cd->m_azRtti->EnumHierarchy(&SerializeContext::EnumerateBaseRTTIEnumCallback, &callbackData);
+            }
         }
+    }
 
-        // call endElemCB
-        if (callContext->m_endElemCB)
+    //=========================================================================
+    // EnumerateAll
+    //=========================================================================
+    void SerializeContext::EnumerateAll(const TypeInfoCB& callback, bool includeGenerics) const
+    {
+        for (auto& uuidToClassPair : m_uuidMap)
         {
-            keepEnumeratingSiblings = callContext->m_endElemCB();
+            const ClassData& classData = uuidToClassPair.second;
+            if (!callback(&classData, classData.m_typeId))
+            {
+                return;
+            }
         }
 
-        if (dataClassInfo->m_eventHandler)
+        if (includeGenerics)
         {
-            if ((callContext->m_accessFlags & ENUM_ACCESS_HOLD) == 0)
+            for (auto& uuidToGenericPair : m_uuidGenericMap)
             {
-                if ((callContext->m_accessFlags & ENUM_ACCESS_FOR_WRITE) == ENUM_ACCESS_FOR_WRITE)
-                {
-                    dataClassInfo->m_eventHandler->OnWriteEnd(objectPtr);
-                }
-                else
+                const ClassData* classData = uuidToGenericPair.second->GetClassData();
+                if (classData)
                 {
-                    dataClassInfo->m_eventHandler->OnReadEnd(objectPtr);
+                    if (!callback(classData, classData->m_typeId))
+                    {
+                        return;
+                    }
                 }
             }
         }
+    }
 
-    #if defined(AZ_ENABLE_SERIALIZER_DEBUG)
-        callContext->m_errorHandler->Pop();
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
-
-        return keepEnumeratingSiblings;
+    void SerializeContext::RegisterDataContainer(AZStd::unique_ptr<IDataContainer> dataContainer)
+    {
+        m_dataContainers.push_back(AZStd::move(dataContainer));
     }
 
     //=========================================================================
-    // EnumerateInstanceConst (deprecated overload)
+    // EnumerateBaseRTTIEnumCallback
+    // [11/13/2012]
     //=========================================================================
-    bool SerializeContext::EnumerateInstanceConst(const void* ptr, const Uuid& classId, const BeginElemEnumCB& beginElemCB, const EndElemEnumCB& endElemCB, unsigned int accessFlags, const ClassData* classData, const ClassElement* classElement, ErrorHandler* errorHandler /*= nullptr*/) const
+    void SerializeContext::EnumerateBaseRTTIEnumCallback(const Uuid& id, void* userData)
     {
-        EnumerateInstanceCallContext callContext(
-            beginElemCB,
-            endElemCB,
-            this,
-            accessFlags,
-            errorHandler);
-
-        return EnumerateInstanceConst(
-            &callContext,
-            ptr,
-            classId,
-            classData,
-            classElement
-        );
+        EnumerateBaseRTTIEnumCallbackData* callbackData = reinterpret_cast<EnumerateBaseRTTIEnumCallbackData*>(userData);
+        // if not reported, report
+        if (AZStd::find(callbackData->m_reportedTypes.begin(), callbackData->m_reportedTypes.end(), id) == callbackData->m_reportedTypes.end())
+        {
+            (*callbackData->m_callback)(nullptr, id);
+        }
     }
+} // namespace AZ
 
+namespace AZ
+{
     //=========================================================================
-    // EnumerateInstance (deprecated overload)
+    // ToString
+    // [11/1/2012]
     //=========================================================================
-    bool SerializeContext::EnumerateInstance(void* ptr, const Uuid& classId, const BeginElemEnumCB& beginElemCB, const EndElemEnumCB& endElemCB, unsigned int accessFlags, const ClassData* classData, const ClassElement* classElement, ErrorHandler* errorHandler /*= nullptr*/) const
+    void SerializeContext::DbgStackEntry::ToString(AZStd::string& str) const
     {
-        EnumerateInstanceCallContext callContext(
-            beginElemCB,
-            endElemCB,
-            this,
-            accessFlags,
-            errorHandler);
-
-        return EnumerateInstance(
-            &callContext,
-            ptr,
-            classId,
-            classData,
-            classElement
-        );
-    }
-
-    struct ObjectCloneData
-    {
-        ObjectCloneData()
+        str += "[";
+        if (m_elementName)
         {
-            m_parentStack.reserve(10);
+            str += AZStd::string::format(" Element: '%s' of", m_elementName);
         }
-        struct ParentInfo
+        //if( m_classElement )
+        //  str += AZStd::string::format(" Offset: %d",m_classElement->m_offset);
+        if (m_classData)
         {
-            void* m_ptr;
-            void* m_reservePtr; ///< Used for associative containers like set to store the original address returned by ReserveElement
-            const SerializeContext::ClassData* m_classData;
-            size_t m_containerIndexCounter; ///< Used for fixed containers like array, where the container doesn't store the size.
-        };
-        typedef AZStd::vector<ParentInfo> ObjectParentStack;
-
-        void*               m_ptr;
-        ObjectParentStack   m_parentStack;
-    };
+            str += AZStd::string::format(" Class: '%s' Version: %d", m_classData->m_name, m_classData->m_version);
+        }
+        str += AZStd::string::format(" Address: %p Uuid: %s", m_dataPtr, m_uuid.ToString<AZStd::string>().c_str());
+        str += " ]\n";
+    }
 
     //=========================================================================
-    // CloneObject
+    // RemoveClassData
     //=========================================================================
-    void* SerializeContext::CloneObject(const void* ptr, const Uuid& classId)
+    void SerializeContext::RemoveClassData(ClassData* classData)
     {
-        AZStd::vector<char> scratchBuffer;
-
-        ObjectCloneData cloneData;
-        ErrorHandler m_errorLogger;
-
-        AZ_Assert(ptr, "SerializeContext::CloneObject - Attempt to clone a nullptr.");
-
-        if (!ptr)
+        if (m_editContext)
         {
-            return nullptr;
+            m_editContext->RemoveClassData(classData);
         }
-
-        EnumerateInstanceCallContext callContext(
-            [&](void* ptr, const ClassData* classData, const ClassElement* elementData) -> bool
-            {
-                return BeginCloneElement(ptr, classData, elementData, &cloneData, &m_errorLogger, &scratchBuffer);
-            },
-            [&]() -> bool
-            {
-                return EndCloneElement(&cloneData);
-            },
-            this, SerializeContext::ENUM_ACCESS_FOR_READ, &m_errorLogger);
-
-        EnumerateInstance(
-            &callContext
-            , const_cast<void*>(ptr)
-            , classId
-            , nullptr
-            , nullptr
-            );
-
-        return cloneData.m_ptr;
     }
 
-    //=========================================================================
-    // CloneObjectInplace
-    //=========================================================================
-    void SerializeContext::CloneObjectInplace(void* dest, const void* ptr, const Uuid& classId)
+    void SerializeContext::RemoveGenericClassInfo(GenericClassInfo* genericClassInfo)
     {
-        AZStd::vector<char> scratchBuffer;
-
-        ObjectCloneData cloneData;
-        cloneData.m_ptr = dest;
-        ErrorHandler m_errorLogger;
-
-        AZ_Assert(ptr, "SerializeContext::CloneObjectInplace - Attempt to clone a nullptr.");
+        const Uuid& classId = genericClassInfo->GetSpecializedTypeId();
+        RemoveClassData(genericClassInfo->GetClassData());
+        // Find the module GenericClassInfo in the SerializeContext GenericClassInfo multimap and remove it from there
+        auto scGenericClassInfoRange = m_uuidGenericMap.equal_range(classId);
+        auto scGenericInfoFoundIt = AZStd::find_if(scGenericClassInfoRange.first, scGenericClassInfoRange.second, [genericClassInfo](const AZStd::pair<AZ::Uuid, GenericClassInfo*>& genericPair)
+        {
+            return genericClassInfo == genericPair.second;
+        });
 
-        if (ptr)
+        if (scGenericInfoFoundIt != scGenericClassInfoRange.second)
         {
-            EnumerateInstanceCallContext callContext(
-                [&](void* ptr, const ClassData* classData, const ClassElement* elementData) -> bool
-                {
-                    return BeginCloneElementInplace(dest, ptr, classData, elementData, &cloneData, &m_errorLogger, &scratchBuffer);
-                },
-                [&]() -> bool
+            m_uuidGenericMap.erase(scGenericInfoFoundIt);
+            if (m_uuidGenericMap.count(classId) == 0)
+            {
+                m_uuidAnyCreationMap.erase(classId);
+                auto classNameRange = m_classNameToUuid.equal_range(Crc32(genericClassInfo->GetClassData()->m_name));
+                for (auto classNameRangeIter = classNameRange.first; classNameRangeIter != classNameRange.second;)
                 {
-                    return EndCloneElement(&cloneData);
-                },
-                this, SerializeContext::ENUM_ACCESS_FOR_READ, &m_errorLogger);
+                    if (classNameRangeIter->second == classId)
+                    {
+                        classNameRangeIter = m_classNameToUuid.erase(classNameRangeIter);
+                    }
+                    else
+                    {
+                        ++classNameRangeIter;
+                    }
+                }
 
-            EnumerateInstance(&callContext, const_cast<void*>(ptr), classId, nullptr, nullptr);
+                auto legacyTypeIdRangeIt = m_legacySpecializeTypeIdToTypeIdMap.equal_range(genericClassInfo->GetLegacySpecializedTypeId());
+                for (auto legacySpecializedTypeIdIt = legacyTypeIdRangeIt.first; legacySpecializedTypeIdIt != legacyTypeIdRangeIt.second; ++legacySpecializedTypeIdIt)
+                {
+                    if (classId == legacySpecializedTypeIdIt->second)
+                    {
+                        m_legacySpecializeTypeIdToTypeIdMap.erase(classId);
+                        break;
+                    }
+                }
+            }
         }
     }
 
-    AZ::SerializeContext::DataPatchUpgrade::DataPatchUpgrade(AZStd::string_view fieldName, unsigned int fromVersion, unsigned int toVersion)
-        : m_targetFieldName(fieldName)
-        , m_targetFieldCRC(m_targetFieldName.data(), m_targetFieldName.size(), true)
-        , m_fromVersion(fromVersion)
-        , m_toVersion(toVersion)
-    {}
-
-    bool AZ::SerializeContext::DataPatchUpgrade::operator==(const DataPatchUpgrade& RHS) const
-    {
-        return m_upgradeType == RHS.m_upgradeType
-            && m_targetFieldCRC == RHS.m_targetFieldCRC
-            && m_fromVersion == RHS.m_fromVersion
-            && m_toVersion == RHS.m_toVersion;
-    }
-
-    bool AZ::SerializeContext::DataPatchUpgrade::operator<(const DataPatchUpgrade& RHS) const
+    //=========================================================================
+    // GetStackDescription
+    //=========================================================================
+    AZStd::string SerializeContext::ErrorHandler::GetStackDescription() const
     {
-        if (m_fromVersion < RHS.m_fromVersion)
-        {
-            return true;
-        }
-
-        if (m_fromVersion > RHS.m_fromVersion)
-        {
-            return false;
-        }
-
-        // We sort on to version in reverse order
-        if (m_toVersion > RHS.m_toVersion)
-        {
-            return true;
-        }
+        AZStd::string stackDescription;
 
-        if (m_toVersion < RHS.m_toVersion)
+    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
+        if (!m_stack.empty())
         {
-            return false;
+            stackDescription += "\n=== Serialize stack ===\n";
+            for (size_t i = 0; i < m_stack.size(); ++i)
+            {
+                m_stack[i].ToString(stackDescription);
+            }
+            stackDescription += "\n";
         }
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
 
-        // When versions are equal, upgrades are prioritized by type in the
-        // order in which they appear in the DataPatchUpgradeType enum.
-        return m_upgradeType < RHS.m_upgradeType;
+        return stackDescription;
     }
 
-    unsigned int AZ::SerializeContext::DataPatchUpgrade::FromVersion() const
+    //=========================================================================
+    // ReportError
+    // [12/11/2012]
+    //=========================================================================
+    void SerializeContext::ErrorHandler::ReportError(const char* message)
     {
-        return m_fromVersion;
+        (void)message;
+        AZ_Error("Serialize", false, "%s\n%s", message, GetStackDescription().c_str());
+        m_nErrors++;
     }
 
-    unsigned int AZ::SerializeContext::DataPatchUpgrade::ToVersion() const
+    //=========================================================================
+    // ReportWarning
+    //=========================================================================
+    void SerializeContext::ErrorHandler::ReportWarning(const char* message)
     {
-        return m_toVersion;
+        (void)message;
+        AZ_Warning("Serialize", false, "%s\n%s", message, GetStackDescription().c_str());
+        m_nWarnings++;
     }
 
-    const AZStd::string& AZ::SerializeContext::DataPatchUpgrade::GetFieldName() const
+    //=========================================================================
+    // Push
+    // [1/3/2013]
+    //=========================================================================
+    void SerializeContext::ErrorHandler::Push([[maybe_unused]] const DbgStackEntry& de)
     {
-        return m_targetFieldName;
+    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
+        m_stack.push_back((de));
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
     }
 
-    AZ::Crc32 AZ::SerializeContext::DataPatchUpgrade::GetFieldCRC() const
+    //=========================================================================
+    // Pop
+    // [1/3/2013]
+    //=========================================================================
+    void SerializeContext::ErrorHandler::Pop()
     {
-        return m_targetFieldCRC;
+    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
+        m_stack.pop_back();
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
     }
 
-    AZ::SerializeContext::DataPatchUpgradeType AZ::SerializeContext::DataPatchUpgrade::GetUpgradeType() const
+    //=========================================================================
+    // Reset
+    // [1/23/2013]
+    //=========================================================================
+    void SerializeContext::ErrorHandler::Reset()
     {
-        return m_upgradeType;
+    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
+        m_stack.clear();
+    #endif // AZ_ENABLE_SERIALIZER_DEBUG
+        m_nErrors = 0;
     }
 
-    AZ::SerializeContext::DataPatchUpgradeHandler::~DataPatchUpgradeHandler()
+    void Internal::AZStdArrayEvents::OnWriteBegin(void* classPtr)
     {
-        for (const auto& fieldUpgrades : m_upgrades)
+        (void)classPtr;
+        if (m_indices)
         {
-            for (const auto& versionUpgrades : fieldUpgrades.second)
+            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
             {
-                for (auto* upgrade : versionUpgrades.second)
-                {
-                    delete upgrade;
-                }
+                // Pointer is already in use to store an index so convert it to a stack
+                size_t previousIndex = reinterpret_cast<uintptr_t>(m_indices) >> 1;
+                Stack* stack = new Stack();
+                AZ_Assert((reinterpret_cast<uintptr_t>(stack) & 1) == 0, "Expected memory allocation to be at least 2 byte aligned.");
+                stack->push(previousIndex);
+                stack->push(0);
+                m_indices = stack;
+            }
+            else
+            {
+                Stack* stack = reinterpret_cast<Stack*>(m_indices);
+                stack->push(0);
             }
         }
+        else
+        {
+            // Use the pointer to just store the one counter instead of allocating memory. Using 1 bit to identify this as a regular
+            // index and not a pointer.
+            m_indices = reinterpret_cast<void*>(1);
+        }
     }
 
-    void AZ::SerializeContext::DataPatchUpgradeHandler::AddFieldUpgrade(DataPatchUpgrade* upgrade)
+    void Internal::AZStdArrayEvents::OnWriteEnd(void* classPtr)
     {
-        // Find the field
-        auto fieldUpgrades = m_upgrades.find(upgrade->GetFieldCRC());
-
-        // If we don't have any upgrades for the field, add this item.
-        if (fieldUpgrades == m_upgrades.end())
-        {
-            m_upgrades[upgrade->GetFieldCRC()][upgrade->FromVersion()].insert(upgrade);
-        }
-        else
+        (void)classPtr;
+        if (m_indices)
         {
-            auto versionUpgrades = fieldUpgrades->second.find(upgrade->FromVersion());
-            if (versionUpgrades == fieldUpgrades->second.end())
+            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
             {
-                fieldUpgrades->second[upgrade->FromVersion()].insert(upgrade);
+                // There was only one entry so no stack. Clear out the final bit that indicated this was an index and not a pointer.
+                m_indices = nullptr;
             }
             else
             {
-                for (auto* existingUpgrade : versionUpgrades->second)
+                Stack* stack = reinterpret_cast<Stack*>(m_indices);
+                stack->pop();
+                if (stack->empty())
                 {
-                    if (*existingUpgrade == *upgrade)
-                    {
-                        AZ_Assert(false, "Duplicate upgrade to field %s from version %u to version %u", upgrade->GetFieldName().c_str(), upgrade->FromVersion(), upgrade->ToVersion());
-
-                        // In a failure case, delete the upgrade as we've assumed control of it.
-                        delete upgrade;
-                        return;
-                    }
+                    delete stack;
+                    m_indices = nullptr;
                 }
-
-                m_upgrades[upgrade->GetFieldCRC()][upgrade->FromVersion()].insert(upgrade);
             }
         }
-    }
-
-    const AZ::SerializeContext::DataPatchFieldUpgrades& AZ::SerializeContext::DataPatchUpgradeHandler::GetUpgrades() const
-    {
-        return m_upgrades;
-    }
-
-    bool AZ::SerializeContext::DataPatchNameUpgrade::operator<(const DataPatchUpgrade& RHS) const
-    {
-        // If the right side is also a Field Name Upgrade, forward this to the
-        // appropriate equivalence operator.
-        return DataPatchUpgrade::operator<(RHS);
-    }
-
-    bool AZ::SerializeContext::DataPatchNameUpgrade::operator<(const DataPatchNameUpgrade& RHS) const
-    {
-        // The default operator is fine for name upgrades
-        return DataPatchUpgrade::operator<(RHS);
-    }
-
-    void AZ::SerializeContext::DataPatchNameUpgrade::Apply(AZ::SerializeContext& context, SerializeContext::DataElementNode& node) const
-    {
-        AZ_UNUSED(context);
-
-        int targetElementIndex = node.FindElement(m_targetFieldCRC);
-
-        AZ_Assert(targetElementIndex >= 0, "Invalid node. Field %s is not a valid element of class %s (Version %u). Check your reflection function.", m_targetFieldName.c_str(), node.GetNameString(), node.GetVersion());
-
-        if (targetElementIndex >= 0)
-        {
-            auto& targetElement = node.GetSubElement(targetElementIndex);
-            targetElement.SetName(m_newNodeName.c_str());
-        }
-    }
-
-    AZStd::string AZ::SerializeContext::DataPatchNameUpgrade::GetNewName() const
-    {
-        return m_newNodeName;
-    }
-
-    //=========================================================================
-    // BeginCloneElement (internal element clone callbacks)
-    //=========================================================================
-    bool SerializeContext::BeginCloneElement(void* ptr, const ClassData* classData, const ClassElement* elementData, void* data, ErrorHandler* errorHandler, AZStd::vector<char>* scratchBuffer)
-    {
-        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
-
-        if (cloneData->m_parentStack.empty())
+        else
         {
-            // Since this is the root element, we will need to allocate it using the creator provided
-            AZ_Assert(classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide factory or change data member '%s' to value not pointer!", classData->m_name, elementData->m_name);
-            cloneData->m_ptr = classData->m_factory->Create(classData->m_name);
+            AZ_Warning("Serialization", false, "AZStdArrayEvents::OnWriteEnd called too often.");
         }
 
-        return BeginCloneElementInplace(cloneData->m_ptr, ptr, classData, elementData, data, errorHandler, scratchBuffer);
     }
 
-    //=========================================================================
-    // BeginCloneElementInplace (internal element clone callbacks)
-    //=========================================================================
-    bool SerializeContext::BeginCloneElementInplace(void* rootDestPtr, void* ptr, const ClassData* classData, const ClassElement* elementData, void* data, ErrorHandler* errorHandler, AZStd::vector<char>* scratchBuffer)
+    size_t Internal::AZStdArrayEvents::GetIndex() const
     {
-        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
-
-        void* srcPtr = ptr;
-        void* destPtr = nullptr;
-        void* reservePtr = nullptr;
-
-        if (classData->m_version == VersionClassDeprecated)
-        {
-            if (classData->m_converter)
-            {
-                AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.");
-            }
-            // push a dummy node in the stack
-            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
-            parentInfo.m_ptr = destPtr;
-            parentInfo.m_reservePtr = reservePtr;
-            parentInfo.m_classData = classData;
-            parentInfo.m_containerIndexCounter = 0;
-            return false;    // do not iterate further.
-        }
-
-
-        if (!cloneData->m_parentStack.empty())
+        if (m_indices)
         {
-            AZ_Assert(elementData, "Non-root nodes need to have a valid elementData!");
-            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.back();
-            void* parentPtr = parentInfo.m_ptr;
-            const ClassData* parentClassData = parentInfo.m_classData;
-            if (parentClassData->m_container)
+            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
             {
-                if (parentClassData->m_container->CanAccessElementsByIndex() && parentClassData->m_container->Size(parentPtr) > parentInfo.m_containerIndexCounter)
-                {
-                    destPtr = parentClassData->m_container->GetElementByIndex(parentPtr, elementData, parentInfo.m_containerIndexCounter);
-                }
-                else
-                {
-                    destPtr = parentClassData->m_container->ReserveElement(parentPtr, elementData);
-                }
-
-                ++parentInfo.m_containerIndexCounter;
+                // The first bit is used to indicate this is a regular index instead of a pointer so shift down one to get the actual index.
+                return reinterpret_cast<uintptr_t>(m_indices) >> 1;
             }
             else
             {
-                // Allocate memory for our element using the creator provided
-                destPtr = reinterpret_cast<char*>(parentPtr) + elementData->m_offset;
-            }
-
-            reservePtr = destPtr;
-            if (elementData->m_flags & ClassElement::FLG_POINTER)
-            {
-                AZ_Assert(classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide a factory or change data member '%s' to value not pointer!", classData->m_name, elementData->m_name);
-                void* newElement = classData->m_factory->Create(classData->m_name);
-                void* basePtr = DownCast(newElement, classData->m_typeId, elementData->m_typeId, classData->m_azRtti, elementData->m_azRtti);
-                *reinterpret_cast<void**>(destPtr) = basePtr; // store the pointer in the class
-                destPtr = newElement;
-            }
-
-            if (!destPtr && errorHandler)
-            {
-                AZStd::string error = AZStd::string::format("Failed to reserve element in container. The container may be full. Element %u will not be added to container.", static_cast<unsigned int>(parentInfo.m_containerIndexCounter));
-                errorHandler->ReportError(error.c_str());
+                const Stack* stack = reinterpret_cast<const Stack*>(m_indices);
+                return stack->top();
             }
         }
         else
         {
-            destPtr = rootDestPtr;
-            reservePtr = rootDestPtr;
-        }
-
-        if (!destPtr)
-        {
-            // There is no valid destination pointer so a dummy node is added to the clone data parent stack
-            // and further descendent type iteration is halted
-            // An error has been reported to the supplied errorHandler in the code above
-            ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
-            parentInfo.m_ptr = destPtr;
-            parentInfo.m_reservePtr = reservePtr;
-            parentInfo.m_classData = classData;
-            parentInfo.m_containerIndexCounter = 0;
-            return false;
+            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to return an index.");
+            return 0;
         }
+    }
 
-        if (elementData && elementData->m_flags & ClassElement::FLG_POINTER)
+    void Internal::AZStdArrayEvents::Increment()
+    {
+        if (m_indices)
         {
-            // if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
-            srcPtr = *(void**)(ptr);
-            if (elementData->m_azRtti)
+            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
             {
-                srcPtr = elementData->m_azRtti->Cast(srcPtr, classData->m_azRtti->GetTypeId());
+                // Increment by 2 because the first bit is used to indicate whether or not a stack is used so the real
+                //      value starts one bit later.
+                size_t index = reinterpret_cast<uintptr_t>(m_indices) + (1 << 1);
+                m_indices = reinterpret_cast<void*>(index);
+            }
+            else
+            {
+                Stack* stack = reinterpret_cast<Stack*>(m_indices);
+                stack->top()++;
             }
         }
-
-        if (classData->m_eventHandler)
+        else
         {
-            classData->m_eventHandler->OnWriteBegin(destPtr);
+            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to increment.");
         }
+    }
 
-        if (classData->m_serializer)
+    void Internal::AZStdArrayEvents::Decrement()
+    {
+        if (m_indices)
         {
-            if (const auto* genericInfo = elementData ? elementData->m_genericClassInfo : FindGenericClassInfo(classData->m_typeId);
-                    genericInfo && genericInfo->GetGenericTypeId() == GetAssetClassId())
+            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
             {
-                // Optimized clone path for asset references.
-                static_cast<AssetSerializer*>(classData->m_serializer.get())->Clone(srcPtr, destPtr);
+                // Decrement by 2 because the first bit is used to indicate whether or not a stack is used so the real
+                //      value starts one bit later. This assumes that index is check to be larger than 0 before calling
+                //      this function.
+                size_t index = reinterpret_cast<uintptr_t>(m_indices) - (1 << 1);
+                m_indices = reinterpret_cast<void*>(index);
             }
             else
             {
-                scratchBuffer->clear();
-                IO::ByteContainerStream<AZStd::vector<char>> stream(scratchBuffer);
-
-                classData->m_serializer->Save(srcPtr, stream);
-                stream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
-
-                classData->m_serializer->Load(destPtr, stream, classData->m_version);
+                Stack* stack = reinterpret_cast<Stack*>(m_indices);
+                stack->top()--;
             }
         }
-
-        // If it is a container, clear it before loading the child
-        // nodes, otherwise we end up with more elements than the ones
-        // we should have
-        if (classData->m_container)
+        else
         {
-            classData->m_container->ClearElements(destPtr, this);
+            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to decrement.");
         }
+    }
 
-        // push this node in the stack
-        ObjectCloneData::ParentInfo& parentInfo = cloneData->m_parentStack.emplace_back();
-        parentInfo.m_ptr = destPtr;
-        parentInfo.m_reservePtr = reservePtr;
-        parentInfo.m_classData = classData;
-        parentInfo.m_containerIndexCounter = 0;
-        return true;
+    bool Internal::AZStdArrayEvents::IsEmpty() const
+    {
+        return m_indices == nullptr;
     }
 
-    //=========================================================================
-    // EndCloneElement (internal element clone callbacks)
-    //=========================================================================
-    bool SerializeContext::EndCloneElement(void* data)
+    bool SerializeContext::IsTypeReflected(AZ::Uuid typeId) const
     {
-        ObjectCloneData* cloneData = reinterpret_cast<ObjectCloneData*>(data);
-        void* dataPtr = cloneData->m_parentStack.back().m_ptr;
-        void* reservePtr = cloneData->m_parentStack.back().m_reservePtr;
+        const AZ::SerializeContext::ClassData* reflectedClassData = FindClassData(typeId);
+        return (reflectedClassData != nullptr);
+    }
 
-        if (!dataPtr)
+    SerializeContext::PerModuleGenericClassInfo::~PerModuleGenericClassInfo()
+    {
+        Cleanup();
+    }
+
+    void SerializeContext::PerModuleGenericClassInfo::Cleanup()
+    {
+        auto genericClassInfoContainer = AZStd::move(m_moduleLocalGenericClassInfos);
+        auto serializeContextSet = AZStd::move(m_serializeContextSet);
+        // Un-reflect GenericClassInfo from each serialize context registered with the module
+        for (AZ::SerializeContext* serializeContext : serializeContextSet)
         {
-            // we failed to clone an object - an assertion was already raised if it needed to be.
-            cloneData->m_parentStack.pop_back();
-            return true; // continue on to siblings.
+            for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
+            {
+                serializeContext->RemoveGenericClassInfo(genericClassInfo);
+            }
+
+            serializeContext->m_perModuleSet.erase(this);
         }
 
-        const ClassData* classData = cloneData->m_parentStack.back().m_classData;
-        if (classData->m_eventHandler)
+        // Cleanup the memory for the GenericClassInfo objects.
+        for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
         {
-            classData->m_eventHandler->OnWriteEnd(dataPtr);
-            classData->m_eventHandler->OnObjectCloned(dataPtr);
-        }
-
-        if (classData->m_serializer)
-        {
-            classData->m_serializer->PostClone(dataPtr);
+            azdestroy(genericClassInfo);
         }
+    }
 
-        cloneData->m_parentStack.pop_back();
-        if (!cloneData->m_parentStack.empty())
-        {
-            const ClassData* parentClassData = cloneData->m_parentStack.back().m_classData;
-            if (parentClassData->m_container)
-            {
-                // Pass in the address returned by IDataContainer::ReserveElement.
-                //AZStdAssociativeContainer is the only DataContainer that uses the second argument passed into IDataContainer::StoreElement
-                parentClassData->m_container->StoreElement(cloneData->m_parentStack.back().m_ptr, reservePtr);
-            }
-        }
-        return true;
+    void SerializeContext::PerModuleGenericClassInfo::RegisterSerializeContext(AZ::SerializeContext* serializeContext)
+    {
+        m_serializeContextSet.emplace(serializeContext);
+        serializeContext->m_perModuleSet.emplace(this);
     }
 
-    //=========================================================================
-    // EnumerateDerived
-    // [11/13/2012]
-    //=========================================================================
-    void SerializeContext::EnumerateDerived(const TypeInfoCB& callback, const Uuid& classId, const Uuid& typeId) const
+    void SerializeContext::PerModuleGenericClassInfo::UnregisterSerializeContext(AZ::SerializeContext* serializeContext)
     {
-        // right now this function is SLOW, traverses all serialized types. If we need faster
-        // we will need to cache/store derived type in the base type.
-        for (SerializeContext::UuidToClassMap::const_iterator it = m_uuidMap.begin(); it != m_uuidMap.end(); ++it)
+        m_serializeContextSet.erase(serializeContext);
+        serializeContext->m_perModuleSet.erase(this);
+        for (const auto& [specializedTypeId, genericClassInfo] : m_moduleLocalGenericClassInfos)
         {
-            const ClassData& cd = it->second;
-
-            if (cd.m_typeId == classId)
-            {
-                continue;
-            }
-
-            if (cd.m_azRtti && typeId != Uuid::CreateNull())
-            {
-                if (cd.m_azRtti->IsTypeOf(typeId))
-                {
-                    if (!callback(&cd, {}))
-                    {
-                        return;
-                    }
-                }
-            }
-
-            if (!classId.IsNull())
-            {
-                for (size_t i = 0; i < cd.m_elements.size(); ++i)
-                {
-                    if ((cd.m_elements[i].m_flags & ClassElement::FLG_BASE_CLASS) != 0)
-                    {
-                        if (cd.m_elements[i].m_typeId == classId)
-                        {
-                            // if both classes have azRtti they will be enumerated already by the code above (azrtti)
-                            if (cd.m_azRtti == nullptr || cd.m_elements[i].m_azRtti == nullptr)
-                            {
-                                if (!callback(&cd, {}))
-                                {
-                                    return;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
+            serializeContext->RemoveGenericClassInfo(genericClassInfo);
         }
     }
 
-    //=========================================================================
-    // EnumerateBase
-    // [11/13/2012]
-    //=========================================================================
-    void SerializeContext::EnumerateBase(const TypeInfoCB& callback, const Uuid& classId)
+    void SerializeContext::PerModuleGenericClassInfo::AddGenericClassInfo(AZ::GenericClassInfo* genericClassInfo)
     {
-        const ClassData* cd = FindClassData(classId);
-        if (cd)
+        if (!genericClassInfo)
         {
-            EnumerateBaseRTTIEnumCallbackData callbackData;
-            callbackData.m_callback = &callback;
-            callbackData.m_reportedTypes.push_back(cd->m_typeId);
-            for (size_t i = 0; i < cd->m_elements.size(); ++i)
-            {
-                if ((cd->m_elements[i].m_flags & ClassElement::FLG_BASE_CLASS) != 0)
-                {
-                    const ClassData* baseClassData = FindClassData(cd->m_elements[i].m_typeId);
-                    if (baseClassData)
-                    {
-                        callbackData.m_reportedTypes.push_back(baseClassData->m_typeId);
-                        if (!callback(baseClassData, {}))
-                        {
-                            return;
-                        }
-                    }
-                }
-            }
-            if (cd->m_azRtti)
-            {
-                cd->m_azRtti->EnumHierarchy(&SerializeContext::EnumerateBaseRTTIEnumCallback, &callbackData);
-            }
+            AZ_Error("SerializeContext", false, "The supplied generic class info object is nullptr. It cannot be added to the SerializeContext module structure");
+            return;
         }
+
+        m_moduleLocalGenericClassInfos.emplace(genericClassInfo->GetSpecializedTypeId(), genericClassInfo);
     }
 
-    //=========================================================================
-    // EnumerateAll
-    //=========================================================================
-    void SerializeContext::EnumerateAll(const TypeInfoCB& callback, bool includeGenerics) const
+    void SerializeContext::PerModuleGenericClassInfo::RemoveGenericClassInfo(const AZ::TypeId& genericTypeId)
     {
-        for (auto& uuidToClassPair : m_uuidMap)
+        if (genericTypeId.IsNull())
         {
-            const ClassData& classData = uuidToClassPair.second;
-            if (!callback(&classData, classData.m_typeId))
-            {
-                return;
-            }
+            AZ_Error("SerializeContext", false, "The supplied generic typeidis invalid. It is not stored the SerializeContext module structure ");
+            return;
         }
 
-        if (includeGenerics)
+        auto genericClassInfoFoundIt = m_moduleLocalGenericClassInfos.find(genericTypeId);
+        if (genericClassInfoFoundIt != m_moduleLocalGenericClassInfos.end())
         {
-            for (auto& uuidToGenericPair : m_uuidGenericMap)
-            {
-                const ClassData* classData = uuidToGenericPair.second->GetClassData();
-                if (classData)
-                {
-                    if (!callback(classData, classData->m_typeId))
-                    {
-                        return;
-                    }
-                }
-            }
+            m_moduleLocalGenericClassInfos.erase(genericClassInfoFoundIt);
         }
     }
 
-    void SerializeContext::RegisterDataContainer(AZStd::unique_ptr<IDataContainer> dataContainer)
+    AZ::GenericClassInfo* SerializeContext::PerModuleGenericClassInfo::FindGenericClassInfo(const AZ::TypeId& genericTypeId) const
     {
-        m_dataContainers.push_back(AZStd::move(dataContainer));
+        auto genericClassInfoFoundIt = m_moduleLocalGenericClassInfos.find(genericTypeId);
+        return genericClassInfoFoundIt != m_moduleLocalGenericClassInfos.end() ? genericClassInfoFoundIt->second : nullptr;
+    }
+
+    // Take advantage of static variables being unique per dll module to clean up module specific registered classes when the module unloads
+    SerializeContext::PerModuleGenericClassInfo& GetCurrentSerializeContextModule()
+    {
+        static SerializeContext::PerModuleGenericClassInfo s_ModuleCleanupInstance;
+        return s_ModuleCleanupInstance;
     }
+} // namespace AZ
 
+namespace AZ::Serialize
+{
+    // Contains Class Member function definitions for types declared in the AZ::Serialize
+    // namespace inside of the forwarding header
+    // * DataElement
+    // * DataElementNode
+    // * IDataConverter
+    // * IDataContainer
+    // * IDataSeralizer
+    // * EnumerateInstanceCallContext
+    // * ClassElement
+    // * ClassData
+
+    // Add definitions for GetO3deTypeName and GetO3deTypeId functions
+    AZ_TYPE_INFO_WITH_NAME_IMPL(ClassElement, "ClassElement", "{7D386902-A1D9-4525-8284-F68435FE1D05}");
+    AZ_TYPE_INFO_WITH_NAME_IMPL(ClassData, "ClassData", "{20EB8E2E-D807-4039-84E2-CE37D7647CD4}");
+    AZ_TYPE_INFO_WITH_NAME_IMPL(IDataContainer, "IDataContainer", "{8565CBEA-C077-4A49-927B-314533A6EDB1}");
+    AZ_TYPE_INFO_WITH_NAME_IMPL(IDataContainer::IAssociativeDataContainer, "IAssociativeDataContainer", "{58CF6250-6B0F-4A25-9864-25A64EB55DB1}");
+    AZ_TYPE_INFO_WITH_NAME_IMPL(EnumerateInstanceCallContext, "EnumerateInstanceCallContext", "{FCC1DB4B-72BD-4D78-9C23-C84B91589D33}");
     //=========================================================================
-    // EnumerateBaseRTTIEnumCallback
-    // [11/13/2012]
+    // DataElement
+    // [5/22/2012]
     //=========================================================================
-    void SerializeContext::EnumerateBaseRTTIEnumCallback(const Uuid& id, void* userData)
+    DataElement::DataElement()
+        : m_name(nullptr)
+        , m_nameCrc(0)
+        , m_dataSize(0)
+        , m_byteStream(&m_buffer)
+        , m_stream(nullptr)
     {
-        EnumerateBaseRTTIEnumCallbackData* callbackData = reinterpret_cast<EnumerateBaseRTTIEnumCallbackData*>(userData);
-        // if not reported, report
-        if (AZStd::find(callbackData->m_reportedTypes.begin(), callbackData->m_reportedTypes.end(), id) == callbackData->m_reportedTypes.end())
-        {
-            (*callbackData->m_callback)(nullptr, id);
-        }
     }
 
     //=========================================================================
-    // ClassData
+    // ~DataElement
+    // [5/22/2012]
     //=========================================================================
-    SerializeContext::ClassData::ClassData()
+    DataElement::~DataElement()
     {
-        m_name = nullptr;
-        m_typeId = Uuid::CreateNull();
-        m_version = 0;
-        m_converter = nullptr;
-        m_serializer = nullptr;
-        m_factory = nullptr;
-        m_persistentId = nullptr;
-        m_doSave = nullptr;
-        m_eventHandler = nullptr;
-        m_container = nullptr;
-        m_azRtti = nullptr;
-        m_editData = nullptr;
+        m_buffer.clear();
     }
 
     //=========================================================================
-    // ClassData
+    // DataElement
+    // [5/22/2012]
     //=========================================================================
-    void SerializeContext::ClassData::ClearAttributes()
+    DataElement::DataElement(const DataElement& rhs)
+        : m_name(rhs.m_name)
+        , m_nameCrc(rhs.m_nameCrc)
+        , m_dataSize(rhs.m_dataSize)
+        , m_byteStream(&m_buffer)
     {
-        m_attributes.clear();
+        m_id = rhs.m_id;
+        m_version = rhs.m_version;
+        m_dataType = rhs.m_dataType;
 
-        for (ClassElement& classElement : m_elements)
+        m_buffer = rhs.m_buffer;
+        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
+        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
+        if (rhs.m_stream == &rhs.m_byteStream)
         {
-            if (classElement.m_attributeOwnership == ClassElement::AttributeOwnership::Parent)
-            {
-                classElement.ClearAttributes();
-            }
+            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
+            m_stream = &m_byteStream;
         }
-    }
-
-    SerializeContext::ClassPersistentId SerializeContext::ClassData::GetPersistentId(const SerializeContext& context) const
-    {
-        ClassPersistentId persistentIdFunction = m_persistentId;
-        if (!persistentIdFunction)
+        else
         {
-            // check the base classes
-            for (const SerializeContext::ClassElement& element : m_elements)
-            {
-                if (element.m_flags & ClassElement::FLG_BASE_CLASS)
-                {
-                    const SerializeContext::ClassData* baseClassData = context.FindClassData(element.m_typeId);
-                    if (baseClassData)
-                    {
-                        persistentIdFunction = baseClassData->GetPersistentId(context);
-                        if (persistentIdFunction)
-                        {
-                            break;
-                        }
-                    }
-                }
-                else
-                {
-                    // base classes are in the beginning of the array
-                    break;
-                }
-            }
+            m_stream = rhs.m_stream;
         }
-        return persistentIdFunction;
     }
 
-    Attribute* SerializeContext::ClassData::FindAttribute(AttributeId attributeId) const
+    //=========================================================================
+    // DataElement
+    // [5/22/2012]
+    //=========================================================================
+    DataElement& DataElement::operator= (const DataElement& rhs)
     {
-        for (const AZ::AttributeSharedPair& attributePair : m_attributes)
+        m_name = rhs.m_name;
+        m_nameCrc = rhs.m_nameCrc;
+        m_id = rhs.m_id;
+        m_version = rhs.m_version;
+        m_dataSize = rhs.m_dataSize;
+        m_dataType = rhs.m_dataType;
+
+        m_buffer = rhs.m_buffer;
+        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
+        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
+
+        if (rhs.m_stream == &rhs.m_byteStream)
         {
-            if (attributePair.first == attributeId)
-            {
-                return attributePair.second.get();
-            }
+            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
+            m_stream = &m_byteStream;
         }
-        return nullptr;
-    }
-
-    bool SerializeContext::ClassData::CanConvertFromType(const TypeId& convertibleTypeId, AZ::SerializeContext& serializeContext) const
-    {
-        // If the convertible type is exactly the type being stored by the ClassData.
-        // True will always be returned in this case
-        if (convertibleTypeId == m_typeId)
+        else
         {
-            return true;
+            m_stream = rhs.m_stream;
         }
 
-        return m_dataConverter ? m_dataConverter->CanConvertFromType(convertibleTypeId, *this, serializeContext) : false;
+        return *this;
     }
 
-    bool SerializeContext::ClassData::ConvertFromType(void*& convertibleTypePtr, const TypeId& convertibleTypeId, void* classPtr, AZ::SerializeContext& serializeContext) const
+    //=========================================================================
+    // DataElement
+    //=========================================================================
+    DataElement::DataElement(DataElement&& rhs)
+        : m_name(rhs.m_name)
+        , m_nameCrc(rhs.m_nameCrc)
+        , m_dataSize(rhs.m_dataSize)
+        , m_byteStream(&m_buffer)
     {
-        // If the convertible type is exactly the type being stored by the ClassData.
-        // the result convertTypePtr is equal to the classPtr
-        if (convertibleTypeId == m_typeId)
+        m_id = rhs.m_id;
+        m_version = rhs.m_version;
+        m_dataType = rhs.m_dataType;
+        if (rhs.m_stream == &rhs.m_byteStream)
         {
-            convertibleTypePtr = classPtr;
-            return true;
+            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
+            m_stream = &m_byteStream;
+        }
+        else
+        {
+            m_stream = rhs.m_stream;
         }
 
-        return m_dataConverter ? m_dataConverter->ConvertFromType(convertibleTypePtr, convertibleTypeId, classPtr, *this, serializeContext) : false;
-    }
+        m_buffer = AZStd::move(rhs.m_buffer);
+        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
+        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
 
-    //=========================================================================
-    // ToString
-    // [11/1/2012]
-    //=========================================================================
-    void SerializeContext::DbgStackEntry::ToString(AZStd::string& str) const
-    {
-        str += "[";
-        if (m_elementName)
+        rhs.m_name = nullptr;
+        rhs.m_nameCrc = 0;
+        rhs.m_id = Uuid::CreateNull();
+        rhs.m_version = 0;
+        rhs.m_dataSize = 0;
+        rhs.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
+        if (m_stream == &m_byteStream)
         {
-            str += AZStd::string::format(" Element: '%s' of", m_elementName);
+            rhs.m_stream = &rhs.m_byteStream;
         }
-        //if( m_classElement )
-        //  str += AZStd::string::format(" Offset: %d",m_classElement->m_offset);
-        if (m_classData)
+        else
         {
-            str += AZStd::string::format(" Class: '%s' Version: %d", m_classData->m_name, m_classData->m_version);
+            rhs.m_stream = nullptr;
         }
-        str += AZStd::string::format(" Address: %p Uuid: %s", m_dataPtr, m_uuid.ToString<AZStd::string>().c_str());
-        str += " ]\n";
     }
 
     //=========================================================================
-    // FreeElementPointer
-    // [12/7/2012]
+    // DataElement
     //=========================================================================
-    void SerializeContext::IDataContainer::DeletePointerData(SerializeContext* context, const ClassElement* classElement, const void* element)
+    DataElement& DataElement::operator= (DataElement&& rhs)
     {
-        AZ_Assert(context != nullptr && classElement != nullptr && element != nullptr, "Invalid input");
-        AZ::Uuid elemUuid = classElement->m_typeId;
-        // find the class data for the specific element
-        const SerializeContext::ClassData* classData = classElement->m_genericClassInfo ? classElement->m_genericClassInfo->GetClassData() : context->FindClassData(elemUuid, nullptr, 0);
-        if (classElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+        m_name = rhs.m_name;
+        m_nameCrc = rhs.m_nameCrc;
+        m_id = rhs.m_id;
+        m_version = rhs.m_version;
+        m_dataSize = rhs.m_dataSize;
+        m_dataType = rhs.m_dataType;
+        if (rhs.m_stream == &rhs.m_byteStream)
         {
-            const void* dataPtr = *reinterpret_cast<void* const*>(element);
-            // if dataAddress is a pointer in this case, cast it's value to a void* (or const void*) and dereference to get to the actual class.
-            if (dataPtr && classElement->m_azRtti)
-            {
-                const AZ::Uuid actualClassId = classElement->m_azRtti->GetActualUuid(dataPtr);
-                if (actualClassId != elemUuid)
-                {
-                    // we are pointing to derived type, adjust class data, uuid and pointer.
-                    classData = context->FindClassData(actualClassId, nullptr, 0);
-                    elemUuid = actualClassId;
-                    if (classData)
-                    {
-                        dataPtr = classElement->m_azRtti->Cast(dataPtr, classData->m_azRtti->GetTypeId());
-                    }
-                }
-            }
+            AZ_Assert(rhs.m_dataSize == rhs.m_buffer.size(), "Temp buffer must contain only the data for current element!");
+            m_stream = &m_byteStream;
         }
-        if (classData == nullptr)
+        else
         {
-            if ((classElement->m_flags & ClassElement::FLG_POINTER) != 0)
-            {
-                const void* dataPtr = *reinterpret_cast<void* const*>(element);
-                AZ_UNUSED(dataPtr); // this prevents a L4 warning if the below line is stripped out in release.
-                AZ_Warning("Serialization", false, "Failed to find class id%s for %p! Memory could leak.", elemUuid.ToFixedString().c_str(), dataPtr);
-            }
-            return;
+            m_stream = rhs.m_stream;
         }
 
-        if (classData->m_container)  // if element is container forward the message
+
+        m_buffer = AZStd::move(rhs.m_buffer);
+        m_byteStream = IO::ByteContainerStream<AZStd::vector<char> >(&m_buffer);
+        m_byteStream.Seek(rhs.m_byteStream.GetCurPos(), IO::GenericStream::ST_SEEK_BEGIN);
+
+        rhs.m_name = nullptr;
+        rhs.m_nameCrc = 0;
+        rhs.m_id = Uuid::CreateNull();
+        rhs.m_version = 0;
+        rhs.m_dataSize = 0;
+        rhs.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
+        if (m_stream == &m_byteStream)
         {
-            // clear all container data
-            classData->m_container->ClearElements(const_cast<void*>(element), context);
+            rhs.m_stream = &rhs.m_byteStream;
         }
         else
         {
-            if ((classElement->m_flags & ClassElement::FLG_POINTER) == 0)
-            {
-                return; // element is stored by value nothing to free
-            }
-
-            // if we get here, its a FLG_POINTER
-            const void* dataPtr = *reinterpret_cast<void* const*>(element);
-            if (dataPtr == nullptr)
-            {
-                return; // Pointer element is nullptr, nothing to delete
-            }
-            if (classData->m_factory)
-            {
-                classData->m_factory->Destroy(dataPtr);
-            }
-            else
-            {
-                AZ_Warning("Serialization", false, "Failed to delete %p '%s' element, no destructor is provided! Memory could leak.", dataPtr, classData->m_name);
-            }
+            rhs.m_stream = nullptr;
         }
+
+        return *this;
     }
 
     //=========================================================================
-    // RemoveClassData
+    // Convert
     //=========================================================================
-    void SerializeContext::RemoveClassData(ClassData* classData)
+    bool DataElementNode::Convert(SerializeContext& sc, const Uuid& id)
     {
-        if (m_editContext)
+        // remove sub elements
+        while (!m_subElements.empty())
         {
-            m_editContext->RemoveClassData(classData);
+            RemoveElement(static_cast<int>(m_subElements.size()) - 1);
         }
+
+        // replace element
+        m_element.m_id = id;
+        m_element.m_dataSize = 0;
+        m_element.m_buffer.clear();
+        m_element.m_stream = &m_element.m_byteStream;
+
+        m_classData = sc.FindClassData(m_element.m_id);
+        AZ_Assert(m_classData, "You are adding element to an unregistered class!");
+        m_element.m_version = m_classData->m_version;
+
+        return true;
     }
 
-    void SerializeContext::RemoveGenericClassInfo(GenericClassInfo* genericClassInfo)
+    //=========================================================================
+    // Convert
+    //=========================================================================
+    bool DataElementNode::Convert(SerializeContext& sc, const char* name, const Uuid& id)
     {
-        const Uuid& classId = genericClassInfo->GetSpecializedTypeId();
-        RemoveClassData(genericClassInfo->GetClassData());
-        // Find the module GenericClassInfo in the SerializeContext GenericClassInfo multimap and remove it from there
-        auto scGenericClassInfoRange = m_uuidGenericMap.equal_range(classId);
-        auto scGenericInfoFoundIt = AZStd::find_if(scGenericClassInfoRange.first, scGenericClassInfoRange.second, [genericClassInfo](const AZStd::pair<AZ::Uuid, GenericClassInfo*>& genericPair)
-        {
-            return genericClassInfo == genericPair.second;
-        });
+        AZ_Assert(name != nullptr && strlen(name) > 0, "Empty name is an INVALID element name!");
+        u32 nameCrc = Crc32(name);
 
-        if (scGenericInfoFoundIt != scGenericClassInfoRange.second)
+#if defined(AZ_ENABLE_TRACING)
+        if (FindElement(nameCrc) != -1)
         {
-            m_uuidGenericMap.erase(scGenericInfoFoundIt);
-            if (m_uuidGenericMap.count(classId) == 0)
-            {
-                m_uuidAnyCreationMap.erase(classId);
-                auto classNameRange = m_classNameToUuid.equal_range(Crc32(genericClassInfo->GetClassData()->m_name));
-                for (auto classNameRangeIter = classNameRange.first; classNameRangeIter != classNameRange.second;)
-                {
-                    if (classNameRangeIter->second == classId)
-                    {
-                        classNameRangeIter = m_classNameToUuid.erase(classNameRangeIter);
-                    }
-                    else
-                    {
-                        ++classNameRangeIter;
-                    }
-                }
+            AZ_Error("Serialize", false, "During reflection of class '%s' - member %s is declared more than once.", m_classData->m_name ? m_classData->m_name : "<unknown class>", name);
+            return false;
+        }
+#endif // AZ_ENABLE_TRACING
 
-                auto legacyTypeIdRangeIt = m_legacySpecializeTypeIdToTypeIdMap.equal_range(genericClassInfo->GetLegacySpecializedTypeId());
-                for (auto legacySpecializedTypeIdIt = legacyTypeIdRangeIt.first; legacySpecializedTypeIdIt != legacyTypeIdRangeIt.second; ++legacySpecializedTypeIdIt)
-                {
-                    if (classId == legacySpecializedTypeIdIt->second)
-                    {
-                        m_legacySpecializeTypeIdToTypeIdMap.erase(classId);
-                        break;
-                    }
-                }
-            }
+        // remove sub elements
+        while (!m_subElements.empty())
+        {
+            RemoveElement(static_cast<int>(m_subElements.size()) - 1);
         }
+
+        // replace element
+        m_element.m_name = name;
+        m_element.m_nameCrc = nameCrc;
+        m_element.m_id = id;
+        m_element.m_dataSize = 0;
+        m_element.m_buffer.clear();
+        m_element.m_stream = &m_element.m_byteStream;
+
+        m_classData = sc.FindClassData(m_element.m_id);
+        AZ_Assert(m_classData, "You are adding element to an unregistered class!");
+        m_element.m_version = m_classData->m_version;
+
+        return true;
     }
 
     //=========================================================================
-    // GetStackDescription
+    // FindElement
+    // [5/22/2012]
     //=========================================================================
-    AZStd::string SerializeContext::ErrorHandler::GetStackDescription() const
+    int DataElementNode::FindElement(u32 crc)
     {
-        AZStd::string stackDescription;
-
-    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
-        if (!m_stack.empty())
+        for (size_t i = 0; i < m_subElements.size(); ++i)
         {
-            stackDescription += "\n=== Serialize stack ===\n";
-            for (size_t i = 0; i < m_stack.size(); ++i)
+            if (m_subElements[i].m_element.m_nameCrc == crc)
             {
-                m_stack[i].ToString(stackDescription);
+                return static_cast<int>(i);
             }
-            stackDescription += "\n";
         }
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
-
-        return stackDescription;
+        return -1;
     }
 
     //=========================================================================
-    // ReportError
-    // [12/11/2012]
+    // FindSubElement
     //=========================================================================
-    void SerializeContext::ErrorHandler::ReportError(const char* message)
+    DataElementNode* DataElementNode::FindSubElement(u32 crc)
     {
-        (void)message;
-        AZ_Error("Serialize", false, "%s\n%s", message, GetStackDescription().c_str());
-        m_nErrors++;
+        int index = FindElement(crc);
+        return index >= 0 ? &m_subElements[index] : nullptr;
     }
 
     //=========================================================================
-    // ReportWarning
-    //=========================================================================
-    void SerializeContext::ErrorHandler::ReportWarning(const char* message)
-    {
-        (void)message;
-        AZ_Warning("Serialize", false, "%s\n%s", message, GetStackDescription().c_str());
-        m_nWarnings++;
-    }
-
-    //=========================================================================
-    // Push
-    // [1/3/2013]
-    //=========================================================================
-    void SerializeContext::ErrorHandler::Push([[maybe_unused]] const DbgStackEntry& de)
-    {
-    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
-        m_stack.push_back((de));
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
-    }
-
-    //=========================================================================
-    // Pop
-    // [1/3/2013]
-    //=========================================================================
-    void SerializeContext::ErrorHandler::Pop()
-    {
-    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
-        m_stack.pop_back();
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
-    }
-
-    //=========================================================================
-    // Reset
-    // [1/23/2013]
+    // RemoveElement
+    // [5/22/2012]
     //=========================================================================
-    void SerializeContext::ErrorHandler::Reset()
+    void DataElementNode::RemoveElement(int index)
     {
-    #ifdef AZ_ENABLE_SERIALIZER_DEBUG
-        m_stack.clear();
-    #endif // AZ_ENABLE_SERIALIZER_DEBUG
-        m_nErrors = 0;
-    }
+        AZ_Assert(index >= 0 && index < static_cast<int>(m_subElements.size()), "Invalid index passed to RemoveElement");
 
-    //=========================================================================
-    // EnumerateInstanceCallContext
-    //=========================================================================
+        DataElementNode& node = m_subElements[index];
 
-    SerializeContext::EnumerateInstanceCallContext::EnumerateInstanceCallContext(
-        const SerializeContext::BeginElemEnumCB& beginElemCB,
-        const SerializeContext::EndElemEnumCB& endElemCB,
-        const SerializeContext* context,
-        unsigned int accessFlags,
-        SerializeContext::ErrorHandler* errorHandler)
-        : m_beginElemCB(beginElemCB)
-        , m_endElemCB(endElemCB)
-        , m_accessFlags(accessFlags)
-        , m_context(context)
-    {
-        m_errorHandler = errorHandler ? errorHandler : &m_defaultErrorHandler;
+        node.m_element.m_dataSize = 0;
+        node.m_element.m_buffer.clear();
+        node.m_element.m_stream = nullptr;
 
-        m_elementCallback = [this](void* ptr, const Uuid& classId, const ClassData* classData, const ClassElement* classElement)->bool
+        while (!node.m_subElements.empty())
         {
-            return m_context->EnumerateInstance(this, ptr, classId, classData, classElement);
-        };
+            node.RemoveElement(static_cast<int>(node.m_subElements.size()) - 1);
+        }
+
+        m_subElements.erase(m_subElements.begin() + index);
     }
 
     //=========================================================================
-    // ~ClassElement
+    // RemoveElementByName
     //=========================================================================
-    SerializeContext::ClassElement::~ClassElement()
+    bool DataElementNode::RemoveElementByName(u32 crc)
     {
-        if (m_attributeOwnership == AttributeOwnership::Self)
+        int index = FindElement(crc);
+        if (index >= 0)
         {
-            ClearAttributes();
+            RemoveElement(index);
+            return true;
         }
+        return false;
     }
 
     //=========================================================================
-    // ClassElement::operator=
+    // AddElement
+    // [5/22/2012]
     //=========================================================================
-    SerializeContext::ClassElement& SerializeContext::ClassElement::operator=(const SerializeContext::ClassElement& other)
+    int DataElementNode::AddElement(const DataElementNode& elem)
     {
-        m_name = other.m_name;
-        m_nameCrc = other.m_nameCrc;
-        m_typeId = other.m_typeId;
-        m_dataSize = other.m_dataSize;
-        m_offset = other.m_offset;
-
-        m_azRtti = other.m_azRtti;
-        m_genericClassInfo = other.m_genericClassInfo;
-        m_editData = other.m_editData;
-        m_attributes = other.m_attributes;
-        // If we're a copy, we don't assume attribute ownership
-        m_attributeOwnership = AttributeOwnership::None;
-        m_flags = other.m_flags;
-
-        return *this;
+        m_subElements.push_back(elem);
+        return static_cast<int>(m_subElements.size() - 1);
     }
 
     //=========================================================================
-    // ClearAttributes
+    // AddElement
+    // [5/22/2012]
     //=========================================================================
-    void SerializeContext::ClassElement::ClearAttributes()
+    int DataElementNode::AddElement(SerializeContext& sc, const char* name, const Uuid& id)
     {
-        m_attributes.clear();
+        const ClassData* classData = sc.FindClassData(id);
+        AZ_Assert(classData, "You are adding element to an unregistered class!");
+        return AddElement(sc, name, *classData);
     }
 
     //=========================================================================
-    // FindAttribute
+    // AddElement
     //=========================================================================
-
-    Attribute* SerializeContext::ClassElement::FindAttribute(AttributeId attributeId) const
+    int DataElementNode::AddElement(SerializeContext& sc, const char* name, const ClassData& classData)
     {
-        for (const AZ::AttributeSharedPair& attributePair : m_attributes)
+        (void)sc;
+        AZ_Assert(name != nullptr && strlen(name) > 0, "Empty name is an INVALID element name!");
+        u32 nameCrc = Crc32(name);
+
+    #if defined(AZ_ENABLE_TRACING)
+        if (!m_classData->m_container && FindElement(nameCrc) != -1)
         {
-            if (attributePair.first == attributeId)
-            {
-                return attributePair.second.get();
-            }
+            AZ_Error("Serialize", false, "During reflection of class '%s' - member %s is declared more than once.", classData.m_name ? classData.m_name : "<unknown class>", name);
+            return -1;
         }
-        return nullptr;
-    }
+    #endif // AZ_ENABLE_TRACING
 
-    void SerializeContext::IDataContainer::ElementsUpdated(void* instance)
-    {
-        (void)instance;
+        DataElementNode node;
+        node.m_element.m_name = name;
+        node.m_element.m_nameCrc = nameCrc;
+        node.m_element.m_id = classData.m_typeId;
+        node.m_classData = &classData;
+        node.m_element.m_version = classData.m_version;
+
+        m_subElements.push_back(node);
+        return static_cast<int>(m_subElements.size() - 1);
     }
 
-    void Internal::AZStdArrayEvents::OnWriteBegin(void* classPtr)
+    int DataElementNode::AddElement(SerializeContext& sc, AZStd::string_view name, GenericClassInfo* genericClassInfo)
     {
-        (void)classPtr;
-        if (m_indices)
-        {
-            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
-            {
-                // Pointer is already in use to store an index so convert it to a stack
-                size_t previousIndex = reinterpret_cast<uintptr_t>(m_indices) >> 1;
-                Stack* stack = new Stack();
-                AZ_Assert((reinterpret_cast<uintptr_t>(stack) & 1) == 0, "Expected memory allocation to be at least 2 byte aligned.");
-                stack->push(previousIndex);
-                stack->push(0);
-                m_indices = stack;
-            }
-            else
-            {
-                Stack* stack = reinterpret_cast<Stack*>(m_indices);
-                stack->push(0);
-            }
-        }
-        else
+        (void)sc;
+        AZ_Assert(!name.empty(), "Empty name is an INVALID element name!");
+
+        if (!genericClassInfo)
         {
-            // Use the pointer to just store the one counter instead of allocating memory. Using 1 bit to identify this as a regular
-            // index and not a pointer.
-            m_indices = reinterpret_cast<void*>(1);
+            AZ_Assert(false, "Supplied GenericClassInfo is nullptr. ClassData cannot be retrieved.");
+            return -1;
         }
+
+        u32 nameCrc = Crc32(name.data());
+        DataElementNode node;
+        node.m_element.m_name = name.data();
+        node.m_element.m_nameCrc = nameCrc;
+        node.m_element.m_id = genericClassInfo->GetClassData()->m_typeId;
+        node.m_classData = genericClassInfo->GetClassData();
+        node.m_element.m_version = node.m_classData->m_version;
+
+        m_subElements.push_back(node);
+        return static_cast<int>(m_subElements.size() - 1);
     }
 
-    void Internal::AZStdArrayEvents::OnWriteEnd(void* classPtr)
+    //=========================================================================
+    // ReplaceElement
+    //=========================================================================
+    int DataElementNode::ReplaceElement(SerializeContext& sc, int index, const char* name, const Uuid& id)
     {
-        (void)classPtr;
-        if (m_indices)
+        DataElementNode& node = m_subElements[index];
+        if (node.Convert(sc, name, id))
         {
-            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
-            {
-                // There was only one entry so no stack. Clear out the final bit that indicated this was an index and not a pointer.
-                m_indices = nullptr;
-            }
-            else
-            {
-                Stack* stack = reinterpret_cast<Stack*>(m_indices);
-                stack->pop();
-                if (stack->empty())
-                {
-                    delete stack;
-                    m_indices = nullptr;
-                }
-            }
+            return index;
         }
         else
         {
-            AZ_Warning("Serialization", false, "AZStdArrayEvents::OnWriteEnd called too often.");
+            return -1;
         }
-
     }
 
-    size_t Internal::AZStdArrayEvents::GetIndex() const
+    //=========================================================================
+    // SetName
+    // [1/16/2013]
+    //=========================================================================
+    void DataElementNode::SetName(const char* newName)
     {
-        if (m_indices)
-        {
-            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
-            {
-                // The first bit is used to indicate this is a regular index instead of a pointer so shift down one to get the actual index.
-                return reinterpret_cast<uintptr_t>(m_indices) >> 1;
-            }
-            else
-            {
-                const Stack* stack = reinterpret_cast<const Stack*>(m_indices);
-                return stack->top();
-            }
-        }
-        else
-        {
-            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to return an index.");
-            return 0;
-        }
+        m_element.m_name = newName;
+        m_element.m_nameCrc = Crc32(newName);
     }
 
-    void Internal::AZStdArrayEvents::Increment()
+    //=========================================================================
+    // SetDataHierarchy
+    //=========================================================================
+    bool DataElementNode::SetDataHierarchy(SerializeContext& sc, const void* objectPtr, const Uuid& classId, SerializeContext::ErrorHandler* errorHandler, const ClassData* classData)
     {
-        if (m_indices)
-        {
-            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
-            {
-                // Increment by 2 because the first bit is used to indicate whether or not a stack is used so the real
-                //      value starts one bit later.
-                size_t index = reinterpret_cast<uintptr_t>(m_indices) + (1 << 1);
-                m_indices = reinterpret_cast<void*>(index);
-            }
-            else
+        AZ_Assert(m_element.m_id == classId, "SetDataHierarchy called with mismatched class type {%s} for element %s",
+            classId.ToString<AZStd::string>().c_str(), m_element.m_name);
+
+        AZStd::vector<DataElementNode*> nodeStack;
+        DataElementNode* topNode = this;
+        bool success = false;
+
+        auto beginCB = [&sc, &nodeStack, topNode, &success, errorHandler](void* ptr, const ClassData* elementClassData, const ClassElement* elementData) -> bool
             {
-                Stack* stack = reinterpret_cast<Stack*>(m_indices);
-                stack->top()++;
+                if (nodeStack.empty())
+                {
+                    success = true;
+                    nodeStack.push_back(topNode);
+                    return true;
+                }
+
+                DataElementNode* parentNode = nodeStack.back();
+                parentNode->m_subElements.reserve(64);
+
+                AZ_Assert(elementData, "Missing element data");
+                AZ_Assert(elementClassData, "Missing class data for element %s", elementData ? elementData->m_name : "<unknown>");
+
+                int elementIndex = -1;
+                if (elementData)
+                {
+                    elementIndex = elementData->m_genericClassInfo
+                        ? parentNode->AddElement(sc, elementData->m_name, elementData->m_genericClassInfo)
+                        : parentNode->AddElement(sc, elementData->m_name, *elementClassData);
+                }
+                if (elementIndex >= 0)
+                {
+                    DataElementNode& newNode = parentNode->GetSubElement(elementIndex);
+
+                    if (elementClassData->m_serializer)
+                    {
+                        void* resolvedObject = ptr;
+                        if (elementData && elementData->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                        {
+                            resolvedObject = *(void**)(resolvedObject);
+
+                            if (resolvedObject && elementData->m_azRtti)
+                            {
+                                AZ::Uuid actualClassId = elementData->m_azRtti->GetActualUuid(resolvedObject);
+                                if (actualClassId != elementData->m_typeId)
+                                {
+                                    const AZ::SerializeContext::ClassData* actualClassData = sc.FindClassData(actualClassId);
+                                    if (actualClassData)
+                                    {
+                                        resolvedObject = elementData->m_azRtti->Cast(resolvedObject, actualClassData->m_azRtti->GetTypeId());
+                                    }
+                                }
+                            }
+                        }
+
+                        AZ_Assert(newNode.m_element.m_byteStream.GetCurPos() == 0, "This stream should be only for our data element");
+                        newNode.m_element.m_dataSize = elementClassData->m_serializer->Save(resolvedObject, newNode.m_element.m_byteStream);
+                        newNode.m_element.m_byteStream.Truncate();
+                        newNode.m_element.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN); // reset stream position
+                        newNode.m_element.m_stream = &newNode.m_element.m_byteStream;
+
+                        newNode.m_element.m_dataType = DataElement::DT_BINARY;
+                    }
+
+                    nodeStack.push_back(&newNode);
+                    success = true;
+                }
+                else
+                {
+                    const AZStd::string error =
+                        AZStd::string::format("Failed to add sub-element \"%s\" to element \"%s\".",
+                            elementData ? elementData->m_name : "<unknown>",
+                            parentNode->m_element.m_name);
+
+                    if (errorHandler)
+                    {
+                        errorHandler->ReportError(error.c_str());
+                    }
+                    else
+                    {
+                        AZ_Error("Serialize", false, "%s", error.c_str());
+                    }
+
+                    success = false;
+                    return false; // Stop enumerating.
+                }
+
+                return true;
+            };
+
+        auto endCB = [&nodeStack, &success]() -> bool
+            {
+                if (success)
+                {
+                    nodeStack.pop_back();
+                }
+
+                return true;
+            };
+
+        EnumerateInstanceCallContext callContext(
+            beginCB,
+            endCB,
+            &sc,
+            SerializeContext::ENUM_ACCESS_FOR_READ,
+            errorHandler);
+
+        sc.EnumerateInstanceConst(
+            &callContext,
+            objectPtr,
+            classId,
+            classData,
+            nullptr
+            );
+
+        return success;
+    }
+
+    bool DataElementNode::GetClassElement(ClassElement& classElement, const DataElementNode& parentDataElement, SerializeContext::ErrorHandler* errorHandler) const
+    {
+        bool elementFound = false;
+        if (parentDataElement.m_classData)
+        {
+            const ClassData* parentClassData = parentDataElement.m_classData;
+            if (parentClassData->m_container)
+            {
+                IDataContainer* classContainer = parentClassData->m_container;
+                // store the container element in classElementMetadata
+                ClassElement classElementMetadata;
+                bool classElementFound = classContainer->GetElement(classElementMetadata, m_element);
+                AZ_Assert(classElementFound, "'%s'(0x%x) is not a valid element name for container type %s", m_element.m_name ? m_element.m_name : "NULL", m_element.m_nameCrc, parentClassData->m_name);
+                if (classElementFound)
+                {
+                    // if the container contains pointers, then the elements could be a derived type,
+                    // otherwise we need the uuids to be exactly the same.
+                    if (classElementMetadata.m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                    {
+                        bool downcastPossible = m_element.m_id == classElementMetadata.m_typeId;
+                        downcastPossible = downcastPossible || (m_classData->m_azRtti && classElementMetadata.m_azRtti && m_classData->m_azRtti->IsTypeOf(classElementMetadata.m_azRtti->GetTypeId()));
+                        if (!downcastPossible)
+                        {
+                            AZStd::string error = AZStd::string::format("Element of type %s cannot be added to container of pointers to type %s!"
+                                , m_element.m_id.ToString<AZStd::string>().c_str(), classElementMetadata.m_typeId.ToString<AZStd::string>().c_str());
+                            errorHandler->ReportError(error.c_str());
+
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (m_element.m_id != classElementMetadata.m_typeId)
+                        {
+                            AZStd::string error = AZStd::string::format("Element of type %s cannot be added to container of type %s!"
+                                , m_element.m_id.ToString<AZStd::string>().c_str(), classElementMetadata.m_typeId.ToString<AZStd::string>().c_str());
+                            errorHandler->ReportError(error.c_str());
+
+                            return false;
+                        }
+                    }
+                    classElement = classElementMetadata;
+                    elementFound = true;
+                }
+            }
+            else
+            {
+                for (size_t i = 0; i < parentClassData->m_elements.size(); ++i)
+                {
+                    const SerializeContext::ClassElement* childElement = &parentClassData->m_elements[i];
+                    if (childElement->m_nameCrc == m_element.m_nameCrc)
+                    {
+                        // if the member is a pointer type, then the pointer could be a derived type,
+                        // otherwise we need the uuids to be exactly the same.
+                        if (childElement->m_flags & SerializeContext::ClassElement::FLG_POINTER)
+                        {
+                            // Verify that a downcast is possible
+                            bool downcastPossible = m_element.m_id == childElement->m_typeId;
+                            downcastPossible = downcastPossible || (m_classData->m_azRtti && childElement->m_azRtti && m_classData->m_azRtti->IsTypeOf(childElement->m_azRtti->GetTypeId()));
+                            if (downcastPossible)
+                            {
+                                classElement = *childElement;
+                                elementFound = true;
+                            }
+                        }
+                        else
+                        {
+                            if (m_element.m_id == childElement->m_typeId)
+                            {
+                                classElement = *childElement;
+                                elementFound = true;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        return elementFound;
+    }
+
+    bool DataElementNode::GetDataHierarchyEnumerate(SerializeContext::ErrorHandler* errorHandler, NodeStack& nodeStack)
+    {
+        if (nodeStack.empty())
+        {
+            return true;
+        }
+
+        void* parentPtr = nodeStack.back().m_ptr;
+        DataElementNode* parentDataElement = nodeStack.back().m_dataElement;
+        AZ_Assert(parentDataElement, "parentDataElement is null, cannot enumerate data from data element (%s:%s)",
+            m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data());
+        if (!parentDataElement)
+        {
+            return false;
+        }
+
+        bool success = true;
+
+        if (!m_classData)
+        {
+            AZ_Error("Serialize", false, R"(Cannot enumerate data from data element (%s:%s) from parent data element (%s:%s) with class name "%s" because the ClassData does not exist.)"
+                " This can indicate that the class is not reflected at the point of this call. If this is class is reflected as part of a gem"
+                " check if that gem is loaded", m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data(),
+                parentDataElement->m_element.m_name ? parentDataElement->m_element.m_name : "", parentDataElement->m_element.m_id.ToString<AZStd::string>().data(), parentDataElement->m_classData->m_name);
+            return false;
+        }
+
+        AZ::SerializeContext::ClassElement classElement;
+        bool classElementFound = parentDataElement && GetClassElement(classElement, *parentDataElement, errorHandler);
+        AZ_Warning("Serialize", classElementFound, R"(Unable to find class element for data element(%s:%s) with class name "%s" that is a child of parent data element(%s:%s) with class name "%s")",
+            m_element.m_name ? m_element.m_name : "", m_element.m_id.ToString<AZStd::string>().data(), m_classData->m_name,
+            parentDataElement->m_element.m_name ? parentDataElement->m_element.m_name : "", parentDataElement->m_element.m_id.ToString<AZStd::string>().data(), parentDataElement->m_classData->m_name);
+
+        if (classElementFound)
+        {
+            void* dataAddress = nullptr;
+            IDataContainer* dataContainer = parentDataElement->m_classData->m_container;
+            if (dataContainer) // container elements
+            {
+                int& parentCurrentContainerElementIndex = nodeStack.back().m_currentContainerElementIndex;
+                // add element to the array
+                if (dataContainer->CanAccessElementsByIndex() && dataContainer->Size(parentPtr) > parentCurrentContainerElementIndex)
+                {
+                    dataAddress = dataContainer->GetElementByIndex(parentPtr, &classElement, parentCurrentContainerElementIndex);
+                }
+                else
+                {
+                    dataAddress = dataContainer->ReserveElement(parentPtr, &classElement);
+                }
+
+                if (dataAddress == nullptr)
+                {
+                    AZStd::string error = AZStd::string::format("Failed to reserve element in container. The container may be full. Element %u will not be added to container.", static_cast<unsigned int>(parentCurrentContainerElementIndex));
+                    errorHandler->ReportError(error.c_str());
+                }
+
+                parentCurrentContainerElementIndex++;
+            }
+            else
+            {   // normal elements
+                dataAddress = reinterpret_cast<char*>(parentPtr) + classElement.m_offset;
+            }
+
+            void* reserveAddress = dataAddress;
+
+            // create a new instance if needed
+            if (classElement.m_flags & SerializeContext::ClassElement::FLG_POINTER)
+            {
+                // create a new instance if we are referencing it by pointer
+                AZ_Assert(m_classData->m_factory != nullptr, "We are attempting to create '%s', but no factory is provided! Either provide factory or change data member '%s' to value not pointer!", m_classData->m_name, classElement.m_name);
+                void* newDataAddress = m_classData->m_factory->Create(m_classData->m_name);
+
+                // we need to account for additional offsets if we have a pointer to
+                // a base class.
+                void* basePtr = nullptr;
+                if (m_element.m_id == classElement.m_typeId)
+                {
+                    basePtr = newDataAddress;
+                }
+                else if(m_classData->m_azRtti && classElement.m_azRtti)
+                {
+                    basePtr = m_classData->m_azRtti->Cast(newDataAddress, classElement.m_azRtti->GetTypeId());
+                }
+                AZ_Assert(basePtr != nullptr, dataContainer
+                    ? "Can't cast container element %s(0x%x) to %s, make sure classes are registered in the system and not generics!"
+                    : "Can't cast %s(0x%x) to %s, make sure classes are registered in the system and not generics!"
+                    , m_element.m_name ? m_element.m_name : "NULL"
+                    , m_element.m_nameCrc
+                    , m_classData->m_name);
+
+                *reinterpret_cast<void**>(dataAddress) = basePtr; // store the pointer in the class
+                dataAddress = newDataAddress;
+            }
+
+            DataElement& rawElement = m_element;
+            if (m_classData->m_serializer && rawElement.m_dataSize != 0)
+            {
+                rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
+                if (rawElement.m_dataType == DataElement::DT_TEXT)
+                {
+                    // convert to binary so we can load the data
+                    AZStd::string text;
+                    text.resize_no_construct(rawElement.m_dataSize);
+                    rawElement.m_byteStream.Read(text.size(), reinterpret_cast<void*>(text.data()));
+                    rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
+                    rawElement.m_dataSize = m_classData->m_serializer->TextToData(text.c_str(), rawElement.m_version, rawElement.m_byteStream);
+                    rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN);
+                    rawElement.m_dataType = DataElement::DT_BINARY;
+                }
+
+                bool isLoaded = m_classData->m_serializer->Load(dataAddress, rawElement.m_byteStream, rawElement.m_version, rawElement.m_dataType == DataElement::DT_BINARY_BE);
+                rawElement.m_byteStream.Seek(0, IO::GenericStream::ST_SEEK_BEGIN); // reset stream position
+                if (!isLoaded)
+                {
+                    const AZStd::string error =
+                        AZStd::string::format(R"(Failed to load rawElement "%s" for class "%s" with parent element "%s".)",
+                            rawElement.m_name ? rawElement.m_name : "<unknown>",
+                            m_classData->m_name,
+                            m_element.m_name);
+
+                    if (errorHandler)
+                    {
+                        errorHandler->ReportError(error.c_str());
+                    }
+                    else
+                    {
+                        AZ_Error("Serialize", false, "%s", error.c_str());
+                    }
+
+                    success = false;
+                }
+            }
+
+            // Push current DataElementNode to stack
+            DataElementInstanceData node;
+            node.m_ptr = dataAddress;
+            node.m_dataElement = this;
+            nodeStack.push_back(node);
+
+            for (int dataElementIndex = 0; dataElementIndex < m_subElements.size(); ++dataElementIndex)
+            {
+                DataElementNode& subElement = m_subElements[dataElementIndex];
+                if (!subElement.GetDataHierarchyEnumerate(errorHandler, nodeStack))
+                {
+                    success = false;
+                    break;
+                }
+            }
+
+            // Pop stack
+            nodeStack.pop_back();
+
+            if (dataContainer)
+            {
+                dataContainer->StoreElement(parentPtr, reserveAddress);
+            }
+        }
+
+        return success;
+    }
+
+    //=========================================================================
+    // GetDataHierarchy
+    //=========================================================================
+    bool DataElementNode::GetDataHierarchy(void* objectPtr, const Uuid& classId, SerializeContext::ErrorHandler* errorHandler)
+    {
+        (void)classId;
+        AZ_Assert(m_element.m_id == classId, "GetDataHierarchy called with mismatched class type {%s} for element %s",
+            classId.ToString<AZStd::string>().c_str(), m_element.m_name);
+
+        NodeStack nodeStack;
+        DataElementInstanceData topNode;
+        topNode.m_ptr = objectPtr;
+        topNode.m_dataElement = this;
+        nodeStack.push_back(topNode);
+
+        bool success = true;
+        for (size_t i = 0; i < m_subElements.size(); ++i)
+        {
+            if (!m_subElements[i].GetDataHierarchyEnumerate(errorHandler, nodeStack))
+            {
+                success = false;
+                break;
+            }
+        }
+
+        return success;
+    }
+
+    // IDataConverter member function definitions
+    bool IDataConverter::CanConvertFromType(const TypeId& convertibleTypeId, const ClassData& classData,
+        SerializeContext&)
+    {
+        return classData.m_typeId == convertibleTypeId;
+    }
+
+    bool IDataConverter::ConvertFromType(void*& convertibleTypePtr, const TypeId& convertibleTypeId, void* classPtr, const ClassData& classData, SerializeContext&)
+    {
+        if (classData.m_typeId == convertibleTypeId)
+        {
+            convertibleTypePtr = classPtr;
+            return true;
+        }
+
+        return false;
+    }
+
+    //=========================================================================
+    // FreeElementPointer
+    // [12/7/2012]
+    //=========================================================================
+    void IDataContainer::DeletePointerData(SerializeContext* context, const ClassElement* classElement, const void* element)
+    {
+        AZ_Assert(context != nullptr && classElement != nullptr && element != nullptr, "Invalid input");
+        AZ::Uuid elemUuid = classElement->m_typeId;
+        // find the class data for the specific element
+        const ClassData* classData = classElement->m_genericClassInfo ? classElement->m_genericClassInfo->GetClassData() : context->FindClassData(elemUuid, nullptr, 0);
+        if (classElement->m_flags & ClassElement::FLG_POINTER)
+        {
+            const void* dataPtr = *reinterpret_cast<void* const*>(element);
+            // if dataAddress is a pointer in this case, cast it's value to a void* (or const void*) and dereference to get to the actual class.
+            if (dataPtr && classElement->m_azRtti)
+            {
+                const AZ::Uuid actualClassId = classElement->m_azRtti->GetActualUuid(dataPtr);
+                if (actualClassId != elemUuid)
+                {
+                    // we are pointing to derived type, adjust class data, uuid and pointer.
+                    classData = context->FindClassData(actualClassId, nullptr, 0);
+                    elemUuid = actualClassId;
+                    if (classData)
+                    {
+                        dataPtr = classElement->m_azRtti->Cast(dataPtr, classData->m_azRtti->GetTypeId());
+                    }
+                }
             }
         }
-        else
+        if (classData == nullptr)
         {
-            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to increment.");
+            if ((classElement->m_flags & ClassElement::FLG_POINTER) != 0)
+            {
+                const void* dataPtr = *reinterpret_cast<void* const*>(element);
+                AZ_UNUSED(dataPtr); // this prevents a L4 warning if the below line is stripped out in release.
+                AZ_Warning("Serialization", false, "Failed to find class id%s for %p! Memory could leak.", elemUuid.ToFixedString().c_str(), dataPtr);
+            }
+            return;
         }
-    }
 
-    void Internal::AZStdArrayEvents::Decrement()
-    {
-        if (m_indices)
+        if (classData->m_container)  // if element is container forward the message
         {
-            if ((reinterpret_cast<uintptr_t>(m_indices) & 1) == 1)
+            // clear all container data
+            classData->m_container->ClearElements(const_cast<void*>(element), context);
+        }
+        else
+        {
+            if ((classElement->m_flags & ClassElement::FLG_POINTER) == 0)
             {
-                // Decrement by 2 because the first bit is used to indicate whether or not a stack is used so the real
-                //      value starts one bit later. This assumes that index is check to be larger than 0 before calling
-                //      this function.
-                size_t index = reinterpret_cast<uintptr_t>(m_indices) - (1 << 1);
-                m_indices = reinterpret_cast<void*>(index);
+                return; // element is stored by value nothing to free
+            }
+
+            // if we get here, its a FLG_POINTER
+            const void* dataPtr = *reinterpret_cast<void* const*>(element);
+            if (dataPtr == nullptr)
+            {
+                return; // Pointer element is nullptr, nothing to delete
+            }
+            if (classData->m_factory)
+            {
+                classData->m_factory->Destroy(dataPtr);
             }
             else
             {
-                Stack* stack = reinterpret_cast<Stack*>(m_indices);
-                stack->top()--;
+                AZ_Warning("Serialization", false, "Failed to delete %p '%s' element, no destructor is provided! Memory could leak.", dataPtr, classData->m_name);
             }
         }
-        else
-        {
-            AZ_Warning("Serialization", false, "AZStdArrayEvents is not in a valid state to decrement.");
-        }
     }
 
-    bool Internal::AZStdArrayEvents::IsEmpty() const
+    void IDataContainer::ElementsUpdated(void* instance)
     {
-        return m_indices == nullptr;
+        (void)instance;
     }
 
-    bool SerializeContext::IsTypeReflected(AZ::Uuid typeId) const
+    IDataSerializerDeleter IDataSerializer::CreateDefaultDeleteDeleter()
     {
-        const AZ::SerializeContext::ClassData* reflectedClassData = FindClassData(typeId);
-        return (reflectedClassData != nullptr);
+        return [](IDataSerializer* ptr)
+        {
+            delete ptr;
+        };
     }
-
-    SerializeContext::PerModuleGenericClassInfo::~PerModuleGenericClassInfo()
+    IDataSerializerDeleter IDataSerializer::CreateNoDeleteDeleter()
     {
-        Cleanup();
+        return [](IDataSerializer*)
+        {
+        };
     }
 
-    void SerializeContext::PerModuleGenericClassInfo::Cleanup()
+    //=========================================================================
+    // EnumerateInstanceCallContext
+    //=========================================================================
+
+    EnumerateInstanceCallContext::EnumerateInstanceCallContext(
+        const SerializeContext::BeginElemEnumCB& beginElemCB,
+        const SerializeContext::EndElemEnumCB& endElemCB,
+        const SerializeContext* context,
+        unsigned int accessFlags,
+        SerializeContext::ErrorHandler* errorHandler)
+        : m_beginElemCB(beginElemCB)
+        , m_endElemCB(endElemCB)
+        , m_accessFlags(accessFlags)
+        , m_context(context)
     {
-        auto genericClassInfoContainer = AZStd::move(m_moduleLocalGenericClassInfos);
-        auto serializeContextSet = AZStd::move(m_serializeContextSet);
-        // Un-reflect GenericClassInfo from each serialize context registered with the module
-        for (AZ::SerializeContext* serializeContext : serializeContextSet)
-        {
-            for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
-            {
-                serializeContext->RemoveGenericClassInfo(genericClassInfo);
-            }
+        m_errorHandler = errorHandler ? errorHandler : &m_defaultErrorHandler;
 
-            serializeContext->m_perModuleSet.erase(this);
-        }
+        m_elementCallback = [this](void* ptr, const Uuid& classId, const ClassData* classData, const ClassElement* classElement)->bool
+        {
+            return m_context->EnumerateInstance(this, ptr, classId, classData, classElement);
+        };
+    }
 
-        // Cleanup the memory for the GenericClassInfo objects.
-        for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
+    //=========================================================================
+    // ~ClassElement
+    //=========================================================================
+    ClassElement::~ClassElement()
+    {
+        if (m_attributeOwnership == AttributeOwnership::Self)
         {
-            azdestroy(genericClassInfo);
+            ClearAttributes();
         }
     }
 
-    void SerializeContext::PerModuleGenericClassInfo::RegisterSerializeContext(AZ::SerializeContext* serializeContext)
+    //=========================================================================
+    // ClassElement::operator=
+    //=========================================================================
+    ClassElement& ClassElement::operator=(const ClassElement& other)
     {
-        m_serializeContextSet.emplace(serializeContext);
-        serializeContext->m_perModuleSet.emplace(this);
+        m_name = other.m_name;
+        m_nameCrc = other.m_nameCrc;
+        m_typeId = other.m_typeId;
+        m_dataSize = other.m_dataSize;
+        m_offset = other.m_offset;
+
+        m_azRtti = other.m_azRtti;
+        m_genericClassInfo = other.m_genericClassInfo;
+        m_editData = other.m_editData;
+        m_attributes = other.m_attributes;
+        // If we're a copy, we don't assume attribute ownership
+        m_attributeOwnership = AttributeOwnership::None;
+        m_flags = other.m_flags;
+
+        return *this;
     }
 
-    void SerializeContext::PerModuleGenericClassInfo::UnregisterSerializeContext(AZ::SerializeContext* serializeContext)
+    //=========================================================================
+    // ClearAttributes
+    //=========================================================================
+    void ClassElement::ClearAttributes()
     {
-        m_serializeContextSet.erase(serializeContext);
-        serializeContext->m_perModuleSet.erase(this);
-        for (const auto& [specializedTypeId, genericClassInfo] : m_moduleLocalGenericClassInfos)
-        {
-            serializeContext->RemoveGenericClassInfo(genericClassInfo);
-        }
+        m_attributes.clear();
     }
 
-    void SerializeContext::PerModuleGenericClassInfo::AddGenericClassInfo(AZ::GenericClassInfo* genericClassInfo)
+    //=========================================================================
+    // FindAttribute
+    //=========================================================================
+
+    Attribute* ClassElement::FindAttribute(AttributeId attributeId) const
     {
-        if (!genericClassInfo)
+        for (const AZ::AttributeSharedPair& attributePair : m_attributes)
         {
-            AZ_Error("SerializeContext", false, "The supplied generic class info object is nullptr. It cannot be added to the SerializeContext module structure");
-            return;
+            if (attributePair.first == attributeId)
+            {
+                return attributePair.second.get();
+            }
         }
+        return nullptr;
+    }
 
-        m_moduleLocalGenericClassInfos.emplace(genericClassInfo->GetSpecializedTypeId(), genericClassInfo);
+
+    //=========================================================================
+    // ClassData
+    //=========================================================================
+    ClassData::ClassData()
+    {
+        m_name = nullptr;
+        m_typeId = Uuid::CreateNull();
+        m_version = 0;
+        m_converter = nullptr;
+        m_serializer = nullptr;
+        m_factory = nullptr;
+        m_persistentId = nullptr;
+        m_doSave = nullptr;
+        m_eventHandler = nullptr;
+        m_container = nullptr;
+        m_azRtti = nullptr;
+        m_editData = nullptr;
     }
 
-    void SerializeContext::PerModuleGenericClassInfo::RemoveGenericClassInfo(const AZ::TypeId& genericTypeId)
+    auto ClassData::CreateImpl(const char* name, const Uuid& typeUuid,
+        IObjectFactory* factory, IDataSerializer* serializer, IDataContainer* container,
+        IRttiHelper* rttiHelper) -> ClassData
     {
-        if (genericTypeId.IsNull())
-        {
-            AZ_Error("SerializeContext", false, "The supplied generic typeidis invalid. It is not stored the SerializeContext module structure ");
-            return;
-        }
+        ClassData cd;
+        cd.m_name = name;
+        cd.m_typeId = typeUuid;
+        cd.m_version = 0;
+        cd.m_converter = nullptr;
+        // A raw ptr to an IDataSerializer isn't owned by the SerializeContext class data
+        cd.m_serializer = IDataSerializerPtr(serializer, IDataSerializer::CreateNoDeleteDeleter());
+        cd.m_factory = factory;
+        cd.m_persistentId = nullptr;
+        cd.m_doSave = nullptr;
+        cd.m_eventHandler = nullptr;
+        cd.m_container = container;
+        cd.m_azRtti = rttiHelper;
+        cd.m_editData = nullptr;
+        return cd;
+    }
 
-        auto genericClassInfoFoundIt = m_moduleLocalGenericClassInfos.find(genericTypeId);
-        if (genericClassInfoFoundIt != m_moduleLocalGenericClassInfos.end())
+    //=========================================================================
+    // ClassData
+    //=========================================================================
+    void ClassData::ClearAttributes()
+    {
+        m_attributes.clear();
+
+        for (ClassElement& classElement : m_elements)
         {
-            m_moduleLocalGenericClassInfos.erase(genericClassInfoFoundIt);
+            if (classElement.m_attributeOwnership == ClassElement::AttributeOwnership::Parent)
+            {
+                classElement.ClearAttributes();
+            }
         }
     }
 
-    AZ::GenericClassInfo* SerializeContext::PerModuleGenericClassInfo::FindGenericClassInfo(const AZ::TypeId& genericTypeId) const
+    SerializeContext::ClassPersistentId ClassData::GetPersistentId(const SerializeContext& context) const
     {
-        auto genericClassInfoFoundIt = m_moduleLocalGenericClassInfos.find(genericTypeId);
-        return genericClassInfoFoundIt != m_moduleLocalGenericClassInfos.end() ? genericClassInfoFoundIt->second : nullptr;
+        SerializeContext::ClassPersistentId persistentIdFunction = m_persistentId;
+        if (!persistentIdFunction)
+        {
+            // check the base classes
+            for (const ClassElement& element : m_elements)
+            {
+                if (element.m_flags & ClassElement::FLG_BASE_CLASS)
+                {
+                    const ClassData* baseClassData = context.FindClassData(element.m_typeId);
+                    if (baseClassData)
+                    {
+                        persistentIdFunction = baseClassData->GetPersistentId(context);
+                        if (persistentIdFunction)
+                        {
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    // base classes are in the beginning of the array
+                    break;
+                }
+            }
+        }
+        return persistentIdFunction;
     }
 
-    // Take advantage of static variables being unique per dll module to clean up module specific registered classes when the module unloads
-    SerializeContext::PerModuleGenericClassInfo& GetCurrentSerializeContextModule()
+    Attribute* ClassData::FindAttribute(AttributeId attributeId) const
     {
-        static SerializeContext::PerModuleGenericClassInfo s_ModuleCleanupInstance;
-        return s_ModuleCleanupInstance;
+        for (const AZ::AttributeSharedPair& attributePair : m_attributes)
+        {
+            if (attributePair.first == attributeId)
+            {
+                return attributePair.second.get();
+            }
+        }
+        return nullptr;
     }
 
-    SerializeContext::IDataSerializerDeleter SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter()
+    bool ClassData::CanConvertFromType(const TypeId& convertibleTypeId, AZ::SerializeContext& serializeContext) const
     {
-        return [](IDataSerializer* ptr)
+        // If the convertible type is exactly the type being stored by the ClassData.
+        // True will always be returned in this case
+        if (convertibleTypeId == m_typeId)
         {
-            delete ptr;
-        };
+            return true;
+        }
+
+        return m_dataConverter ? m_dataConverter->CanConvertFromType(convertibleTypeId, *this, serializeContext) : false;
     }
-    SerializeContext::IDataSerializerDeleter SerializeContext::IDataSerializer::CreateNoDeleteDeleter()
+
+    bool ClassData::ConvertFromType(void*& convertibleTypePtr, const TypeId& convertibleTypeId, void* classPtr, AZ::SerializeContext& serializeContext) const
     {
-        return [](IDataSerializer*)
+        // If the convertible type is exactly the type being stored by the ClassData.
+        // the result convertTypePtr is equal to the classPtr
+        if (convertibleTypeId == m_typeId)
         {
-        };
-    }
-
+            convertibleTypePtr = classPtr;
+            return true;
+        }
 
-} // namespace AZ
+        return m_dataConverter ? m_dataConverter->ConvertFromType(convertibleTypePtr, convertibleTypeId, classPtr, *this, serializeContext) : false;
+    }
+} // namespace AZ::Serialize

Fișier diff suprimat deoarece este prea mare
+ 233 - 722
Code/Framework/AzCore/AzCore/Serialization/SerializeContext.h


+ 2 - 2
Code/Framework/AzCore/AzCore/Serialization/SerializeContextEnum.cpp

@@ -34,13 +34,13 @@ namespace AZ
         {
             return this; // we have already removed the class data.
         }
-        AZ_Assert(version != VersionClassDeprecated, "You cannot use %u as the version, it is reserved by the system!", version);
+        AZ_Assert(version != Serialize::VersionClassDeprecated, "You cannot use %u as the version, it is reserved by the system!", version);
         m_classData->second.m_version = version;
         m_classData->second.m_converter = converter;
         return this;
     }
 
-    auto SerializeContext::EnumBuilder::Serializer(IDataSerializerPtr serializer) -> EnumBuilder*
+    auto SerializeContext::EnumBuilder::Serializer(Serialize::IDataSerializerPtr serializer) -> EnumBuilder*
     {
         if (m_context->IsRemovingReflection())
         {

+ 4 - 4
Code/Framework/AzCore/AzCore/Serialization/SerializeContextEnum.inl

@@ -57,7 +57,7 @@ namespace AZ
 
         template<class EnumType>
         class EnumSerializer
-            : public SerializeContext::IDataSerializer
+            : public Serialize::IDataSerializer
         {
             static_assert(AZStd::is_enum<EnumType>::value, "Enum Serializer can only be used with enum types");
             using UnderlyingType = AZStd::RemoveEnumT<EnumType>;
@@ -150,7 +150,7 @@ namespace AZ
             if (enumTypeIter != m_uuidMap.end())
             {
                 RemoveClassData(&enumTypeIter->second);
-                
+
                 auto classNameRange = m_classNameToUuid.equal_range(Crc32(name));
                 for (auto classNameRangeIter = classNameRange.first; classNameRangeIter != classNameRange.second;)
                 {
@@ -176,11 +176,11 @@ namespace AZ
             {
                 typename UuidToClassMap::pair_iter_bool enumTypeInsertIter = m_uuidMap.emplace(enumTypeId, ClassData::Create<EnumType>(name, enumTypeId, factory));
                 ClassData& enumClassData = enumTypeInsertIter.first->second;
-                enumClassData.m_serializer = IDataSerializerPtr{ new SerializeContextEnumInternal::EnumSerializer<EnumType>(), IDataSerializer::CreateDefaultDeleteDeleter() };
+                enumClassData.m_serializer = Serialize::IDataSerializerPtr{ new SerializeContextEnumInternal::EnumSerializer<EnumType>(), IDataSerializer::CreateDefaultDeleteDeleter() };
 
                 m_classNameToUuid.emplace(Crc32(name), enumTypeId);
                 m_uuidAnyCreationMap.emplace(enumTypeId, &AnyTypeInfoConcept<EnumType>::CreateAny);
-                
+
                 // Store the underlying type as an attribute within the ClassData
                 enumClassData.m_attributes.emplace_back(Serialize::Attributes::EnumUnderlyingType, aznew AZ::AttributeContainerType<AZ::TypeId>(underlyingTypeId));
                 enumTypeIter = enumTypeInsertIter.first;

+ 44 - 0
Code/Framework/AzCore/AzCore/Serialization/SerializeContext_fwd.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+// Forward declare common classes and structs that allows the references
+// to the SerializeContext without any includes
+namespace AZ
+{
+    template<class T, class>
+    struct AnyTypeInfoConcept;
+
+    class GenericClassInfo;
+    class ReflectContext;
+    class SerializeContext;
+}
+
+namespace AZ::Serialize
+{
+    template<class, bool, bool>
+    struct InstanceFactory;
+
+    class ClassData;
+    struct EnumerateInstanceCallContext;
+    struct ClassElement;
+    struct DataElement;
+    class DataElementNode;
+    class IObjectFactory;
+    class IDataSerializer;
+    class IDataContainer;
+    class IEventHandler;
+    class IDataConverter;
+}
+
+// Put this macro on your class to allow serialization with a private default constructor.
+#define AZ_SERIALIZE_FRIEND() \
+    template <typename, typename> \
+    friend struct AZ::AnyTypeInfoConcept; \
+    template <typename, bool, bool> \
+    friend struct AZ::Serialize::InstanceFactory;

+ 2 - 0
Code/Framework/AzCore/AzCore/azcore_files.cmake

@@ -414,6 +414,7 @@ set(FILES
     Memory/HphaAllocator.cpp
     Memory/HphaAllocator.h
     Memory/IAllocator.h
+    Memory/Memory_fwd.h
     Memory/Memory.cpp
     Memory/Memory.h
     Memory/nedmalloc.inl
@@ -553,6 +554,7 @@ set(FILES
     Serialization/ObjectStream.h
     Serialization/SerializeContext.cpp
     Serialization/SerializeContext.h
+    Serialization/SerializeContext_fwd.h
     Serialization/SerializeContextEnum.cpp
     Serialization/SerializeContextEnum.inl
     Serialization/DataPatch.h

+ 2 - 2
Code/Framework/AzCore/Tests/Serialization.cpp

@@ -7680,7 +7680,7 @@ namespace UnitTest
     TEST_F(Serialization, CustomSerializerWithDefaultDeleter_IsDeletedOnUnreflect)
     {
         bool serializerDeleted = false;
-        AZ::SerializeContext::IDataSerializerPtr customSerializer{ new TestDeleterSerializer{ serializerDeleted }, AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() };
+        AZ::Serialize::IDataSerializerPtr customSerializer{ new TestDeleterSerializer{ serializerDeleted }, AZ::SerializeContext::IDataSerializer::CreateDefaultDeleteDeleter() };
         m_serializeContext->Class<TestLeafNode>()
             ->Version(1)
             ->Serializer(AZStd::move(customSerializer));
@@ -7697,7 +7697,7 @@ namespace UnitTest
     {
         bool serializerDeleted = false;
         TestDeleterSerializer* serializerInstance = new TestDeleterSerializer{ serializerDeleted };
-        AZ::SerializeContext::IDataSerializerPtr customSerializer{ serializerInstance, AZ::SerializeContext::IDataSerializer::CreateNoDeleteDeleter() };
+        AZ::Serialize::IDataSerializerPtr customSerializer{ serializerInstance, AZ::SerializeContext::IDataSerializer::CreateNoDeleteDeleter() };
         m_serializeContext->Class<TestLeafNode>()
             ->Version(1)
             ->Serializer(AZStd::move(customSerializer));

+ 0 - 1
Code/Framework/AzFramework/AzFramework/Asset/AssetCatalog.h

@@ -10,7 +10,6 @@
 
 #include <AzCore/Asset/AssetCommon.h>
 #include <AzCore/Asset/AssetManager.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 #include <AzCore/std/parallel/thread.h>
 #include <AzCore/std/smart_ptr/unique_ptr.h>

+ 1 - 0
Code/Framework/AzFramework/AzFramework/Asset/AssetRegistry.cpp

@@ -9,6 +9,7 @@
 
 #include <AzFramework/Asset/AssetRegistry.h>
 #include <AzCore/Math/Crc.h>
+#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/ranges/transform_view.h>
 #include <AzCore/std/string/conversions.h>
 #include <AzCore/IO/SystemFile.h> // for max path

+ 5 - 1
Code/Framework/AzFramework/AzFramework/Asset/AssetRegistry.h

@@ -11,10 +11,14 @@
 
 #include <AzCore/Asset/AssetCommon.h>
 #include <AzCore/Asset/AssetManagerBus.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/containers/unordered_map.h>
 #include <AzCore/std/smart_ptr/shared_ptr.h>
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 namespace AzFramework
 {
     /**

+ 7 - 4
Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h

@@ -9,10 +9,13 @@
 #pragma once
 
 #include <AzCore/Component/Component.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+
+namespace AZ
+{
+    class ReflectContxt;
+}
 
 namespace AzFramework
 {

+ 1 - 0
Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl

@@ -6,6 +6,7 @@
  *
  */
 
+#include <AzCore/Serialization/SerializeContext.h>
 #include <AzFramework/Components/ComponentAdapterHelpers.h>
 
 namespace AzFramework

+ 5 - 1
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/Reflection/LegacyReflectionBridge.h

@@ -9,10 +9,14 @@
 #pragma once
 
 #include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzFramework/DocumentPropertyEditor/Reflection/Attribute.h>
 #include <AzFramework/DocumentPropertyEditor/Reflection/Visitor.h>
 
+namespace AZ
+{
+    class SerializeContext;
+}
+
 namespace AZ::Reflection
 {
     //! These synthetic attributes are injected into legacy reflection data to give additional context

+ 0 - 1
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/ReflectionAdapter.h

@@ -10,7 +10,6 @@
 
 #include <AzFramework/DocumentPropertyEditor/AdapterBuilder.h>
 #include <AzFramework/DocumentPropertyEditor/RoutingAdapter.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/string/string_view.h>
 
 namespace AZ::DocumentPropertyEditor

+ 6 - 0
Code/Framework/AzFramework/AzFramework/Physics/Character.h

@@ -9,6 +9,7 @@
 #pragma once
 
 #include <AzCore/Math/Vector3.h>
+#include <AzCore/Outcome/Outcome.h>
 
 #include <AzFramework/Physics/Shape.h>
 
@@ -18,6 +19,11 @@
 #include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
 #include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace Physics
 {
     class Character;

+ 1 - 1
Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h

@@ -58,7 +58,7 @@ namespace AzPhysics
         // padding was added. But having this structure limits the warnings to this member usage because
         // SystemConfiguration won't need extra padding to achieve 16 byte alignment.
         AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") // structure was padded due to alignment
-        struct alignas(16)
+        [[maybe_unused]] struct alignas(16)
         {
             unsigned char m_unused[16];
         } m_unusedPadding;

+ 6 - 6
Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h

@@ -13,13 +13,13 @@
 #include <AzCore/Math/Transform.h>
 #include <AzCore/Math/Vector2.h>
 #include <AzCore/Math/Vector3.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzFramework/Physics/HeightfieldProviderBus.h>
 
 namespace AZ
 {
     class Capsule;
     class Obb;
+    class ReflectContext;
     class Sphere;
 } // namespace AZ
 
@@ -159,7 +159,7 @@ namespace Physics
                                 ///< and don't need to be kept alive by the caller;
     };
 
-    class PhysicsAssetShapeConfiguration 
+    class PhysicsAssetShapeConfiguration
         : public ShapeConfiguration
     {
     public:
@@ -187,7 +187,7 @@ namespace Physics
         AZ::Vector3 m_nativeShapeScale = AZ::Vector3::CreateOne(); ///< Native shape scale. This will be serialised
     };
 
-    class CookedMeshShapeConfiguration 
+    class CookedMeshShapeConfiguration
         : public ShapeConfiguration
     {
     public:
@@ -200,7 +200,7 @@ namespace Physics
             TriangleMesh = 0,
             Convex
         };
-        
+
         CookedMeshShapeConfiguration() = default;
         CookedMeshShapeConfiguration(const CookedMeshShapeConfiguration&);
         CookedMeshShapeConfiguration& operator=(const CookedMeshShapeConfiguration&);
@@ -213,7 +213,7 @@ namespace Physics
         //! (e.g. in PhysX: result of cookTriangleMesh or cookConvexMesh).
         void SetCookedMeshData(const AZ::u8* cookedData, size_t cookedDataSize, MeshType type);
         const AZStd::vector<AZ::u8>& GetCookedMeshData() const;
-        
+
         MeshType GetMeshType() const;
 
         void* GetCachedNativeMesh();
@@ -225,7 +225,7 @@ namespace Physics
 
         AZStd::vector<AZ::u8> m_cookedData;
         MeshType m_type = MeshType::TriangleMesh;
-        
+
         //! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized.
         void* m_cachedNativeMesh = nullptr;
     };

+ 2 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.cpp

@@ -8,6 +8,8 @@
 
 #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 namespace AZStd
 {
     template class vector<AzToolsFramework::AssetSystem::JobInfo>;

+ 5 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h

@@ -9,7 +9,6 @@
 #pragma once
 
 #include <AzCore/EBus/EBus.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/Outcome/Outcome.h>
 #include <AzCore/Math/Crc.h>
@@ -17,6 +16,11 @@
 #include <AzCore/Asset/AssetManagerBus.h>
 #include <AzCore/PlatformDef.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace AzToolsFramework
 {
     namespace AssetSystem

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorEntityAPI.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <AzToolsFramework/Entity/EntityTypes.h>
 

+ 0 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/API/EntityCompositionNotificationBus.h

@@ -11,7 +11,6 @@
 #include <AzCore/Component/ComponentBus.h>
 #include <AzCore/Component/Entity.h>
 #include <AzCore/EBus/EBus.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 #include <AzToolsFramework/Entity/EntityTypes.h>
 

+ 13 - 11
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManager.cpp

@@ -13,6 +13,8 @@
 #include <AzToolsFramework/ActionManager/Action/ActionManager.h>
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
 
+#include <AzCore/Interface/Interface.h>
+
 namespace AzToolsFramework
 {
     void ApplicationWatcher::SetShortcutTriggeredFlag()
@@ -54,7 +56,7 @@ namespace AzToolsFramework
         , m_editorActionContext(editorActionContext)
     {
     }
-    
+
     bool ActionContextWidgetWatcher::eventFilter(QObject* watched, QEvent* event)
     {
         switch (event->type())
@@ -88,7 +90,7 @@ namespace AzToolsFramework
             {
                 keyCode += Qt::META;
             }
-            
+
             QKeySequence keySequence(keyCode);
             QWidget* watchedWidget = qobject_cast<QWidget*>(watched);
 
@@ -100,7 +102,7 @@ namespace AzToolsFramework
                 event->accept();
                 return true;
             }
-            
+
             break;
         }
         case QEvent::Shortcut:
@@ -226,7 +228,7 @@ namespace AzToolsFramework
         {
             return AZ::Failure(AZStd::string::format(
                 "Action Manager - Could not register action \"%s\" - context \"%s\" has not been registered.",
-                actionIdentifier.c_str(), 
+                actionIdentifier.c_str(),
                 contextIdentifier.c_str()
             ));
         }
@@ -272,7 +274,7 @@ namespace AzToolsFramework
         {
             return AZ::Failure(AZStd::string::format(
                 "Action Manager - Could not register action \"%s\" - context \"%s\" has not been registered.",
-                actionIdentifier.c_str(), 
+                actionIdentifier.c_str(),
                 contextIdentifier.c_str()
             ));
         }
@@ -311,7 +313,7 @@ namespace AzToolsFramework
     {
         return m_actions.contains(actionIdentifier);
     }
-    
+
     ActionManagerGetterResult ActionManager::GetActionName(const AZStd::string& actionIdentifier)
     {
         auto actionIterator = m_actions.find(actionIdentifier);
@@ -415,7 +417,7 @@ namespace AzToolsFramework
                 "Action Manager - Could not set icon path of action \"%s\" as no action with that identifier was registered.",
                 actionIdentifier.c_str()));
         }
-        
+
         actionIterator->second->SetIconPath(iconPath);
         return AZ::Success();
     }
@@ -475,7 +477,7 @@ namespace AzToolsFramework
         actionIterator->second->AddEnabledStateCallback(AZStd::move(enabledStateCallback));
         return AZ::Success();
     }
-    
+
     ActionManagerOperationResult ActionManager::UpdateAction(const AZStd::string& actionIdentifier)
     {
         auto actionIterator = m_actions.find(actionIdentifier);
@@ -485,12 +487,12 @@ namespace AzToolsFramework
                 "Action Manager - Could not update action \"%s\" as no action with that identifier was registered.",
                 actionIdentifier.c_str()));
         }
-        
+
         actionIterator->second->Update();
 
         return AZ::Success();
     }
-    
+
     ActionManagerOperationResult ActionManager::RegisterActionUpdater(const AZStd::string& actionUpdaterIdentifier)
     {
         if (m_actionUpdaters.contains(actionUpdaterIdentifier))
@@ -516,7 +518,7 @@ namespace AzToolsFramework
                 actionUpdaterIdentifier.c_str()
             ));
         }
-        
+
         if (!m_actions.contains(actionIdentifier))
         {
             return AZ::Failure(AZStd::string::format(

+ 9 - 8
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManagerInterface.h

@@ -8,9 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/std/function/function_base.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <AzToolsFramework/ActionManager/Action/EditorActionUtils.h>
 
@@ -33,7 +34,7 @@ namespace AzToolsFramework
 
         AZStd::string m_name; //!< The friendly name for the Action Context.
     };
-    
+
     //! Action Properties object.
     //! Used to streamline registration of an Action.
     struct ActionProperties
@@ -189,7 +190,7 @@ namespace AzToolsFramework
         //! @param actionIdentifier The identifier for the action to trigger.
         //! @return A successful outcome object, or a string with a message detailing the error in case of failure.
         virtual ActionManagerOperationResult TriggerAction(const AZStd::string& actionIdentifier) = 0;
-        
+
         //! Installs an enabled state callback to an action that will set its enabled state when the action is updated.
         //! An action can only have a single enabled state callback. The function will fail if called multiple times.
         //! @param actionIdentifier The identifier for the action to install the callback to.
@@ -197,7 +198,7 @@ namespace AzToolsFramework
             const AZStd::string& actionIdentifier,
             AZStd::function<bool()> enabledStateCallback
         ) = 0;
-        
+
         //! Update the state of an Action via its identifier.
         //! This will update both the enabled and checked state.
         //! @param actionIdentifier The identifier for the action to update.
@@ -210,13 +211,13 @@ namespace AzToolsFramework
         //! @param actionUpdaterIdentifier The identifier for the newly registered action updater.
         //! @return A successful outcome object, or a string with a message detailing the error in case of failure.
         virtual ActionManagerOperationResult RegisterActionUpdater(const AZStd::string& actionUpdaterIdentifier) = 0;
-        
+
         //! Adds an action identifier to the updater's list.
         //! @param actionUpdaterIdentifier The identifier for the updater to add the action to.
         //! @param actionIdentifier The identifier for the action to add the updater's list.
         //! @return A successful outcome object, or a string with a message detailing the error in case of failure.
         virtual ActionManagerOperationResult AddActionToUpdater(const AZStd::string& actionUpdaterIdentifier, const AZStd::string& actionIdentifier) = 0;
-        
+
         //! Trigger an update on all actions registered to the Action Updater.
         //! @param actionUpdaterIdentifier The identifier for the action updater to trigger an update on.
         //! @return A successful outcome object, or a string with a message detailing the error in case of failure.

+ 2 - 3
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/ActionManagerInternalInterface.h

@@ -8,9 +8,8 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/std/function/function_base.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/std/string/string.h>
 
 class QAction;
 class QWidget;

+ 3 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Action/EditorAction.cpp

@@ -10,6 +10,8 @@
 
 #include <AzToolsFramework/ActionManager/Action/ActionManagerNotificationBus.h>
 
+#include <AzCore/Interface/Interface.h>
+
 #include <QAction>
 #include <QIcon>
 
@@ -162,7 +164,7 @@ namespace AzToolsFramework
     {
         return m_action;
     }
-    
+
     void EditorAction::AddEnabledStateCallback(AZStd::function<bool()> enabledStateCallback)
     {
         if (enabledStateCallback)

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/HotKey/HotKeyManagerInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 class QWidget;
 

+ 2 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/HotKey/HotKeyManagerInternalInterface.h

@@ -8,8 +8,8 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 
 namespace AzToolsFramework
 {

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/EditorMenu.cpp

@@ -12,6 +12,8 @@
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInternalInterface.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 #include <QMenu>
 
 namespace AzToolsFramework
@@ -31,7 +33,7 @@ namespace AzToolsFramework
     {
         m_menuItems[sortKey].emplace_back();
     }
-    
+
     void EditorMenu::AddAction(int sortKey, AZStd::string actionIdentifier)
     {
         if (ContainsAction(actionIdentifier))
@@ -114,7 +116,7 @@ namespace AzToolsFramework
             m_menuItems[sortKey].emplace_back(MenuItemType::Widget, AZStd::move(widgetActionIdentifier));
         }
     }
-    
+
     bool EditorMenu::ContainsAction(const AZStd::string& actionIdentifier) const
     {
         return m_actionToSortKeyMap.contains(actionIdentifier);

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/EditorMenuBar.cpp

@@ -10,6 +10,8 @@
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h>
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInternalInterface.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 #include <QMainWindow>
 #include <QMenuBar>
 
@@ -19,13 +21,13 @@ namespace AzToolsFramework
         : m_mainWindow(mainWindow)
     {
     }
-    
+
     void EditorMenuBar::AddMenu(int sortKey, AZStd::string menuIdentifier)
     {
         m_menuToSortKeyMap.insert(AZStd::make_pair(menuIdentifier, sortKey));
         m_menus[sortKey].push_back(AZStd::move(menuIdentifier));
     }
-    
+
     bool EditorMenuBar::ContainsMenu(const AZStd::string& menuIdentifier) const
     {
         return m_menuToSortKeyMap.contains(menuIdentifier);

+ 5 - 3
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/MenuManagerInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 class QMainWindow;
 
@@ -53,7 +55,7 @@ namespace AzToolsFramework
         //! @param menuIdentifier The identifier for the menu to query.
         //! @return True if a Menu with the identifier provided was found, false otherwise.
         virtual bool IsMenuRegistered(const AZStd::string& menuIdentifier) const = 0;
-        
+
         //! Add an Action to a Menu. Will prompt an update of the menu.
         //! @param menuIdentifier The identifier for the menu the action is being added to.
         //! @param actionIdentifier The identifier for the action to add to the menu.

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/Menu/MenuManagerInternalInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 class QMenu;
 class QMenuBar;

+ 3 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/EditorToolBar.cpp

@@ -13,6 +13,8 @@
 #include <AzToolsFramework/ActionManager/Menu/MenuManagerInternalInterface.h>
 #include <AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInterface.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 #include <QMenu>
 #include <QToolBar>
 #include <QToolButton>
@@ -32,7 +34,7 @@ namespace AzToolsFramework
     {
         m_toolBarItems[sortKey].emplace_back();
     }
-    
+
     void EditorToolBar::AddAction(int sortKey, AZStd::string actionIdentifier)
     {
         m_actionToSortKeyMap.insert(AZStd::make_pair(actionIdentifier, sortKey));

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/EditorToolBarArea.cpp

@@ -10,6 +10,8 @@
 #include <AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInterface.h>
 #include <AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInternalInterface.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 #include <AzQtComponents/Components/StyleManager.h>
 
 #include <QMainWindow>
@@ -21,13 +23,13 @@ namespace AzToolsFramework
         , m_toolBarArea(toolBarArea)
     {
     }
-    
+
     void EditorToolBarArea::AddToolBar(int sortKey, AZStd::string toolBarIdentifier)
     {
         m_toolBarToSortKeyMap.insert(AZStd::make_pair(toolBarIdentifier, sortKey));
         m_toolBars[sortKey].push_back(AZStd::move(toolBarIdentifier));
     }
-    
+
     bool EditorToolBarArea::ContainsToolBar(const AZStd::string& toolBarIdentifier) const
     {
         return m_toolBarToSortKeyMap.contains(toolBarIdentifier);

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <QToolBar>
 

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ActionManager/ToolBar/ToolBarManagerInternalInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 namespace AzToolsFramework
 {

+ 16 - 12
Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSeedManager.h

@@ -9,20 +9,24 @@
 #pragma once
 
 #include <AzCore/Asset/AssetCommon.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/containers/array.h>
 #include <AzCore/std/containers/vector.h>
 #include <AzFramework/Asset/AssetRegistry.h>
 #include <AzFramework/Asset/AssetSeedList.h>
 #include <AzFramework/Platform/PlatformDefaults.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace AzToolsFramework
 {
     class AssetFileDebugInfo;
     class AssetFileDebugInfoList;
 
     // AssetFileInfo class will be used to store information
-    // related to the asset file including modification time 
+    // related to the asset file including modification time
     // and the the hash of the entire file content.
     class AssetFileInfo
     {
@@ -62,9 +66,9 @@ namespace AzToolsFramework
     };
 
     /*
-   * Implements an Asset Seed Manager that can be used to handle seed assets. 
-   * Given a list of seed assets, this class can retrieve a complete 
-   * list of all the product dependencies. 
+   * Implements an Asset Seed Manager that can be used to handle seed assets.
+   * Given a list of seed assets, this class can retrieve a complete
+   * list of all the product dependencies.
    */
     class AssetSeedManager
     {
@@ -75,7 +79,7 @@ namespace AzToolsFramework
         using AssetsInfoList = AZStd::vector<AZ::Data::AssetInfo>;
 
         ~AssetSeedManager();
-        
+
         bool AddSeedAsset(AZ::Data::AssetId assetId, AzFramework::PlatformFlags platformFlags, AZStd::string path = AZStd::string(), const AZStd::string& seedListFilePath = AZStd::string());
         bool AddSeedAsset(const AZStd::string& assetPath, AzFramework::PlatformFlags platformFlags, const AZStd::string& seedListFilePath = AZStd::string());
 
@@ -100,25 +104,25 @@ namespace AzToolsFramework
         bool Save(const AZStd::string& destinationFilePath);
 
         //! Updates the seed path for all seeds.
-        //! If a seed is enabled for multiple platforms, it will update the path 
+        //! If a seed is enabled for multiple platforms, it will update the path
         //! with the information provided by the first asset catalog in which that seed exists.
         void UpdateSeedPath();
 
         //! Removes seed path hint for all existing seeds.
         void RemoveSeedPath();
 
-        //! Loads the asset seed file from the source path and 
-        //! adds root assets from the file to the seed list 
+        //! Loads the asset seed file from the source path and
+        //! adds root assets from the file to the seed list
         bool Load(const AZStd::string& sourceFilePath);
 
         const AzFramework::AssetSeedList& GetAssetSeedList() const;
 
         AZ::Outcome<void, AZStd::string> SetSeedPlatformFlags(int index, AzFramework::PlatformFlags platformFlags);
 
-        // Using the entries in the seed list retrieves a list of product dependencies and their AssetInfo 
+        // Using the entries in the seed list retrieves a list of product dependencies and their AssetInfo
         AssetsInfoList GetDependenciesInfo(AzFramework::PlatformId platformIndex, const AZStd::unordered_set<AZ::Data::AssetId>& exclusionList, AssetFileDebugInfoList* optionalDebugList = nullptr, const AZStd::vector<AZStd::string>& wildcardPatternExclusionList = AZStd::vector<AZStd::string>()) const;
 
-        // Creates a AssetFileInfoList comprising of all known product dependencies from the seed list. 
+        // Creates a AssetFileInfoList comprising of all known product dependencies from the seed list.
         AssetFileInfoList GetDependencyList(AzFramework::PlatformId platformIndex, const AZStd::unordered_set<AZ::Data::AssetId>& exclusionList = {}, AssetFileDebugInfoList* optionalDebugList = nullptr, const AZStd::vector<AZStd::string>& wildcardPatternExclusionList = AZStd::vector<AZStd::string>()) const;
 
         // Expands the current seed list to gather all dependencies based on the given platform. If given a debugFilePath,
@@ -148,7 +152,7 @@ namespace AzToolsFramework
         static AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& assetId, const AzFramework::PlatformId& platformIndex, const AZStd::string& seedListfilePath = AZStd::string(), const AZStd::string& asetHintPath = AZStd::string());
     private:
         AZ::Outcome<AZStd::vector<AZ::Data::ProductDependency>, AZStd::string> GetAllProductDependencies(
-            const AZ::Data::AssetId& assetId, 
+            const AZ::Data::AssetId& assetId,
             const AzFramework::PlatformId& platformIndex,
             const AZStd::unordered_set<AZ::Data::AssetId>& exclusionList,
             AssetFileDebugInfoList* optionalDebugList = nullptr,

+ 3 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserThumbnailView.cpp

@@ -18,6 +18,8 @@
 #include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
 #include <AzToolsFramework/AssetBrowser/Views/AssetBrowserViewUtils.h>
 
+#include <AzCore/Interface/Interface.h>
+
 #include <AzQtComponents/Components/Widgets/AssetFolderThumbnailView.h>
 
 #if !defined(Q_MOC_RUN)
@@ -175,7 +177,7 @@ namespace AzToolsFramework
                   }
             }
         }
- 
+
         AzQtComponents::AssetFolderThumbnailView* AssetBrowserThumbnailView::GetThumbnailViewWidget() const
         {
             return m_thumbnailViewWidget;

+ 2 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp

@@ -8,6 +8,7 @@
 #include <API/EditorAssetSystemAPI.h>
 
 #include <AzCore/Asset/AssetManagerBus.h>
+#include <AzCore/Interface/Interface.h>
 #include <AzCore/Math/Crc.h>
 #include <AzCore/std/containers/vector.h>
 #include <AzCore/std/ranges/split_view.h>
@@ -249,7 +250,7 @@ namespace AzToolsFramework
             // Get all entries in the AssetBrowser-relative path-to-product
             AZStd::vector<AZStd::string> entries;
             AssetBrowserEntry* entry = itABEntry->second;
-            do 
+            do
             {
                 entries.push_back(entry->GetName());
                 entry = entry->GetParent();

+ 0 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalogManager.h

@@ -10,7 +10,6 @@
 
 #include <AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalog.h>
 #include <AzFramework/Asset/NetworkAssetNotification_private.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/smart_ptr/unique_ptr.h>
 #include <AzCore/std/containers/vector.h>
 

+ 1 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.cpp

@@ -10,6 +10,7 @@
 
 #include <sqlite3.h>
 
+#include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/SystemFile.h>
 #include <AzFramework/StringFunc/StringFunc.h>
 #include <AzToolsFramework/SQLite/SQLiteConnection.h>

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <AzFramework/Entity/EntityContextBus.h>
 

+ 5 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EntityUtilityComponent.h

@@ -9,14 +9,17 @@
 
 #include <AzCore/Component/Component.h>
 #include <AzCore/Component/Entity.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
 #include <AzToolsFramework/ToolsComponents/EditorDisabledCompositionBus.h>
 #include <AzToolsFramework/ToolsComponents/EditorPendingCompositionBus.h>
 #include <AzToolsFramework/API/EntityCompositionRequestBus.h>
-#include <AzCore/Component/ComponentApplication.h>
 #include <AzFramework/Entity/BehaviorEntity.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace AzToolsFramework
 {
     struct ComponentDetails

+ 2 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h

@@ -8,8 +8,8 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 
 #include <AzFramework/Entity/EntityContextBus.h>
 

+ 0 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h

@@ -10,8 +10,6 @@
 
 #include <AzCore/Component/Entity.h>
 #include <AzCore/Component/EntityId.h>
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 #include <AzFramework/Entity/EntityContextBus.h>
 

+ 0 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/TranslationManipulators.cpp

@@ -35,7 +35,6 @@ namespace AzToolsFramework
 
     TranslationManipulators::TranslationManipulators(
         const Dimensions dimensions, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale)
-        : m_dimensions(dimensions)
     {
         switch (dimensions)
         {

+ 0 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/TranslationManipulators.h

@@ -99,8 +99,6 @@ namespace AzToolsFramework
         // Manipulators
         void ProcessManipulators(const AZStd::function<void(BaseManipulator*)>&) override;
 
-        const Dimensions m_dimensions; //!< How many dimensions of freedom does this manipulator have.
-
         AZStd::vector<AZStd::shared_ptr<LinearManipulator>> m_linearManipulators;
         AZStd::vector<AZStd::shared_ptr<PlanarManipulator>> m_planarManipulators;
         AZStd::shared_ptr<SurfaceManipulator> m_surfaceManipulator = nullptr;

+ 2 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/MetaUuidEntry.cpp

@@ -8,6 +8,8 @@
 
 #include <AzToolsFramework/Metadata/MetaUuidEntry.h>
 
+#include <AzCore/Serialization/SerializeContext.h>
+
 namespace AzToolsFramework
 {
     void AzToolsFramework::MetaUuidEntry::Reflect(AZ::ReflectContext* context)

+ 8 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/MetaUuidEntry.h

@@ -8,7 +8,14 @@
 
 #pragma once
 
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/std/containers/unordered_set.h>
+#include <AzCore/std/string/string.h>
+
+namespace AZ
+{
+    class ReflectContext;
+}
 
 namespace AzToolsFramework
 {

+ 4 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/Metadata/UuidUtils.h

@@ -10,8 +10,11 @@
 
 #include <AzCore/Component/Component.h>
 #include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
 namespace AzToolsFramework
 {
     struct IUuidUtil

+ 5 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsSystemComponent.h

@@ -9,11 +9,15 @@
 
 #include <AzCore/Component/Component.h>
 #include <AzCore/Component/Entity.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzToolsFramework/ActionManager/ActionManagerRegistrationNotificationBus.h>
 #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettings.h>
 #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsRequestBus.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace AzToolsFramework
 {
     //! GlobalPaintBrushSettingsSystemComponent owns the current global paintbrush settings for the Editor.

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <AzFramework/Entity/EntityContext.h>
 

+ 4 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h

@@ -8,8 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/std/string/string.h>
 
 #include <AzFramework/Entity/EntityContext.h>
 

+ 4 - 3
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h

@@ -8,9 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
+
 #include <AzCore/IO/Path/Path.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 #include <AzToolsFramework/Prefab/PrefabIdTypes.h>
 
 namespace AzToolsFramework
@@ -21,7 +22,7 @@ namespace AzToolsFramework
         {
             AskEveryTime,
             SaveAll,
-            SaveNone 
+            SaveNone
         };
 
         /*!

+ 3 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderScriptingBus.h

@@ -8,9 +8,10 @@
 
 #pragma once
 
-#include <AzCore/Interface/Interface.h>
 #include <AzCore/IO/Path/Path.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/std/string/string.h>
 #include <AzToolsFramework/Prefab/PrefabIdTypes.h>
 #include <AzCore/EBus/EBus.h>
 

+ 5 - 6
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h

@@ -11,7 +11,6 @@
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/Math/Vector3.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 #include <AzToolsFramework/Entity/EntityTypes.h>
 
@@ -98,7 +97,7 @@ namespace AzToolsFramework
              * Store the changes between the current entity state and its last cached state into undo/redo commands.
              * These changes are stored as patches to the owning prefab instance template, as appropriate.
              * The function also triggers the redo() of the nodes it creates, triggering propagation on the next tick.
-             * 
+             *
              * @param entityId The entity to patch.
              * @param parentUndoBatch The undo batch the undo nodes should be parented to.
              * @return Returns Success if the node was generated correctly, or an error message otherwise.
@@ -112,14 +111,14 @@ namespace AzToolsFramework
              * @return True if the entity is owned by a procedural prefab instance, false otherwise.
              */
             virtual bool IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const = 0;
-            
+
             /**
              * Detects if an entity is the container entity for its owning prefab instance.
              * @param entityId The entity to query.
              * @return True if the entity is the container entity for its owning prefab instance, false otherwise.
              */
             virtual bool IsInstanceContainerEntity(AZ::EntityId entityId) const = 0;
-            
+
             /**
              * Detects if an entity is the container entity for the level prefab instance.
              * @param entityId The entity to query.
@@ -141,7 +140,7 @@ namespace AzToolsFramework
              * @return The entity id of the instance container owning the queried entity.
              */
             virtual AZ::EntityId GetInstanceContainerEntityId(AZ::EntityId entityId) const = 0;
-            
+
             /**
              * Gets the entity id for the instance container of the level instance.
              * @return The entity id of the instance container for the currently loaded level.
@@ -181,7 +180,7 @@ namespace AzToolsFramework
             /**
               * If the entity id is a container entity id, detaches the prefab instance corresponding to it. This includes converting
               * the container entity into a regular entity and putting it under the parent prefab, removing the link between this
-              * instance and the parent, removing links between this instance and its nested instances, and adding entities directly 
+              * instance and the parent, removing links between this instance and its nested instances, and adding entities directly
               * owned by this instance under the parent instance.
               * Bails if the entity is not a container entity or belongs to the level prefab instance.
               * @param containerEntityId The container entity id of the instance to detach.

+ 1 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h

@@ -10,7 +10,6 @@
 
 #include <AzCore/Component/Component.h>
 #include <AzCore/Component/TickBus.h>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/containers/unordered_map.h>
 #include <AzCore/std/containers/unordered_set.h>
 #include <AzCore/std/containers/vector.h>
@@ -36,6 +35,7 @@ AZ_DECLARE_BUDGET(PrefabSystem);
 namespace AZ
 {
     class Entity;
+    class SerializeContext;
 } // namespace AZ
 
 namespace AzToolsFramework

+ 3 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/ScriptingPrefabLoader.h

@@ -11,6 +11,8 @@
 #include <Prefab/PrefabLoaderInterface.h>
 #include <Prefab/PrefabLoaderScriptingBus.h>
 
+#include <AzCore/Memory/SystemAllocator.h>
+
 namespace AzToolsFramework
 {
     namespace Prefab
@@ -27,7 +29,7 @@ namespace AzToolsFramework
 
             void Connect(PrefabLoaderInterface* prefabLoaderInterface);
             void Disconnect();
-            
+
         private:
 
             //////////////////////////////////////////////////////////////////////////

+ 3 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h

@@ -11,14 +11,15 @@
 #include <AzCore/base.h>
 #include <AzCore/Memory/SystemAllocator.h>
 #include <AzCore/Asset/AssetCommon.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 
 #include <QtCore/QString>
 
 namespace AZ
 {
     struct ClassDataReflection;
+    class ReflectContext;
 }
 
 class QMimeData;

+ 3 - 3
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ComponentMimeData.h

@@ -14,12 +14,12 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QTreeWidgetI
 #include <QTreeWidgetItem>
 AZ_POP_DISABLE_WARNING
 #include <AzCore/base.h>
-#include <AzCore/RTTI/RTTI.h>
 #include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/containers/vector.h>
 #include <AzCore/std/smart_ptr/unique_ptr.h>
-#include <AzCore/RTTI/ReflectContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
 
 class QMimeData;
 

+ 3 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorAssetMimeDataContainer.h

@@ -11,14 +11,15 @@
 #include <AzCore/base.h>
 #include <AzCore/Memory/SystemAllocator.h>
 #include <AzCore/Asset/AssetCommon.h>
-#include <AzCore/RTTI/RTTI.h>
-#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+#include <AzCore/RTTI/RTTIMacros.h>
 
 #include <QtCore/QString>
 
 namespace AZ
 {
     struct ClassDataReflection;
+    class ReflectContext;
 }
 
 class QMimeData;

+ 5 - 3
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h

@@ -8,12 +8,14 @@
 
 #pragma once
 
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
-#include <AzCore/Serialization/SerializeContext.h>
 #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
 #include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
 
+namespace AZ
+{
+    class ReflectContext;
+}
+
 namespace AzToolsFramework
 {
     namespace Components

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff