Przeglądaj źródła

Simulation interfaces gem - initial code and features (#848)

* Spawning and spawnables

Signed-off-by: Michał Pełka <[email protected]>

* Test and renaming Editor SystemComponents

Signed-off-by: Michał Pełka <[email protected]>

* Added class skeleton

Signed-off-by: Michał Pełka <[email protected]>

* prevent tool crashing

Signed-off-by: Michał Pełka <[email protected]>

* physics stepping

Signed-off-by: Michał Pełka <[email protected]>

* review comments

Signed-off-by: Michał Pełka <[email protected]>

* Adjusted to review

Signed-off-by: Michał Pełka <[email protected]>

---------

Signed-off-by: Michał Pełka <[email protected]>
Michał Pełka 3 miesięcy temu
rodzic
commit
9e440b2984
63 zmienionych plików z 3124 dodań i 0 usunięć
  1. 61 0
      Gems/SimulationInterfaces/.clang-format
  2. 0 0
      Gems/SimulationInterfaces/.gitignore
  3. 137 0
      Gems/SimulationInterfaces/Assets/SampleAsset/TestSimulationEntity.prefab
  4. 11 0
      Gems/SimulationInterfaces/CMakeLists.txt
  5. 287 0
      Gems/SimulationInterfaces/Code/CMakeLists.txt
  6. 102 0
      Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationEntityManagerRequestBus.h
  7. 31 0
      Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationInterfacesTypeIds.h
  8. 45 0
      Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationMangerRequestBus.h
  9. 9 0
      Gems/SimulationInterfaces/Code/Platform/Android/PAL_android.cmake
  10. 8 0
      Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_api_files.cmake
  11. 13 0
      Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_private_files.cmake
  12. 13 0
      Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_shared_files.cmake
  13. 9 0
      Gems/SimulationInterfaces/Code/Platform/Linux/PAL_linux.cmake
  14. 8 0
      Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_api_files.cmake
  15. 8 0
      Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_editor_api_files.cmake
  16. 13 0
      Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_private_files.cmake
  17. 13 0
      Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_shared_files.cmake
  18. 9 0
      Gems/SimulationInterfaces/Code/Platform/Mac/PAL_mac.cmake
  19. 8 0
      Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_api_files.cmake
  20. 8 0
      Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_editor_api_files.cmake
  21. 13 0
      Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_private_files.cmake
  22. 13 0
      Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_shared_files.cmake
  23. 9 0
      Gems/SimulationInterfaces/Code/Platform/Windows/PAL_windows.cmake
  24. 8 0
      Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_api_files.cmake
  25. 8 0
      Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_editor_api_files.cmake
  26. 13 0
      Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_private_files.cmake
  27. 13 0
      Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_shared_files.cmake
  28. 9 0
      Gems/SimulationInterfaces/Code/Platform/iOS/PAL_ios.cmake
  29. 8 0
      Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_api_files.cmake
  30. 13 0
      Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_private_files.cmake
  31. 13 0
      Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_shared_files.cmake
  32. 31 0
      Gems/SimulationInterfaces/Code/Source/Clients/CommonUtilities.cpp
  33. 20 0
      Gems/SimulationInterfaces/Code/Source/Clients/CommonUtilities.h
  34. 224 0
      Gems/SimulationInterfaces/Code/Source/Clients/ConsoleCommands.inl
  35. 586 0
      Gems/SimulationInterfaces/Code/Source/Clients/SimulationEntitiesManager.cpp
  36. 94 0
      Gems/SimulationInterfaces/Code/Source/Clients/SimulationEntitiesManager.h
  37. 27 0
      Gems/SimulationInterfaces/Code/Source/Clients/SimulationInterfacesModule.cpp
  38. 127 0
      Gems/SimulationInterfaces/Code/Source/Clients/SimulationManager.cpp
  39. 49 0
      Gems/SimulationInterfaces/Code/Source/Clients/SimulationManager.h
  40. 41 0
      Gems/SimulationInterfaces/Code/Source/SimulationInterfacesModuleInterface.cpp
  41. 30 0
      Gems/SimulationInterfaces/Code/Source/SimulationInterfacesModuleInterface.h
  42. 70 0
      Gems/SimulationInterfaces/Code/Source/Tools/SimulationEntitiesManagerEditor.cpp
  43. 42 0
      Gems/SimulationInterfaces/Code/Source/Tools/SimulationEntitiesManagerEditor.h
  44. 48 0
      Gems/SimulationInterfaces/Code/Source/Tools/SimulationInterfacesEditorModule.cpp
  45. 68 0
      Gems/SimulationInterfaces/Code/Source/Tools/SimulationManagerEditor.cpp
  46. 43 0
      Gems/SimulationInterfaces/Code/Source/Tools/SimulationManagerEditor.h
  47. 11 0
      Gems/SimulationInterfaces/Code/Tests/Clients/SimulationInterfacesTest.cpp
  48. 170 0
      Gems/SimulationInterfaces/Code/Tests/Tools/SimulationInterfaceTests.cpp
  49. 139 0
      Gems/SimulationInterfaces/Code/Tests/Tools/SimulationIterfaceAppTest.cpp
  50. 151 0
      Gems/SimulationInterfaces/Code/Tests/Tools/TestFixture.cpp
  51. 94 0
      Gems/SimulationInterfaces/Code/Tests/Tools/TestFixture.h
  52. 11 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_api_files.cmake
  53. 9 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_editor_api_files.cmake
  54. 11 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_editor_app_test.cmake
  55. 12 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_editor_private_files.cmake
  56. 9 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_editor_shared_files.cmake
  57. 11 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_editor_tests_files.cmake
  58. 16 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_private_files.cmake
  59. 9 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_shared_files.cmake
  60. 9 0
      Gems/SimulationInterfaces/Code/simulationinterfaces_tests_files.cmake
  61. 18 0
      Gems/SimulationInterfaces/Registry/assetprocessor_settings.setreg
  62. 28 0
      Gems/SimulationInterfaces/gem.json
  63. 3 0
      Gems/SimulationInterfaces/preview.png

+ 61 - 0
Gems/SimulationInterfaces/.clang-format

@@ -0,0 +1,61 @@
+Language: Cpp
+
+AccessModifierOffset: -4
+AlignAfterOpenBracket: AlwaysBreak
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: false
+AlignTrailingComments: false
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortFunctionsOnASingleLine: None
+AllowShortLambdasOnASingleLine: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: false
+BinPackParameters: false
+BreakBeforeBraces: Custom
+BraceWrapping:
+    AfterClass: true
+    AfterControlStatement: true
+    AfterEnum: true
+    AfterFunction: true
+    AfterNamespace: true
+    BeforeLambdaBody: true
+    AfterStruct: true
+    BeforeElse: true
+    SplitEmptyFunction: true
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeComma
+BreakInheritanceList: BeforeComma
+ColumnLimit: 140
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: false
+FixNamespaceComments: true
+IncludeBlocks: Preserve
+IndentCaseBlocks: true
+IndentCaseLabels: false
+IndentPPDirectives: None
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: false
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: All
+PenaltyReturnTypeOnItsOwnLine: 1000
+PointerAlignment: Left
+SortIncludes: true
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesInAngles: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+Standard: c++17
+UseTab: Never

+ 0 - 0
Gems/SimulationInterfaces/.gitignore


+ 137 - 0
Gems/SimulationInterfaces/Assets/SampleAsset/TestSimulationEntity.prefab

@@ -0,0 +1,137 @@
+{
+    "ContainerEntity": {
+        "Id": "ContainerEntity",
+        "Name": "TestSimulationEntity",
+        "Components": {
+            "EditorDisabledCompositionComponent": {
+                "$type": "EditorDisabledCompositionComponent",
+                "Id": 13342689700908152991
+            },
+            "EditorEntityIconComponent": {
+                "$type": "EditorEntityIconComponent",
+                "Id": 8584796089140035515
+            },
+            "EditorEntitySortComponent": {
+                "$type": "EditorEntitySortComponent",
+                "Id": 17941228157017035486,
+                "Child Entity Order": [
+                    "Entity_[2555577822056]"
+                ]
+            },
+            "EditorInspectorComponent": {
+                "$type": "EditorInspectorComponent",
+                "Id": 16387168034938951622
+            },
+            "EditorLockComponent": {
+                "$type": "EditorLockComponent",
+                "Id": 5868718090530092403
+            },
+            "EditorOnlyEntityComponent": {
+                "$type": "EditorOnlyEntityComponent",
+                "Id": 10685569871653723108
+            },
+            "EditorPendingCompositionComponent": {
+                "$type": "EditorPendingCompositionComponent",
+                "Id": 13486227769083255940
+            },
+            "EditorPrefabComponent": {
+                "$type": "EditorPrefabComponent",
+                "Id": 9974721317876760075
+            },
+            "EditorVisibilityComponent": {
+                "$type": "EditorVisibilityComponent",
+                "Id": 18186949152932686714
+            },
+            "TransformComponent": {
+                "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                "Id": 13473127497085401640,
+                "Parent Entity": ""
+            }
+        }
+    },
+    "Entities": {
+        "Entity_[2555577822056]": {
+            "Id": "Entity_[2555577822056]",
+            "Name": "TestSimulationEntity",
+            "Components": {
+                "EditorBoxShapeComponent": {
+                    "$type": "EditorBoxShapeComponent",
+                    "Id": 17815707635495439549,
+                    "GameView": true
+                },
+                "EditorColliderComponent": {
+                    "$type": "EditorColliderComponent",
+                    "Id": 7164453177612248133,
+                    "ColliderConfiguration": {
+                        "MaterialSlots": {
+                            "Slots": [
+                                {
+                                    "Name": "Entire object"
+                                }
+                            ]
+                        }
+                    },
+                    "ShapeConfiguration": {
+                        "ShapeType": 0
+                    }
+                },
+                "EditorDisabledCompositionComponent": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 14547453815095477983
+                },
+                "EditorEntityIconComponent": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 11928217918748032436
+                },
+                "EditorEntitySortComponent": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 16175661524427525128
+                },
+                "EditorInspectorComponent": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 7165286389418841970
+                },
+                "EditorLockComponent": {
+                    "$type": "EditorLockComponent",
+                    "Id": 18134844107097174864
+                },
+                "EditorOnlyEntityComponent": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 3157917745503616515
+                },
+                "EditorPendingCompositionComponent": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 10603658429884530304
+                },
+                "EditorRigidBodyComponent": {
+                    "$type": "EditorRigidBodyComponent",
+                    "Id": 11637898985208574279,
+                    "Configuration": {
+                        "entityId": "",
+                        "Mass": 523.5988159179688,
+                        "Inertia tensor": [
+                            52.35987854003906,
+                            0.0,
+                            0.0,
+                            0.0,
+                            52.35987854003906,
+                            0.0,
+                            0.0,
+                            0.0,
+                            52.35987854003906
+                        ]
+                    }
+                },
+                "EditorVisibilityComponent": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 6275443825220336439
+                },
+                "TransformComponent": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 14994870681931426785,
+                    "Parent Entity": "ContainerEntity"
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Gems/SimulationInterfaces/CMakeLists.txt

@@ -0,0 +1,11 @@
+# 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
+#
+
+o3de_gem_setup("SimulationInterfaces")
+
+ly_add_external_target_path(${CMAKE_CURRENT_SOURCE_DIR}/3rdParty)
+
+add_subdirectory(Code)

+ 287 - 0
Gems/SimulationInterfaces/Code/CMakeLists.txt

