Browse Source

Added TypeIds header file which contains string literals of Uuids to the Project and Gem Templates (#15113)

* Added TypeIds header file which contains string literals of Uuids to the
Project and Gem Templates

Added an AZ_COMPONENT_BASE_DECL and AZ_COMPONENT_BASE_IMPL macros to
allow AZ::Component derived classes to define their `CreateDescriptor`
functions in a cpp file.

Updated the Project and Gem templates to move definitions of TypeInfo,
RTTI, Component Descriptors and Allocator methods to cpp files.

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

* Added Multiplayer Gem as a dependency of the UnifiedGem template gem

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

* Adding AZ_COMPONENT_DECL and AZ_COMPONENT_IMPL* macros

The AZ_COMPONENT_DECL macro combines the AzTypeInfo, Rtti, Component Descriptor and Allocator declaration macros
The AZ_COMPONENT_IMPL and AZ_COMPONENT_IMPL_INLINE macros cominbes the
AzTypeInfo, Rtti, Component Descriptor and Allocator implementation
macros.

As part of this change, the AZ_ALLOCATOR_IMPL macro was updated to
support template placeholder parameters which allows class templates to
use these macros as well.

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

* Updated the SystemComponents in the Project and Gem Templates to use the
`AZ_COMPONENT_DECL` and `AZ_COMPONENT_IMPL` macros

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

---------

Signed-off-by: lumberyard-employee-dm <[email protected]>
lumberyard-employee-dm 2 years ago
parent
commit
b16fb0aa4f
76 changed files with 981 additions and 294 deletions
  1. 174 1
      Code/Framework/AzCore/AzCore/Component/Component.h
  2. 81 53
      Code/Framework/AzCore/AzCore/Memory/Memory_fwd.h
  3. 41 43
      Code/Framework/AzCore/AzCore/RTTI/TemplateInfo.h
  4. 8 2
      Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h
  5. 78 0
      Code/Framework/AzCore/AzCore/variadic.h
  6. 40 0
      Code/Framework/AzCore/Tests/Components.cpp
  7. 1 1
      Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestVectorHandler.cpp
  8. 1 0
      Templates/CppToolGem/Template/Code/${NameLower}_api_files.cmake
  9. 1 0
      Templates/CppToolGem/Template/Code/${NameLower}_private_files.cmake
  10. 3 1
      Templates/CppToolGem/Template/Code/CMakeLists.txt
  11. 28 0
      Templates/CppToolGem/Template/Code/Include/${Name}/${Name}TypeIds.h
  12. 42 0
      Templates/CppToolGem/Template/Code/Source/${Name}ModuleInterface.cpp
  13. 8 20
      Templates/CppToolGem/Template/Code/Source/${Name}ModuleInterface.h
  14. 3 2
      Templates/CppToolGem/Template/Code/Source/Clients/${Name}Module.cpp
  15. 7 12
      Templates/CppToolGem/Template/Code/Source/Clients/${Name}SystemComponent.cpp
  16. 1 1
      Templates/CppToolGem/Template/Code/Source/Clients/${Name}SystemComponent.h
  17. 3 2
      Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorModule.cpp
  18. 5 0
      Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp
  19. 3 2
      Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h
  20. 8 0
      Templates/CppToolGem/template.json
  21. 3 1
      Templates/DefaultComponent/Template/Source/${Name}Component.cpp
  22. 1 1
      Templates/DefaultComponent/Template/Source/${Name}Component.h
  23. 1 0
      Templates/DefaultGem/Template/Code/${NameLower}_api_files.cmake
  24. 1 0
      Templates/DefaultGem/Template/Code/${NameLower}_private_files.cmake
  25. 3 1
      Templates/DefaultGem/Template/Code/CMakeLists.txt
  26. 4 2
      Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h
  27. 28 0
      Templates/DefaultGem/Template/Code/Include/${Name}/${Name}TypeIds.h
  28. 42 0
      Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.cpp
  29. 8 20
      Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.h
  30. 3 3
      Templates/DefaultGem/Template/Code/Source/Clients/${Name}Module.cpp
  31. 7 12
      Templates/DefaultGem/Template/Code/Source/Clients/${Name}SystemComponent.cpp
  32. 1 1
      Templates/DefaultGem/Template/Code/Source/Clients/${Name}SystemComponent.h
  33. 3 2
      Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorModule.cpp
  34. 5 0
      Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp
  35. 2 1
      Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h
  36. 8 0
      Templates/DefaultGem/template.json
  37. 1 0
      Templates/DefaultProject/Template/Gem/${NameLower}_files.cmake
  38. 3 1
      Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}Bus.h
  39. 23 0
      Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}TypeIds.h
  40. 4 2
      Templates/DefaultProject/Template/Gem/Source/${Name}Module.cpp
  41. 9 14
      Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.cpp
  42. 1 1
      Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.h
  43. 8 0
      Templates/DefaultProject/template.json
  44. 1 0
      Templates/MinimalProject/Template/Gem/${NameLower}_files.cmake
  45. 5 3
      Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}Bus.h
  46. 23 0
      Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}TypeIds.h
  47. 4 2
      Templates/MinimalProject/Template/Gem/Source/${Name}Module.cpp
  48. 12 19
      Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.cpp
  49. 1 1
      Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.h
  50. 8 0
      Templates/MinimalProject/template.json
  51. 5 1
      Templates/PythonToolGem/Template/CMakeLists.txt
  52. 1 0
      Templates/PythonToolGem/Template/Code/${NameLower}_editor_api_files.cmake
  53. 1 0
      Templates/PythonToolGem/Template/Code/${NameLower}_editor_private_files.cmake
  54. 4 2
      Templates/PythonToolGem/Template/Code/Include/${Name}/${Name}Bus.h
  55. 24 0
      Templates/PythonToolGem/Template/Code/Include/${Name}/${Name}TypeIds.h
  56. 32 0
      Templates/PythonToolGem/Template/Code/Source/${Name}ModuleInterface.cpp
  57. 8 11
      Templates/PythonToolGem/Template/Code/Source/${Name}ModuleInterface.h
  58. 3 2
      Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorModule.cpp
  59. 5 0
      Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp
  60. 4 3
      Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h
  61. 8 0
      Templates/PythonToolGem/template.json
  62. 1 0
      Templates/UnifiedMultiplayerGem/Template/Code/${NameLower}_api_files.cmake
  63. 1 0
      Templates/UnifiedMultiplayerGem/Template/Code/${NameLower}_private_files.cmake
  64. 4 2
      Templates/UnifiedMultiplayerGem/Template/Code/Include/${Name}/${Name}Bus.h
  65. 28 0
      Templates/UnifiedMultiplayerGem/Template/Code/Include/${Name}/${Name}TypeIds.h
  66. 42 0
      Templates/UnifiedMultiplayerGem/Template/Code/Source/${Name}ModuleInterface.cpp
  67. 8 20
      Templates/UnifiedMultiplayerGem/Template/Code/Source/${Name}ModuleInterface.h
  68. 3 2
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorModule.cpp
  69. 5 0
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp
  70. 2 1
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h
  71. 3 3
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}Module.cpp
  72. 7 12
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}SystemComponent.cpp
  73. 1 1
      Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}SystemComponent.h
  74. 7 1
      Templates/UnifiedMultiplayerGem/Template/gem.json
  75. 8 0
      Templates/UnifiedMultiplayerGem/template.json
  76. 7 6
      engine.json

+ 174 - 1
Code/Framework/AzCore/AzCore/Component/Component.h

@@ -284,6 +284,58 @@ namespace AZ
         return aznew DescriptorType; \
         return aznew DescriptorType; \
     }
     }
 
 
+    //! Declares the functions needed to make the component work with the Component Descriptor system
+    //! Does not provide any definitions, nor added AZ_CLASS_ALLOCATOR for the type
+    #define AZ_COMPONENT_BASE_DECL() \
+    template<class Comp, class Void> friend class AZ::HasComponentReflect; \
+    template<class Comp, class Void> friend class AZ::HasComponentProvidedServices; \
+    template<class Comp, class Void> friend class AZ::HasComponentDependentServices; \
+    template<class Comp, class Void> friend class AZ::HasComponentRequiredServices; \
+    template<class Comp, class Void> friend class AZ::HasComponentIncompatibleServices; \
+    static AZ::ComponentDescriptor* CreateDescriptor();
+
+    #define AZ_COMPONENT_BASE_IMPL_0(_ComponentClass, _Inline, _TemplateParamsParen) \
+    AZ_TYPE_INFO_SIMPLE_TEMPLATE_ID _TemplateParamsParen \
+    _Inline AZ::ComponentDescriptor* _ComponentClass AZ_TYPE_INFO_TEMPLATE_ARGUMENT_LIST _TemplateParamsParen ::CreateDescriptor() \
+    { \
+        static const char* s_typeName = _ComponentClass::RTTI_TypeName(); \
+        static const AZ::TypeId s_typeId = _ComponentClass::RTTI_Type(); \
+        AZ::ComponentDescriptor* descriptor = nullptr; \
+        AZ::ComponentDescriptorBus::EventResult(descriptor, s_typeId, &AZ::ComponentDescriptor::GetDescriptor); \
+        if (descriptor) \
+        { \
+            /* Compare strings first, then pointers. */ \
+            if (descriptor->GetName() != AZStd::string_view(s_typeName)) \
+            { \
+                AZ_Error("Component", false, "Two different components have the same UUID (%s), which is not allowed.\n" \
+                    "Change the UUID on one of them.\nComponent A: %s\nComponent B: %s", \
+                    s_typeId.ToFixedString().c_str(), descriptor->GetName(), s_typeName); \
+                return nullptr; \
+            } \
+            return descriptor; \
+        } \
+        return aznew DescriptorType; \
+    }
+
+    //! Implements the CreateDescriptor function
+    //! If the Component Class is a template, the variadic arguments
+    //! are AZ_TYPE_INFO_CLASS, AZ_TYPE_INFO_AUTO placeholder parameters
+    //! that can be used to create an out of line definition
+    #define AZ_COMPONENT_BASE_IMPL(_ComponentClass, ...) \
+        AZ_COMPONENT_BASE_IMPL_0( \
+            _ComponentClass,, \
+            AZ_WRAP(AZ_UNWRAP(__VA_ARGS__)) \
+        )
+
+    //! Implements the CreateDescriptor function with the `inline` keyword in front of the function signature
+    //! This is suitable for adding an implementation to an .inl or header file
+    #define AZ_COMPONENT_BASE_IMPL_INLINE(_ComponentClass, ...) \
+        AZ_COMPONENT_BASE_IMPL_0( \
+            _ComponentClass, \
+            inline, \
+            AZ_WRAP(AZ_UNWRAP(__VA_ARGS__)) \
+        )
+
     /**
     /**
      * Declares a descriptor class.
      * Declares a descriptor class.
      * Unless you are implementing very advanced internal functionality, we recommend using
      * Unless you are implementing very advanced internal functionality, we recommend using
@@ -294,7 +346,7 @@ namespace AZ
      */
      */
     #define AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(_ComponentClass)         \
     #define AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(_ComponentClass)         \
     friend class AZ::ComponentDescriptorDefault<_ComponentClass>;           \
     friend class AZ::ComponentDescriptorDefault<_ComponentClass>;           \
