Revamped AzFramework::Scene (#332)
Updated AzFramework::Scene to allow it to serve as the one-stop location for localized singletons. Localized singletons in this case are instance that can only occur once in an environment but multiple times within an application. As an example, this allows settings up a single camera per viewport for instance. Highlights of changes: Replaced the original ebuses with interfaces and events for easy of use and performance. Removed the Entity Context specific code and moved that to new locations within the Entity Context itself. Allowed basic inheritance. If a subsystem isn't found in a scene the parent can optionally be searched. Scenes can enter a zombie state and avoid immediately being deleted. This is needed for situations where subsystems can't be destroyed until async calls have been completed.main
parent
45fd86c2bf
commit
5e4094b258
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
template<typename T>
|
||||
bool Scene::SetSubsystem(T&& system)
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
for (const AZ::TypeId& key : m_systemKeys)
|
||||
{
|
||||
if (key == targetType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_systemKeys.push_back(targetType);
|
||||
m_systemObjects.emplace_back(AZStd::forward<T>(system));
|
||||
m_subsystemEvent.Signal(*this, SubsystemEventType::Added, targetType);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Scene::UnsetSubsystem()
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const size_t m_systemKeysCount = m_systemKeys.size();
|
||||
for (size_t i = 0; i < m_systemKeysCount; ++i)
|
||||
{
|
||||
if (m_systemKeys[i] != targetType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveSubsystem(i, targetType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Scene::UnsetSubsystem(const T& system)
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const size_t systemKeysCount = m_systemKeys.size();
|
||||
for (size_t i = 0; i < systemKeysCount; ++i)
|
||||
{
|
||||
if (m_systemKeys[i] != targetType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
[[maybe_unused]] T* instance = AZStd::any_cast<T>(&m_systemObjects[i]);
|
||||
AZ_Assert(
|
||||
instance && *instance == system,
|
||||
"Subsystem being released matched type, but wasn't pointing to the same system that was stored.");
|
||||
RemoveSubsystem(i, targetType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Scene::FindSubsystem()
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
AZStd::any* subSystem = FindSubsystem(targetType);
|
||||
return subSystem ? AZStd::any_cast<T>(subSystem) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* Scene::FindSubsystem() const
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const AZStd::any* subSystem = FindSubsystem(targetType);
|
||||
return subSystem ? AZStd::any_cast<const T>(subSystem) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Scene::FindSubsystemInScene()
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
AZStd::any* subSystem = FindSubsystemInScene(targetType);
|
||||
return subSystem ? AZStd::any_cast<T>(subSystem) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* Scene::FindSubsystemInScene() const
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const AZStd::any* subSystem = FindSubsystemInScene(targetType);
|
||||
return subSystem ? AZStd::any_cast<const T>(subSystem) : nullptr;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
// Forward declarations
|
||||
class Scene;
|
||||
|
||||
//! Interface used to create, get, or destroy scenes.
|
||||
class SceneSystemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~SceneSystemRequests() = default;
|
||||
|
||||
//! Single handler policy since there should only be one instance of this system component.
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
|
||||
//! Creates a scene with a given name.
|
||||
//! - If there is already a scene with the provided name this will return AZ::Failure().
|
||||
//! - If isDefault is set to true and there is already a default scene, the default scene will be switched to this one.
|
||||
virtual AZ::Outcome<Scene*, AZStd::string> CreateScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Gets a scene with a given name
|
||||
//! - If a scene does not exist with the given name, nullptr is returned.
|
||||
virtual Scene* GetScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Gets all the scenes that currently exist.
|
||||
virtual AZStd::vector<Scene*> GetAllScenes() = 0;
|
||||
|
||||
//! Remove a scene with a given name and return if the operation was successful.
|
||||
//! - If the removed scene is the default scene, there will no longer be a default scene.
|
||||
virtual bool RemoveScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Add a mapping from the provided EntityContextId to a Scene
|
||||
//! - If a scene is already associated with this EntityContextId, nothing is changed and false is returned.
|
||||
virtual bool SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0;
|
||||
|
||||
//! Remove a mapping from the provided EntityContextId to a Scene
|
||||
//! - If no scene is found from the provided EntityContextId, false is returned.
|
||||
virtual bool RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0;
|
||||
|
||||
//! Get the scene associated with an EntityContextId
|
||||
//! - If no scene is found for the provided EntityContextId, nullptr is returned.
|
||||
virtual Scene* GetSceneFromEntityContextId(EntityContextId entityContextId) = 0;
|
||||
};
|
||||
|
||||
using SceneSystemRequestBus = AZ::EBus<SceneSystemRequests>;
|
||||
|
||||
//! Interface used for notifications from the scene system
|
||||
class SceneSystemNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~SceneSystemNotifications() = default;
|
||||
|
||||
//! There can be multiple listeners to changes in the scene system.
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
//! Called when a scene has been created.
|
||||
virtual void SceneCreated(Scene& /*scene*/) {};
|
||||
|
||||
//! Called just before a scene is removed.
|
||||
virtual void SceneAboutToBeRemoved(Scene& /*scene*/) {};
|
||||
|
||||
};
|
||||
|
||||
using SceneSystemNotificationBus = AZ::EBus<SceneSystemNotifications>;
|
||||
|
||||
//! Interface used for notifications about individual scenes
|
||||
class SceneNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~SceneNotifications() = default;
|
||||
|
||||
//! There can be multiple listeners to changes in the scene system.
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
//! Bus is listened to using the pointer of the scene
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
|
||||
//! Specifies that events are addressed by the pointer to the scene
|
||||
using BusIdType = Scene*;
|
||||
|
||||
//! Called just before a scene is removed.
|
||||
virtual void SceneAboutToBeRemoved() {};
|
||||
|
||||
//! Called when an entity context is mapped to this scene.
|
||||
virtual void EntityContextMapped(EntityContextId /*entityContextId*/) {};
|
||||
|
||||
//! Called when an entity context is unmapped from this scene.
|
||||
virtual void EntityContextUnmapped(EntityContextId /*entityContextId*/) {};
|
||||
};
|
||||
|
||||
using SceneNotificationBus = AZ::EBus<SceneNotifications>;
|
||||
|
||||
} // AzFramework
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Scene/Scene.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! Interface used to create, get, or destroy scenes.
|
||||
//! This interface is single thread and is intended to be called from a single thread, commonly the main thread. The exception
|
||||
//! is connecting events, which is thread safe.
|
||||
class ISceneSystem
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AzFramework::ISceneSystem, "{DAE482A8-88AE-4BD3-8A5B-52D19A96E15F}");
|
||||
AZ_DISABLE_COPY_MOVE(ISceneSystem);
|
||||
|
||||
enum class EventType
|
||||
{
|
||||
SceneCreated,
|
||||
ScenePendingRemoval
|
||||
};
|
||||
using SceneEvent = AZ::Event<EventType, const AZStd::shared_ptr<Scene>&>;
|
||||
|
||||
ISceneSystem() = default;
|
||||
virtual ~ISceneSystem() = default;
|
||||
|
||||
using ActiveIterationCallback = AZStd::function<bool(const AZStd::shared_ptr<Scene>& scene)>;
|
||||
using ZombieIterationCallback = AZStd::function<bool(Scene& scene)>;
|
||||
|
||||
//! Creates a scene with a given name.
|
||||
//! - If there is already a scene with the provided name this will return AZ::Failure().
|
||||
virtual AZ::Outcome<AZStd::shared_ptr<Scene>, AZStd::string> CreateScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Creates a scene with a given name and a parent.
|
||||
//! - If there is already a scene with the provided name this will return AZ::Failure().
|
||||
virtual AZ::Outcome<AZStd::shared_ptr<Scene>, AZStd::string> CreateSceneWithParent(
|
||||
AZStd::string_view name, AZStd::shared_ptr<Scene> parent) = 0;
|
||||
|
||||
//! Gets a scene with a given name
|
||||
//! - If a scene does not exist with the given name, nullptr is returned.
|
||||
[[nodiscard]] virtual AZStd::shared_ptr<Scene> GetScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Iterates over all scenes that are in active use. Iteration stops if the callback returns false or all scenes have been listed.
|
||||
virtual void IterateActiveScenes(const ActiveIterationCallback& callback) = 0;
|
||||
//! Iterates over all zombie scenes. Zombie scenes are scenes that have been removed but still have references held on to. This can
|
||||
//! happen because scenes hold on to subsystems that can't immediately be deleted. These subsystems may still require being called
|
||||
//! such as a periodic tick. Iteration stops if the callback returns false or all scenes have been listed.
|
||||
virtual void IterateZombieScenes(const ZombieIterationCallback& callback) = 0;
|
||||
|
||||
//! Remove a scene with a given name and return if the operation was successful.
|
||||
virtual bool RemoveScene(AZStd::string_view name) = 0;
|
||||
|
||||
//! Connects the provided handler to the events that are called after scenes are created or before they get removed.
|
||||
virtual void ConnectToEvents(SceneEvent::Handler& handler) = 0;
|
||||
|
||||
protected:
|
||||
// Strictly a forwarding function to call private functions on the scene.
|
||||
void MarkSceneForDestruction(Scene& scene) { scene.MarkForDestruction(); }
|
||||
};
|
||||
|
||||
using SceneSystemInterface = AZ::Interface<ISceneSystem>;
|
||||
|
||||
// EBus wrapper for ScriptCanvas
|
||||
class ISceneSystemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
};
|
||||
using ILoggerRequestBus = AZ::EBus<ISceneSystem, ISceneSystemRequests>;
|
||||
} // AzFramework
|
||||
Loading…
Reference in New Issue