@@ -0,0 +1,287 @@
+# 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
+#
+
+# Currently we are in the Code folder: ${CMAKE_CURRENT_LIST_DIR}
+# Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}
+# Note: o3de_pal_dir will take care of the details for us, as this may be a restricted platform
+#       in which case it will see if that platform is present here or in the restricted folder.
+#       i.e. It could here in our gem : Gems/SimulationInterfaces/Code/Platform/<platorm_name>  or
+#            <restricted_folder>/<platform_name>/Gems/SimulationInterfaces/Code
+o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} "${gem_restricted_path}" "${gem_path}" "${gem_parent_relative_path}")
+
+# Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the
+# traits for this platform. Traits for a platform are defines for things like whether or not something in this gem
+# is supported by this platform.
+include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
+
+# Check to see if building the Gem Modules are supported for the current platform
+if(NOT PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED)
+    return()
+endif()
+
+# The ${gem_name}.API target declares the common interface that users of this gem should depend on in their targets
+ly_add_target(
+    NAME ${gem_name}.API INTERFACE
+    NAMESPACE Gem
+    FILES_CMAKE
+        simulationinterfaces_api_files.cmake
+        ${pal_dir}/simulationinterfaces_api_files.cmake
+    INCLUDE_DIRECTORIES
+        INTERFACE
+            Include
+    BUILD_DEPENDENCIES
+        INTERFACE
+           AZ::AzCore
+)
+
+# The ${gem_name}.Private.Object target is an internal target
+# It should not be used outside of this Gems CMakeLists.txt
+ly_add_target(
+    NAME ${gem_name}.Private.Object STATIC
+    NAMESPACE Gem
+    FILES_CMAKE
+        simulationinterfaces_private_files.cmake
+        ${pal_dir}/simulationinterfaces_private_files.cmake
+    TARGET_PROPERTIES
+        O3DE_PRIVATE_TARGET TRUE
+    INCLUDE_DIRECTORIES
+        PRIVATE
+            Include
+            Source
+    BUILD_DEPENDENCIES
+        PUBLIC
+            AZ::AzCore
+            AZ::AzFramework
+)
+
+# Here add ${gem_name} target, it depends on the Private Object library and Public API interface
+ly_add_target(
+    NAME ${gem_name} ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
+    NAMESPACE Gem
+    FILES_CMAKE
+        simulationinterfaces_shared_files.cmake
+        ${pal_dir}/simulationinterfaces_shared_files.cmake
+    INCLUDE_DIRECTORIES
+        PUBLIC
+            Include
+        PRIVATE
+            Source
+    BUILD_DEPENDENCIES
+        PUBLIC
+            Gem::${gem_name}.API
+        PRIVATE
+            Gem::${gem_name}.Private.Object
+)
+
+# Include the gem name into the Client Module source file
+# for use with the AZ_DECLARE_MODULE_CLASS macro
+# This is to allow renaming of the gem to also cause
+# the CreateModuleClass_Gem_<gem-name> function which
+# is used to bootstrap the gem in monolithic builds to link to the new gem name
+ly_add_source_properties(
+SOURCES
+    Source/Clients/SimulationInterfacesModule.cpp
+PROPERTY COMPILE_DEFINITIONS
+    VALUES
+        O3DE_GEM_NAME=${gem_name}
+        O3DE_GEM_VERSION=${gem_version})
+
+# By default, we will specify that the above target ${gem_name} would be used by
+# Client and Server type targets when this gem is enabled.  If you don't want it
+# active in Clients or Servers by default, delete one of both of the following lines:
+ly_create_alias(NAME ${gem_name}.Clients NAMESPACE Gem TARGETS Gem::${gem_name})
+ly_create_alias(NAME ${gem_name}.Servers NAMESPACE Gem TARGETS Gem::${gem_name})
+ly_create_alias(NAME ${gem_name}.Unified NAMESPACE Gem TARGETS Gem::${gem_name})
+
+# For the Client and Server variants of ${gem_name} Gem, an alias to the ${gem_name}.API target will be made
+ly_create_alias(NAME ${gem_name}.Clients.API NAMESPACE Gem TARGETS Gem::${gem_name}.API)
+ly_create_alias(NAME ${gem_name}.Servers.API NAMESPACE Gem TARGETS Gem::${gem_name}.API)
+ly_create_alias(NAME ${gem_name}.Unified.API NAMESPACE Gem TARGETS Gem::${gem_name}.API)
+
+# Add in CMake dependencies for each gem dependency listed in this gem's gem.json file
+# for the Clients, Servers, Unified gem variants
+o3de_add_variant_dependencies_for_gem_dependencies(GEM_NAME ${gem_name} VARIANTS Clients Servers Unified)
+
+# If we are on a host platform, we want to add the host tools targets like the ${gem_name}.Editor MODULE target
+if(PAL_TRAIT_BUILD_HOST_TOOLS)
+    # The ${gem_name}.Editor.API target can be used by other gems that want to interact with the ${gem_name}.Editor module
+    ly_add_target(
+        NAME ${gem_name}.Editor.API INTERFACE
+        NAMESPACE Gem
+        FILES_CMAKE
+            simulationinterfaces_editor_api_files.cmake
+            ${pal_dir}/simulationinterfaces_editor_api_files.cmake
+        INCLUDE_DIRECTORIES
+            INTERFACE
+                Include
+        BUILD_DEPENDENCIES
+            INTERFACE
+                AZ::AzToolsFramework
+    )
+
+    # The ${gem_name}.Editor.Private.Object target is an internal target
+    # which is only to be used by this gems CMakeLists.txt and any subdirectories
+    # Other gems should not use this target
+    ly_add_target(
+        NAME ${gem_name}.Editor.Private.Object STATIC
+        NAMESPACE Gem
+        FILES_CMAKE
+            simulationinterfaces_editor_private_files.cmake
+        TARGET_PROPERTIES
+            O3DE_PRIVATE_TARGET TRUE
+        INCLUDE_DIRECTORIES
+            PRIVATE
+                Include
+                Source
+        BUILD_DEPENDENCIES
+            PUBLIC
+                AZ::AzToolsFramework
+                ${gem_name}.Private.Object
+    )
+
+    ly_add_target(
+        NAME ${gem_name}.Editor GEM_MODULE
+        NAMESPACE Gem
+        AUTOMOC
+        FILES_CMAKE
+            simulationinterfaces_editor_shared_files.cmake
+        INCLUDE_DIRECTORIES
+            PRIVATE
+                Source
+            PUBLIC
+                Include
+        BUILD_DEPENDENCIES
+            PUBLIC
+                Gem::${gem_name}.Editor.API
+            PRIVATE
+                Gem::${gem_name}.Editor.Private.Object
+
+
+    )
+
+    # Include the gem name into the Editor Module source file
+    # for use with the AZ_DECLARE_MODULE_CLASS macro
+    # This is to allow renaming of the gem to also cause
+    # the CreateModuleClass_Gem_<gem-name> function which
+    # is used to bootstrap the gem in monolithic builds to link to the new gem name
+    ly_add_source_properties(
+    SOURCES
+        Source/Tools/SimulationInterfacesEditorModule.cpp
+    PROPERTY COMPILE_DEFINITIONS
+        VALUES
+            O3DE_GEM_NAME=${gem_name}
+            O3DE_GEM_VERSION=${gem_version})
+
+    # By default, we will specify that the above target ${gem_name} would be used by
+    # Tool and Builder type targets when this gem is enabled.  If you don't want it
+    # active in Tools or Builders by default, delete one of both of the following lines:
+    ly_create_alias(NAME ${gem_name}.Tools    NAMESPACE Gem TARGETS Gem::${gem_name}.Editor)
+    ly_create_alias(NAME ${gem_name}.Builders NAMESPACE Gem TARGETS Gem::${gem_name}.Editor)
+
+    # For the Tools and Builders variants of ${gem_name} Gem, an alias to the ${gem_name}.Editor API target will be made
+    ly_create_alias(NAME ${gem_name}.Tools.API NAMESPACE Gem TARGETS Gem::${gem_name}.Editor.API)
+    ly_create_alias(NAME ${gem_name}.Builders.API NAMESPACE Gem TARGETS Gem::${gem_name}.Editor.API)
+
+    # Add in CMake dependencies for each gem dependency listed in this gem's gem.json file
+    # for the Tools and Builders gem variants
+    o3de_add_variant_dependencies_for_gem_dependencies(GEM_NAME ${gem_name} VARIANTS Tools Builders)
+endif()
+
+################################################################################
+# Tests
+################################################################################
+# See if globally, tests are supported
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
+    # We globally support tests, see if we support tests on this platform for ${gem_name}.Tests
+    if(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED)
+        # We support ${gem_name}.Tests on this platform, add dependency on the Private Object target
+        ly_add_target(
+            NAME ${gem_name}.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
+            NAMESPACE Gem
+            FILES_CMAKE
+                simulationinterfaces_tests_files.cmake
+            INCLUDE_DIRECTORIES
+                PRIVATE
+                    Tests
+                    Source
+                    Include
+            BUILD_DEPENDENCIES
+                PRIVATE
+                    AZ::AzTest
+                    AZ::AzFramework
+                    Gem::${gem_name}.Private.Object
+        )
+
+        # Add ${gem_name}.Tests to googletest
+        ly_add_googletest(
+            NAME Gem::${gem_name}.Tests
+        )
+    endif()
+
+    # If we are a host platform we want to add tools test like editor tests here
+    if(PAL_TRAIT_BUILD_HOST_TOOLS)
+        # We are a host platform, see if Editor tests are supported on this platform
+        if(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED)
+            # We support ${gem_name}.Editor.Tests on this platform, add ${gem_name}.Editor.Tests target which depends on
+            # private ${gem_name}.Editor.Private.Object target
+            ly_add_target(
+                NAME ${gem_name}.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
+                NAMESPACE Gem
+                FILES_CMAKE
+                    simulationinterfaces_editor_tests_files.cmake
+                INCLUDE_DIRECTORIES
+                    PRIVATE
+                        Tests
+                        Source
+                        Include
+                BUILD_DEPENDENCIES
+                    PRIVATE
+                        AZ::AzTest
+                        AZ::AzTestShared
+                        AZ::AzToolsFramework
+                        Legacy::CryCommon
+                        Legacy::EditorCommon
+                        Legacy::Editor.Headers
+                        AZ::AzManipulatorTestFramework.Static
+                        Gem::${gem_name}.API
+                        Gem::${gem_name}.Editor.Private.Object
+            )
+
+            # Add ${gem_name}.Editor.Tests to googletest
+            ly_add_googletest(
+                NAME Gem::${gem_name}.Editor.Tests
+            )
+
+            ly_add_target(
+                    NAME ${gem_name}.TestApp ${PAL_TRAIT_TEST_TARGET_TYPE}
+                    NAMESPACE Gem
+                    FILES_CMAKE
+                    simulationinterfaces_editor_app_test.cmake
+                    INCLUDE_DIRECTORIES
+                    PRIVATE
+                    Tests
+                    Source
+                    Include
+                    BUILD_DEPENDENCIES
+                    PRIVATE
+                    AZ::AzTest
+                    AZ::AzTestShared
+                    AZ::AzToolsFramework
+                    Legacy::CryCommon
+                    Legacy::EditorCommon
+                    Legacy::Editor.Headers
+                    AZ::AzManipulatorTestFramework.Static
+                    Gem::${gem_name}.API
+                    Gem::${gem_name}.Editor.Private.Object
+            )
+
+            # Add ${gem_name}.Editor.Tests to googletest
+            ly_add_googletest(
+                    NAME Gem::${gem_name}.TestApp
+            )
+        endif()
+    endif()
+endif()

+ 102 - 0
Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationEntityManagerRequestBus.h

@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+#include <AzCore/EBus/EBus.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzCore/std/smart_ptr/shared_ptr.h>
+#include <AzFramework/Physics/ShapeConfiguration.h>
+
+namespace SimulationInterfaces
+{
+    //! # A set of filters to apply to entity queries. See GetEntities, GetEntitiesStates.
+    //! # The filters are combined with a logical AND.
+    //! @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/msg/EntityFilters.msg">EntityFilters.msg</a>
+    struct EntityFilters
+    {
+        AZStd::string m_filter; //! A posix regular expression to match against entity names
+        AZStd::shared_ptr<Physics::ShapeConfiguration>
+            m_bounds_shape; //! A shape to use for filtering entities, null means no bounds filtering
+        AZ::Transform m_bounds_pose{ AZ::Transform::CreateIdentity() };
+    };
+
+    //!  @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/msg/EntityState.msg">EntityState.msg</a>
+    struct EntityState
+    {
+        AZ::Transform m_pose; //! The pose of the entity
+        AZ::Vector3 m_twist_linear; //! The linear velocity of the entity (in the entity frame)
+        AZ::Vector3 m_twist_angular; //! The angular velocity of the entity (in the entity frame)
+    };
+
+    struct Spawnable
+    {
+        AZStd::string m_uri;
+        AZStd::string m_description;
+        AZStd::string m_bounds_sphere;
+    };
+
+    class SimulationEntityManagerRequests
+    {
+    public:
+        AZ_RTTI(SimulationEntityManagerRequests, SimulationInterfacesRequestsTypeId);
+        virtual ~SimulationEntityManagerRequests() = default;
+
+        //! # Get a list of entities that match the filter.
+        //! Supported filters:
+        //! - name : a posix regular expression to match against entity names
+        //! - bounds : a shape to use for filtering entities, null means no bounds filtering
+        //!  @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/srv/GetEntities.srv">GetEntities.srv</a>
+        virtual AZStd::vector<AZStd::string> GetEntities(const EntityFilters& filter) = 0;
+
+        //! Get the state of an entity.
+        //!  @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/srv/GetEntityState.srv">GetEntityState.srv</a>
+        virtual EntityState GetEntityState(const AZStd::string& name) = 0;
+
+        //! Get the state of all entities that match the filter.
+        //! @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/srv/GetEntitiesStates.srv">GetEntitiesStates.srv</a>
+        virtual AZStd::unordered_map<AZStd::string, EntityState> GetEntitiesStates(const EntityFilters& filter) = 0;
+
+        //! Set the state of an entity.
+        //! @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/srv/SetEntityState.srv">SetEntityState.srv</a>
+        virtual bool SetEntityState(const AZStd::string& name, const EntityState& state) = 0;
+
+        //! Remove previously spawned entity from the simulation.
+        //! @see <a href="https://github.com/ros-simulation/simulation_interfaces/blob/main/srv/DeleteEntity.srv">DeleteEntity.srv</a>
+        virtual bool DeleteEntity(const AZStd::string& name) = 0;
+
+        virtual AZStd::vector<Spawnable> GetSpawnables() = 0;
+
+        //! Callback for when an entity has been spawned and registered. The string is the name of the entity in the simulation interface.
+        //! Note : The names is empty, if the entity could not be registered (e.g. prefab has no simulated entities)
+        using SpawnCompletedCb = AZStd::function<void(const AZ::Outcome<AZStd::string, AZStd::string>&)>;
+
+        virtual void SpawnEntity(
+            const AZStd::string& name,
+            const AZStd::string& uri,
+            const AZStd::string& entityNamespace,
+            const AZ::Transform& initialPose,
+            SpawnCompletedCb completedCb) = 0;
+    };
+
+    class SimulationInterfacesBusTraits : public AZ::EBusTraits
+    {
+    public:
+        //////////////////////////////////////////////////////////////////////////
+        // EBusTraits overrides
+        static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+        static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+        //////////////////////////////////////////////////////////////////////////
+    };
+
+    using SimulationEntityManagerRequestBus = AZ::EBus<SimulationEntityManagerRequests, SimulationInterfacesBusTraits>;
+    using SimulationEntityManagerInterface = AZ::Interface<SimulationEntityManagerRequests>;
+
+} // namespace SimulationInterfaces

+ 31 - 0
Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationInterfacesTypeIds.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+namespace SimulationInterfaces
+{
+    // System Component TypeIds
+    inline constexpr const char* SimulationEntitiesManagerTypeId = "{4BF53AF2-A295-4F99-A166-F85FBFBDC077}";
+    inline constexpr const char* SimulationEntitiesManagerEditorTypeId = "{B035007B-BAD3-40FA-880F-F45054A4C232}";
+
+    inline constexpr const char* SimulationManagerTypeId = "{5BB34EB0-1263-4DA1-A35C-CE613A088F4B}";
+    inline constexpr const char* SimulationManagerEditorTypeId = "{2CC8D67B-CFD3-4E89-AAF0-8935640B51C1}";
+
+    // Module derived classes TypeIds
+    inline constexpr const char* SimulationInterfacesModuleInterfaceTypeId = "{675797BF-E5D5-438A-BF86-4B4554F09CEF}";
+    inline constexpr const char* SimulationInterfacesModuleTypeId = "{8D6741FD-3105-4CB0-9700-152123B6D135}";
+    // The Editor Module by default is mutually exclusive with the Client Module
+    // so they use the Same TypeId
+    inline constexpr const char* SimulationInterfacesEditorModuleTypeId = SimulationInterfacesModuleTypeId;
+
+    // Interface TypeIds
+    inline constexpr const char* SimulationInterfacesRequestsTypeId = "{6818E5E3-BBF5-41BD-96BB-7AF57CCC7528}";
+    inline constexpr const char* SimulationManagerRequestsTypeId = "{056477BA-8153-4901-9401-0146A5E3E9ED}";
+
+} // namespace SimulationInterfaces