-    typedef AZ::ComponentDescriptorDefault<_ComponentClass> DescriptorType;
+    using DescriptorType = AZ::ComponentDescriptorDefault<_ComponentClass>;
 
 
     /**
     /**
      * Declares a component with the default settings.
      * Declares a component with the default settings.
@@ -317,6 +369,127 @@ namespace AZ
     AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(_ComponentClass)     \
     AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(_ComponentClass)     \
     AZ_COMPONENT_BASE(_ComponentClass, __VA_ARGS__)
     AZ_COMPONENT_BASE(_ComponentClass, __VA_ARGS__)
 
 
+    //! Declares the required AzTypeInfo(GetO3deTypeName and GetO3deTypeId),
+    //! RTTI (RTTI_TypeName and RTTI_Type),
+    //! static placement allocator functions(operator new and operator delete)
+    //! and Component Descriptor functions (CreateDescriptor).
+    //! This macro does not provide any definitions for those functions
+    //! and it's primary use is to avoid function definitions and include dependencies
+    //! that are needed in a header to reduce compilation time
+    #define AZ_COMPONENT_DECL(_ComponentClass) \
+    AZ_TYPE_INFO_WITH_NAME_DECL(_ComponentClass) \
+    AZ_RTTI_NO_TYPE_INFO_DECL() \
+    AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(AZ_USE_FIRST_ARG(AZ_UNWRAP(_ComponentClass))) \
+    AZ_COMPONENT_BASE_DECL() \
+    AZ_CLASS_ALLOCATOR_DECL
+
+    // Helper macro for allowing expansion of macro parameters
+    // in the second pass over the AZ_COMPONENT_IMPL when making a call
+    // The reason these macros are needed, is to avoid recursively invoking
+    // the same call helper macro.
+    // During second pass over a macro the preprocessor suppresses expansion of the token it processing
+    // So if there are two macros called
+    // #define FOO() AZ_MACRO_CALL(AZ_JOIN(BAR, _1))
+    // #define BAR_1() "7"
+    // Then using the AZ_MACRO_CALL macro to call the FOO macro
+    // such as `AZ_MACRO_CALL(FOO)` would not expand the inner call to `AZ_MACRO_CALL(AZ_JOIN(BAR, _1))`
+    #define AZ_COMPONENT_MACRO_CALL_II(macro, ...) macro(__VA_ARGS__)
+    #define AZ_COMPONENT_MACRO_CALL_I(macro, ...) AZ_COMPONENT_MACRO_CALL_II(macro, __VA_ARGS__)
+    #define AZ_COMPONENT_MACRO_CALL(macro, ...) AZ_COMPONENT_MACRO_CALL_I(macro, __VA_ARGS__)
+
+    //! Implements the the required definitions
+    //! needed for AzTypeInfo, RTTI, Allocator opt-in and
+    //! Component Descriptor creation
+    //! This macro pairs with the AZ_COMPONENT_DECL macro.
+    //! It is suitable for used in a cpp file within the same namespace
+    //! where the component class was created
+    //! @param _ComponentClassOrTemplate The C++ identifier associated with the component class
+    //! NOTES: The first argument should be either the class name for a regular class or when specifying the arguments for a class template
+    //! the simple-template-name  with no angle brackets(i.e `ComponentTemplate`, not `ComponentTemplate<T>`)
+    //! inside of an inner set of parenthesis, followed by 0 or template placeholder arguments
+    //! ex. class `class EditorInspectorComponent`
+    //!     -> `AZ_COMPONENT_IMPL(EditorInspectorComponent, ...)`
+    //! ex. class template `template<class, class, class> class EditorComponentAdapter`
+    //!    -> `AZ_COMPONENT_IMPL_INLINE((EditorComponentAdapter, AZ_CLASS, AZ_CLASS, AZ_CLASS), ...);
+    //! @param _DisplayName cstring which is used by AzTypeInfo as the TypeName for lookups
+    //! @param _Uuid unique identifier associated with AzTypeInfo and pairs with the _DisplayName
+    //! @param __VA_ARGS__ optional parameters used for specifying the base class of the component
+    //!        This is only used for RTTI to allow conversions from base pointer to derived types
+    //!        using azrtti_typeof and azrtti_cast
+    //!
+    //! The following is examples illustrate how to use the macro for a regular component class
+    //! ```
+    //! class TestToolGemSystemComponent : public BaseSystemComponent {};
+    //!  //... Later in a cpp file
+    //! AZ_COMPONENT_IMPL(TestToolGemSystemComponent, "TestToolGemSystemComponent", TestToolGemSystemComponentTypeId, BaseSystemComponent)
+    //! ```
+    //! Macro call breakdown:
+    //! 1. `AZ_TYPE_INFO_WITH_NAME_IMPL`: The call to `AZ_TYPE_INFO_WITH_NAME_IMPL` expects the template placeholder arguments to be passed as variadic arguments
+    //! while the simple template name is passed as the first parameter.
+    //! So the `_ComponentClassOrTemplate` has the first argument queried from it if it was wrapped in parenthesis
+    //! If `_ComponentClassOrTemplate` isn't wrapped in parenthesis it is returned as is
+    //! Any template arguments are supplied after the `_Uuid` argument via using the `AZ_INTERNAL_SKIP_FIRST` macro
+    //! combined with the AZ_VA_OPT to optionally add a comma after the `_Uuid` argument if there are any template parameters
+    //!
+    //! 2. `AZ_RTTI_NO_TYPE_INFO_IMPL`: The call to `AZ_RTTI_NO_TYPE_INFO_IMPL` expects the template placeholder arguments
+    //! to be wrapped in parenthesis along with the simple template name in the first argument.
+    //! Therefore no special processing needs to be done for it here, as the `AZ_RTTI_NO_TYPE_INFO_IMPL` will split out the
+    //! template placeholder arguments
+    //!
+    //! 3. `AZ_COMPONENT_BASE_IMPL`: The call to `AZ_COMPONENT_BASE_IMPL` requires the template placeholder arguments to be supplied as variadic args,
+    //! with the simple template name as the first parameter.
+    //! It goes through the same transformation as the `AZ_TYPE_INFO_WITH_NAME_IMPL` macro to split out the template name
+    //! from the template placholder parameters via parenthesis unwrapping and using the `AZ_INTERNAL_USE_FIRST_ELEMENT` and `AZ_INTERNAL_SKIP_FIRST`
+    //! macros
+    //!
+    //! 4. `AZ_CLASS_ALLOCATOR_IMPL`: The call to `AZ_CLASS_ALLOCATOR_IMPL` requires template placeholder argument
+    //! to be wrapped in parenthesis with the simple template name as the entire first argument
+    //! This is the same way wrapping that is needed for the `AZ_RTTI_NO_TYPE_INFO_IMPL` macro when supplying a template class
+    //!
+    //! Next is an example of using the macro with a template class
+    //! ```
+    //! template<class T, class U, size_t N>
+    //! class TestTemplateGemSystemComponent : public BaseSystemComponent {};
+    //!  //... Later in a cpp file
+    //! AZ_COMPONENT_IMPL_INLINE((TestTemplateGemSystemComponent, AZ_CLASS, AZ_CLASS, AZ_AUTO),
+    //!     "TestTemplateGemSystemComponent", TestTemplateGemSystemComponentTypeId, BaseSystemComponent)
+    //! ```
+    //! The `AZ_CLASS` is a placeholder macro that is used to substitute `class` template parameters
+    //! For non-type template parameters such as `size_t` or `int` the `AZ_AUTO` placeholder can be used
+    #define AZ_COMPONENT_IMPL(_ComponentClassOrTemplate, _DisplayName, _Uuid, ...) \
+    AZ_COMPONENT_MACRO_CALL(AZ_TYPE_INFO_WITH_NAME_IMPL, \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)), \
+        _DisplayName, \
+        _Uuid \
+        AZ_VA_OPT(AZ_COMMA_SEPARATOR, AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate))) \
+        AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+    ) \
+    AZ_RTTI_NO_TYPE_INFO_IMPL(_ComponentClassOrTemplate, __VA_ARGS__) \
+    AZ_COMPONENT_MACRO_CALL(AZ_COMPONENT_BASE_IMPL, \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+        AZ_VA_OPT(AZ_COMMA_SEPARATOR, AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate))) \
+        AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+    ) \
+    AZ_CLASS_ALLOCATOR_IMPL(_ComponentClassOrTemplate, AZ::SystemAllocator)
+
+    //! Version of the AZ_COMPONENT_IMPL macro which can be used in a header or inline file
+    //! which is included in multiple translation units
+    #define AZ_COMPONENT_IMPL_INLINE(_ComponentClassOrTemplate, _DisplayName, _Uuid, ...) \
+    AZ_COMPONENT_MACRO_CALL(AZ_TYPE_INFO_WITH_NAME_IMPL_INLINE, \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)), \
+        _DisplayName, \
+        _Uuid \
+        AZ_VA_OPT(AZ_COMMA_SEPARATOR, AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate))) \
+        AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+    ) \
+    AZ_RTTI_NO_TYPE_INFO_IMPL_INLINE(_ComponentClassOrTemplate, __VA_ARGS__) \
+    AZ_COMPONENT_MACRO_CALL(AZ_COMPONENT_BASE_IMPL_INLINE, \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+        AZ_VA_OPT(AZ_COMMA_SEPARATOR, AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate))) \
+        AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ComponentClassOrTemplate)) \
+    ) \
+    AZ_CLASS_ALLOCATOR_IMPL_INLINE(_ComponentClassOrTemplate, AZ::SystemAllocator)
+
     /**
     /**
      * Provides an interface through which the system can get the details of a component
      * Provides an interface through which the system can get the details of a component
      * and reflect the component data to a variety of contexts.
      * and reflect the component data to a variety of contexts.

+ 81 - 53
Code/Framework/AzCore/AzCore/Memory/Memory_fwd.h

@@ -236,62 +236,90 @@
 
 
 #if __cpp_aligned_new
 #if __cpp_aligned_new
 // Defines the C++17 aligned_new operator new/operator delete overloads
 // 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!");                                                                         \
+#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs) \
+     AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders  \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::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)); \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::operator new(std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept { \
+        return operator new(size, align); \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::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; \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t&) noexcept { \
+        return operator new[](size, align); \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::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)); } \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::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
 #else
-#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _Template)
+#define _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs)
 #endif
 #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<>)
+#define AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs) \
+    /* ========== standard operator new/delete ========== */ \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::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 )); \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::operator delete(void* p, std::size_t size) { \
+        if (p) { AZ::AllocatorInstance< _Allocator >::Get().deallocate(p, size, alignof( _Class )); } \
+    } \
+    /* ========== AZ_CLASS_ALLOCATOR API ========== */ \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void* _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::AZ_CLASS_ALLOCATOR_Allocate() { \
+        return AZ::AllocatorInstance< _Allocator >::Get().allocate(sizeof(_Class), alignof( _Class )); \
+    } \
+    AZ_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
+    _FuncSpecs void _Class AZ_TEMPLATE_ARGUMENT_LIST _TemplatePlaceholders ::AZ_CLASS_ALLOCATOR_DeAllocate(void* object) { \
+        AZ::AllocatorInstance< _Allocator >::Get().deallocate(object, sizeof(_Class), alignof( _Class )); \
+    } \
+    _AZ_CLASS_ALLOCATOR_IMPL_ALIGNED_NEW(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs)
+
+#define AZ_CLASS_ALLOCATOR_IMPL_INTERNAL_HELPER(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs) \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(_Class, _Allocator, _TemplatePlaceholders, _FuncSpecs)
+
+#define AZ_CLASS_ALLOCATOR_IMPL(_Class, _Allocator, ...) \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL( \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_Class)), \
+        _Allocator, \
+        AZ_WRAP(AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_Class))), \
+        ) \
+
+#define AZ_CLASS_ALLOCATOR_IMPL_TEMPLATE(_Class, _Allocator, ...) \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL( \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_Class)), \
+        _Allocator, \
+        AZ_WRAP(AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_Class))),\
+        template<>) \
+
+//! This performs the same transformation as the AZ_CLASS_ALLOCATOR_IMPL macro
+//! with the addition that it adds the function specifier of `inline` in front
+//! of each function definition
+//! This macro is suitable for use with template classes member definitions in header or .inl files
+#define AZ_CLASS_ALLOCATOR_IMPL_INLINE(_Class, _Allocator) \
+    AZ_CLASS_ALLOCATOR_IMPL_INTERNAL( \
+        AZ_USE_FIRST_ARG(AZ_UNWRAP(_Class)), \
+        _Allocator, \
+        AZ_WRAP(AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_Class))), \
+        inline) \
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 // new operator overloads
 // new operator overloads

