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>
monroegm-disable-blank-issue-2
Danilo Aimini 4 years ago committed by GitHub
parent aa2ba82cea
commit 322a6c495a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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;

@ -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);

@ -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 ...

@ -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)

Loading…
Cancel
Save