+ 45 - 0
Gems/SimulationInterfaces/Code/Include/SimulationInterfaces/SimulationMangerRequestBus.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+#include <AzCore/EBus/EBus.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzCore/std/smart_ptr/shared_ptr.h>
+#include <AzFramework/Physics/ShapeConfiguration.h>
+
+namespace SimulationInterfaces
+{
+
+    class SimulationManagerRequests
+    {
+    public:
+        AZ_RTTI(SimulationManagerRequests, SimulationManagerRequestsTypeId);
+        virtual ~SimulationManagerRequests() = default;
+
+        virtual void SetSimulationPaused(bool paused) = 0;
+        virtual void StepSimulation(AZ::u32 steps) = 0;
+
+    };
+
+    class SimulationMangerRequestBusTraits : public AZ::EBusTraits
+    {
+    public:
+        //////////////////////////////////////////////////////////////////////////
+        // EBusTraits overrides
+        static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+        static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+        //////////////////////////////////////////////////////////////////////////
+    };
+
+    using SimulationManagerRequestBus = AZ::EBus<SimulationManagerRequests, SimulationMangerRequestBusTraits>;
+    using SimulationManagerRequestBusInterface = AZ::Interface<SimulationManagerRequests>;
+
+} // namespace SimulationInterfaces