+ 41 - 43
Code/Framework/AzCore/AzCore/RTTI/TemplateInfo.h

@@ -72,7 +72,7 @@ namespace AZ::AzGenericTypeInfo::Internal
     //! MSVC has the both overloaded functions as ambiguous
     //! MSVC has the both overloaded functions as ambiguous
     //!
     //!
     //! One particular case is AZStd::basic_fixed_string
     //! One particular case is AZStd::basic_fixed_string
-    //! It is template parmeters are
+    //! It is template parameters are
     //! `<class Element, size_t MaxElementCount, class Traits = char_traits<Element>>`
     //! `<class Element, size_t MaxElementCount, class Traits = char_traits<Element>>`
     //!
     //!
     //! The way to avoid the is to make sure that none of the template template parameters
     //! The way to avoid the is to make sure that none of the template template parameters
@@ -176,33 +176,31 @@ namespace AZ::AzGenericTypeInfo
     }
     }
 }
 }
 
 
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME__TYPE typename
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME__ARG(A) A
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME__UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME__NAME(A) AZ::Internal::GetTypeName< A >()
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_TYPE typename
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_ARG(A) A
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_NAME(A) AZ::Internal::GetTypeName< A >()
 
 
-#define AZ_TYPE_INFO_INTERNAL_CLASS__TYPE class
-#define AZ_TYPE_INFO_INTERNAL_CLASS__ARG(A) A
-#define AZ_TYPE_INFO_INTERNAL_CLASS__UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
-#define AZ_TYPE_INFO_INTERNAL_CLASS__NAME(A) AZ::Internal::GetTypeName< A >()
+#define AZ_TYPE_INFO_INTERNAL_CLASS_TYPE class
+#define AZ_TYPE_INFO_INTERNAL_CLASS_ARG(A) A
+#define AZ_TYPE_INFO_INTERNAL_CLASS_UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
+#define AZ_TYPE_INFO_INTERNAL_CLASS_NAME(A) AZ::Internal::GetTypeName< A >()
 
 
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS__TYPE typename...
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS__ARG(A) A...
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS__UUID(A) AZ::Internal::AggregateTypes< A... >::GetCanonicalTypeId()
-#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS__NAME(A) AZ::Internal::AggregateTypes< A... >::TypeName()
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS_TYPE typename...
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS_ARG(A) A...
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS_UUID(A) AZ::Internal::AggregateTypes< A... >::GetCanonicalTypeId()
+#define AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS_NAME(A) AZ::Internal::AggregateTypes< A... >::TypeName()
 
 
-#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS__TYPE class...
-#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS__ARG(A) A...
-#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS__UUID(A) AZ::Internal::AggregateTypes< A... >::GetCanonicalTypeId()
-#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS__NAME(A) AZ::Internal::AggregateTypes< A... >::TypeName()
+#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS_TYPE class...
+#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS_ARG(A) A...
+#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS_UUID(A) AZ::Internal::AggregateTypes< A... >::GetCanonicalTypeId()
+#define AZ_TYPE_INFO_INTERNAL_CLASS_VARARGS_NAME(A) AZ::Internal::AggregateTypes< A... >::TypeName()
 
 
-#define AZ_TYPE_INFO_INTERNAL_AUTO__TYPE auto
-#define AZ_TYPE_INFO_INTERNAL_AUTO__ARG(A) A
-#define AZ_TYPE_INFO_INTERNAL_AUTO__UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
-#define AZ_TYPE_INFO_INTERNAL_AUTO__NAME(A) AZ::Internal::GetTypeName< A >()
+#define AZ_TYPE_INFO_INTERNAL_AUTO_TYPE auto
+#define AZ_TYPE_INFO_INTERNAL_AUTO_ARG(A) A
+#define AZ_TYPE_INFO_INTERNAL_AUTO_UUID(A) AZ::Internal::GetCanonicalTypeId< A >()
+#define AZ_TYPE_INFO_INTERNAL_AUTO_NAME(A) AZ::Internal::GetTypeName< A >()
 
 
-#define AZ_TYPE_INFO_INTERNAL_EXPAND_I(NAME, TARGET)     NAME##__##TARGET
-#define AZ_TYPE_INFO_INTERNAL_EXPAND(NAME, TARGET)       AZ_TYPE_INFO_INTERNAL_EXPAND_I(NAME, TARGET)
 
 
 // NOTE: This the same macro logic as the `AZ_MACRO_SPECIALIZE`, but it must used instead of
 // NOTE: This the same macro logic as the `AZ_MACRO_SPECIALIZE`, but it must used instead of
 // `AZ_MACRO_SPECIALIZE` macro as the C preprocessor macro expansion will not expand a macro with the same
 // `AZ_MACRO_SPECIALIZE` macro as the C preprocessor macro expansion will not expand a macro with the same
@@ -225,32 +223,32 @@ namespace AZ::AzGenericTypeInfo
 #   define AZ_TYPE_INFO_INTERNAL_MACRO_CALL_I(MACRO_NAME, NPARAMS, PARAMS)     AZ_TYPE_INFO_INTERNAL_MACRO_CALL_II(MACRO_NAME, NPARAMS, PARAMS)
 #   define AZ_TYPE_INFO_INTERNAL_MACRO_CALL_I(MACRO_NAME, NPARAMS, PARAMS)     AZ_TYPE_INFO_INTERNAL_MACRO_CALL_II(MACRO_NAME, NPARAMS, PARAMS)
 #   define AZ_TYPE_INFO_INTERNAL_MACRO_CALL(MACRO_NAME, NPARAMS, PARAMS)       AZ_TYPE_INFO_INTERNAL_MACRO_CALL_I(MACRO_NAME, NPARAMS, PARAMS)
 #   define AZ_TYPE_INFO_INTERNAL_MACRO_CALL(MACRO_NAME, NPARAMS, PARAMS)       AZ_TYPE_INFO_INTERNAL_MACRO_CALL_I(MACRO_NAME, NPARAMS, PARAMS)
 
 
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_1(_1)                                                                                  AZ_TYPE_INFO_INTERNAL_EXPAND(_1, TYPE) T1
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_1(_1),             AZ_TYPE_INFO_INTERNAL_EXPAND(_2, TYPE) T2
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_2(_1, _2),         AZ_TYPE_INFO_INTERNAL_EXPAND(_3, TYPE) T3
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3),     AZ_TYPE_INFO_INTERNAL_EXPAND(_4, TYPE) T4
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4), AZ_TYPE_INFO_INTERNAL_EXPAND(_5, TYPE) T5
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_1(_1)                                                                                  AZ_JOIN(_1, _TYPE) T1
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_1(_1),             AZ_JOIN(_2, _TYPE) T2
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_2(_1, _2),         AZ_JOIN(_3, _TYPE) T3
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3),     AZ_JOIN(_4, _TYPE) T4
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4), AZ_JOIN(_5, _TYPE) T5
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_TYPE_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 
 
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_1(_1)                                                                                      AZ_TYPE_INFO_INTERNAL_EXPAND(_1, ARG)(T1)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_1(_1),             AZ_TYPE_INFO_INTERNAL_EXPAND(_2, ARG)(T2)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2),         AZ_TYPE_INFO_INTERNAL_EXPAND(_3, ARG)(T3)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3),     AZ_TYPE_INFO_INTERNAL_EXPAND(_4, ARG)(T4)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4), AZ_TYPE_INFO_INTERNAL_EXPAND(_5, ARG)(T5)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_1(_1)                                                                                      AZ_JOIN(_1, _ARG)(T1)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_1(_1),             AZ_JOIN(_2, _ARG)(T2)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2),         AZ_JOIN(_3, _ARG)(T3)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3),     AZ_JOIN(_4, _ARG)(T4)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4), AZ_JOIN(_5, _ARG)(T5)
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_ARGUMENT_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 
 
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_1(_1)                                                                                  AZ_TYPE_INFO_INTERNAL_EXPAND(_1, NAME)(T1)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_1(_1),             AZ_TYPE_INFO_INTERNAL_EXPAND(_2, NAME)(T2)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_2(_1, _2),         AZ_TYPE_INFO_INTERNAL_EXPAND(_3, NAME)(T3)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_3(_1, _2, _3),     AZ_TYPE_INFO_INTERNAL_EXPAND(_4, NAME)(T4)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_4(_1, _2, _3, _4), AZ_TYPE_INFO_INTERNAL_EXPAND(_5, NAME)(T5)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_1(_1)                                                                                  AZ_JOIN(_1, _NAME)(T1)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_2(_1, _2)             AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_1(_1),             AZ_JOIN(_2, _NAME)(T2)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_3(_1, _2, _3)         AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_2(_1, _2),         AZ_JOIN(_3, _NAME)(T3)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_4(_1, _2, _3, _4)     AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_3(_1, _2, _3),     AZ_JOIN(_4, _NAME)(T4)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_4(_1, _2, _3, _4), AZ_JOIN(_5, _NAME)(T5)
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_NAME_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 
 
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_1(_1)                                                                                    AZ_TYPE_INFO_INTERNAL_EXPAND(_1, UUID)(T1)
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_2(_1, _2)             (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_1(_1) +             AZ_TYPE_INFO_INTERNAL_EXPAND(_2, UUID)(T2))
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_3(_1, _2, _3)         (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_2(_1, _2) +         AZ_TYPE_INFO_INTERNAL_EXPAND(_3, UUID)(T3))
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_4(_1, _2, _3, _4)     (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_3(_1, _2, _3) +     AZ_TYPE_INFO_INTERNAL_EXPAND(_4, UUID)(T4))
-#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_5(_1, _2, _3, _4, _5) (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_4(_1, _2, _3, _4) + AZ_TYPE_INFO_INTERNAL_EXPAND(_5, UUID)(T5))
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_1(_1)                                                                                    AZ_JOIN(_1, _UUID)(T1)
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_2(_1, _2)             (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_1(_1) +             AZ_JOIN(_2, _UUID)(T2))
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_3(_1, _2, _3)         (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_2(_1, _2) +         AZ_JOIN(_3, _UUID)(T3))
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_4(_1, _2, _3, _4)     (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_3(_1, _2, _3) +     AZ_JOIN(_4, _UUID)(T4))
+#define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_5(_1, _2, _3, _4, _5) (AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_4(_1, _2, _3, _4) + AZ_JOIN(_5, _UUID)(T5))
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 #define AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION(...) AZ_TYPE_INFO_INTERNAL_MACRO_CALL(AZ_TYPE_INFO_INTERNAL_TEMPLATE_UUID_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
 
 
 
 

+ 8 - 2
Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h

@@ -602,14 +602,20 @@ namespace AZ
 // This pairs with the AZ_TYPE_INFO_WITH_NAME_IMPL/AZ_TYPE_INFO_WITH_NAME_IMPL_INLINE where an implemenation can be provided
 // This pairs with the AZ_TYPE_INFO_WITH_NAME_IMPL/AZ_TYPE_INFO_WITH_NAME_IMPL_INLINE where an implemenation can be provided
 // in a translation unit(.cpp) or a an inline(.inl) file in order to help reduce compile times
 // in a translation unit(.cpp) or a an inline(.inl) file in order to help reduce compile times
 // https://godbolt.org/z/EGPvKr7xM
 // https://godbolt.org/z/EGPvKr7xM
-#define AZ_TYPE_INFO_WITH_NAME_DECL(_ClassName) \
+#define AZ_TYPE_INFO_WITH_NAME_DECL_HELPER(_ClassName, _TemplatePlaceholders) \
+    AZ_TYPE_INFO_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
     friend AZ::TypeNameString GetO3deTypeName(AZ::Adl, AZStd::type_identity<_ClassName>); \
     friend AZ::TypeNameString GetO3deTypeName(AZ::Adl, AZStd::type_identity<_ClassName>); \
