SceneSystemComponent.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzFramework/Scene/SceneSystemComponent.h>
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <AzCore/std/smart_ptr/make_shared.h>
  12. namespace AzFramework
  13. {
  14. void SceneSystemComponent::Reflect(AZ::ReflectContext* context)
  15. {
  16. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  17. {
  18. serializeContext->Class<SceneSystemComponent, AZ::Component>();
  19. if (AZ::EditContext* editContext = serializeContext->GetEditContext())
  20. {
  21. editContext->Class<SceneSystemComponent>(
  22. "Scene System Component", "System component responsible for owning scenes")
  23. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  24. ->Attribute(AZ::Edit::Attributes::Category, "Editor")
  25. ;
  26. }
  27. }
  28. }
  29. SceneSystemComponent::SceneSystemComponent() = default;
  30. SceneSystemComponent::~SceneSystemComponent() = default;
  31. void SceneSystemComponent::Activate()
  32. {
  33. }
  34. void SceneSystemComponent::Deactivate()
  35. {
  36. }
  37. void SceneSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  38. {
  39. provided.push_back(AZ_CRC_CE("SceneSystemComponentService"));
  40. }
  41. void SceneSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  42. {
  43. incompatible.push_back(AZ_CRC_CE("SceneSystemComponentService"));
  44. }
  45. AZ::Outcome<AZStd::shared_ptr<Scene>, AZStd::string> SceneSystemComponent::CreateScene(AZStd::string_view name)
  46. {
  47. return CreateSceneWithParent(name, nullptr);
  48. }
  49. AZ::Outcome<AZStd::shared_ptr<Scene>, AZStd::string> SceneSystemComponent::CreateSceneWithParent(
  50. AZStd::string_view name, AZStd::shared_ptr<Scene> parent)
  51. {
  52. const AZStd::shared_ptr<Scene>& existingScene = GetScene(name);
  53. if (existingScene)
  54. {
  55. return AZ::Failure<AZStd::string>("A scene already exists with this name.");
  56. }
  57. auto newScene = AZStd::make_shared<Scene>(name, AZStd::move(parent));
  58. m_activeScenes.push_back(newScene);
  59. {
  60. AZStd::lock_guard lock(m_eventMutex);
  61. m_events.Signal(EventType::SceneCreated, newScene);
  62. }
  63. return AZ::Success(AZStd::move(newScene));
  64. }
  65. AZStd::shared_ptr<Scene> SceneSystemComponent::GetScene(AZStd::string_view name)
  66. {
  67. auto sceneIterator = AZStd::find_if(m_activeScenes.begin(), m_activeScenes.end(),
  68. [name](auto& scene) -> bool
  69. {
  70. return scene->GetName() == name;
  71. }
  72. );
  73. return sceneIterator == m_activeScenes.end() ? nullptr : *sceneIterator;
  74. }
  75. void SceneSystemComponent::IterateActiveScenes(const ActiveIterationCallback& callback)
  76. {
  77. bool keepGoing = true;
  78. auto end = m_activeScenes.end();
  79. for (auto it = m_activeScenes.begin(); it != end && keepGoing; ++it)
  80. {
  81. keepGoing = callback(*it);
  82. }
  83. }
  84. void SceneSystemComponent::IterateZombieScenes(const ZombieIterationCallback& callback)
  85. {
  86. bool keepGoing = true;
  87. auto end = m_zombieScenes.end();
  88. for (auto it = m_zombieScenes.begin(); it != end && keepGoing;)
  89. {
  90. if (!it->expired())
  91. {
  92. keepGoing = callback(*(it->lock()));
  93. ++it;
  94. }
  95. else
  96. {
  97. *it = m_zombieScenes.back();
  98. m_zombieScenes.pop_back();
  99. end = m_zombieScenes.end();
  100. }
  101. }
  102. }
  103. bool SceneSystemComponent::RemoveScene(AZStd::string_view name)
  104. {
  105. for (AZStd::shared_ptr<Scene>& scene : m_activeScenes)
  106. {
  107. if (scene->GetName() == name)
  108. {
  109. MarkSceneForDestruction(*scene);
  110. {
  111. AZStd::lock_guard lock(m_eventMutex);
  112. m_events.Signal(EventType::ScenePendingRemoval, scene);
  113. }
  114. // Zombies are weak pointers that are kept around for situations where there's a delay in deleting the scene. This can happen
  115. // if there are outstanding calls like in-progress async calls or resources locked by hardware. A weak_ptr of the original
  116. // scene is kept so the zombie scene can still be found through iteration as it may require additional calls such as Tick calls.
  117. m_zombieScenes.push_back(scene);
  118. scene = AZStd::move(m_activeScenes.back());
  119. m_activeScenes.pop_back();
  120. // The scene may not be held onto anymore, so check here to see if the previously added zombie can be released.
  121. if (m_zombieScenes.back().expired())
  122. {
  123. m_zombieScenes.pop_back();
  124. }
  125. return true;
  126. }
  127. }
  128. AZ_Warning("SceneSystemComponent", false, R"(Attempting to remove scene name "%.*s", but that scene was not found.)", AZ_STRING_ARG(name));
  129. return false;
  130. }
  131. void SceneSystemComponent::ConnectToEvents(SceneEvent::Handler& handler)
  132. {
  133. AZStd::lock_guard lock(m_eventMutex);
  134. handler.Connect(m_events);
  135. }
  136. } // namespace AzFramework