Focus Mode | Improvements to GetFocusedEntities (#7708)
* Ensure that the system works at startup and after Clear. Ensure the invalid entityId is not added to the list. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Return a const reference to the list of entities in FocusModeInterface Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix SetFocusRoot to trigger notifications appropriately Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Optimize the entity removal via swap and pop, since we don't care about the order. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Introduce additional check to prevent possibly adding the same entity to the list twice. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix mock after API changes Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Typo. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fixed logic that needed to be updated when the code was moved. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
This commit is contained in:
@@ -39,7 +39,7 @@ namespace AzToolsFramework
|
||||
virtual AZ::EntityId GetFocusRoot(AzFramework::EntityContextId entityContextId) = 0;
|
||||
|
||||
//! Returns a list of the ids of all the entities that are descendants of the focus root.
|
||||
virtual EntityIdList GetFocusedEntities(AzFramework::EntityContextId entityContextId) = 0;
|
||||
virtual const EntityIdList& GetFocusedEntities(AzFramework::EntityContextId entityContextId) = 0;
|
||||
|
||||
//! Returns whether the entity id provided is part of the focused sub-tree.
|
||||
virtual bool IsInFocusSubTree(AZ::EntityId entityId) const = 0;
|
||||
|
||||
+52
-24
@@ -42,6 +42,8 @@ namespace AzToolsFramework
|
||||
AZ::Interface<FocusModeInterface>::Register(this);
|
||||
EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
|
||||
RefreshFocusedEntityIdList();
|
||||
}
|
||||
|
||||
void FocusModeSystemComponent::Deactivate()
|
||||
@@ -74,29 +76,28 @@ namespace AzToolsFramework
|
||||
|
||||
void FocusModeSystemComponent::SetFocusRoot(AZ::EntityId entityId)
|
||||
{
|
||||
if (m_focusRoot == entityId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto tracker = AZ::Interface<ViewportEditorModeTrackerInterface>::Get())
|
||||
{
|
||||
if (!m_focusRoot.IsValid() && entityId.IsValid())
|
||||
{
|
||||
tracker->ActivateMode({ GetEntityContextId() }, ViewportEditorMode::Focus);
|
||||
}
|
||||
else if (m_focusRoot.IsValid() && !entityId.IsValid())
|
||||
{
|
||||
tracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Focus);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId previousFocusEntityId = m_focusRoot;
|
||||
m_focusRoot = entityId;
|
||||
|
||||
RefreshFocusedEntityIdList();
|
||||
|
||||
FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot);
|
||||
// Only trigger notifications if the focus root has changed.
|
||||
if (m_focusRoot != previousFocusEntityId)
|
||||
{
|
||||
if (auto tracker = AZ::Interface<ViewportEditorModeTrackerInterface>::Get())
|
||||
{
|
||||
if (!previousFocusEntityId.IsValid() && m_focusRoot.IsValid())
|
||||
{
|
||||
tracker->ActivateMode({ GetEntityContextId() }, ViewportEditorMode::Focus);
|
||||
}
|
||||
else if (previousFocusEntityId.IsValid() && !m_focusRoot.IsValid())
|
||||
{
|
||||
tracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Focus);
|
||||
}
|
||||
}
|
||||
|
||||
FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusModeSystemComponent::ClearFocusRoot([[maybe_unused]] AzFramework::EntityContextId entityContextId)
|
||||
@@ -109,13 +110,14 @@ namespace AzToolsFramework
|
||||
return m_focusRoot;
|
||||
}
|
||||
|
||||
EntityIdList FocusModeSystemComponent::GetFocusedEntities([[maybe_unused]] AzFramework::EntityContextId entityContextId)
|
||||
const EntityIdList& FocusModeSystemComponent::GetFocusedEntities([[maybe_unused]] AzFramework::EntityContextId entityContextId)
|
||||
{
|
||||
return m_focusedEntityIdList;
|
||||
}
|
||||
|
||||
bool FocusModeSystemComponent::IsInFocusSubTree(AZ::EntityId entityId) const
|
||||
{
|
||||
// If the focus is on the root, all entities are in the focus subtree.
|
||||
if (m_focusRoot == AZ::EntityId())
|
||||
{
|
||||
return true;
|
||||
@@ -126,9 +128,30 @@ namespace AzToolsFramework
|
||||
|
||||
void FocusModeSystemComponent::OnEntityInfoUpdatedAddChildEnd(AZ::EntityId parentId, AZ::EntityId childId)
|
||||
{
|
||||
// If the parent's entityId is in the list, add the child.
|
||||
if (auto iter = AZStd::find(m_focusedEntityIdList.begin(), m_focusedEntityIdList.end(), parentId);
|
||||
iter != m_focusedEntityIdList.end())
|
||||
// If the parent's entityId is in the list and the child isn't, add the child to the list.
|
||||
bool isParentInList = false;
|
||||
bool isChildInList = false;
|
||||
|
||||
for (auto iter = m_focusedEntityIdList.begin(); iter != m_focusedEntityIdList.end(); ++iter)
|
||||
{
|
||||
if (*iter == parentId)
|
||||
{
|
||||
isParentInList = true;
|
||||
}
|
||||
|
||||
if (*iter == childId)
|
||||
{
|
||||
isChildInList = true;
|
||||
}
|
||||
|
||||
// Early out
|
||||
if (isChildInList)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isParentInList && !isChildInList)
|
||||
{
|
||||
m_focusedEntityIdList.push_back(childId);
|
||||
}
|
||||
@@ -140,7 +163,9 @@ namespace AzToolsFramework
|
||||
if (auto iter = AZStd::find(m_focusedEntityIdList.begin(), m_focusedEntityIdList.end(), childId);
|
||||
iter != m_focusedEntityIdList.end())
|
||||
{
|
||||
m_focusedEntityIdList.erase(iter);
|
||||
// Swap and pop since we don't care about the ordering.
|
||||
*iter = m_focusedEntityIdList.back();
|
||||
m_focusedEntityIdList.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +187,10 @@ namespace AzToolsFramework
|
||||
AZ::EntityId entityId = entityIdQueue.front();
|
||||
entityIdQueue.pop();
|
||||
|
||||
m_focusedEntityIdList.push_back(entityId);
|
||||
if (entityId.IsValid())
|
||||
{
|
||||
m_focusedEntityIdList.push_back(entityId);
|
||||
}
|
||||
|
||||
EntityIdList children;
|
||||
EditorEntityInfoRequestBus::EventResult(children, entityId, &EditorEntityInfoRequestBus::Events::GetChildren);
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ namespace AzToolsFramework
|
||||
void SetFocusRoot(AZ::EntityId entityId) override;
|
||||
void ClearFocusRoot(AzFramework::EntityContextId entityContextId) override;
|
||||
AZ::EntityId GetFocusRoot(AzFramework::EntityContextId entityContextId) override;
|
||||
EntityIdList GetFocusedEntities(AzFramework::EntityContextId entityContextId) override;
|
||||
const EntityIdList& GetFocusedEntities(AzFramework::EntityContextId entityContextId) override;
|
||||
bool IsInFocusSubTree(AZ::EntityId entityId) const override;
|
||||
|
||||
// EditorEntityInfoNotificationBus overrides ...
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ namespace UnitTest
|
||||
MOCK_METHOD1(SetFocusRoot, void(AZ::EntityId entityId));
|
||||
MOCK_METHOD1(ClearFocusRoot, void(AzFramework::EntityContextId entityContextId));
|
||||
MOCK_METHOD1(GetFocusRoot, AZ::EntityId(AzFramework::EntityContextId entityContextId));
|
||||
MOCK_METHOD1(GetFocusedEntities, AzToolsFramework::EntityIdList(AzFramework::EntityContextId entityContextId));
|
||||
MOCK_METHOD1(GetFocusedEntities, const AzToolsFramework::EntityIdList&(AzFramework::EntityContextId entityContextId));
|
||||
MOCK_CONST_METHOD1(IsInFocusSubTree, bool(AZ::EntityId entityId));
|
||||
};
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -31,18 +31,58 @@ namespace UnitTest
|
||||
EXPECT_EQ(m_focusModeInterface->GetFocusRoot(m_editorEntityContextId), AZ::EntityId());
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeFixture, GetFocusedEntitiesRoot)
|
||||
{
|
||||
AzToolsFramework::EntityIdList entities = m_focusModeInterface->GetFocusedEntities(m_editorEntityContextId);
|
||||
|
||||
using ::testing::UnorderedElementsAre;
|
||||
EXPECT_EQ(entities.size(), 6);
|
||||
EXPECT_THAT(
|
||||
entities,
|
||||
UnorderedElementsAre(
|
||||
m_entityMap[CityEntityName],
|
||||
m_entityMap[StreetEntityName],
|
||||
m_entityMap[CarEntityName],
|
||||
m_entityMap[Passenger1EntityName],
|
||||
m_entityMap[SportsCarEntityName],
|
||||
m_entityMap[Passenger2EntityName]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeFixture, GetFocusedEntitiesClear)
|
||||
{
|
||||
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
|
||||
|
||||
AzToolsFramework::EntityIdList entities = m_focusModeInterface->GetFocusedEntities(m_editorEntityContextId);
|
||||
|
||||
using ::testing::UnorderedElementsAre;
|
||||
EXPECT_EQ(entities.size(), 6);
|
||||
EXPECT_THAT(
|
||||
entities,
|
||||
UnorderedElementsAre(
|
||||
m_entityMap[CityEntityName], m_entityMap[StreetEntityName], m_entityMap[CarEntityName], m_entityMap[Passenger1EntityName],
|
||||
m_entityMap[SportsCarEntityName], m_entityMap[Passenger2EntityName]));
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeFixture, GetFocusedEntitiesBase)
|
||||
{
|
||||
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
|
||||
|
||||
AzToolsFramework::EntityIdList entities = m_focusModeInterface->GetFocusedEntities(m_editorEntityContextId);
|
||||
|
||||
using ::testing::UnorderedElementsAre;
|
||||
EXPECT_EQ(entities.size(), 5);
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[StreetEntityName]) != entities.end());
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[CarEntityName]) != entities.end());
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[Passenger1EntityName]) != entities.end());
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[SportsCarEntityName]) != entities.end());
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[Passenger2EntityName]) != entities.end());
|
||||
EXPECT_THAT(
|
||||
entities,
|
||||
UnorderedElementsAre(
|
||||
m_entityMap[StreetEntityName],
|
||||
m_entityMap[CarEntityName],
|
||||
m_entityMap[Passenger1EntityName],
|
||||
m_entityMap[SportsCarEntityName],
|
||||
m_entityMap[Passenger2EntityName]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeFixture, GetFocusedEntitiesSiblings)
|
||||
@@ -51,9 +91,9 @@ namespace UnitTest
|
||||
|
||||
AzToolsFramework::EntityIdList entities = m_focusModeInterface->GetFocusedEntities(m_editorEntityContextId);
|
||||
|
||||
using ::testing::UnorderedElementsAre;
|
||||
EXPECT_EQ(entities.size(), 2);
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[SportsCarEntityName]) != entities.end());
|
||||
EXPECT_TRUE(AZStd::find(entities.begin(), entities.end(), m_entityMap[Passenger2EntityName]) != entities.end());
|
||||
EXPECT_THAT(entities, UnorderedElementsAre(m_entityMap[SportsCarEntityName], m_entityMap[Passenger2EntityName]));
|
||||
}
|
||||
|
||||
TEST_F(EditorFocusModeFixture, GetFocusedEntitiesAddEntity)
|
||||
|
||||
Reference in New Issue
Block a user