+    AZ_TYPE_INFO_SIMPLE_TEMPLATE_ID _TemplatePlaceholders \
     friend AZ::TypeId GetO3deTypeId(AZ::Adl,AZStd::type_identity<_ClassName>); \
     friend AZ::TypeId GetO3deTypeId(AZ::Adl,AZStd::type_identity<_ClassName>); \
     static const char* TYPEINFO_Name(); \
     static const char* TYPEINFO_Name(); \
     static AZ::TypeId TYPEINFO_Uuid();
     static AZ::TypeId TYPEINFO_Uuid();
 
 
+#define AZ_TYPE_INFO_WITH_NAME_DECL(_ClassNameOrTemplateName) \
+    AZ_TYPE_INFO_WITH_NAME_DECL_HELPER(AZ_USE_FIRST_ARG(AZ_UNWRAP(_ClassNameOrTemplateName)), \
+    AZ_WRAP(AZ_SKIP_FIRST_ARG(AZ_UNWRAP(_ClassNameOrTemplateName))) )
 
 
-// Repeat of AZ_TYPE_INFO_MACRO_CALL with a different name oo allow
+
+// Repeat of AZ_TYPE_INFO_MACRO_CALL with a different name to allow
 // calling a macro if inside of an expansion of a current AZ_TYPE_INFO_MACRO_CALL call
 // calling a macro if inside of an expansion of a current AZ_TYPE_INFO_MACRO_CALL call
 #define AZ_TYPE_INFO_MACRO_CALL_NEW_II(MACRO_NAME, NPARAMS, PARAMS)    MACRO_NAME##NPARAMS PARAMS
 #define AZ_TYPE_INFO_MACRO_CALL_NEW_II(MACRO_NAME, NPARAMS, PARAMS)    MACRO_NAME##NPARAMS PARAMS
 #define AZ_TYPE_INFO_MACRO_CALL_NEW_I(MACRO_NAME, NPARAMS, PARAMS)     AZ_TYPE_INFO_MACRO_CALL_NEW_II(MACRO_NAME, NPARAMS, PARAMS)
 #define AZ_TYPE_INFO_MACRO_CALL_NEW_I(MACRO_NAME, NPARAMS, PARAMS)     AZ_TYPE_INFO_MACRO_CALL_NEW_II(MACRO_NAME, NPARAMS, PARAMS)

+ 78 - 0
Code/Framework/AzCore/AzCore/variadic.h

@@ -454,7 +454,13 @@ static_assert(AZ_VA_NUM_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
 #define AZ_WRAP_I(...) (__VA_ARGS__)
 #define AZ_WRAP_I(...) (__VA_ARGS__)
 #define AZ_WRAP(...) AZ_WRAP_I(__VA_ARGS__)
 #define AZ_WRAP(...) AZ_WRAP_I(__VA_ARGS__)
 
 
+// Extracts the first argument from a list of variadic arguments
+#define AZ_USE_FIRST_ARG_1(_1, ...) _1
+#define AZ_USE_FIRST_ARG(...) AZ_USE_FIRST_ARG_1(__VA_ARGS__)
 
 
+// Removes the first arguments from a list of variardic arguments
+#define AZ_SKIP_FIRST_ARG_I(_1, ...)  __VA_ARGS__
+#define AZ_SKIP_FIRST_ARG(...) AZ_SKIP_FIRST_ARG_I(__VA_ARGS__)
 
 
 // Provides a level of indirection for a macro function like call to allow expansion to occur
 // Provides a level of indirection for a macro function like call to allow expansion to occur
 // This will invoke the macro in the second pass over the macro arguments
 // This will invoke the macro in the second pass over the macro arguments
@@ -467,3 +473,75 @@ static_assert(AZ_VA_NUM_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
 #define AZ_MACRO_CALL_FIRST_PASS(macro, ...) macro(__VA_ARGS__)
 #define AZ_MACRO_CALL_FIRST_PASS(macro, ...) macro(__VA_ARGS__)
 #define AZ_MACRO_CALL_INDEX(prefix, ...) AZ_MACRO_CALL(AZ_JOIN(prefix, AZ_VA_NUM_ARGS(AZ_UNWRAP(__VA_ARGS__))), AZ_UNWRAP(__VA_ARGS__))
 #define AZ_MACRO_CALL_INDEX(prefix, ...) AZ_MACRO_CALL(AZ_JOIN(prefix, AZ_VA_NUM_ARGS(AZ_UNWRAP(__VA_ARGS__))), AZ_UNWRAP(__VA_ARGS__))
 #define AZ_MACRO_CALL_WRAP(macro, ...)  AZ_MACRO_CALL(macro, __VA_ARGS__)
 #define AZ_MACRO_CALL_WRAP(macro, ...)  AZ_MACRO_CALL(macro, __VA_ARGS__)
+
+
+// Provides macro call expansion solely for the AZ_SIMPLE_TEMPLATE_ID_<N> and AZ_TEMPLATE_ARGUMENT_LIST_<N> macros below
+#define AZ_TEMPLATE_MACRO_CALL_II(macro, nparams, params) macro##nparams params
+#define AZ_TEMPLATE_MACRO_CALL_I(macro, nparams, params) AZ_TEMPLATE_MACRO_CALL_II(macro, nparams, params)
+#define AZ_TEMPLATE_MACRO_CALL(macro, nparams, params) AZ_TEMPLATE_MACRO_CALL_I(macro, nparams, params)
+
+#define AZ_TEMPLATE_MACRO_EXPANSION_CALL_II(macro, nparams, params) macro##nparams params
+#define AZ_TEMPLATE_MACRO_EXPANSION_CALL_I(macro, nparams, params) AZ_TEMPLATE_MACRO_EXPANSION_CALL_II(macro, nparams, params)
+#define AZ_TEMPLATE_MACRO_EXPANSION_CALL(macro, nparams, params) AZ_TEMPLATE_MACRO_EXPANSION_CALL_I(macro, nparams, params)
+
+#define AZ_CLASS_TYPE class
+#define AZ_CLASS_ARG(A) A
+
+#define AZ_CLASS_VARARGS_TYPE class...
+#define AZ_CLASS_VARARGS_ARG(A) A...
+
+#define AZ_AUTO_TYPE auto
+#define AZ_AUTO_ARG(A) A
+
+#define AZ_TEMPLATE_TYPE_EXPANSION_0(_1)
+#define AZ_TEMPLATE_TYPE_EXPANSION_1(_1) AZ_JOIN(_1, _TYPE) T1
+#define AZ_TEMPLATE_TYPE_EXPANSION_2(_1, _2) AZ_TEMPLATE_TYPE_EXPANSION_1(_1),             AZ_JOIN(_2, _TYPE) T2
+#define AZ_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3) AZ_TEMPLATE_TYPE_EXPANSION_2(_1, _2),         AZ_JOIN(_3, _TYPE) T3
+#define AZ_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4) AZ_TEMPLATE_TYPE_EXPANSION_3(_1, _2, _3),     AZ_JOIN(_4, _TYPE) T4
+#define AZ_TEMPLATE_TYPE_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TEMPLATE_TYPE_EXPANSION_4(_1, _2, _3, _4), AZ_JOIN(_5, _TYPE) T5
+#define AZ_TEMPLATE_TYPE_EXPANSION(...) AZ_TEMPLATE_MACRO_EXPANSION_CALL(AZ_TEMPLATE_TYPE_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_0(_1)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_1(_1) AZ_JOIN(_1, _ARG)(T1)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2) AZ_TEMPLATE_ARGUMENT_EXPANSION_1(_1),             AZ_JOIN(_2, _ARG)(T2)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3) AZ_TEMPLATE_ARGUMENT_EXPANSION_2(_1, _2),         AZ_JOIN(_3, _ARG)(T3)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4) AZ_TEMPLATE_ARGUMENT_EXPANSION_3(_1, _2, _3),     AZ_JOIN(_4, _ARG)(T4)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION_5(_1, _2, _3, _4, _5) AZ_TEMPLATE_ARGUMENT_EXPANSION_4(_1, _2, _3, _4), AZ_JOIN(_5, _ARG)(T5)
+#define AZ_TEMPLATE_ARGUMENT_EXPANSION(...) AZ_TEMPLATE_MACRO_EXPANSION_CALL(AZ_TEMPLATE_ARGUMENT_EXPANSION_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+#define AZ_SIMPLE_TEMPLATE_ID_0(...)
+#define AZ_SIMPLE_TEMPLATE_ID_1(...) template< AZ_TEMPLATE_TYPE_EXPANSION(__VA_ARGS__) >
+#define AZ_SIMPLE_TEMPLATE_ID_2(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_3(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_4(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_5(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_6(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_7(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_8(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_9(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_10(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_11(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_12(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_13(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_14(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID_15(...) AZ_SIMPLE_TEMPLATE_ID_1(__VA_ARGS__)
+#define AZ_SIMPLE_TEMPLATE_ID(...) AZ_TEMPLATE_MACRO_CALL(AZ_SIMPLE_TEMPLATE_ID_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
+
+
+#define AZ_TEMPLATE_ARGUMENT_LIST_0(...)
+#define AZ_TEMPLATE_ARGUMENT_LIST_1(...) < AZ_TEMPLATE_ARGUMENT_EXPANSION(__VA_ARGS__) >
+#define AZ_TEMPLATE_ARGUMENT_LIST_2(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_3(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_4(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_5(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_6(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_7(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_8(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_9(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_10(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_11(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_12(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_13(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_14(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST_15(...) AZ_TEMPLATE_ARGUMENT_LIST_1(__VA_ARGS__)
+#define AZ_TEMPLATE_ARGUMENT_LIST(...) AZ_TEMPLATE_MACRO_CALL(AZ_TEMPLATE_ARGUMENT_LIST_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))

+ 40 - 0
Code/Framework/AzCore/Tests/Components.cpp

@@ -1948,7 +1948,47 @@ namespace UnitTest
         EXPECT_EQ(dependencyList[1], AZ_CRC("AnotherService"));
         EXPECT_EQ(dependencyList[1], AZ_CRC("AnotherService"));
         EXPECT_EQ(dependencyList[2], AZ_CRC("SomeService"));
         EXPECT_EQ(dependencyList[2], AZ_CRC("SomeService"));
         EXPECT_EQ(dependencyList[3], AZ_CRC("YetAnotherService"));
         EXPECT_EQ(dependencyList[3], AZ_CRC("YetAnotherService"));
+    }
+
+    class ComponentDeclImpl
+        : public AZ::Component
+    {
+    public:
+        AZ_COMPONENT_DECL(ComponentDeclImpl);
+        void Activate() override {}
+        void Deactivate() override {}
+
+        static void Reflect(AZ::ReflectContext*) {}
+    };
+
+    AZ_COMPONENT_IMPL(ComponentDeclImpl, "ComponentDeclImpl", "{8E5C2D28-8A6D-402E-8018-5AEC828CC3B1}");
+
+    template<class T, class U>
+    class TemplateComponent
+        : public ComponentDeclImpl
+    {
+    public:
+        AZ_COMPONENT_DECL((TemplateComponent, AZ_CLASS, AZ_CLASS));
+    };
+
+    AZ_COMPONENT_IMPL_INLINE((TemplateComponent, AZ_CLASS, AZ_CLASS), "TemplateComponent", "{E8B62C59-CAAC-466C-A583-4FCAABC399E6}", ComponentDeclImpl);
+
+    TEST_F(Components, ComponentDecl_ComponentImpl_Macros_ProvidesCompleteComponentDescriptor_Succeeds)
+    {
+        {
+            auto componentDeclImplDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(ComponentDeclImpl::CreateDescriptor());
+            ASSERT_NE(nullptr, componentDeclImplDescriptor);
+            auto componentDeclImplComponent = AZStd::unique_ptr<AZ::Component>(componentDeclImplDescriptor->CreateComponent());
+            EXPECT_NE(nullptr, componentDeclImplComponent);
+        }
 
 
+        {
+            using SpecializedComponent = TemplateComponent<int, int>;
+            auto specializedDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(SpecializedComponent::CreateDescriptor());
+            ASSERT_NE(nullptr, specializedDescriptor);
+            auto specializedDescriptorComponent = AZStd::unique_ptr<AZ::Component>(specializedDescriptor->CreateComponent());
+            EXPECT_NE(nullptr, specializedDescriptorComponent);
+        }
     }
     }
 } // namespace UnitTest
 } // namespace UnitTest
 
 