+ 9 - 0
Gems/SimulationInterfaces/Code/Platform/Android/PAL_android.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED FALSE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED FALSE)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_private_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Android
+# i.e. ../Source/Android/SimulationInterfacesAndroid.cpp
+#      ../Source/Android/SimulationInterfacesAndroid.h
+#      ../Include/Android/SimulationInterfacesAndroid.h
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Android/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Android
+# i.e. ../Source/Android/SimulationInterfacesAndroid.cpp
+#      ../Source/Android/SimulationInterfacesAndroid.h
+#      ../Include/Android/SimulationInterfacesAndroid.h
+
+set(FILES
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/Platform/Linux/PAL_linux.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED TRUE)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_editor_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_private_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Linux
+# i.e. ../Source/Linux/SimulationInterfacesLinux.cpp
+#      ../Source/Linux/SimulationInterfacesLinux.h
+#      ../Include/Linux/SimulationInterfacesLinux.h
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Linux/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Linux
+# i.e. ../Source/Linux/SimulationInterfacesLinux.cpp
+#      ../Source/Linux/SimulationInterfacesLinux.h
+#      ../Include/Linux/SimulationInterfacesLinux.h
+
+set(FILES
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/Platform/Mac/PAL_mac.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED FALSE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED FALSE)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_editor_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_private_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Mac
+# i.e. ../Source/Mac/SimulationInterfacesMac.cpp
+#      ../Source/Mac/SimulationInterfacesMac.h
+#      ../Include/Mac/SimulationInterfacesMac.h
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Mac/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Mac
+# i.e. ../Source/Mac/SimulationInterfacesMac.cpp
+#      ../Source/Mac/SimulationInterfacesMac.h
+#      ../Include/Mac/SimulationInterfacesMac.h
+
+set(FILES
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/Platform/Windows/PAL_windows.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED FALSE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED FALSE)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_editor_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_private_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Windows
+# i.e. ../Source/Windows/SimulationInterfacesWindows.cpp
+#      ../Source/Windows/SimulationInterfacesWindows.h
+#      ../Include/Windows/SimulationInterfacesWindows.h
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/Windows/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for Windows
+# i.e. ../Source/Windows/SimulationInterfacesWindows.cpp
+#      ../Source/Windows/SimulationInterfacesWindows.h
+#      ../Include/Windows/SimulationInterfacesWindows.h
+
+set(FILES
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/Platform/iOS/PAL_ios.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(PAL_TRAIT_SIMULATIONINTERFACES_SUPPORTED TRUE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_TEST_SUPPORTED FALSE)
+set(PAL_TRAIT_SIMULATIONINTERFACES_EDITOR_TEST_SUPPORTED FALSE)

+ 8 - 0
Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_api_files.cmake

@@ -0,0 +1,8 @@
+# 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
+#
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_private_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for iOS
+# i.e. ../Source/iOS/SimulationInterfacesiOS.cpp
+#      ../Source/iOS/SimulationInterfacesiOS.h
+#      ../Include/iOS/SimulationInterfacesiOS.h
+
+set(FILES
+)

+ 13 - 0
Gems/SimulationInterfaces/Code/Platform/iOS/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,13 @@
+# 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
+#
+
+# Platform specific files for iOS
+# i.e. ../Source/iOS/SimulationInterfacesiOS.cpp
+#      ../Source/iOS/SimulationInterfacesiOS.h
+#      ../Include/iOS/SimulationInterfacesiOS.h
+
+set(FILES
+)

+ 31 - 0
Gems/SimulationInterfaces/Code/Source/Clients/CommonUtilities.cpp

@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ */
+
+#include "CommonUtilities.h"
+
+namespace SimulationInterfaces::Utils
+{
+    const char* const ProductAssetPrefix = "product_asset:///";
+    AZStd::string RelPathToUri(AZStd::string_view relPath)
+    {
+        AZStd::string uri = relPath;
+        AZStd::replace(uri.begin(), uri.end(), '\\', '/');
+        uri.insert(0, ProductAssetPrefix);
+        return uri;
+    }
+
+    AZStd::string UriToRelPath(AZStd::string_view uri)
+    {
+        if (uri.starts_with(ProductAssetPrefix))
+        {
+            const AZStd::string_view productAssetPrefix{ ProductAssetPrefix };
+            return uri.substr(productAssetPrefix.length());
+        }
+        return {};
+    }
+} // namespace SimulationInterfaces::Utils

+ 20 - 0
Gems/SimulationInterfaces/Code/Source/Clients/CommonUtilities.h

@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/std/string/string.h>
+namespace SimulationInterfaces::Utils
+{
+    //! Convert a relative path to a URI
+    //! relative path: "path/to/file.txt"
+    //! URI: "product_asset:///path/to/file.txt"
+    AZStd::string RelPathToUri(AZStd::string_view relPath);
+    AZStd::string UriToRelPath(AZStd::string_view relPath);
+
+} // namespace SimulationInterfaces::Utils

+ 224 - 0
Gems/SimulationInterfaces/Code/Source/Clients/ConsoleCommands.inl

@@ -0,0 +1,224 @@
+/*
+ * 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
+ *
+ */
+
+#include <AzCore/Component/ComponentApplicationBus.h>
+#include <AzCore/Console/IConsole.h>
+#include <AzCore/Math/MathScriptHelpers.h>
+#include <AzCore/std/smart_ptr/make_shared.h>
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+#include <SimulationInterfaces/SimulationMangerRequestBus.h>
+
+namespace SimulationInterfacesCommands
+{
+
+    using namespace SimulationInterfaces;
+    static void simulationinterfaces_GetEntities(const AZ::ConsoleCommandContainer& arguments)
+    {
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        AZ_Printf("SimulationInterfacesConsole", "Number of simulation entities: %d\n", entities.size());
+        for (const auto& entity : entities)
+        {
+            AZ_Printf("SimulationInterfacesConsole", "      - %s\n", entity.c_str());
+        }
+    }
+
+    static void simulationinterfaces_Pause(const AZ::ConsoleCommandContainer& arguments)
+    {
+        SimulationManagerRequestBus::Broadcast(&SimulationManagerRequestBus::Events::SetSimulationPaused, true);
+    }
+
+    static void simulationinterfaces_Resume(const AZ::ConsoleCommandContainer& arguments)
+    {
+        SimulationManagerRequestBus::Broadcast(&SimulationManagerRequestBus::Events::SetSimulationPaused, false);
+    }
+
+
+    static void simulationinterfaces_Step(const AZ::ConsoleCommandContainer& arguments)
+    {
+        if (arguments.empty())
+        {
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_Step <number of steps>\n");
+            return;
+        }
+        uint32_t steps = AZStd::stoi(AZStd::string(arguments[0]));
+
+        SimulationManagerRequestBus::Broadcast(&SimulationManagerRequestBus::Events::StepSimulation, steps);
+    }
+
+
+
+    static void simulationinterfaces_GetEntitiesSphere(const AZ::ConsoleCommandContainer& arguments)
+    {
+        float sphereShape = 10.f;
+        AZ::Vector3 position = AZ::Vector3::CreateZero();
+        sphereShape = arguments.empty() ? 10.f : (AZStd::stof(AZStd::string(arguments[0])));
+        position.SetX(arguments.size() > 1 ? (AZStd::stof(AZStd::string(arguments[1]))) : 0.f);
+        position.SetY(arguments.size() > 2 ? (AZStd::stof(AZStd::string(arguments[2]))) : 0.f);
+        position.SetZ(arguments.size() > 3 ? (AZStd::stof(AZStd::string(arguments[3]))) : 0.f);
+
+        AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_GetEntities in radius %f \n", sphereShape);
+        AZ_Printf("SimulationInterfacesConsole", "position %f %f %f \n", position.GetX(), position.GetY(), position.GetZ());
+        EntityFilters filter;
+        filter.m_bounds_shape = AZStd::make_shared<Physics::SphereShapeConfiguration>(sphereShape);
+
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
+        AZ_Printf("SimulationInterfacesConsole", "Number of simulation entities: %d\n", entities.size());
+        for (const auto& entity : entities)
+        {
+            AZ_Printf("SimulationInterfacesConsole", "      - %s\n", entity.c_str());
+        }
+    }
+
+    static void simulationinterfaces_GetEntityState(const AZ::ConsoleCommandContainer& arguments)
+    {
+        if (arguments.empty())
+        {
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_GetEntityState requires entity name\n");
+            return;
+        }
+        const AZStd::string entityName = arguments[0];
+        AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_GetEntityState %s\n", entityName.c_str());
+        EntityState entityState;
+        SimulationEntityManagerRequestBus::BroadcastResult(entityState, &SimulationEntityManagerRequestBus::Events::GetEntityState, entityName);
+        AZ_Printf("SimulationInterfacesConsole", "Entity %s\n", entityName.c_str());
+        AZ_Printf(
+            "SimulationInterfacesConsole",
+            "Pose %s\n",
+            AZ::Vector3ToString(entityState.m_pose.GetTranslation()).c_str());
+        AZ_Printf(
+            "SimulationInterfacesConsole",
+            "Rotation %s \n",
+             AZ::QuaternionToString(entityState.m_pose.GetRotation()).c_str());
+
+        const AZ::Vector3 euler = entityState.m_pose.GetRotation().GetEulerDegrees();
+        AZ_Printf("SimulationInterfacesConsole", "Rotation (euler) %s\n", AZ::Vector3ToString(euler).c_str());
+        AZ_Printf(
+            "SimulationInterfacesConsole",
+            "Twist Linear %s\n",
+            AZ::Vector3ToString(entityState.m_twist_linear).c_str());
+        AZ_Printf(
+            "SimulationInterfacesConsole",
+            "Twist Angular %s\n",
+            AZ::Vector3ToString(entityState.m_twist_angular).c_str());
+    }
+
+    static void simulationinterfaces_SetStateXYZ(const AZ::ConsoleCommandContainer& arguments)
+    {
+        if (arguments.empty())
+        {
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_GetEntityState requires entity name\n");
+            return;
+        }
+        const AZStd::string entityName = arguments[0];
+        AZ::Vector3 position = AZ::Vector3::CreateZero();
+        position.SetX(arguments.size() > 1 ? (AZStd::stof(AZStd::string(arguments[1]))) : 0.f);
+        position.SetY(arguments.size() > 2 ? (AZStd::stof(AZStd::string(arguments[2]))) : 0.f);
+        position.SetZ(arguments.size() > 3 ? (AZStd::stof(AZStd::string(arguments[3]))) : 0.f);
+        EntityState entityState{};
+        entityState.m_pose = AZ::Transform::CreateIdentity();
+        entityState.m_pose.SetTranslation(position);
+        bool isOk = false;
+        SimulationEntityManagerRequestBus::BroadcastResult(
+            isOk, &SimulationEntityManagerRequestBus::Events::SetEntityState, entityName, entityState);
+        if (isOk)
+        {
+            AZ_Printf("SimulationInterfacesConsole", "Entity %s state set\n", entityName.c_str());
+        }
+        else
+        {
+            AZ_Printf("SimulationInterfacesConsole", "Entity %s state NOT set\n", entityName.c_str());
+        }
+    }
+
+    static void simulationinterfaces_DeleteEntity(const AZ::ConsoleCommandContainer& arguments)
+    {
+        if (arguments.empty())
+        {
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_DeleteEntity requires entity name\n");
+            return;
+        }
+        const AZStd::string entityName = arguments[0];
+        AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_DeleteEntity %s\n", entityName.c_str());
+        bool isOk = false;
+        SimulationEntityManagerRequestBus::BroadcastResult(isOk, &SimulationEntityManagerRequestBus::Events::DeleteEntity, entityName);
+        if (isOk)
+        {
+            AZ_Printf("SimulationInterfacesConsole", "Entity %s deleted\n", entityName.c_str());
+        }
+        else
+        {
+            AZ_Printf("SimulationInterfacesConsole", "Entity %s NOT deleted\n", entityName.c_str());
+        }
+    }
+
+    static void simulationinterfaces_GetSpawnables(const AZ::ConsoleCommandContainer& arguments)
+    {
+        AZ_Printf("SimulationInterfacesConsole", "simulationinterfaces_GetSpawnables\n");
+        AZStd::vector<Spawnable> spawnables;
+        SimulationEntityManagerRequestBus::BroadcastResult(spawnables, &SimulationEntityManagerRequestBus::Events::GetSpawnables);
+        AZ_Printf("SimulationInterfacesConsole", "Number of spawnables: %d\n", spawnables.size());
+        for (const auto& spawnable : spawnables)
+        {
+            AZ_Printf("SimulationInterfaces", "      - %s\n", spawnable.m_uri.c_str());
+        }
+    }
+
+    static void simulationinterfaces_Spawn(const AZ::ConsoleCommandContainer& arguments)
+    {
+        if (arguments.size() < 2)
+        {
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterface_Spawn minimal :\n");
+            AZ_Printf("SimulationInterfacesConsole", "     simulationinterface_Spawn <name> <uri>\n");
+            AZ_Printf("SimulationInterfacesConsole", "simulationinterface_Spawn optional :\n");
+            AZ_Printf("SimulationInterfacesConsole", "     simulationinterface_Spawn <name> <uri> <namespace> <x> <y> <z> \n");
+            return;
+        }
+        AZStd::string name = arguments[0];
+        AZStd::string uri = arguments[1];
+        AZStd::string entityNamespace = arguments.size() > 2 ? arguments[2] : "";
+        AZ::Transform initialPose = AZ::Transform::CreateIdentity();
+        if (arguments.size() > 5)
+        {
+            initialPose.SetTranslation(
+                AZ::Vector3(
+                    AZStd::stof(AZStd::string(arguments[3])),
+                    AZStd::stof(AZStd::string(arguments[4])),
+                    AZStd::stof(AZStd::string(arguments[5]))));
+        }
+        SimulationEntityManagerRequests::SpawnCompletedCb completedCb = [](const AZ::Outcome<AZStd::string, AZStd::string>& name)
+        {
+            if (name.IsSuccess())
+            {
+                AZ_Printf("SimulationInterfacesConsole", "Entity %s spawned and registered\n", name.GetValue().c_str());
+            }
+            else
+            {
+                AZ_Printf("SimulationInterfacesConsole", "Entity NOT spawned. Error : %s\n", name.GetError().c_str());
+            }
+        };
+        SimulationEntityManagerRequestBus::Broadcast(&SimulationEntityManagerRequestBus::Events::SpawnEntity, name, uri, entityNamespace, initialPose, completedCb);
+        AZ_Printf("SimulationInterfacesConsole", "simulationinterface_Spawn %s %s\n", name.c_str(), uri.c_str());
+    }
+
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_Pause, AZ::ConsoleFunctorFlags::DontReplicate, "Pause simulation.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_Resume, AZ::ConsoleFunctorFlags::DontReplicate, "Resume simulation.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_Step, AZ::ConsoleFunctorFlags::DontReplicate, "Step simulation.");
+
+    AZ_CONSOLEFREEFUNC(
+        simulationinterfaces_GetEntities, AZ::ConsoleFunctorFlags::DontReplicate, "Get all simulated entities in the scene.");
+    AZ_CONSOLEFREEFUNC(
+        simulationinterfaces_GetEntitiesSphere, AZ::ConsoleFunctorFlags::DontReplicate, "Get all simulated entities in the radius.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_GetEntityState, AZ::ConsoleFunctorFlags::DontReplicate, "Get state of the entity.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_SetStateXYZ, AZ::ConsoleFunctorFlags::DontReplicate, "Set state of the entity.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_DeleteEntity, AZ::ConsoleFunctorFlags::DontReplicate, "Delete entity.");
+    AZ_CONSOLEFREEFUNC(
+        simulationinterfaces_GetSpawnables, AZ::ConsoleFunctorFlags::DontReplicate, "Get all spawnable entities in the scene.");
+    AZ_CONSOLEFREEFUNC(simulationinterfaces_Spawn, AZ::ConsoleFunctorFlags::DontReplicate, "Spawn entity.");
+} // namespace SimulationInterfacesCommands

+ 586 - 0
Gems/SimulationInterfaces/Code/Source/Clients/SimulationEntitiesManager.cpp

@@ -0,0 +1,586 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationEntitiesManager.h"
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+#include "CommonUtilities.h"
+#include "ConsoleCommands.inl"
+#include <AzCore/Asset/AssetManager.h>
+#include <AzCore/Asset/AssetManagerBus.h>
+#include <AzCore/Component/ComponentApplicationBus.h>
+#include <AzCore/Component/TransformBus.h>
+#include <AzCore/Console/IConsole.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/std/string/regex.h>
+#include <AzFramework/Components/TransformComponent.h>
+#include <AzFramework/Physics/PhysicsSystem.h>
+#include <AzFramework/Physics/RigidBodyBus.h>
+#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
+#include <AzFramework/Spawnable/Spawnable.h>
+#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
+
+namespace SimulationInterfaces
+{
+    void SetRigidBodyVelocities(AzPhysics::RigidBody* rigidBody, const EntityState& state)
+    {
+        if (!state.m_twist_angular.IsClose(AZ::Vector3::CreateZero(), AZ::Constants::FloatEpsilon))
+        {
+            // get transform
+            AZ::Vector3 angularVelWorld = rigidBody->GetTransform().TransformVector(state.m_twist_angular);
+            rigidBody->SetAngularVelocity(angularVelWorld);
+        }
+
+        if (!state.m_twist_linear.IsClose(AZ::Vector3::CreateZero(), AZ::Constants::FloatEpsilon))
+        {
+            // get transform
+            AZ::Vector3 linearVelWorld = rigidBody->GetTransform().TransformVector(state.m_twist_linear);
+            rigidBody->SetAngularVelocity(linearVelWorld);
+        }
+    }
+
+    AZ_COMPONENT_IMPL(SimulationEntitiesManager, "SimulationEntitiesManager", SimulationEntitiesManagerTypeId);
+
+    void SimulationEntitiesManager::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<SimulationEntitiesManager, AZ::Component>()->Version(0);
+        }
+    }
+
+    void SimulationEntitiesManager::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(AZ_CRC_CE("SimulationInterfacesService"));
+    }
+
+    void SimulationEntitiesManager::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        incompatible.push_back(AZ_CRC_CE("SimulationInterfacesService"));
+    }
+
+    void SimulationEntitiesManager::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        required.push_back(AZ_CRC_CE("AssetCatalogService"));
+    }
+
+    void SimulationEntitiesManager::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    {
+        dependent.push_back(AZ_CRC_CE("PhysicsService"));
+    }
+
+    SimulationEntitiesManager::SimulationEntitiesManager()
+    {
+        if (SimulationEntityManagerInterface::Get() == nullptr)
+        {
+            SimulationEntityManagerInterface::Register(this);
+        }
+    }
+
+    SimulationEntitiesManager::~SimulationEntitiesManager()
+    {
+        if (SimulationEntityManagerInterface::Get() == this)
+        {
+            SimulationEntityManagerInterface::Unregister(this);
+        }
+    }
+
+    void SimulationEntitiesManager::Init()
+    {
+    }
+
+    AzPhysics::Scene* GetSceneHelper(AzPhysics::SceneHandle sceneHandle)
+    {
+        AzPhysics::SystemInterface* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+        AZ_Assert(physicsSystem, "Physics system is not available.");
+        AzPhysics::Scene* scene = physicsSystem->GetScene(sceneHandle);
+        return scene;
+    }
+
+    void SimulationEntitiesManager::Activate()
+    {
+        m_simulationBodyAddedHandler = AzPhysics::SceneEvents::OnSimulationBodyAdded::Handler(
+            [this](AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle)
+            {
+                auto* scene = GetSceneHelper(sceneHandle);
+                if (scene == nullptr)
+                {
+                    return;
+                }
+                auto* body = scene->GetSimulatedBodyFromHandle(bodyHandle);
+                AZ_Assert(body, "Simulated body is not available.");
+                auto* rigidBody = azdynamic_cast<AzPhysics::RigidBody*>(body);
+                if (rigidBody != nullptr)
+                {
+                    [[maybe_unused]] auto shapeCount = rigidBody->GetShapeCount();
+                    AZ_Warning(
+                        "SimulationInterfaces",
+                        shapeCount > 0,
+                        "Entity %s has no collider shapes, it won't be available by bound search",
+                        rigidBody->GetEntityId().ToString().c_str());
+                }
+                const AZ::EntityId entityId = body->GetEntityId();
+                AZ::Entity* entity = nullptr;
+                AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
+                AZ_Assert(entity, "Entity is not available.");
+                // check if entity is not spawned by this component
+                const auto ticketId = entity->GetEntitySpawnTicketId();
+                AZStd::string proposedName{};
+                // check if ticket is in the unregistered list
+
+                auto spawnData = m_spawnCompletedCallbacks.find(ticketId);
+                if (spawnData != m_spawnCompletedCallbacks.end())
+                {
+                    proposedName = spawnData->second.m_userProposedName;
+                }
+
+                const AZStd::string registeredName = this->AddSimulatedEntity(entityId, proposedName);
+                // call the callback
+                if (spawnData != m_spawnCompletedCallbacks.end())
+                {
+                    // call and remove the callback
+                    spawnData->second.m_completedCb(AZ::Success(registeredName));
+                    m_spawnCompletedCallbacks.erase(spawnData);
+                }
+            });
+        m_simulationBodyRemovedHandler = AzPhysics::SceneEvents::OnSimulationBodyRemoved::Handler(
+            [this](AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle)
+            {
+                auto* scene = GetSceneHelper(sceneHandle);
+                if (scene == nullptr)
+                {
+                    return;
+                }
+                const auto* body = scene->GetSimulatedBodyFromHandle(bodyHandle);
+                AZ_Assert(body, "Simulated body is not available.");
+                const AZ::EntityId entityId = body->GetEntityId();
+                // remove simulated entity
+                this->RemoveSimulatedEntity(entityId);
+            });
+
+        m_sceneAddedHandler = AzPhysics::SystemEvents::OnSceneAddedEvent::Handler(
+            [this](AzPhysics::SceneHandle sceneHandle)
+            {
+                AZ_Warning("SimulationInterfaces", m_physicsScenesHandle == AzPhysics::InvalidSceneHandle, "Hmm, we already have a scene");
+                auto* scene = GetSceneHelper(sceneHandle);
+                AZ_Assert(scene, "Scene is not available.");
+                if (scene == nullptr)
+                {
+                    return;
+                }
+                scene->RegisterSimulationBodyAddedHandler(m_simulationBodyAddedHandler);
+                scene->RegisterSimulationBodyRemovedHandler(m_simulationBodyRemovedHandler);
+
+                AZ_Printf("SimulationInterfaces", "Registered simulation body added handler\n");
+                m_physicsScenesHandle = sceneHandle;
+            });
+        m_sceneRemovedHandler = AzPhysics::SystemEvents::OnSceneRemovedEvent::Handler(
+            [this](AzPhysics::SceneHandle sceneHandle)
+            {
+                if (m_physicsScenesHandle == sceneHandle)
+                {
+                    m_entityIdToSimulatedEntityMap.clear();
+                    m_simulatedEntityToEntityIdMap.clear();
+                    m_simulationBodyAddedHandler.Disconnect();
+                    m_simulationBodyRemovedHandler.Disconnect();
+                    m_physicsScenesHandle = AzPhysics::InvalidSceneHandle;
+                }
+            });
+        AzPhysics::SystemInterface* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+        if (physicsSystem)
+        {
+            physicsSystem->RegisterSceneAddedEvent(m_sceneAddedHandler);
+            physicsSystem->RegisterSceneRemovedEvent(m_sceneRemovedHandler);
+            SimulationEntityManagerRequestBus::Handler::BusConnect();
+        }
+    }
+
+    void SimulationEntitiesManager::Deactivate()
+    {
+        SimulationEntityManagerRequestBus::Handler::BusDisconnect();
+        if (m_simulationBodyAddedHandler.IsConnected())
+        {
+            m_simulationBodyAddedHandler.Disconnect();
+        }
+        if (m_simulationBodyRemovedHandler.IsConnected())
+        {
+            m_simulationBodyRemovedHandler.Disconnect();
+        }
+        m_physicsScenesHandle = AzPhysics::InvalidSceneHandle;
+        if (m_sceneAddedHandler.IsConnected())
+        {
+            m_sceneAddedHandler.Disconnect();
+        }
+        if (m_sceneAddedHandler.IsConnected())
+        {
+            m_sceneAddedHandler.Disconnect();
+        }
+    }
+
+    AZStd::string SimulationEntitiesManager::AddSimulatedEntity(AZ::EntityId entityId, const AZStd::string& userProposedName)
+    {
+        if (!entityId.IsValid())
+        {
+            return "";
+        }
+        // check if entity is already registered
+        auto findIt = m_entityIdToSimulatedEntityMap.find(entityId);
+        if (findIt != m_entityIdToSimulatedEntityMap.end())
+        {
+            return findIt->second;
+        }
+        // register entity under unique name
+        AZStd::string simulatedEntityName = GetSimulatedEntityName(entityId, userProposedName);
+        m_simulatedEntityToEntityIdMap[simulatedEntityName] = entityId;
+        m_entityIdToSimulatedEntityMap[entityId] = simulatedEntityName;
+        AZ_Printf("SimulationInterfaces", "Registered entity %s\n", simulatedEntityName.c_str());
+        return simulatedEntityName;
+    }
+
+    void SimulationEntitiesManager::RemoveSimulatedEntity(AZ::EntityId entityId)
+    {
+        auto findIt = m_entityIdToSimulatedEntityMap.find(entityId);
+        if (findIt != m_entityIdToSimulatedEntityMap.end())
+        {
+            const auto& simulatedEntityName = findIt->second;
+            m_entityIdToSimulatedEntityMap.erase(findIt);
+            m_simulatedEntityToEntityIdMap.erase(simulatedEntityName);
+        }
+    }
+
+    AZStd::vector<AZStd::string> SimulationEntitiesManager::GetEntities(const EntityFilters& filter)
+    {
+        const bool reFilter = !filter.m_filter.empty();
+        const bool shapeCastFilter = filter.m_bounds_shape != nullptr;
+
+        AZStd::vector<AZStd::string> entities;
+        if (!shapeCastFilter)
+        {
+            // get all entities from the map
+            entities.reserve(m_entityIdToSimulatedEntityMap.size());
+            AZStd::transform(
+                m_entityIdToSimulatedEntityMap.begin(),
+                m_entityIdToSimulatedEntityMap.end(),
+                AZStd::back_inserter(entities),
+                [](const auto& pair)
+                {
+                    return pair.second;
+                });
+        }
+        else
+        {
+            auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
+            AZ_Assert(sceneInterface, "Physics scene interface is not available.");
+
+            if (m_physicsScenesHandle == AzPhysics::InvalidSceneHandle)
+            {
+                return entities;
+            }
+
+            AzPhysics::OverlapRequest request;
+            request.m_shapeConfiguration = filter.m_bounds_shape;
+            request.m_pose = filter.m_bounds_pose;
+            request.m_maxResults = AZStd::numeric_limits<AZ::u32>::max();
+
+            AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(m_physicsScenesHandle, &request);
+            for (const auto& hit : result.m_hits)
+            {
+                const AZ::EntityId entityId = hit.m_entityId;
+                auto findIt = m_entityIdToSimulatedEntityMap.find(entityId);
+                if (findIt != m_entityIdToSimulatedEntityMap.end())
+                {
+                    entities.push_back(findIt->second);
+                }
+            }
+        }
+        if (reFilter)
+        {
+            const AZStd::vector<AZStd::string> prefilteredEntities = AZStd::move(entities);
+            entities.clear();
+            const AZStd::regex regex(filter.m_filter);
+            if (regex.Valid())
+            {
+                AZStd::ranges::copy_if(
+                    prefilteredEntities,
+                    AZStd::back_inserter(entities),
+                    [&regex](const AZStd::string& entityName)
+                    {
+                        return AZStd::regex_search(entityName, regex);
+                    });
+            }
+        }
+        return entities;
+    }
+
+    EntityState SimulationEntitiesManager::GetEntityState(const AZStd::string& name)
+    {
+        const auto findIt = m_simulatedEntityToEntityIdMap.find(name);
+        AZ_Error("SimulationInterfaces", findIt != m_simulatedEntityToEntityIdMap.end(), "Entity %s not found", name.c_str());
+        if (findIt != m_simulatedEntityToEntityIdMap.end())
+        {
+            EntityState entityState{};
+            const AZ::EntityId entityId = findIt->second;
+            AZ_Assert(entityId.IsValid(), "EntityId is not valid");
+            AZ::TransformBus::EventResult(entityState.m_pose, entityId, &AZ::TransformBus::Events::GetWorldTM);
+
+            AZ::Vector3 linearVelocity = AZ::Vector3::CreateZero();
+            Physics::RigidBodyRequestBus::EventResult(linearVelocity, entityId, &Physics::RigidBodyRequests::GetLinearVelocity);
+
+            AZ::Vector3 angularVelocity = AZ::Vector3::CreateZero();
+            Physics::RigidBodyRequestBus::EventResult(angularVelocity, entityId, &Physics::RigidBodyRequests::GetAngularVelocity);
+
+            // transform linear and angular velocities to entity frame
+            AZ::Transform entityTransformInv = entityState.m_pose.GetInverse();
+            entityState.m_twist_linear = entityTransformInv.TransformVector(linearVelocity);
+            entityState.m_twist_angular = entityTransformInv.TransformVector(angularVelocity);
+            return entityState;
+        }
+        return {};
+    }
+
+    bool SimulationEntitiesManager::SetEntityState(const AZStd::string& name, const EntityState& state)
+    {
+        const auto findIt = m_simulatedEntityToEntityIdMap.find(name);
+        if (findIt != m_simulatedEntityToEntityIdMap.end())
+        {
+            const AZ::EntityId entityId = findIt->second;
+            AZ_Assert(entityId.IsValid(), "EntityId is not valid");
+
+            // get entity and all descendants
+            AZStd::vector<AZ::EntityId> entityAndDescendants;
+            AZ::TransformBus::EventResult(entityAndDescendants, entityId, &AZ::TransformBus::Events::GetEntityAndAllDescendants);
+
+            if (state.m_pose.IsOrthogonal())
+            {
+                // disable simulation for all entities
+                AZStd::map<AZ::EntityId, AZ::Transform> entityTransforms;
+                for (const auto& descendant : entityAndDescendants)
+                {
+                    // get name
+                    AZStd::string entityName = "Unknown";
+                    AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, descendant);
+                    AZ_Printf("SimulationInterfaces", "Disable physics for entity %s\n", entityName.c_str());
+                    Physics::RigidBodyRequestBus::Event(descendant, &Physics::RigidBodyRequests::DisablePhysics);
+                }
+
+                AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalTM, state.m_pose);
+
+                for (const auto& descendant : entityAndDescendants)
+                {
+                    Physics::RigidBodyRequestBus::Event(descendant, &Physics::RigidBodyRequests::EnablePhysics);
+                    Physics::RigidBodyRequestBus::Event(
+                        descendant, &Physics::RigidBodyRequests::SetAngularVelocity, AZ::Vector3::CreateZero());
+                    Physics::RigidBodyRequestBus::Event(
+                        descendant, &Physics::RigidBodyRequests::SetLinearVelocity, AZ::Vector3::CreateZero());
+                }
+            }
+            if (!state.m_twist_linear.IsZero(AZ::Constants::FloatEpsilon) || !state.m_twist_angular.IsZero(AZ::Constants::FloatEpsilon))
+            {
+                // get rigid body
+                AzPhysics::RigidBody* rigidBody = nullptr;
+                Physics::RigidBodyRequestBus::EventResult(rigidBody, entityId, &Physics::RigidBodyRequests::GetRigidBody);
+                if (rigidBody != nullptr)
+                {
+                    SetRigidBodyVelocities(rigidBody, state);
+                }
+            }
+        }
+        return false;
+    }
+
+    bool SimulationEntitiesManager::DeleteEntity(const AZStd::string& name)
+    {
+        const auto findIt = m_simulatedEntityToEntityIdMap.find(name);
+
+        if (findIt == m_simulatedEntityToEntityIdMap.end())
+        {
+            return false;
+        }
+
+        const AZ::EntityId entityId = findIt->second;
+        AZ_Assert(entityId.IsValid(), "EntityId is not valid");
+        // get entity
+        AZ::Entity* entity = nullptr;
+        AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
+        AZ_Assert(entity, "Entity is not available.");
+        // check if entity is spawned by this component
+        const auto ticketId = entity->GetEntitySpawnTicketId();
+        if (m_spawnedTickets.find(ticketId) != m_spawnedTickets.end())
+        {
+            // remove the ticket
+            m_spawnedTickets.erase(ticketId);
+        }
+        else
+        {
+            AZ_Warning("SimulationInterfaces", false, "Entity %s was not spawned by this component, wont delete it", name.c_str());
+            return false;
+        }
+#ifdef POTENTIALY_UNSAFE
+        if (findIt != m_simulatedEntityToEntityIdMap.end())
+        {
+            const AZ::EntityId entityId = findIt->second;
+            AZ_Assert(entityId.IsValid(), "EntityId is not valid");
+            // get all descendants
+            AZStd::vector<AZ::EntityId> entityAndDescendants;
+            AZ::TransformBus::EventResult(entityAndDescendants, entityId, &AZ::TransformBus::Events::GetEntityAndAllDescendants);
+            for (const auto& descendant : entityAndDescendants)
+            {
+                // I am not sure if this is the safe way to delete an entity
+                AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, descendant);
+            }
+
+            return true;
+        }
+#endif
+        return false;
+    }
+
+    AZStd::unordered_map<AZStd::string, EntityState> SimulationEntitiesManager::GetEntitiesStates(const EntityFilters& filter)
+    {
+        AZStd::unordered_map<AZStd::string, EntityState> entitiesStates;
+        const auto& entities = GetEntities(filter);
+        for (const auto& entity : entities)
+        {
+            entitiesStates.emplace(AZStd::make_pair(entity, GetEntityState(entity)));
+        }
+        return entitiesStates;
+    }
+
+    AZStd::vector<Spawnable> SimulationEntitiesManager::GetSpawnables()
+    {
+        AZStd::vector<Spawnable> spawnables;
+
+        const auto enumCallback = [&spawnables](const AZ::Data::AssetId assetId, const AZ::Data::AssetInfo& assetInfo)
+        {
+            bool isSpawnable = false;
+            AZ::Data::AssetCatalogRequestBus::BroadcastResult(
+                isSpawnable, &AZ::Data::AssetCatalogRequests::DoesAssetIdMatchWildcardPattern, assetId, "*.spawnable");
+
+            if (isSpawnable)
+            {
+                Spawnable spawnable;
+                spawnable.m_uri = Utils::RelPathToUri(assetInfo.m_relativePath);
+                spawnables.push_back(spawnable);
+            }
+        };
+
+        AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnumerateAssets, nullptr, enumCallback, nullptr);
+        return spawnables;
+    }
+
+    void SimulationEntitiesManager::SpawnEntity(
+        const AZStd::string& name,
+        const AZStd::string& uri,
+        const AZStd::string& entityNamespace,
+        const AZ::Transform& initialPose,
+        SpawnCompletedCb completedCb)
+    {
+        // get rel path from uri
+        const AZStd::string relPath = Utils::UriToRelPath(uri);
+
+        // create spawnnable
+        AZ::Data::AssetId assetId;
+        AZ::Data::AssetCatalogRequestBus::BroadcastResult(
+            assetId,
+            &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
+            relPath.c_str(),
+            azrtti_typeid<AZ::Data::AssetData>(),
+            false);
+        AZ_Warning("SimulationInterfaces", assetId.IsValid(), "AssetId is not valid, relative path %s", relPath.c_str());
+
+        auto spawner = AZ::Interface<AzFramework::SpawnableEntitiesDefinition>::Get();
+        AZ_Assert(spawner, "SpawnableEntitiesDefinition is not available.");
+
+        AZ::Data::Asset<AzFramework::Spawnable> spawnableAsset =
+            AZ::Data::AssetManager::Instance().GetAsset<AzFramework::Spawnable>(assetId, AZ::Data::AssetLoadBehavior::NoLoad);
+        if (!spawnableAsset)
+        {
+            completedCb(AZ::Failure("Failed to get spawnable asset - incorrect uri"));
+            return;
+        }
+
+        auto ticket = AzFramework::EntitySpawnTicket(spawnableAsset);
+        AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
+
+        optionalArgs.m_preInsertionCallback = [initialPose, entityNamespace, name](auto id, auto view)
+        {
+            if (view.empty())
+            {
+                return;
+            }
+            const AZ::Entity* root = *view.begin();
+
+            // change names for all entites
+            for (auto* entity : view)
+            {
+                AZStd::string entityName = AZStd::string::format("%s_%s", name.c_str(), entity->GetName().c_str());
+                entity->SetName(entityName);
+            }
+
+            auto* transformInterface = root->FindComponent<AzFramework::TransformComponent>();
+            if (transformInterface)
+            {
+                transformInterface->SetWorldTM(initialPose);
+            }
+
+            if (!entityNamespace.empty())
+            {
+                // TODO: Mpelka set ROS 2 namespace here
+                AZ_Error("SimulationInterfaces", false, "ROS 2 namespace is not implemented yet in spawning");
+            }
+        };
+        optionalArgs.m_completionCallback =
+            [this](AzFramework::EntitySpawnTicket::Id ticketId, AzFramework::SpawnableConstEntityContainerView view)
+        {
+            // at this point the entities are spawned and should be registered in simulation interface and callback should be called
+            // if that is not a case, it means that the AZFrameworrk::Pshysics::OnSimulationBodyAdded event was not called.
+            // That means the prefab has no physics component or the physics component is not enabled - we need to call the callback here
+            // and return the error.
+            auto spawnData = m_spawnCompletedCallbacks.find(ticketId);
+            if (spawnData != m_spawnCompletedCallbacks.end())
+            {
+                // call and remove the callback
+                spawnData->second.m_completedCb(AZ::Failure(
+                    "Entity was not registered in simulation interface - no physics component or physics component is not enabled."));
+                m_spawnCompletedCallbacks.erase(spawnData);
+            }
+        };
+
+        spawner->SpawnAllEntities(ticket, optionalArgs);
+
+        auto ticketId = ticket.GetId();
+        AZ_Printf("SimulationInterfaces", "Spawning uri %s with ticket id %d\n", uri.c_str(), ticketId);
+
+        SpawnCompletedCbData data;
+        data.m_userProposedName = name;
+        data.m_completedCb = completedCb;
+        m_spawnCompletedCallbacks[ticketId] = data;
+        m_spawnedTickets[ticketId] = ticket;
+    }
+
+    AZStd::string SimulationEntitiesManager::GetSimulatedEntityName(AZ::EntityId entityId, const AZStd::string& proposedName) const
+    {
+        // Get O3DE entity name
+        AZStd::string entityName = proposedName;
+        if (entityName.empty())
+        {
+            AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, entityId);
+        }
+        // Generate unique simulated entity name
+        AZStd::string simulatedEntityName = entityName;
+        // check if name is unique
+        auto otherEntityIt = m_simulatedEntityToEntityIdMap.find(simulatedEntityName);
+        if (otherEntityIt != m_simulatedEntityToEntityIdMap.end())
+        {
+            // name is not unique, add entityId to name
+            simulatedEntityName = AZStd::string::format("%s_%s", entityName.c_str(), entityId.ToString().c_str());
+        }
+        return simulatedEntityName;
+    }
+} // namespace SimulationInterfaces

