LYN-7279 + LYN-7192 | Focus Mode - Container unit tests + Clear container entity open state on new level load (#4558)

* Change SetContainerOpenState to SetContainerOpen.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Introduce Clear function to avoid retaining all lingering open states when switching contexts/loading a new level.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Minor FocusMode fixture refactors to support ContainerEntity tests

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Introduce tests for the ContainerEntity API

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Add include to fix issue with EntityContextId not being defined.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Minor comment fixes. Moved environment clear functions to TearDown function of test fixture.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Use default editor context id in ContainerEntitySystemComponent

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Revert previous change as the EditorEntityContextId would not be initialized correctly on ContainerEntitySystemComponent Activate.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
This commit is contained in:
Danilo Aimini
2021-10-12 13:34:51 -07:00
committed by GitHub
parent c38c9739da
commit 6318247b3d
12 changed files with 575 additions and 130 deletions
@@ -11,6 +11,8 @@
#include <AzCore/Interface/Interface.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Entity/EntityContextBus.h>
namespace AzToolsFramework
{
//! Outcome object that returns an error message in case of failure to allow caller to handle internal errors.
@@ -43,7 +45,7 @@ namespace AzToolsFramework
//! @param entityId The entityId whose open state will be set.
//! @param open True if the container should be opened, false if it should be closed.
//! @return An error message if the operation was invalid, success otherwise.
virtual ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) = 0;
virtual ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) = 0;
//! If the entity id provided is registered as a container, it returns whether it's open.
//! @note the default value for non-containers is true, so this function can be called without
@@ -56,6 +58,13 @@ namespace AzToolsFramework
//! @return The highest closed entity container id if any, or entityId otherwise.
virtual AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const = 0;
//! Clears all open state information for Container Entities for the EntityContextId provided.
//! Used when context is switched, for example in the case of a new root prefab being loaded
//! in place of an old one.
//! @note Clear is meant to be called when no container is registered for the context provided.
//! @return An error message if any container was registered for the context, success otherwise.
virtual ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) = 0;
};
} // namespace AzToolsFramework
@@ -10,16 +10,19 @@
#include <AzCore/Component/TransformBus.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityNotificationBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
namespace AzToolsFramework
{
void ContainerEntitySystemComponent::Activate()
{
AZ::Interface<ContainerEntityInterface>::Register(this);
EditorEntityContextNotificationBus::Handler::BusConnect();
}
void ContainerEntitySystemComponent::Deactivate()
{
EditorEntityContextNotificationBus::Handler::BusDisconnect();
AZ::Interface<ContainerEntityInterface>::Unregister(this);
}
@@ -63,7 +66,7 @@ namespace AzToolsFramework
return m_containers.contains(entityId);
}
ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpenState(AZ::EntityId entityId, bool open)
ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpen(AZ::EntityId entityId, bool open)
{
if (!IsContainer(entityId))
{
@@ -87,7 +90,7 @@ namespace AzToolsFramework
bool ContainerEntitySystemComponent::IsContainerOpen(AZ::EntityId entityId) const
{
// If the entity is not a container, it should behave as open.
// Non-container entities behave the same as open containers. This saves the caller an additional check.
if(!m_containers.contains(entityId))
{
return true;
@@ -117,4 +120,36 @@ namespace AzToolsFramework
return highestSelectableEntityId;
}
void ContainerEntitySystemComponent::OnEntityStreamLoadSuccess()
{
// We don't yet support multiple entity contexts, so just use the default.
auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
Clear(editorEntityContextId);
}
ContainerEntityOperationResult ContainerEntitySystemComponent::Clear(AzFramework::EntityContextId entityContextId)
{
// We don't yet support multiple entity contexts, so only clear the default.
auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
if (entityContextId != editorEntityContextId)
{
return AZ::Failure(AZStd::string(
"Error in ContainerEntitySystemComponent::Clear - cannot clear non-default Entity Context!"));
}
if (!m_containers.empty())
{
return AZ::Failure(AZStd::string(
"Error in ContainerEntitySystemComponent::Clear - cannot clear container states if entities are still registered!"));
}
m_openContainers.clear();
return AZ::Success();
}
} // namespace AzToolsFramework
@@ -12,6 +12,7 @@
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
namespace AzToolsFramework
{
@@ -23,6 +24,7 @@ namespace AzToolsFramework
class ContainerEntitySystemComponent final
: public AZ::Component
, private ContainerEntityInterface
, private EditorEntityContextNotificationBus::Handler
{
public:
AZ_COMPONENT(ContainerEntitySystemComponent, "{74349759-B36B-44A6-B89F-F45D7111DD11}");
@@ -42,9 +44,13 @@ namespace AzToolsFramework
ContainerEntityOperationResult RegisterEntityAsContainer(AZ::EntityId entityId) override;
ContainerEntityOperationResult UnregisterEntityAsContainer(AZ::EntityId entityId) override;
bool IsContainer(AZ::EntityId entityId) const override;
ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) override;
ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) override;
bool IsContainerOpen(AZ::EntityId entityId) const override;
AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const override;
ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) override;
// EditorEntityContextNotificationBus overrides ...
void OnEntityStreamLoadSuccess() override;
private:
AZStd::unordered_set<AZ::EntityId> m_containers; //!< All entities in this set are containers.
@@ -196,6 +196,9 @@ namespace AzToolsFramework::Prefab
Initialize();
}
// Clear the old focus vector
m_instanceFocusVector.clear();
// Focus on the root prefab (AZ::EntityId() will default to it)
FocusOnOwningPrefab(AZ::EntityId());
}
@@ -230,7 +233,7 @@ namespace AzToolsFramework::Prefab
{
if (instance.has_value())
{
m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), true);
m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), true);
}
}
}
@@ -241,7 +244,7 @@ namespace AzToolsFramework::Prefab
{
if (instance.has_value())
{
m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), false);
m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), false);
}
}
}