+ 1 - 1
Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestVectorHandler.cpp

@@ -19,7 +19,7 @@ namespace AZ
     {
     {
         namespace UI
         namespace UI
         {
         {
-            AZ_CLASS_ALLOCATOR_IMPL_INTERNAL(IManifestVectorHandler<ManifestType>, SystemAllocator, template<typename ManifestType>)
+            AZ_CLASS_ALLOCATOR_IMPL((IManifestVectorHandler, AZ_CLASS), SystemAllocator);
 
 
             template<typename ManifestType> SerializeContext* IManifestVectorHandler<ManifestType>::s_serializeContext = nullptr;
             template<typename ManifestType> SerializeContext* IManifestVectorHandler<ManifestType>::s_serializeContext = nullptr;
             template<typename ManifestType> IManifestVectorHandler<ManifestType>* IManifestVectorHandler<ManifestType>::s_instance = nullptr;
             template<typename ManifestType> IManifestVectorHandler<ManifestType>* IManifestVectorHandler<ManifestType>::s_instance = nullptr;

+ 1 - 0
Templates/CppToolGem/Template/Code/${NameLower}_api_files.cmake

@@ -8,4 +8,5 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
 )
 )

+ 1 - 0
Templates/CppToolGem/Template/Code/${NameLower}_private_files.cmake

@@ -7,6 +7,7 @@
 # {END_LICENSE}
 # {END_LICENSE}
 
 
 set(FILES
 set(FILES
+    Source/${Name}ModuleInterface.cpp
     Source/${Name}ModuleInterface.h
     Source/${Name}ModuleInterface.h
     Source/Clients/${Name}SystemComponent.cpp
     Source/Clients/${Name}SystemComponent.cpp
     Source/Clients/${Name}SystemComponent.h
     Source/Clients/${Name}SystemComponent.h

+ 3 - 1
Templates/CppToolGem/Template/Code/CMakeLists.txt

@@ -176,6 +176,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
                 PRIVATE
                 PRIVATE
                     Tests
                     Tests
                     Source
                     Source
+                    Include
             BUILD_DEPENDENCIES
             BUILD_DEPENDENCIES
                 PRIVATE
                 PRIVATE
                     AZ::AzTest
                     AZ::AzTest
@@ -204,10 +205,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
                     PRIVATE
                     PRIVATE
                         Tests
                         Tests
                         Source
                         Source
+                        Include
                 BUILD_DEPENDENCIES
                 BUILD_DEPENDENCIES
                     PRIVATE
                     PRIVATE
                         AZ::AzTest
                         AZ::AzTest
-                        Gem::${gem_name}.Private.Object
+                        Gem::${gem_name}.Editor.Private.Object
             )
             )
 
 
             # Add ${gem_name}.Editor.Tests to googletest
             # Add ${gem_name}.Editor.Tests to googletest

+ 28 - 0
Templates/CppToolGem/Template/Code/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,28 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}SystemComponentTypeId = "${SysCompClassId}";
+    inline constexpr const char* ${SanitizedCppName}EditorSystemComponentTypeId = "${EditorSysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleInterfaceTypeId = "{${Random_Uuid}}";
+    inline constexpr const char* ${SanitizedCppName}ModuleTypeId = "${ModuleClassId}";
+    // The Editor Module by default is mutually exclusive with the Client Module
+    // so they use the Same TypeId
+    inline constexpr const char* ${SanitizedCppName}EditorModuleTypeId = ${SanitizedCppName}ModuleTypeId;
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 42 - 0
Templates/CppToolGem/Template/Code/Source/${Name}ModuleInterface.cpp

@@ -0,0 +1,42 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#include "${Name}ModuleInterface.h"
+#include <AzCore/Memory/Memory.h>
+
+#include <${Name}/${Name}TypeIds.h>
+
+#include <Clients/${Name}SystemComponent.h>
+
+namespace ${SanitizedCppName}
+{
+    AZ_TYPE_INFO_WITH_NAME_IMPL(${SanitizedCppName}ModuleInterface,
+        "${SanitizedCppName}ModuleInterface", ${SanitizedCppName}ModuleInterfaceTypeId);
+    AZ_RTTI_NO_TYPE_INFO_IMPL(${SanitizedCppName}ModuleInterface, AZ::Module);
+    AZ_CLASS_ALLOCATOR_IMPL(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator);
+
+    ${SanitizedCppName}ModuleInterface::${SanitizedCppName}ModuleInterface()
+    {
+        // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
+        // Add ALL components descriptors associated with this gem to m_descriptors.
+        // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
+        // This happens through the [MyComponent]::Reflect() function.
+        m_descriptors.insert(m_descriptors.end(), {
+            ${SanitizedCppName}SystemComponent::CreateDescriptor(),
+            });
+    }
+
+    AZ::ComponentTypeList ${SanitizedCppName}ModuleInterface::GetRequiredSystemComponents() const
+    {
+        return AZ::ComponentTypeList{
+            azrtti_typeid<${SanitizedCppName}SystemComponent>(),
+        };
+    }
+} // namespace ${SanitizedCppName}

+ 8 - 20
Templates/CppToolGem/Template/Code/Source/${Name}ModuleInterface.h

@@ -8,9 +8,10 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/Memory/Memory_fwd.h>
 #include <AzCore/Module/Module.h>
 #include <AzCore/Module/Module.h>
-#include <Clients/${Name}SystemComponent.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
@@ -18,28 +19,15 @@ namespace ${SanitizedCppName}
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO_WITH_NAME_DECL(${SanitizedCppName}ModuleInterface)
+        AZ_RTTI_NO_TYPE_INFO_DECL()
+        AZ_CLASS_ALLOCATOR_DECL
 
 
-        ${SanitizedCppName}ModuleInterface()
-        {
-            // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
-            // Add ALL components descriptors associated with this gem to m_descriptors.
-            // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
-            // This happens through the [MyComponent]::Reflect() function.
-            m_descriptors.insert(m_descriptors.end(), {
-                ${SanitizedCppName}SystemComponent::CreateDescriptor(),
-                });
-        }
+        ${SanitizedCppName}ModuleInterface();
 
 
         /**
         /**
          * Add required SystemComponents to the SystemEntity.
          * Add required SystemComponents to the SystemEntity.
          */
          */
-        AZ::ComponentTypeList GetRequiredSystemComponents() const override
-        {
-            return AZ::ComponentTypeList{
-                azrtti_typeid<${SanitizedCppName}SystemComponent>(),
-            };
-        }
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override;
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}

+ 3 - 2
Templates/CppToolGem/Template/Code/Source/Clients/${Name}Module.cpp

@@ -8,6 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
@@ -17,8 +18,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}Module, ${SanitizedCppName}ModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator);
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}
 
 

+ 7 - 12
Templates/CppToolGem/Template/Code/Source/Clients/${Name}SystemComponent.cpp

@@ -10,27 +10,22 @@
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}SystemComponent, "${SanitizedCppName}SystemComponent",
+        ${SanitizedCppName}SystemComponentTypeId);
+
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
-            serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
+            serializeContext->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
                 ->Version(0)
                 ->Version(0)
                 ;
                 ;
-
-            if (AZ::EditContext* ec = serialize->GetEditContext())
-            {
-                ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
-                    ;
-            }
         }
         }
     }
     }
 
 

+ 1 - 1
Templates/CppToolGem/Template/Code/Source/Clients/${Name}SystemComponent.h

@@ -22,7 +22,7 @@ namespace ${SanitizedCppName}
         , public AZ::TickBus::Handler
         , public AZ::TickBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}SystemComponent);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 

+ 3 - 2
Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorModule.cpp

@@ -8,6 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
@@ -23,8 +24,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}EditorModule, ${SanitizedCppName}EditorModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}EditorModule()
         ${SanitizedCppName}EditorModule()
         {
         {

+ 5 - 0
Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp

@@ -15,8 +15,13 @@
 #include "${Name}Widget.h"
 #include "${Name}Widget.h"
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}EditorSystemComponent, "${SanitizedCppName}EditorSystemComponent",
+        ${SanitizedCppName}EditorSystemComponentTypeId, BaseSystemComponent);
+
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))

+ 3 - 2
Templates/CppToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h

@@ -19,11 +19,12 @@ namespace ${SanitizedCppName}
     /// System component for ${SanitizedCppName} editor
     /// System component for ${SanitizedCppName} editor
     class ${SanitizedCppName}EditorSystemComponent
     class ${SanitizedCppName}EditorSystemComponent
         : public ${SanitizedCppName}SystemComponent
         : public ${SanitizedCppName}SystemComponent
-        , private AzToolsFramework::EditorEvents::Bus::Handler
+        , protected AzToolsFramework::EditorEvents::Bus::Handler
     {
     {
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}", BaseSystemComponent);
+        AZ_COMPONENT_DECL(${SanitizedCppName}EditorSystemComponent);
+
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
         ${SanitizedCppName}EditorSystemComponent();
         ${SanitizedCppName}EditorSystemComponent();

+ 8 - 0
Templates/CppToolGem/template.json

@@ -64,6 +64,10 @@
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "isTemplated": true
             "isTemplated": true
@@ -156,6 +160,10 @@
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Source/${Name}ModuleInterface.cpp",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Source/${Name}ModuleInterface.h",
             "file": "Code/Source/${Name}ModuleInterface.h",
             "isTemplated": true
             "isTemplated": true

+ 3 - 1
Templates/DefaultComponent/Template/Source/${Name}Component.cpp

@@ -16,6 +16,8 @@
 
 
 namespace ${GemName}
 namespace ${GemName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}Component, "${SanitizedCppName}Component", "{${Random_Uuid}}");