+ 94 - 0
Gems/SimulationInterfaces/Code/Source/Clients/SimulationEntitiesManager.h

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <AzCore/Component/TickBus.h>
+#include <AzCore/Script/ScriptTimePoint.h>
+#include <AzFramework/Entity/EntityContextBus.h>
+#include <AzFramework/Physics/PhysicsScene.h>
+#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+
+namespace SimulationInterfaces
+{
+    class SimulationEntitiesManager
+        : public AZ::Component
+        , protected SimulationEntityManagerRequestBus::Handler
+    {
+    public:
+        AZ_COMPONENT_DECL(SimulationEntitiesManager);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+        static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
+
+        SimulationEntitiesManager();
+        ~SimulationEntitiesManager();
+
+    protected:
+        // SimulationEntityManagerRequestBus interface implementation
+        AZStd::vector<AZStd::string> GetEntities(const EntityFilters& filter) override;
+        EntityState GetEntityState(const AZStd::string& name) override;
+        AZStd::unordered_map<AZStd::string, EntityState> GetEntitiesStates(const EntityFilters& filter) override;
+        bool SetEntityState(const AZStd::string& name, const EntityState& state) override;
+        bool DeleteEntity(const AZStd::string& name) override;
+        AZStd::vector<Spawnable> GetSpawnables() override;
+        void SpawnEntity(
+            const AZStd::string& name,
+            const AZStd::string& uri,
+            const AZStd::string& entityNamespace,
+            const AZ::Transform& initialPose,
+            SpawnCompletedCb completedCb) override;
+
+        // AZ::Component interface implementation
+        void Init() override;
+        void Activate() override;
+        void Deactivate() override;
+
+    private:
+        //! Registers simulated entity to entity id mapping.
+        //! Note that the entityId will be registered under unique name.
+        //! \param entityId The entity id to register
+        //! \param proposedName Optional user proposed name for the simulated entity
+        //! \return returns the simulated entity name
+        AZStd::string AddSimulatedEntity(AZ::EntityId entityId, const AZStd::string& proposedName);
+
+        //! Removes simulated entity from the mapping.
+        void RemoveSimulatedEntity(AZ::EntityId entityId);
+
+        //! Returns the simulated entity name for the given entity id.
+        AZStd::string GetSimulatedEntityName(AZ::EntityId entityId, const AZStd::string& proposedName) const;
+
+        AzPhysics::SceneEvents::OnSimulationBodyAdded::Handler m_simulationBodyAddedHandler;
+        AzPhysics::SceneEvents::OnSimulationBodyRemoved::Handler m_simulationBodyRemovedHandler;
+
+        AzPhysics::SystemEvents::OnSceneAddedEvent::Handler m_sceneAddedHandler;
+        AzPhysics::SystemEvents::OnSceneRemovedEvent::Handler m_sceneRemovedHandler;
+        AzPhysics::SceneHandle m_physicsScenesHandle = AzPhysics::InvalidSceneHandle;
+        AZStd::unordered_map<AZStd::string, AZ::EntityId> m_simulatedEntityToEntityIdMap;
+        AZStd::unordered_map<AZ::EntityId, AZStd::string> m_entityIdToSimulatedEntityMap;
+        AZStd::unordered_set<AzPhysics::SimulatedBodyHandle> m_disabledBodies;
+
+        AZStd::unordered_map<AzFramework::EntitySpawnTicket::Id, AzFramework::EntitySpawnTicket> m_spawnedTickets;
+
+        struct SpawnCompletedCbData
+        {
+            AZStd::string m_userProposedName; //! Name proposed by the User in spawn request
+            SpawnCompletedCb m_completedCb; //! User callback to be called when the entity is registered
+            AZ::ScriptTimePoint m_spawnCompletedTime; //! Time at which the entity was spawned
+        };
+        AZStd::unordered_map<AzFramework::EntitySpawnTicket::Id, SpawnCompletedCbData>
+            m_spawnCompletedCallbacks; //! Callbacks to be called when the entity is registered
+    };
+
+} // namespace SimulationInterfaces