+
     void ${SanitizedCppName}Component::Activate()
     void ${SanitizedCppName}Component::Activate()
     {
     {
         ${SanitizedCppName}RequestBus::Handler::BusConnect(GetEntityId());
         ${SanitizedCppName}RequestBus::Handler::BusConnect(GetEntityId());
@@ -28,7 +30,7 @@ namespace ${GemName}
 
 
     void ${SanitizedCppName}Component::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}Component::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
             serializeContext->Class<${SanitizedCppName}Component, AZ::Component>()
             serializeContext->Class<${SanitizedCppName}Component, AZ::Component>()
                 ->Version(1)
                 ->Version(1)

+ 1 - 1
Templates/DefaultComponent/Template/Source/${Name}Component.h

@@ -25,7 +25,7 @@ namespace ${GemName}
         , public ${SanitizedCppName}RequestBus::Handler
         , public ${SanitizedCppName}RequestBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${GemName}::${SanitizedCppName}Component, "{${Random_Uuid}}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}Component);
 
 
         /*
         /*
         * Reflects component data into the reflection contexts, including the serialization, edit, and behavior contexts.
         * Reflects component data into the reflection contexts, including the serialization, edit, and behavior contexts.

+ 1 - 0
Templates/DefaultGem/Template/Code/${NameLower}_api_files.cmake

@@ -8,4 +8,5 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
 )
 )

+ 1 - 0
Templates/DefaultGem/Template/Code/${NameLower}_private_files.cmake

@@ -7,6 +7,7 @@
 # {END_LICENSE}
 # {END_LICENSE}
 
 
 set(FILES
 set(FILES
+    Source/${Name}ModuleInterface.cpp
     Source/${Name}ModuleInterface.h
     Source/${Name}ModuleInterface.h
     Source/Clients/${Name}SystemComponent.cpp
     Source/Clients/${Name}SystemComponent.cpp
     Source/Clients/${Name}SystemComponent.h
     Source/Clients/${Name}SystemComponent.h

+ 3 - 1
Templates/DefaultGem/Template/Code/CMakeLists.txt

@@ -174,6 +174,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
                 PRIVATE
                 PRIVATE
                     Tests
                     Tests
                     Source
                     Source
+                    Include
             BUILD_DEPENDENCIES
             BUILD_DEPENDENCIES
                 PRIVATE
                 PRIVATE
                     AZ::AzTest
                     AZ::AzTest
@@ -202,10 +203,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
                     PRIVATE
                     PRIVATE
                         Tests
                         Tests
                         Source
                         Source
+                        Include
                 BUILD_DEPENDENCIES
                 BUILD_DEPENDENCIES
                     PRIVATE
                     PRIVATE
                         AZ::AzTest
                         AZ::AzTest
-                        Gem::${gem_name}.Private.Object
+                        Gem::${gem_name}.Editor.Private.Object
             )
             )
 
 
             # Add ${gem_name}.Editor.Tests to googletest
             # Add ${gem_name}.Editor.Tests to googletest

+ 4 - 2
Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h

@@ -10,6 +10,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 
 
@@ -18,11 +20,11 @@ namespace ${SanitizedCppName}
     class ${SanitizedCppName}Requests
     class ${SanitizedCppName}Requests
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}");
+        AZ_RTTI(${SanitizedCppName}Requests, ${SanitizedCppName}RequestsTypeId);
         virtual ~${SanitizedCppName}Requests() = default;
         virtual ~${SanitizedCppName}Requests() = default;
         // Put your public methods here
         // Put your public methods here
     };
     };
-    
+
     class ${SanitizedCppName}BusTraits
     class ${SanitizedCppName}BusTraits
         : public AZ::EBusTraits
         : public AZ::EBusTraits
     {
     {

+ 28 - 0
Templates/DefaultGem/Template/Code/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,28 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}SystemComponentTypeId = "${SysCompClassId}";
+    inline constexpr const char* ${SanitizedCppName}EditorSystemComponentTypeId = "${EditorSysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleInterfaceTypeId = "{${Random_Uuid}}";
+    inline constexpr const char* ${SanitizedCppName}ModuleTypeId = "${ModuleClassId}";
+    // The Editor Module by default is mutually exclusive with the Client Module
+    // so they use the Same TypeId
+    inline constexpr const char* ${SanitizedCppName}EditorModuleTypeId = ${SanitizedCppName}ModuleTypeId;
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 42 - 0
Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.cpp

@@ -0,0 +1,42 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#include "${Name}ModuleInterface.h"
+#include <AzCore/Memory/Memory.h>
+
+#include <${Name}/${Name}TypeIds.h>
+
+#include <Clients/${Name}SystemComponent.h>
+
+namespace ${SanitizedCppName}
+{
+    AZ_TYPE_INFO_WITH_NAME_IMPL(${SanitizedCppName}ModuleInterface,
+        "${SanitizedCppName}ModuleInterface", ${SanitizedCppName}ModuleInterfaceTypeId);
+    AZ_RTTI_NO_TYPE_INFO_IMPL(${SanitizedCppName}ModuleInterface, AZ::Module);
+    AZ_CLASS_ALLOCATOR_IMPL(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator);
+
+    ${SanitizedCppName}ModuleInterface::${SanitizedCppName}ModuleInterface()
+    {
+        // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
+        // Add ALL components descriptors associated with this gem to m_descriptors.
+        // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
+        // This happens through the [MyComponent]::Reflect() function.
+        m_descriptors.insert(m_descriptors.end(), {
+            ${SanitizedCppName}SystemComponent::CreateDescriptor(),
+            });
+    }
+
+    AZ::ComponentTypeList ${SanitizedCppName}ModuleInterface::GetRequiredSystemComponents() const
+    {
+        return AZ::ComponentTypeList{
+            azrtti_typeid<${SanitizedCppName}SystemComponent>(),
+        };
+    }
+} // namespace ${SanitizedCppName}

+ 8 - 20
Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.h

@@ -8,9 +8,10 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/Memory/Memory_fwd.h>
 #include <AzCore/Module/Module.h>
 #include <AzCore/Module/Module.h>
-#include <Clients/${Name}SystemComponent.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
@@ -18,28 +19,15 @@ namespace ${SanitizedCppName}
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO_WITH_NAME_DECL(${SanitizedCppName}ModuleInterface)
+        AZ_RTTI_NO_TYPE_INFO_DECL()
+        AZ_CLASS_ALLOCATOR_DECL
 
 
-        ${SanitizedCppName}ModuleInterface()
-        {
-            // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
-            // Add ALL components descriptors associated with this gem to m_descriptors.
-            // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
-            // This happens through the [MyComponent]::Reflect() function.
-            m_descriptors.insert(m_descriptors.end(), {
-                ${SanitizedCppName}SystemComponent::CreateDescriptor(),
-                });
-        }
+        ${SanitizedCppName}ModuleInterface();
 
 
         /**
         /**
          * Add required SystemComponents to the SystemEntity.
          * Add required SystemComponents to the SystemEntity.
          */
          */
-        AZ::ComponentTypeList GetRequiredSystemComponents() const override
-        {
-            return AZ::ComponentTypeList{
-                azrtti_typeid<${SanitizedCppName}SystemComponent>(),
-            };
-        }
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override;
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}

+ 3 - 3
Templates/DefaultGem/Template/Code/Source/Clients/${Name}Module.cpp

@@ -8,7 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
@@ -18,8 +18,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}Module, ${SanitizedCppName}ModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator);
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}
 
 

+ 7 - 12
Templates/DefaultGem/Template/Code/Source/Clients/${Name}SystemComponent.cpp

@@ -10,27 +10,22 @@
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}SystemComponent, "${SanitizedCppName}SystemComponent",
+        ${SanitizedCppName}SystemComponentTypeId);
+
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
-            serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
+            serializeContext->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
                 ->Version(0)
                 ->Version(0)
                 ;
                 ;
-
-            if (AZ::EditContext* ec = serialize->GetEditContext())
-            {
-                ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
-                    ;
-            }
         }
         }
     }
     }
 
 

+ 1 - 1
Templates/DefaultGem/Template/Code/Source/Clients/${Name}SystemComponent.h

@@ -22,7 +22,7 @@ namespace ${SanitizedCppName}
         , public AZ::TickBus::Handler
         , public AZ::TickBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}SystemComponent);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 

+ 3 - 2
Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorModule.cpp

@@ -8,6 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
@@ -17,8 +18,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}EditorModule, ${SanitizedCppName}EditorModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}EditorModule()
         ${SanitizedCppName}EditorModule()
         {
         {

+ 5 - 0
Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp

@@ -11,8 +11,13 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}EditorSystemComponent, "${SanitizedCppName}EditorSystemComponent",
+        ${SanitizedCppName}EditorSystemComponentTypeId, BaseSystemComponent);
+
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))

+ 2 - 1
Templates/DefaultGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h

@@ -23,7 +23,8 @@ namespace ${SanitizedCppName}
     {
     {
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}", BaseSystemComponent);
+        AZ_COMPONENT_DECL(${SanitizedCppName}EditorSystemComponent);
+
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
         ${SanitizedCppName}EditorSystemComponent();
         ${SanitizedCppName}EditorSystemComponent();

+ 8 - 0
Templates/DefaultGem/template.json

@@ -64,6 +64,10 @@
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "isTemplated": true
             "isTemplated": true
@@ -156,6 +160,10 @@
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Source/${Name}ModuleInterface.cpp",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Source/${Name}ModuleInterface.h",
             "file": "Code/Source/${Name}ModuleInterface.h",
             "isTemplated": true
             "isTemplated": true

+ 1 - 0
Templates/DefaultProject/Template/Gem/${NameLower}_files.cmake

@@ -8,6 +8,7 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
     Source/${Name}SystemComponent.cpp
     Source/${Name}SystemComponent.cpp
     Source/${Name}SystemComponent.h
     Source/${Name}SystemComponent.h
 )
 )

+ 3 - 1
Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}Bus.h

@@ -10,6 +10,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 
 
@@ -18,7 +20,7 @@ namespace ${SanitizedCppName}
     class ${SanitizedCppName}Requests
     class ${SanitizedCppName}Requests
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}");
+        AZ_RTTI(${SanitizedCppName}Requests, ${SanitizedCppName}RequestsTypeId);
         virtual ~${SanitizedCppName}Requests() = default;
         virtual ~${SanitizedCppName}Requests() = default;
         // Put your public methods here
         // Put your public methods here
     };
     };

+ 23 - 0
Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,23 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}SystemComponentTypeId = "${SysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleTypeId = "${ModuleClassId}";
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 4 - 2
Templates/DefaultProject/Template/Gem/Source/${Name}Module.cpp

@@ -13,14 +13,16 @@
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
     class ${SanitizedCppName}Module
     class ${SanitizedCppName}Module
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}Module, ${SanitizedCppName}ModuleTypeId, AZ::Module);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}Module()
         ${SanitizedCppName}Module()
             : AZ::Module()
             : AZ::Module()

+ 9 - 14
Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.cpp

@@ -9,39 +9,34 @@
  // {END_LICENSE}
  // {END_LICENSE}
 
 
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}SystemComponent, "${SanitizedCppName}SystemComponent",
+        ${SanitizedCppName}SystemComponentTypeId);
+
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
-            serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
+            serializeContext->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
                 ->Version(0)
                 ->Version(0)
                 ;
                 ;
-
-            if (AZ::EditContext* ec = serialize->GetEditContext())
-            {
-                ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
-                    ;
-            }
         }
         }
     }
     }
 
 
     void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
     void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
     {
     {
-        provided.push_back(AZ_CRC("${SanitizedCppName}Service"));
+        provided.push_back(AZ_CRC_CE("${SanitizedCppName}Service"));
     }
     }
 
 
     void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
     void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
     {
     {
-        incompatible.push_back(AZ_CRC("${SanitizedCppName}Service"));
+        incompatible.push_back(AZ_CRC_CE("${SanitizedCppName}Service"));
     }
     }
 
 
     void ${SanitizedCppName}SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
     void ${SanitizedCppName}SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)

+ 1 - 1
Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.h

@@ -21,7 +21,7 @@ namespace ${SanitizedCppName}
         , protected ${SanitizedCppName}RequestBus::Handler
         , protected ${SanitizedCppName}RequestBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}SystemComponent);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 

+ 8 - 0
Templates/DefaultProject/template.json

@@ -26,6 +26,10 @@
             "file": "CMakeLists.txt",
             "file": "CMakeLists.txt",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "CMakePresets.json",
+            "isTemplated": true
+        },
         {
         {
             "file": "cmake/EngineFinder.cmake",
             "file": "cmake/EngineFinder.cmake",
             "isTemplated": true
             "isTemplated": true
@@ -54,6 +58,10 @@
             "file": "Gem/Include/${Name}/${Name}Bus.h",
             "file": "Gem/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Gem/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Gem/Platform/Android/${NameLower}_android_files.cmake",
             "file": "Gem/Platform/Android/${NameLower}_android_files.cmake",
             "isTemplated": false
             "isTemplated": false

+ 1 - 0
Templates/MinimalProject/Template/Gem/${NameLower}_files.cmake

@@ -8,6 +8,7 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
     Source/${Name}SystemComponent.cpp
     Source/${Name}SystemComponent.cpp
     Source/${Name}SystemComponent.h
     Source/${Name}SystemComponent.h
 )
 )