+ 27 - 0
Gems/SimulationInterfaces/Code/Source/Clients/SimulationInterfacesModule.cpp

@@ -0,0 +1,27 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationEntitiesManager.h"
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+#include <SimulationInterfacesModuleInterface.h>
+
+namespace SimulationInterfaces
+{
+    class SimulationInterfacesModule : public SimulationInterfacesModuleInterface
+    {
+    public:
+        AZ_RTTI(SimulationInterfacesModule, SimulationInterfacesModuleTypeId, SimulationInterfacesModuleInterface);
+        AZ_CLASS_ALLOCATOR(SimulationInterfacesModule, AZ::SystemAllocator);
+    };
+} // namespace SimulationInterfaces
+
+#if defined(O3DE_GEM_NAME)
+AZ_DECLARE_MODULE_CLASS(AZ_JOIN(Gem_, O3DE_GEM_NAME), SimulationInterfaces::SimulationInterfacesModule)
+#else
+AZ_DECLARE_MODULE_CLASS(Gem_SimulationInterfaces, SimulationInterfaces::SimulationInterfacesModule)
+#endif

+ 127 - 0
Gems/SimulationInterfaces/Code/Source/Clients/SimulationManager.cpp

@@ -0,0 +1,127 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationManager.h"
+
+#include <AzCore/Component/ComponentApplicationBus.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzFramework/Physics/PhysicsSystem.h>
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+namespace SimulationInterfaces
+{
+
+    AZ_COMPONENT_IMPL(SimulationManager, "SimulationManager", SimulationManagerTypeId);
+
+    void SimulationManager::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<SimulationManager, AZ::Component>()->Version(0);
+        }
+    }
+
+    void SimulationManager::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(AZ_CRC_CE("SimulationManagerService"));
+    }
+
+    void SimulationManager::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        incompatible.push_back(AZ_CRC_CE("SimulationManagerService"));
+    }
+
+    void SimulationManager::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        required.push_back(AZ_CRC_CE("PhysicsService"));
+    }
+
+    void SimulationManager::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    {
+    }
+
+    SimulationManager::SimulationManager()
+    {
+        if (SimulationManagerRequestBusInterface::Get() == nullptr)
+        {
+            SimulationManagerRequestBusInterface::Register(this);
+        }
+    }
+
+    SimulationManager::~SimulationManager()
+    {
+        if (SimulationManagerRequestBusInterface::Get() == this)
+        {
+            SimulationManagerRequestBusInterface::Unregister(this);
+        }
+    }
+
+    void SimulationManager::Init()
+    {
+    }
+
+    void SimulationManager::Activate()
+    {
+        SimulationManagerRequestBus::Handler::BusConnect();
+    }
+
+    void SimulationManager::Deactivate()
+    {
+        SimulationManagerRequestBus::Handler::BusDisconnect();
+    }
+
+    void SimulationManager::SetSimulationPaused(bool paused)
+    {
+        // get az physics system
+        auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+        AZ_Assert(physicsSystem, "Physics system is not available");
+        const auto& sceneHandlers = physicsSystem->GetAllScenes();
+        auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
+        AZ_Assert(sceneInterface, "Physics scene interface is not available");
+        for (auto& scene : sceneHandlers)
+        {
+            AZ_Assert(scene, "Physics scene is not available");
+            scene->SetEnabled(!paused);
+        }
+    }
+
+    void SimulationManager::StepSimulation(AZ::u32 steps)
+    {
+        m_numberOfPhysicsSteps = steps;
+
+        // install handler
+        m_simulationFinishEvent = AzPhysics::SceneEvents::OnSceneSimulationFinishHandler(
+            [this](AzPhysics::SceneHandle sceneHandle, float)
+            {
+                m_numberOfPhysicsSteps--;
+                AZ_Printf("SimulationManager", "Physics simulation step finished. Remaining steps: %d", m_numberOfPhysicsSteps);
+                if (m_numberOfPhysicsSteps <= 0)
+                {
+                    SetSimulationPaused(true);
+                    // remove handler
+                    m_simulationFinishEvent.Disconnect();
+                }
+            });
+
+        // get default scene
+        auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+        AZ_Assert(physicsSystem, "Physics system is not available");
+        auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
+        AZ_Assert(sceneInterface, "Physics scene interface is not available");
+        AzPhysics::SceneHandle defaultScene = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
+
+        auto scene = sceneInterface->GetScene(defaultScene);
+        AZ_Assert(scene, "Default physics scene is not available");
+
+        // install handler
+        scene->RegisterSceneSimulationFinishHandler(m_simulationFinishEvent);
+        SetSimulationPaused(false);
+
+    }
+
+} // namespace SimulationInterfaces

+ 49 - 0
Gems/SimulationInterfaces/Code/Source/Clients/SimulationManager.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <AzCore/Component/TickBus.h>
+#include <AzCore/Script/ScriptTimePoint.h>
+#include <AzFramework/Entity/EntityContextBus.h>
+#include <AzFramework/Physics/PhysicsScene.h>
+#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+#include <SimulationInterfaces/SimulationMangerRequestBus.h>
+namespace SimulationInterfaces
+{
+    class SimulationManager :
+        public AZ::Component,
+        protected SimulationManagerRequestBus::Handler
+    {
+    public:
+        AZ_COMPONENT_DECL(SimulationManager);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+        static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
+
+        SimulationManager();
+        ~SimulationManager();
+
+        // AZ::Component
+        void Init() override;
+        void Activate() override;
+        void Deactivate() override;
+    protected:
+        void SetSimulationPaused(bool paused) override;
+        void StepSimulation(AZ::u32 steps) override;
+        uint32_t m_numberOfPhysicsSteps = 0;
+        AzPhysics::SceneEvents::OnSceneSimulationFinishHandler m_simulationFinishEvent;
+
+    };
+} // namespace SimulationInterfaces

+ 41 - 0
Gems/SimulationInterfaces/Code/Source/SimulationInterfacesModuleInterface.cpp

@@ -0,0 +1,41 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationInterfacesModuleInterface.h"
+#include <AzCore/Memory/Memory.h>
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+#include <Clients/SimulationEntitiesManager.h>
+#include "Clients/SimulationManager.h"
+
+namespace SimulationInterfaces
+{
+    AZ_TYPE_INFO_WITH_NAME_IMPL(
+        SimulationInterfacesModuleInterface, "SimulationInterfacesModuleInterface", SimulationInterfacesModuleInterfaceTypeId);
+    AZ_RTTI_NO_TYPE_INFO_IMPL(SimulationInterfacesModuleInterface, AZ::Module);
+    AZ_CLASS_ALLOCATOR_IMPL(SimulationInterfacesModuleInterface, AZ::SystemAllocator);
+
+    SimulationInterfacesModuleInterface::SimulationInterfacesModuleInterface()
+    {
+        m_descriptors.insert(
+            m_descriptors.end(),
+            {
+                SimulationEntitiesManager::CreateDescriptor(),
+                SimulationManager::CreateDescriptor(),
+            });
+    }
+
+    AZ::ComponentTypeList SimulationInterfacesModuleInterface::GetRequiredSystemComponents() const
+    {
+        return AZ::ComponentTypeList{
+            azrtti_typeid<SimulationEntitiesManager>(),
+            azrtti_typeid<SimulationManager>(),
+        };
+    }
+} // namespace SimulationInterfaces

+ 30 - 0
Gems/SimulationInterfaces/Code/Source/SimulationInterfacesModuleInterface.h

@@ -0,0 +1,30 @@
+/*
+ * 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
+ *
+ */
+
+#include <AzCore/Memory/Memory_fwd.h>
+#include <AzCore/Module/Module.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/RTTI/TypeInfoSimple.h>
+
+namespace SimulationInterfaces
+{
+    class SimulationInterfacesModuleInterface : public AZ::Module
+    {
+    public:
+        AZ_TYPE_INFO_WITH_NAME_DECL(SimulationInterfacesModuleInterface)
+        AZ_RTTI_NO_TYPE_INFO_DECL()
+        AZ_CLASS_ALLOCATOR_DECL
+
+        SimulationInterfacesModuleInterface();
+
+        /**
+         * Add required SystemComponents to the SystemEntity.
+         */
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override;
+    };
+} // namespace SimulationInterfaces

+ 70 - 0
Gems/SimulationInterfaces/Code/Source/Tools/SimulationEntitiesManagerEditor.cpp

@@ -0,0 +1,70 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationEntitiesManagerEditor.h"
+#include <AzCore/Serialization/SerializeContext.h>
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+namespace SimulationInterfaces
+{
+    AZ_COMPONENT_IMPL(
+        SimulationEntitiesManagerEditor,
+        "SimulationEntitiesManagerEditor",
+        SimulationEntitiesManagerEditorTypeId,
+        BaseSystemComponent);
+
+    void SimulationEntitiesManagerEditor::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<SimulationEntitiesManagerEditor, SimulationEntitiesManager>()->Version(0);
+        }
+    }
+
+    SimulationEntitiesManagerEditor::SimulationEntitiesManagerEditor() = default;
+
+    SimulationEntitiesManagerEditor::~SimulationEntitiesManagerEditor() = default;
+
+    void SimulationEntitiesManagerEditor::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        BaseSystemComponent::GetProvidedServices(provided);
+        provided.push_back(AZ_CRC_CE("SimulationInterfacesEditorService"));
+    }
+
+    void SimulationEntitiesManagerEditor::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        BaseSystemComponent::GetIncompatibleServices(incompatible);
+        incompatible.push_back(AZ_CRC_CE("SimulationInterfacesEditorService"));
+    }
+
+    void SimulationEntitiesManagerEditor::GetRequiredServices(
+        [[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        BaseSystemComponent::GetRequiredServices(required);
+    }
+
+    void SimulationEntitiesManagerEditor::GetDependentServices(
+        [[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    {
+        BaseSystemComponent::GetDependentServices(dependent);
+    }
+
+    void SimulationEntitiesManagerEditor::Activate()
+    {
+        SimulationEntitiesManager::Activate();
+        AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
+    }
+
+    void SimulationEntitiesManagerEditor::Deactivate()
+    {
+        AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
+        SimulationEntitiesManager::Deactivate();
+    }
+
+} // namespace SimulationInterfaces

+ 42 - 0
Gems/SimulationInterfaces/Code/Source/Tools/SimulationEntitiesManagerEditor.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzToolsFramework/API/ToolsApplicationAPI.h>
+
+#include <Clients/SimulationEntitiesManager.h>
+
+namespace SimulationInterfaces
+{
+    /// System component for SimulationInterfaces editor
+    class SimulationEntitiesManagerEditor
+        : public SimulationEntitiesManager
+        , protected AzToolsFramework::EditorEvents::Bus::Handler
+    {
+        using BaseSystemComponent = SimulationEntitiesManager;
+
+    public:
+        AZ_COMPONENT_DECL(SimulationEntitiesManagerEditor);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        SimulationEntitiesManagerEditor();
+        ~SimulationEntitiesManagerEditor();
+
+    private:
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+        static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
+
+        // AZ::Component
+        void Activate() override;
+        void Deactivate() override;
+    };
+} // namespace SimulationInterfaces

+ 48 - 0
Gems/SimulationInterfaces/Code/Source/Tools/SimulationInterfacesEditorModule.cpp

@@ -0,0 +1,48 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationEntitiesManagerEditor.h"
+#include "SimulationManagerEditor.h"
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+#include <SimulationInterfacesModuleInterface.h>
+namespace SimulationInterfaces
+{
+    class SimulationInterfacesEditorModule : public SimulationInterfacesModuleInterface
+    {
+    public:
+        AZ_RTTI(SimulationInterfacesEditorModule, SimulationInterfacesEditorModuleTypeId, SimulationInterfacesModuleInterface);
+        AZ_CLASS_ALLOCATOR(SimulationInterfacesEditorModule, AZ::SystemAllocator);
+
+        SimulationInterfacesEditorModule()
+        {
+            m_descriptors.insert(
+                m_descriptors.end(),
+                {
+                    SimulationEntitiesManagerEditor::CreateDescriptor(),
+                    SimulationManagerEditor::CreateDescriptor(),
+                });
+        }
+
+        /**
+         * Add required SystemComponents to the SystemEntity.
+         * Non-SystemComponents should not be added here
+         */
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override
+        {
+            return AZ::ComponentTypeList{
+                azrtti_typeid<SimulationEntitiesManagerEditor>(),
+            };
+        }
+    };
+} // namespace SimulationInterfaces
+
+#if defined(O3DE_GEM_NAME)
+AZ_DECLARE_MODULE_CLASS(AZ_JOIN(Gem_, O3DE_GEM_NAME, _Editor), SimulationInterfaces::SimulationInterfacesEditorModule)
+#else
+AZ_DECLARE_MODULE_CLASS(Gem_SimulationInterfaces_Editor, SimulationInterfaces::SimulationInterfacesEditorModule)
+#endif

+ 68 - 0
Gems/SimulationInterfaces/Code/Source/Tools/SimulationManagerEditor.cpp

@@ -0,0 +1,68 @@
+/*
+ * 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
+ *
+ */
+
+#include "SimulationManagerEditor.h"
+#include <AzCore/Serialization/SerializeContext.h>
+
+#include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
+
+namespace SimulationInterfaces
+{
+    AZ_COMPONENT_IMPL(SimulationManagerEditor, "SimulationMangerEditor", SimulationManagerEditorTypeId, BaseSystemComponent);
+
+    void SimulationManagerEditor::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<SimulationManagerEditor, SimulationManager>()->Version(0);
+        }
+    }
+
+    SimulationManagerEditor::SimulationManagerEditor() = default;
+
+    SimulationManagerEditor::~SimulationManagerEditor() = default;
+
+    void SimulationManagerEditor::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        BaseSystemComponent::GetProvidedServices(provided);
+        provided.push_back(AZ_CRC_CE("SimulationManagerEditorService"));
+    }
+
+    void SimulationManagerEditor::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        BaseSystemComponent::GetIncompatibleServices(incompatible);
+        incompatible.push_back(AZ_CRC_CE("SimulationManagerEditorService"));
+    }
+
+    void SimulationManagerEditor::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        BaseSystemComponent::GetRequiredServices(required);
+    }
+
+    void SimulationManagerEditor::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    {
+        BaseSystemComponent::GetDependentServices(dependent);
+    }
+    void SimulationManagerEditor::Init()
+    {
+        BaseSystemComponent::Init();
+    }
+
+    void SimulationManagerEditor::Activate()
+    {
+        BaseSystemComponent::Activate();
+        AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
+    }
+
+    void SimulationManagerEditor::Deactivate()
+    {
+        AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
+        BaseSystemComponent::Deactivate();
+    }
+
+} // namespace SimulationInterfaces

+ 43 - 0
Gems/SimulationInterfaces/Code/Source/Tools/SimulationManagerEditor.h

@@ -0,0 +1,43 @@
+/*
+* Copyright (c) Contributors to the Open 3D Engine Project.
+* For complete copyright and license terms please see the LICENSE at the root of this distribution.
+*
+* SPDX-License-Identifier: Apache-2.0 OR MIT
+*
+*/
+
+#pragma once
+
+#include <AzToolsFramework/API/ToolsApplicationAPI.h>
+
+#include <Clients/SimulationManager.h>
+
+namespace SimulationInterfaces
+{
+   /// System component for SimulationInterfaces editor
+   class SimulationManagerEditor
+       : public SimulationManager
+       , protected AzToolsFramework::EditorEvents::Bus::Handler
+   {
+       using BaseSystemComponent = SimulationManager;
+
+   public:
+       AZ_COMPONENT_DECL(SimulationManagerEditor);
+
+       static void Reflect(AZ::ReflectContext* context);
+
+       SimulationManagerEditor();
+       ~SimulationManagerEditor();
+
+   private:
+       static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+       static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+       static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+       static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
+
+       // AZ::Component
+       void Init() override;
+       void Activate() override;
+       void Deactivate() override;
+   };
+} // namespace SimulationInterfaces

+ 11 - 0
Gems/SimulationInterfaces/Code/Tests/Clients/SimulationInterfacesTest.cpp

@@ -0,0 +1,11 @@
+/*
+ * 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
+ *
+ */
+
+#include <AzTest/AzTest.h>
+
+AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);

+ 170 - 0
Gems/SimulationInterfaces/Code/Tests/Tools/SimulationInterfaceTests.cpp

@@ -0,0 +1,170 @@
+
+/*
+ * 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
+ *
+ */
+
+#include "TestFixture.h"
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+namespace UnitTest
+{
+
+    TEST_F(SimulationInterfaceTestFixture, EmptyScene)
+    {
+        using namespace SimulationInterfaces;
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities.size(), 0);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, AddSimulatedEntityThenRemove)
+    {
+        using namespace SimulationInterfaces;
+        const AZ::EntityId entityId1 = CreateEntityWithStaticBodyComponent("Foo", AZ::Transform::CreateIdentity());
+        const AZ::EntityId entityId2 = CreateEntityWithStaticBodyComponent("Bar", AZ::Transform::CreateIdentity());
+
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        ASSERT_EQ(entities.size(), 2);
+        DeleteEntity(entityId1);
+
+        AZStd::vector<AZStd::string> entities2;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities2, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities2.size(), 1);
+
+        DeleteEntity(entityId2);
+        AZStd::vector<AZStd::string> entities3;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities3, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities3.size(), 0);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, AddEntitiesWithDupName)
+    {
+        using namespace SimulationInterfaces;
+
+        const AZ::EntityId entityId1 = CreateEntityWithStaticBodyComponent("Bar1", AZ::Transform::CreateIdentity());
+        const AZ::EntityId entityId2 = CreateEntityWithStaticBodyComponent("Bar1", AZ::Transform::CreateIdentity());
+        AZStd::vector<AZStd::string> entities;
+
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities.size(), 2);
+        EXPECT_NE(entities[0], entities[1]);
+        DeleteEntity(entityId1);
+        DeleteEntity(entityId2);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, TestShapeFilter)
+    {
+        // This test is disabled since due to some issue outside to this gem, the rigid body is created without the collider shape
+        // and the filter is not applied. This test will be enabled once the issue is resolved.
+        GTEST_SKIP()<<"Need to fix the issue with the collider shape creation.";
+        using namespace SimulationInterfaces;
+        const AZ::EntityId entityId1 =
+            CreateEntityWithStaticBodyComponent("Inside", AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)));
+        const AZ::EntityId entityId2 =
+            CreateEntityWithStaticBodyComponent("Outside", AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)));
+
+        EntityFilters filter;
+        filter.m_bounds_shape = AZStd::make_shared<Physics::SphereShapeConfiguration>(2.0f);
+
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
+        auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+        physicsSystem->Simulate(1.0f / 60.0f);
+
+        ASSERT_EQ(entities.size(), 1);
+        EXPECT_EQ(entities.front(), "Inside");
+
+        DeleteEntity(entityId1);
+        DeleteEntity(entityId2);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, TestRegexFilter)
+    {
+        using namespace SimulationInterfaces;
+        const AZ::EntityId entityId1 =
+            CreateEntityWithStaticBodyComponent("WillMatch", AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)));
+        const AZ::EntityId entityId2 =
+            CreateEntityWithStaticBodyComponent("WontMatch", AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)));
+
+        EntityFilters filter;
+        filter.m_filter = "Will.*";
+
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
+
+        ASSERT_EQ(entities.size(), 1);
+        EXPECT_EQ(entities.front(), "WillMatch");
+
+        DeleteEntity(entityId1);
+        DeleteEntity(entityId2);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, TestRegexFilterInvalid)
+    {
+        // Invalid regex should not match any entity
+        using namespace SimulationInterfaces;
+        const AZ::EntityId entityId1 =
+            CreateEntityWithStaticBodyComponent("WillMatch", AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)));
+        const AZ::EntityId entityId2 =
+            CreateEntityWithStaticBodyComponent("WontMatch", AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 0.0f, 0.0f)));
+
+        EntityFilters filter;
+        filter.m_filter = "[a-z";
+
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
+
+        EXPECT_EQ(entities.size(), 0);
+        DeleteEntity(entityId1);
+        DeleteEntity(entityId2);
+    }
+
+    TEST_F(SimulationInterfaceTestFixture, SmokeTestGetEntityState)
+    {
+        // Invalid regex should not match any entity
+        using namespace SimulationInterfaces;
+        const AZStd::string entityName = "DroppedBall";
+        const AZ::EntityId entityId1 =
+            CreateEntityWithStaticBodyComponent(entityName, AZ::Transform::CreateTranslation(AZ::Vector3(2.0f, 0.0f, 10.0f)));
+
+        EntityFilters filter;
+        EntityState stateBefore;
+        SimulationEntityManagerRequestBus::BroadcastResult(stateBefore, &SimulationEntityManagerRequestBus::Events::GetEntityState, entityName);
+        EXPECT_EQ(stateBefore.m_pose.GetTranslation(), AZ::Vector3(2.0f, 0.0f, 10.0f));
+        for (int i = 0; i < 10; i++)
+        {
+            auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+            physicsSystem->Simulate(1.0f / 60.0f);
+        }
+        EntityState stateAfter;
+        SimulationEntityManagerRequestBus::BroadcastResult(stateAfter, &SimulationEntityManagerRequestBus::Events::GetEntityState, entityName);
+        AZ::Vector3 deltaPos = stateAfter.m_pose.GetTranslation() - stateBefore.m_pose.GetTranslation();
+
+        // check if the entity moved
+        EXPECT_GT(deltaPos.GetLength(), 0.0f);
+
+        // check if entity has velocity
+        EXPECT_GT(stateAfter.m_twist_linear.GetLength(), 0.0f);
+
+        DeleteEntity(entityId1);
+    }
+
+} // namespace UnitTest
+
+// required to support running integration tests with Qt and PhysX
+AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv)
+{
+    ::testing::InitGoogleMock(&argc, argv);
+    AzQtComponents::PrepareQtPaths();
+    QApplication app(argc, argv);
+    AZ::Test::printUnusedParametersWarning(argc, argv);
+    AZ::Test::addTestEnvironments({ new UnitTest::SimulationInterfaceTestEnvironment() });
+    int result = RUN_ALL_TESTS();
+    return result;
+}
+
+IMPLEMENT_TEST_EXECUTABLE_MAIN();

+ 139 - 0
Gems/SimulationInterfaces/Code/Tests/Tools/SimulationIterfaceAppTest.cpp

@@ -0,0 +1,139 @@
+
+/*
+ * 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
+ *
+ */
+
+#include "TestFixture.h"
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+
+namespace UnitTest
+{
+    class SimulationInterfaceTestEnvironmentWithAssets : public SimulationInterfaceTestEnvironment
+    {
+    protected:
+        void PostSystemEntityActivate();
+    };
+
+    void SimulationInterfaceTestEnvironmentWithAssets::PostSystemEntityActivate()
+    {
+        // Prepare the asset catalog and ensure that our test asset (testsimulationentity.spawnable) is loaded and
+        // ready to be used in test scenarios.
+        AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+
+        AZ::ComponentApplication* app = nullptr;
+        AZ::ComponentApplicationBus::BroadcastResult(app, &AZ::ComponentApplicationBus::Events::GetApplication);
+        AZ_Assert(app, "Failed to get application");
+        auto products = AZ::Utils::GetProjectProductPathForPlatform().c_str();
+        AZ::IO::Path assetCatalogPath = AZ::IO::Path(products) / "assetcatalog.xml";
+        bool catalogExists = AZ::IO::FileIOBase::GetInstance()->Exists(assetCatalogPath.c_str());
+        AZ_Assert(catalogExists, "Asset Catalog in %s does not exist", assetCatalogPath.c_str());
+
+        AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, assetCatalogPath.c_str());
+
+        const AZ::IO::Path TestSpawnable = "sampleasset/testsimulationentity.spawnable";
+        const AZ::IO::Path TestSpawnableGlobalPath = AZ::IO::Path(products) / TestSpawnable;
+        bool spawnableExists = AZ::IO::FileIOBase::GetInstance()->Exists(assetCatalogPath.c_str());
+        AZ_Assert(spawnableExists, "%s does not exist", TestSpawnableGlobalPath.c_str());
+
+        AZ::Data::AssetId assetId;
+        AZ::Data::AssetCatalogRequestBus::BroadcastResult(
+            assetId,
+            &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
+            TestSpawnable.c_str(),
+            AZ::Data::s_invalidAssetType,
+            false);
+        AZ_Assert(assetId.IsValid(), "Failed to get asset id for %s", TestSpawnable.c_str());
+    }
+
+
+    TEST_F(SimulationInterfaceTestFixture, SpawnAppTest)
+    {
+        // This is an integration test that runs the test application with the SimulationInterfaces gem enabled.
+        // It has prepared asset catalog, and we are able to spawn entities with the test asset.
+
+        using namespace SimulationInterfaces;
+        constexpr AZStd::string_view entityName = "MySuperDuperEntity";
+        const AZ::Transform initialPose = AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f));
+        constexpr AZStd::string_view uri = "product_asset:///sampleasset/testsimulationentity.spawnable";
+        constexpr AZStd::string_view entityNamespace = "";
+        AZStd::atomic_bool completed = false;
+        SimulationEntityManagerRequests::SpawnCompletedCb completedCb = [&](const AZ::Outcome<AZStd::string, AZStd::string>& result)
+        {
+            EXPECT_TRUE(result.IsSuccess());
+            completed = true;
+        };
+
+        SimulationEntityManagerRequestBus::Broadcast(
+            &SimulationEntityManagerRequestBus::Events::SpawnEntity, entityName, uri, entityNamespace, initialPose, completedCb);
+
+        // entities are spawned asynchronously, so we need to tick the app to let the entity be spawned
+        TickApp(100);
+        EXPECT_TRUE(completed);
+
+        // list simulation entities
+        AZStd::vector<AZStd::string> entities;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities.size(), 1);
+
+        ASSERT_FALSE(entities.empty())<< "Simulated Entities Empty";
+        const AZStd::string spawnedEntityName = entities.front();
+        printf("Spawned entity name %s\n", spawnedEntityName.c_str());
+
+        // run physics simulation
+        StepPhysics(100);
+
+        // Get entity state,
+        AZStd::unordered_map<AZStd::string, EntityState> entityStates;
+        SimulationEntityManagerRequestBus::BroadcastResult(
+            entityStates, &SimulationEntityManagerRequestBus::Events::GetEntitiesStates, EntityFilters());
+        auto entityState = entityStates.find(spawnedEntityName);
+        ASSERT_NE(entityState, entityStates.end());
+        EXPECT_EQ(entityState->first, spawnedEntityName);
+
+        // check if the entity moved
+        EXPECT_GE(entityState->second.m_pose.GetTranslation().GetDistance(initialPose.GetTranslation()), 1.0f);
+
+        // set new entity state - move the entity to X=1000 meters
+        const AZ::Vector3 newPosition = AZ::Vector3(1000.0f, 0.0f, 0.0f);
+        const EntityState newState = { AZ::Transform::CreateTranslation(newPosition), AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero() };
+        SimulationEntityManagerRequestBus::Broadcast(&SimulationEntityManagerRequestBus::Events::SetEntityState, spawnedEntityName, newState);
+
+        StepPhysics();
+
+        // Check if entity was teleported by setting the new state, we use a filter to check if the entity is at the new position
+        EntityFilters filter;
+        filter.m_bounds_shape = AZStd::make_shared<Physics::SphereShapeConfiguration>(2.0f);
+        filter.m_bounds_pose = AZ::Transform::CreateTranslation(AZ::Vector3(1000.0f, 0.0f, 0.0f));
+        AZStd::vector<AZStd::string> entitiesFiltered;
+        SimulationEntityManagerRequestBus::BroadcastResult(entitiesFiltered, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
+        EXPECT_EQ(entitiesFiltered.size(), 1);
+
+        // delete entity using its name
+        SimulationEntityManagerRequestBus::Broadcast(&SimulationEntityManagerRequestBus::Events::DeleteEntity, entityName);
+        TickApp(100);
+
+        // list simulation entities after deletion, expect no simulation entities
+        AZStd::vector<AZStd::string> entities2;
+        SimulationEntityManagerRequestBus::BroadcastResult(entities2, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
+        EXPECT_EQ(entities2.size(), 0);
+    }
+
+} // namespace UnitTest
+
+// required to support running integration tests with Qt and PhysX
+AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv)
+{
+    ::testing::InitGoogleMock(&argc, argv);
+    AzQtComponents::PrepareQtPaths();
+    QApplication app(argc, argv);
+    AZ::Test::printUnusedParametersWarning(argc, argv);
+    AZ::Test::addTestEnvironments({ new UnitTest::SimulationInterfaceTestEnvironmentWithAssets() });
+    int result = RUN_ALL_TESTS();
+    return result;
+}
+
+IMPLEMENT_TEST_EXECUTABLE_MAIN();