+ 5 - 3
Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}Bus.h

@@ -6,10 +6,12 @@
  * SPDX-License-Identifier: Apache-2.0 OR MIT
  * SPDX-License-Identifier: Apache-2.0 OR MIT
  *
  *
  */
  */
- // {END_LICENSE}
+// {END_LICENSE}
 
 
 #pragma once
 #pragma once
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 
 
@@ -18,11 +20,11 @@ namespace ${SanitizedCppName}
     class ${SanitizedCppName}Requests
     class ${SanitizedCppName}Requests
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Requests, "${Random_Uuid}");
+        AZ_RTTI(${SanitizedCppName}Requests, ${SanitizedCppName}RequestsTypeId);
         virtual ~${SanitizedCppName}Requests() = default;
         virtual ~${SanitizedCppName}Requests() = default;
         // Put your public methods here
         // Put your public methods here
     };
     };
-    
+
     class ${SanitizedCppName}BusTraits
     class ${SanitizedCppName}BusTraits
         : public AZ::EBusTraits
         : public AZ::EBusTraits
     {
     {

+ 23 - 0
Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,23 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}SystemComponentTypeId = "${SysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleTypeId = "${ModuleClassId}";
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 4 - 2
Templates/MinimalProject/Template/Gem/Source/${Name}Module.cpp

@@ -13,14 +13,16 @@
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
     class ${SanitizedCppName}Module
     class ${SanitizedCppName}Module
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}Module, ${SanitizedCppName}ModuleTypeId, AZ::Module);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}Module()
         ${SanitizedCppName}Module()
             : AZ::Module()
             : AZ::Module()

+ 12 - 19
Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.cpp

@@ -9,51 +9,44 @@
  // {END_LICENSE}
  // {END_LICENSE}
 
 
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}SystemComponent, "${SanitizedCppName}SystemComponent",
+        ${SanitizedCppName}SystemComponentTypeId);
+
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
-            serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
+            serializeContext->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
                 ->Version(0)
                 ->Version(0)
                 ;
                 ;
-
-            if (AZ::EditContext* ec = serialize->GetEditContext())
-            {
-                ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
-                    ;
-            }
         }
         }
     }
     }
 
 
     void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
     void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
     {
     {
-        provided.push_back(AZ_CRC("${SanitizedCppName}Service"));
+        provided.push_back(AZ_CRC_CE("${SanitizedCppName}Service"));
     }
     }
 
 
     void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
     void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
     {
     {
-        incompatible.push_back(AZ_CRC("${SanitizedCppName}Service"));
+        incompatible.push_back(AZ_CRC_CE("${SanitizedCppName}Service"));
     }
     }
 
 
-    void ${SanitizedCppName}SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
+    void ${SanitizedCppName}SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
     {
     {
-        AZ_UNUSED(required);
     }
     }
 
 
-    void ${SanitizedCppName}SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    void ${SanitizedCppName}SystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
     {
     {
-        AZ_UNUSED(dependent);
     }
     }
-    
+
     ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent()
     ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent()
     {
     {
         if (${SanitizedCppName}Interface::Get() == nullptr)
         if (${SanitizedCppName}Interface::Get() == nullptr)

+ 1 - 1
Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.h

@@ -21,7 +21,7 @@ namespace ${SanitizedCppName}
         , protected ${SanitizedCppName}RequestBus::Handler
         , protected ${SanitizedCppName}RequestBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}SystemComponent);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 

+ 8 - 0
Templates/MinimalProject/template.json

@@ -26,6 +26,10 @@
             "file": "CMakeLists.txt",
             "file": "CMakeLists.txt",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "CMakePresets.json",
+            "isTemplated": true
+        },
         {
         {
             "file": "cmake/EngineFinder.cmake",
             "file": "cmake/EngineFinder.cmake",
             "isTemplated": false
             "isTemplated": false
@@ -50,6 +54,10 @@
             "file": "Gem/Include/${Name}/${Name}Bus.h",
             "file": "Gem/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Gem/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Gem/Platform/Android/${NameLower}_android_files.cmake",
             "file": "Gem/Platform/Android/${NameLower}_android_files.cmake",
             "isTemplated": true
             "isTemplated": true

+ 5 - 1
Templates/PythonToolGem/Template/CMakeLists.txt

@@ -20,6 +20,10 @@ endif()
 
 
 set(gem_json ${gem_path}/gem.json)
 set(gem_json ${gem_path}/gem.json)
 
 
-o3de_restricted_path(${gem_json} o3de_gem_restricted_path)
+o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path)
+
+o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME} "${gem_restricted_path}" "${gem_path}" "${gem_parent_relative_path}")
+
+ly_add_external_target_path(${CMAKE_CURRENT_SOURCE_DIR}/3rdParty)
 
 
 add_subdirectory(Code)
 add_subdirectory(Code)

+ 1 - 0
Templates/PythonToolGem/Template/Code/${NameLower}_editor_api_files.cmake

@@ -9,4 +9,5 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
 )
 )

+ 1 - 0
Templates/PythonToolGem/Template/Code/${NameLower}_editor_private_files.cmake

@@ -7,6 +7,7 @@
 # {END_LICENSE}
 # {END_LICENSE}
 
 
 set(FILES
 set(FILES
+    Source/${Name}ModuleInterface.cpp
     Source/${Name}ModuleInterface.h
     Source/${Name}ModuleInterface.h
     Source/Tools/${Name}EditorSystemComponent.cpp
     Source/Tools/${Name}EditorSystemComponent.cpp
     Source/Tools/${Name}EditorSystemComponent.h
     Source/Tools/${Name}EditorSystemComponent.h

+ 4 - 2
Templates/PythonToolGem/Template/Code/Include/${Name}/${Name}Bus.h

@@ -10,6 +10,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 
 
@@ -18,11 +20,11 @@ namespace ${SanitizedCppName}
     class ${SanitizedCppName}Requests
     class ${SanitizedCppName}Requests
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}");
+        AZ_RTTI(${SanitizedCppName}Requests, ${SanitizedCppName}RequestsTypeId);
         virtual ~${SanitizedCppName}Requests() = default;
         virtual ~${SanitizedCppName}Requests() = default;
         // Put your public methods here
         // Put your public methods here
     };
     };
-    
+
     class ${SanitizedCppName}BusTraits
     class ${SanitizedCppName}BusTraits
         : public AZ::EBusTraits
         : public AZ::EBusTraits
     {
     {

+ 24 - 0
Templates/PythonToolGem/Template/Code/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,24 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}EditorSystemComponentTypeId = "${EditorSysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleInterfaceTypeId = "{${Random_Uuid}}";
+    inline constexpr const char* ${SanitizedCppName}EditorModuleTypeId = "${ModuleClassId}";
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 32 - 0
Templates/PythonToolGem/Template/Code/Source/${Name}ModuleInterface.cpp

@@ -0,0 +1,32 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#include "${Name}ModuleInterface.h"
+#include <AzCore/Memory/Memory.h>
+
+#include <${Name}/${Name}TypeIds.h>
+
+namespace ${SanitizedCppName}
+{
+    AZ_TYPE_INFO_WITH_NAME_IMPL(${SanitizedCppName}ModuleInterface,
+        "${SanitizedCppName}ModuleInterface", ${SanitizedCppName}ModuleInterfaceTypeId);
+    AZ_RTTI_NO_TYPE_INFO_IMPL(${SanitizedCppName}ModuleInterface, AZ::Module);
+    AZ_CLASS_ALLOCATOR_IMPL(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator);
+
+    ${SanitizedCppName}ModuleInterface::${SanitizedCppName}ModuleInterface()
+    {
+    }
+
+    AZ::ComponentTypeList ${SanitizedCppName}ModuleInterface::GetRequiredSystemComponents() const
+    {
+        return AZ::ComponentTypeList{
+        };
+    }
+} // namespace ${SanitizedCppName}

+ 8 - 11
Templates/PythonToolGem/Template/Code/Source/${Name}ModuleInterface.h

@@ -8,8 +8,10 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/Memory/Memory_fwd.h>
 #include <AzCore/Module/Module.h>
 #include <AzCore/Module/Module.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
@@ -17,20 +19,15 @@ namespace ${SanitizedCppName}
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO_WITH_NAME_DECL(${SanitizedCppName}ModuleInterface)
+        AZ_RTTI_NO_TYPE_INFO_DECL()
+        AZ_CLASS_ALLOCATOR_DECL
 
 
-        ${SanitizedCppName}ModuleInterface()
-        {
-        }
+        ${SanitizedCppName}ModuleInterface();
 
 
         /**
         /**
          * Add required SystemComponents to the SystemEntity.
          * Add required SystemComponents to the SystemEntity.
          */
          */
-        AZ::ComponentTypeList GetRequiredSystemComponents() const override
-        {
-            return AZ::ComponentTypeList{
-            };
-        }
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override;
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}

+ 3 - 2
Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorModule.cpp

@@ -8,6 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 #include <AzToolsFramework/API/PythonLoader.h>
 #include <AzToolsFramework/API/PythonLoader.h>
@@ -27,8 +28,8 @@ namespace ${SanitizedCppName}
         , public AzToolsFramework::EmbeddedPython::PythonLoader
         , public AzToolsFramework::EmbeddedPython::PythonLoader
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}EditorModule, ${SanitizedCppName}EditorModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}EditorModule()
         ${SanitizedCppName}EditorModule()
         {
         {

+ 5 - 0
Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp

@@ -11,8 +11,13 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}EditorSystemComponent, "${SanitizedCppName}EditorSystemComponent",
+        ${SanitizedCppName}EditorSystemComponentTypeId);
+
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))

+ 4 - 3
Templates/PythonToolGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h

@@ -21,7 +21,8 @@ namespace ${SanitizedCppName}
         , public AZ::Component
         , public AZ::Component
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}EditorSystemComponent);
+
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
         ${SanitizedCppName}EditorSystemComponent();
         ${SanitizedCppName}EditorSystemComponent();
@@ -34,7 +35,7 @@ namespace ${SanitizedCppName}
         static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
         static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
 
 
         // AZ::Component
         // AZ::Component
-        void Activate();
-        void Deactivate();
+        void Activate() override;
+        void Deactivate() override;
     };
     };
 } // namespace ${SanitizedCppName}
 } // namespace ${SanitizedCppName}

+ 8 - 0
Templates/PythonToolGem/template.json

@@ -50,6 +50,10 @@
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Platform/Linux/${NameLower}_editor_api_files.cmake",
             "file": "Code/Platform/Linux/${NameLower}_editor_api_files.cmake",
             "isTemplated": true
             "isTemplated": true
@@ -98,6 +102,10 @@
             "file": "Code/Platform/Windows/PAL_windows.cmake",
             "file": "Code/Platform/Windows/PAL_windows.cmake",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Source/${Name}ModuleInterface.cpp",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Source/${Name}ModuleInterface.h",
             "file": "Code/Source/${Name}ModuleInterface.h",
             "isTemplated": true
             "isTemplated": true

+ 1 - 0
Templates/UnifiedMultiplayerGem/Template/Code/${NameLower}_api_files.cmake

@@ -8,4 +8,5 @@
 
 
 set(FILES
 set(FILES
     Include/${Name}/${Name}Bus.h
     Include/${Name}/${Name}Bus.h
+    Include/${Name}/${Name}TypeIds.h
 )
 )

+ 1 - 0
Templates/UnifiedMultiplayerGem/Template/Code/${NameLower}_private_files.cmake