+ 151 - 0
Gems/SimulationInterfaces/Code/Tests/Tools/TestFixture.cpp

@@ -0,0 +1,151 @@
+
+/*
+ * 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
+ *
+ */
+
+#include "TestFixture.h"
+#include "Clients/SimulationEntitiesManager.h"
+#include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
+namespace UnitTest
+{
+    void SimulationInterfaceTestEnvironment::AddGemsAndComponents()
+    {
+        constexpr AZStd::array<AZStd::string_view, 3> requiredGems = { "PhysX5", // required for PhysX Dynamic
+                                                                       "LmbrCentral", // for shapes
+                                                                       "SimulationInterfaces" };
+        AddActiveGems(requiredGems);
+        AddDynamicModulePaths({ "PhysX5.Gem" });
+        AddDynamicModulePaths({ "LmbrCentral" });
+        AddComponentDescriptors({
+            SimulationInterfaces::SimulationEntitiesManager::CreateDescriptor(),
+        });
+        AddRequiredComponents({ SimulationInterfaces::SimulationEntitiesManager::TYPEINFO_Uuid() });
+    }
+
+    void SimulationInterfaceTestEnvironment::PostSystemEntityActivate()
+    {
+        AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+
+        // load asset catalog
+    }
+
+    AZ::ComponentApplication* SimulationInterfaceTestEnvironment::CreateApplicationInstance()
+    {
+        // Using ToolsTestApplication to have AzFramework and AzToolsFramework components.
+        return aznew UnitTest::ToolsTestApplication("SimulationInterfaceTestEnvironment");
+    }
+
+    void SimulationInterfaceTestFixture::AddAsset(const AZStd::string& assetPath)
+    {
+        AZ::Data::AssetInfo info;
+        info.m_relativePath = assetPath;
+        info.m_sizeBytes = 1;
+        AZ::Data::AssetId id = AZ::Data::AssetId(AZ::Uuid::CreateRandom());
+        AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, id, info);
+        m_registeredAssets.insert(id);
+    }
+
+    AzPhysics::SceneHandle SimulationInterfaceTestFixture::GetDefaultSceneHandle() const
+    {
+        return m_testSceneHandle;
+    }
+
+    AZ::EntityId SimulationInterfaceTestFixture::CreateEntityWithStaticBodyComponent(
+        const AZStd::string& entityName, const AZ::Transform& transform)
+    {
+        AZStd::unique_ptr<AZ::Entity> entity = AZStd::make_unique<AZ::Entity>(entityName.c_str());
+        auto* transformComponent = entity->CreateComponent(AZ::TransformComponentTypeId);
+        AZ_Assert(transformComponent, "Failed to create TransformComponent");
+        auto* transformInterface = azrtti_cast<AZ::TransformInterface*>(transformComponent);
+        AZ_Assert(transformInterface, "Failed to get TransformInterface");
+        transformInterface->SetWorldTM(transform);
+        entity->CreateComponent(AZ::Uuid(PhysXRigidBodyComponentTypeId));
+        entity->CreateComponent(AZ::Uuid(PhysXShapeColliderComponentTypeId));
+        entity->CreateComponent(AZ::Uuid(SphereShapeComponentTypeId));
+        entity->Init();
+        entity->Activate();
+        AZ_Assert(entity->GetState() == AZ::Entity::State::Active, "Entity is not active");
+
+        auto id = entity->GetId();
+        m_entities.emplace(AZStd::make_pair(id, AZStd::move(entity)));
+
+        return id;
+    }
+
+    void SimulationInterfaceTestFixture::ClearEntities()
+    {
+        for (auto& entity : m_entities)
+        {
+            entity.second->Deactivate();
+        }
+        m_entities.clear();
+    }
+    void SimulationInterfaceTestFixture::DeleteEntity(const AZ::EntityId& entityId)
+    {
+        auto findIt = m_entities.find(entityId);
+        if (findIt != m_entities.end())
+        {
+            findIt->second->Deactivate();
+            m_entities.erase(findIt);
+        }
+    }
+
+    void SimulationInterfaceTestFixture::SetUp()
+    {
+        if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
+        {
+            AzPhysics::SceneConfiguration sceneConfiguration = physicsSystem->GetDefaultSceneConfiguration();
+            sceneConfiguration.m_sceneName = AzPhysics::DefaultPhysicsSceneName;
+            m_testSceneHandle = physicsSystem->AddScene(sceneConfiguration);
+            m_defaultScene = physicsSystem->GetScene(m_testSceneHandle);
+        }
+
+        Physics::DefaultWorldBus::Handler::BusConnect();
+    }
+
+    void SimulationInterfaceTestFixture::TearDown()
+    {
+        ClearEntities();
+        Physics::DefaultWorldBus::Handler::BusDisconnect();
+        m_defaultScene = nullptr;
+
+        // Clean up the Test scene
+        if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
+        {
+            physicsSystem->RemoveScene(m_testSceneHandle);
+        }
+        m_testSceneHandle = AzPhysics::InvalidSceneHandle;
+
+        for (const auto& id : m_registeredAssets)
+        {
+            AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::UnregisterAsset, id);
+        }
+        m_registeredAssets.clear();
+    }
+
+    void SimulationInterfaceTestFixture::StepPhysics(int numSteps)
+    {
+        for (int i = 0; i < numSteps; i++)
+        {
+            auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
+            physicsSystem->Simulate(1.0f / 60.0f);
+        }
+
+    }
+
+    void SimulationInterfaceTestFixture::TickApp(int numTicks)
+    {
+        AZ::ComponentApplication* app = nullptr;
+        AZ::ComponentApplicationBus::BroadcastResult(app, &AZ::ComponentApplicationBus::Events::GetApplication);
+        AZ_Assert(app, "Failed to get application");
+        for (int i = 0; i < numTicks; i++)
+        {
+            app->Tick();
+        }
+    }
+
+} // namespace UnitTest

+ 94 - 0
Gems/SimulationInterfaces/Code/Tests/Tools/TestFixture.h

@@ -0,0 +1,94 @@
+
+/*
+ * 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
+ *
+ */
+
+#include <AzCore/Asset/AssetManagerComponent.h>
+#include <AzCore/Component/ComponentApplication.h>
+#include <AzCore/Component/ComponentApplicationBus.h>
+#include <AzCore/Component/Entity.h>
+#include <AzCore/Component/EntityId.h>
+#include <AzCore/RTTI/RTTIMacros.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Slice/SliceAssetHandler.h>
+#include <AzCore/UserSettings/UserSettingsComponent.h>
+#include <AzCore/std/containers/array.h>
+#include <AzCore/std/string/string_view.h>
+#include <AzQtComponents/Utilities/QtPluginPaths.h>
+#include <AzTest/GemTestEnvironment.h>
+#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
+#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
+#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
+#include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
+
+#include <QApplication>
+#include <gtest/gtest.h>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <AzCore/Utils/Utils.h>
+#include <AzFramework/Asset/AssetCatalog.h>
+#include <AzFramework/Physics/Configuration/SystemConfiguration.h>
+#include <AzFramework/Physics/PhysicsSystem.h>
+#include <AzFramework/Physics/RigidBodyBus.h>
+#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
+#include <AzFramework/Physics/SystemBus.h>
+
+namespace UnitTest
+{
+    class SimulationInterfaceTestEnvironment : public AZ::Test::GemTestEnvironment
+    {
+        // AZ::Test::GemTestEnvironment overrides ...
+        void AddGemsAndComponents() override;
+        AZ::ComponentApplication* CreateApplicationInstance() override;
+
+    protected:
+        void PostSystemEntityActivate() override;
+
+    public:
+        SimulationInterfaceTestEnvironment() = default;
+        ~SimulationInterfaceTestEnvironment() override = default;
+    };
+
+    class SimulationInterfaceTestFixture
+        : public ::testing::Test
+        , protected Physics::DefaultWorldBus::Handler
+    {
+    protected:
+        constexpr static auto PhysXRigidBodyComponentTypeId = "{D4E52A70-BDE1-4819-BD3C-93AB3F4F3BE3}"; // From PhysX
+        constexpr static auto PhysXStaticBodyComponentTypeId = "{A2CCCD3D-FB31-4D65-8DCD-2CD7E1D09538}"; // From PhysX
+        constexpr static auto PhysXShapeColliderComponentTypeId = "{30CC9E77-378C-49DF-9617-6BF191901FE0}"; // From PhysX
+        constexpr static auto PhysXSphereColliderComponentTypeId = "{108CD341-E5C3-4AE1-B712-21E81ED6C277}"; // From PhysX
+        constexpr static auto SphereShapeComponentTypeId = "{E24CBFF0-2531-4F8D-A8AB-47AF4D54BCD2}"; // From LmbrCentral
+
+        void SetUp() override;
+        void TearDown() override;
+
+        AZ::EntityId CreateEntityWithStaticBodyComponent(const AZStd::string& entityName, const AZ::Transform& transform);
+
+        void DeleteEntity(const AZ::EntityId& entityId);
+        void ClearEntities();
+
+        AZStd::unordered_map<AZ::EntityId, AZStd::unique_ptr<AZ::Entity>> m_entities;
+
+        void AddAsset(const AZStd::string& assetPath);
+
+        //! Ask the physics system to step forward in time
+        void StepPhysics(int numSteps = 1);
+
+        //! Ask the application to tick forward in time
+        void TickApp(int numTicks = 1);
+
+    private:
+        AzPhysics::SceneHandle GetDefaultSceneHandle() const override;
+        AzPhysics::Scene* m_defaultScene = nullptr;
+        AzPhysics::SceneHandle m_testSceneHandle = AzPhysics::InvalidSceneHandle;
+        AZStd::unordered_set<AZ::Data::AssetId> m_registeredAssets;
+    };
+} // namespace UnitTest

+ 11 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_api_files.cmake

@@ -0,0 +1,11 @@
+# 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
+#
+
+set(FILES
+        Include/SimulationInterfaces/SimulationEntityManagerRequestBus.h
+    Include/SimulationInterfaces/SimulationMangerRequestBus.h
+    Include/SimulationInterfaces/SimulationInterfacesTypeIds.h
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_editor_api_files.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+
+set(FILES
+)

+ 11 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_editor_app_test.cmake

@@ -0,0 +1,11 @@
+# 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
+#
+
+set(FILES
+    Tests/Tools/TestFixture.cpp
+    Tests/Tools/TestFixture.h
+    Tests/Tools/SimulationIterfaceAppTest.cpp
+)

+ 12 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_editor_private_files.cmake

@@ -0,0 +1,12 @@
+# 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
+#
+
+set(FILES
+        Source/Tools/SimulationManagerEditor.cpp
+        Source/Tools/SimulationManagerEditor.h
+        Source/Tools/SimulationEntitiesManagerEditor.cpp
+        Source/Tools/SimulationEntitiesManagerEditor.h
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_editor_shared_files.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(FILES
+    Source/Tools/SimulationInterfacesEditorModule.cpp
+)

+ 11 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_editor_tests_files.cmake

@@ -0,0 +1,11 @@
+# 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
+#
+
+set(FILES
+    Tests/Tools/TestFixture.cpp
+    Tests/Tools/TestFixture.h
+    Tests/Tools/SimulationInterfaceTests.cpp
+)

+ 16 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_private_files.cmake

@@ -0,0 +1,16 @@
+# 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
+#
+
+set(FILES
+    Source/SimulationInterfacesModuleInterface.cpp
+    Source/SimulationInterfacesModuleInterface.h
+    Source/Clients/SimulationManager.cpp
+    Source/Clients/SimulationManager.h
+    Source/Clients/SimulationEntitiesManager.cpp
+    Source/Clients/SimulationEntitiesManager.h
+    Source/Clients/CommonUtilities.cpp
+    Source/Clients/CommonUtilities.h
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_shared_files.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(FILES
+    Source/Clients/SimulationInterfacesModule.cpp
+)

+ 9 - 0
Gems/SimulationInterfaces/Code/simulationinterfaces_tests_files.cmake

@@ -0,0 +1,9 @@
+# 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
+#
+
+set(FILES
+    Tests/Clients/SimulationInterfacesTest.cpp
+)

+ 18 - 0
Gems/SimulationInterfaces/Registry/assetprocessor_settings.setreg

@@ -0,0 +1,18 @@
+{
+    "Amazon": {
+        "AssetProcessor": {
+            "Settings": {
+                "ScanFolder SimulationInterfaces/Assets": {
+                    "watch": "@GEMROOT:SimulationInterfaces@/Assets",
+                    "recursive": 1,
+                    "order": 101
+                },
+                "ScanFolder SimulationInterfaces/Registry": {
+                    "watch": "@GEMROOT:SimulationInterfaces@/Registry",
+                    "recursive": 1,
+                    "order": 102
+                }
+            }
+        }
+    }
+}

+ 28 - 0
Gems/SimulationInterfaces/gem.json

@@ -0,0 +1,28 @@
+{
+    "gem_name": "SimulationInterfaces",
+    "version": "1.0.0",
+    "display_name": "SimulationInterfaces",
+    "license": "Apache-2.0 ",
+    "license_url": "https://opensource.org/licenses/Apache-2.0",
+    "origin": "RobotecAI",
+    "origin_url": "https://robotec.ai",
+    "type": "Code",
+    "summary": "This gem provides C++ API for simulation interfaces.",
+    "canonical_tags": [
+        "Gem"
+    ],
+    "user_tags": [
+        "SimulationInterfaces", "ROS2", "ROS 2"
+    ],
+    "platforms": [
+        ""
+    ],
+    "icon_path": "preview.png",
+    "requirements": "",
+    "documentation_url": "",
+    "dependencies": [],
+    "repo_uri": "",
+    "compatible_engines": [],
+    "engine_api_dependencies": [],
+    "restricted": "SimulationInterfaces"
+}

+ 3 - 0
Gems/SimulationInterfaces/preview.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c2484ef49dcaa7474517f608e551ff2619ed5b1206febdd9c1d885b90b41c502
+size 4987