@@ -7,6 +7,7 @@
 # {END_LICENSE}
 # {END_LICENSE}
 
 
 set(FILES
 set(FILES
+    Source/${Name}ModuleInterface.cpp
     Source/${Name}ModuleInterface.h
     Source/${Name}ModuleInterface.h
     Source/Unified/${Name}SystemComponent.cpp
     Source/Unified/${Name}SystemComponent.cpp
     Source/Unified/${Name}SystemComponent.h
     Source/Unified/${Name}SystemComponent.h

+ 4 - 2
Templates/UnifiedMultiplayerGem/Template/Code/Include/${Name}/${Name}Bus.h

@@ -10,6 +10,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 
 
@@ -18,11 +20,11 @@ namespace ${SanitizedCppName}
     class ${SanitizedCppName}Requests
     class ${SanitizedCppName}Requests
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}");
+        AZ_RTTI(${SanitizedCppName}Requests, ${SanitizedCppName}RequestsTypeId);
         virtual ~${SanitizedCppName}Requests() = default;
         virtual ~${SanitizedCppName}Requests() = default;
         // Put your public methods here
         // Put your public methods here
     };
     };
-    
+
     class ${SanitizedCppName}BusTraits
     class ${SanitizedCppName}BusTraits
         : public AZ::EBusTraits
         : public AZ::EBusTraits
     {
     {

+ 28 - 0
Templates/UnifiedMultiplayerGem/Template/Code/Include/${Name}/${Name}TypeIds.h

@@ -0,0 +1,28 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#pragma once
+
+namespace ${SanitizedCppName}
+{
+    // System Component TypeIds
+    inline constexpr const char* ${SanitizedCppName}SystemComponentTypeId = "${SysCompClassId}";
+    inline constexpr const char* ${SanitizedCppName}EditorSystemComponentTypeId = "${EditorSysCompClassId}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* ${SanitizedCppName}ModuleInterfaceTypeId = "{${Random_Uuid}}";
+    inline constexpr const char* ${SanitizedCppName}ModuleTypeId = "${ModuleClassId}";
+    // The Editor Module by default is mutually exclusive with the Client Module
+    // so they use the Same TypeId
+    inline constexpr const char* ${SanitizedCppName}EditorModuleTypeId = ${SanitizedCppName}ModuleTypeId;
+
+    // Interface TypeIds
+    inline constexpr const char* ${SanitizedCppName}RequestsTypeId = "{${Random_Uuid}}";
+} // namespace ${SanitizedCppName}

+ 42 - 0
Templates/UnifiedMultiplayerGem/Template/Code/Source/${Name}ModuleInterface.cpp

@@ -0,0 +1,42 @@
+// {BEGIN_LICENSE}
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+// {END_LICENSE}
+
+#include "${Name}ModuleInterface.h"
+#include <AzCore/Memory/Memory.h>
+
+#include <${Name}/${Name}TypeIds.h>
+
+#include <Unified/${Name}SystemComponent.h>
+
+namespace ${SanitizedCppName}
+{
+    AZ_TYPE_INFO_WITH_NAME_IMPL(${SanitizedCppName}ModuleInterface,
+        "${SanitizedCppName}ModuleInterface", ${SanitizedCppName}ModuleInterfaceTypeId);
+    AZ_RTTI_NO_TYPE_INFO_IMPL(${SanitizedCppName}ModuleInterface, AZ::Module);
+    AZ_CLASS_ALLOCATOR_IMPL(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator);
+
+    ${SanitizedCppName}ModuleInterface::${SanitizedCppName}ModuleInterface()
+    {
+        // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
+        // Add ALL components descriptors associated with this gem to m_descriptors.
+        // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
+        // This happens through the [MyComponent]::Reflect() function.
+        m_descriptors.insert(m_descriptors.end(), {
+            ${SanitizedCppName}SystemComponent::CreateDescriptor(),
+            });
+    }
+
+    AZ::ComponentTypeList ${SanitizedCppName}ModuleInterface::GetRequiredSystemComponents() const
+    {
+        return AZ::ComponentTypeList{
+            azrtti_typeid<${SanitizedCppName}SystemComponent>(),
+        };
+    }
+} // namespace ${SanitizedCppName}

+ 8 - 20
Templates/UnifiedMultiplayerGem/Template/Code/Source/${Name}ModuleInterface.h

@@ -8,9 +8,10 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/Memory/Memory_fwd.h>
 #include <AzCore/Module/Module.h>
 #include <AzCore/Module/Module.h>
-#include <Unified/${Name}SystemComponent.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
@@ -18,28 +19,15 @@ namespace ${SanitizedCppName}
         : public AZ::Module
         : public AZ::Module
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO_WITH_NAME_DECL(${SanitizedCppName}ModuleInterface)
+        AZ_RTTI_NO_TYPE_INFO_DECL()
+        AZ_CLASS_ALLOCATOR_DECL
 
 
-        ${SanitizedCppName}ModuleInterface()
-        {
-            // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
-            // Add ALL components descriptors associated with this gem to m_descriptors.
-            // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.
-            // This happens through the [MyComponent]::Reflect() function.
-            m_descriptors.insert(m_descriptors.end(), {
-                ${SanitizedCppName}SystemComponent::CreateDescriptor(),
-                });
-        }
+        ${SanitizedCppName}ModuleInterface();
 
 
         /**
         /**
          * Add required SystemComponents to the SystemEntity.
          * Add required SystemComponents to the SystemEntity.
          */
          */
-        AZ::ComponentTypeList GetRequiredSystemComponents() const override
-        {
-            return AZ::ComponentTypeList{
-                azrtti_typeid<${SanitizedCppName}SystemComponent>(),
-            };
-        }
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override;
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}

+ 3 - 2
Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorModule.cpp

@@ -8,6 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
@@ -17,8 +18,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}EditorModule, ${SanitizedCppName}EditorModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator);
 
 
         ${SanitizedCppName}EditorModule()
         ${SanitizedCppName}EditorModule()
         {
         {

+ 5 - 0
Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.cpp

@@ -11,8 +11,13 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include "${Name}EditorSystemComponent.h"
 #include "${Name}EditorSystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}EditorSystemComponent, "${SanitizedCppName}EditorSystemComponent",
+        ${SanitizedCppName}EditorSystemComponentTypeId, BaseSystemComponent);
+
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}EditorSystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))

+ 2 - 1
Templates/UnifiedMultiplayerGem/Template/Code/Source/Tools/${Name}EditorSystemComponent.h

@@ -23,7 +23,8 @@ namespace ${SanitizedCppName}
     {
     {
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
         using BaseSystemComponent = ${SanitizedCppName}SystemComponent;
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}", BaseSystemComponent);
+        AZ_COMPONENT_DECL(${SanitizedCppName}EditorSystemComponent);
+
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
         ${SanitizedCppName}EditorSystemComponent();
         ${SanitizedCppName}EditorSystemComponent();

+ 3 - 3
Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}Module.cpp

@@ -8,7 +8,7 @@
  */
  */
 // {END_LICENSE}
 // {END_LICENSE}
 
 
-
+#include <${Name}/${Name}TypeIds.h>
 #include <${Name}ModuleInterface.h>
 #include <${Name}ModuleInterface.h>
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
@@ -18,8 +18,8 @@ namespace ${SanitizedCppName}
         : public ${SanitizedCppName}ModuleInterface
         : public ${SanitizedCppName}ModuleInterface
     {
     {
     public:
     public:
-        AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
-        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0);
+        AZ_RTTI(${SanitizedCppName}Module, ${SanitizedCppName}ModuleTypeId, ${SanitizedCppName}ModuleInterface);
+        AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator);
     };
     };
 }// namespace ${SanitizedCppName}
 }// namespace ${SanitizedCppName}
 
 

+ 7 - 12
Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}SystemComponent.cpp

@@ -10,27 +10,22 @@
 
 
 #include "${Name}SystemComponent.h"
 #include "${Name}SystemComponent.h"
 
 
+#include <${Name}/${Name}TypeIds.h>
+
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-#include <AzCore/Serialization/EditContextConstants.inl>
 
 
 namespace ${SanitizedCppName}
 namespace ${SanitizedCppName}
 {
 {
+    AZ_COMPONENT_IMPL(${SanitizedCppName}SystemComponent, "${SanitizedCppName}SystemComponent",
+        ${SanitizedCppName}SystemComponentTypeId);
+
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context)
     {
     {
-        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
         {
         {
-            serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
+            serializeContext->Class<${SanitizedCppName}SystemComponent, AZ::Component>()
                 ->Version(0)
                 ->Version(0)
                 ;
                 ;
-
-            if (AZ::EditContext* ec = serialize->GetEditContext())
-            {
-                ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
-                    ;
-            }
         }
         }
     }
     }
 
 

+ 1 - 1
Templates/UnifiedMultiplayerGem/Template/Code/Source/Unified/${Name}SystemComponent.h

@@ -22,7 +22,7 @@ namespace ${SanitizedCppName}
         , public AZ::TickBus::Handler
         , public AZ::TickBus::Handler
     {
     {
     public:
     public:
-        AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}");
+        AZ_COMPONENT_DECL(${SanitizedCppName}SystemComponent);
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 

+ 7 - 1
Templates/UnifiedMultiplayerGem/Template/gem.json

@@ -1,5 +1,6 @@
 {
 {
     "gem_name": "${Name}",
     "gem_name": "${Name}",
+    "version": "${Version}",
     "display_name": "${DisplayName}",
     "display_name": "${DisplayName}",
     "license": "${License}",
     "license": "${License}",
     "license_url": "${LicenseURL}",
     "license_url": "${LicenseURL}",
@@ -20,6 +21,11 @@
     "requirements": "${Requirements}",
     "requirements": "${Requirements}",
     "documentation_url": "${DocumentationURL}",
     "documentation_url": "${DocumentationURL}",
     "dependencies": [
     "dependencies": [
+        "Multiplayer"
     ],
     ],
-    "repo_uri": "${RepoURI}"
+    "repo_uri": "${RepoURI}",
+    "compatible_engines": [
+    ],
+    "engine_api_dependencies":[
+    ]
 }
 }

+ 8 - 0
Templates/UnifiedMultiplayerGem/template.json

@@ -64,6 +64,10 @@
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "file": "Code/Include/${Name}/${Name}Bus.h",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Include/${Name}/${Name}TypeIds.h",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "file": "Code/Platform/Android/${NameLower}_private_files.cmake",
             "isTemplated": true
             "isTemplated": true
@@ -156,6 +160,10 @@
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "file": "Code/Platform/iOS/PAL_ios.cmake",
             "isTemplated": true
             "isTemplated": true
         },
         },
+        {
+            "file": "Code/Source/${Name}ModuleInterface.cpp",
+            "isTemplated": true
+        },
         {
         {
             "file": "Code/Source/${Name}ModuleInterface.h",
             "file": "Code/Source/${Name}ModuleInterface.h",
             "isTemplated": true
             "isTemplated": true

+ 7 - 6
engine.json

@@ -3,13 +3,13 @@
     "restricted": "o3de",
     "restricted": "o3de",
     "O3DEVersion": "0.1.0.0",
     "O3DEVersion": "0.1.0.0",
     "O3DEBuildNumber": 0,
     "O3DEBuildNumber": 0,
-    "display_version":"00.00",
-    "version":"2.0.0",
+    "display_version": "00.00",
+    "version": "2.0.0",
     "api_versions": {
     "api_versions": {
-        "editor":"1.0.0",
-        "framework":"1.0.0",
-        "launcher":"1.0.0",
-        "tools":"1.0.0"
+        "editor": "1.0.0",
+        "framework": "1.0.0",
+        "launcher": "1.0.0",
+        "tools": "1.0.0"
     },
     },
     "file_version": 2,
     "file_version": 2,
     "copyright_year": 2023,
     "copyright_year": 2023,
@@ -114,6 +114,7 @@
         "AutomatedTesting"
         "AutomatedTesting"
     ],
     ],
     "templates": [
     "templates": [
+        "Templates/UnifiedMultiplayerGem",
         "Templates/PrebuiltGem",
         "Templates/PrebuiltGem",
         "Templates/GemRepo",
         "Templates/GemRepo",
         "Templates/AssetGem",
         "Templates/AssetGem",