Merge branch 'development' of https://github.com/o3de/o3de into TerrainMaterialsFix

This commit is contained in:
Sergey Pereslavtsev
2022-02-10 10:40:38 +00:00
325 changed files with 7728 additions and 5528 deletions
@@ -292,7 +292,7 @@ namespace AzToolsFramework::Prefab
return false;
}
const InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
if (!instance.has_value())
{
return false;
@@ -308,7 +308,7 @@ namespace AzToolsFramework::Prefab
return false;
}
InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
while (instance.has_value())
{
if (instance->get().GetAbsoluteInstanceAliasPath() == m_rootAliasFocusPath)
@@ -235,10 +235,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
if (!asset->GetId().IsValid())
{
AZ_Error(
"Prefab", false,
"Invalid asset found referenced in scene while entering game mode. The asset was stored in an instance of %s.",
classData->m_name);
// Invalid asset found referenced in scene while entering game mode.
return false;
}
@@ -7,6 +7,7 @@
*/
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx>
#include <AzCore/Interface/Interface.h>
@@ -117,9 +118,16 @@ namespace AzToolsFramework
{
}
bool EditorEntityUiHandlerBase::OnEntityDoubleClick([[maybe_unused]] AZ::EntityId entityId) const
bool EditorEntityUiHandlerBase::OnOutlinerItemDoubleClick([[maybe_unused]] const QModelIndex& index) const
{
return false;
}
AZ::EntityId EditorEntityUiHandlerBase::GetEntityIdFromIndex(const QModelIndex& index)
{
QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName);
return AZ::EntityId(firstColumnIndex.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
}
} // namespace AzToolsFramework
@@ -21,7 +21,6 @@ class QTreeView;
namespace AzToolsFramework
{
//! Defines a handler that can customize entity UI appearance and behavior in the Entity Outliner.
//! This class is meant to be abstract, entities do not have a handler by default.
class EditorEntityUiHandlerBase
{
protected:
@@ -33,7 +32,7 @@ namespace AzToolsFramework
public:
EditorEntityUiHandlerId GetHandlerId();
// # Entity Outliner
// # Entity Outliner Item
//! Returns the item info string that is appended to the item name in the Outliner.
virtual QString GenerateItemInfoString(AZ::EntityId entityId) const;
@@ -41,10 +40,12 @@ namespace AzToolsFramework
virtual QString GenerateItemTooltip(AZ::EntityId entityId) const;
//! Returns the item icon pixmap to display in the Outliner.
virtual QIcon GenerateItemIcon(AZ::EntityId entityId) const;
//! Returns whether the element's lock and visibility state should be accessible in the Outliner
virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const;
//! Returns whether the element's name should be editable
virtual bool CanRename(AZ::EntityId entityId) const;
//! Returns whether the element's lock and visibility state should be accessible in the Outliner
virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const;
// Qt-specific painting functions
//! Paints the background of the item in the Outliner.
virtual void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
@@ -54,24 +55,27 @@ namespace AzToolsFramework
//! Paints the background of the descendant branches of the item in the Outliner.
virtual void PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect,
const QModelIndex& index, const QModelIndex& descendantIndex) const;
//! Paints visual elements on the foreground of the item in the Outliner.
virtual void PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
//! Paints visual elements on the foreground of the descendants of the item in the Outliner.
virtual void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const;
// Outliner-specific interactions
//! Triggered when the entity is clicked in the Outliner.
//! @return True if the click has been handled and should not be propagated, false otherwise.
virtual bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const;
//! Triggered when the entity is double-clicked in the Outliner.
//! @return True if the double-click has been handled and should not be propagated, false otherwise.
virtual bool OnOutlinerItemDoubleClick(const QModelIndex& index) const;
//! Triggered when an entity's children are expanded in the Outliner.
virtual void OnOutlinerItemExpand(const QModelIndex& index) const;
//! Triggered when an entity's children are collapsed in the Outliner.
virtual void OnOutlinerItemCollapse(const QModelIndex& index) const;
//! Triggered when the entity is double clicked in the Outliner or in the Viewport.
//! @return True if the double click has been handled and should not be propagated, false otherwise.
virtual bool OnEntityDoubleClick(AZ::EntityId entityId) const;
protected:
static AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index);
private:
EditorEntityUiHandlerId m_handlerId = 0;
@@ -945,7 +945,7 @@ namespace AzToolsFramework
{
if (AZ::EntityId entityId = GetEntityIdFromIndex(index); auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId))
{
entityUiHandler->OnEntityDoubleClick(entityId);
entityUiHandler->OnOutlinerItemDoubleClick(index);
}
}
@@ -33,7 +33,7 @@ namespace AzToolsFramework
}
}
QIcon LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const
QIcon LevelRootUiHandler::GenerateItemIcon([[maybe_unused]] AZ::EntityId entityId) const
{
return QIcon(m_levelRootIconPath);
}
@@ -62,17 +62,18 @@ namespace AzToolsFramework
return infoString;
}
bool LevelRootUiHandler::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const
bool LevelRootUiHandler::CanToggleLockVisibility([[maybe_unused]] AZ::EntityId entityId) const
{
return false;
}
bool LevelRootUiHandler::CanRename(AZ::EntityId /*entityId*/) const
bool LevelRootUiHandler::CanRename([[maybe_unused]] AZ::EntityId entityId) const
{
return false;
}
void LevelRootUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
void LevelRootUiHandler::PaintItemBackground(
QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const
{
if (!painter)
{
@@ -94,8 +95,10 @@ namespace AzToolsFramework
painter->restore();
}
bool LevelRootUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const
bool LevelRootUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const
{
AZ::EntityId entityId = GetEntityIdFromIndex(index);
if (auto prefabFocusPublicInterface = AZ::Interface<Prefab::PrefabFocusPublicInterface>::Get();
!prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
@@ -33,7 +33,7 @@ namespace AzToolsFramework
bool CanToggleLockVisibility(AZ::EntityId entityId) const override;
bool CanRename(AZ::EntityId entityId) const override;
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
bool OnEntityDoubleClick(AZ::EntityId entityId) const override;
bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override;
private:
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
@@ -99,7 +99,7 @@ namespace AzToolsFramework
return;
}
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AZ::EntityId entityId = GetEntityIdFromIndex(index);
const bool isFirstColumn = index.column() == EntityOutlinerListModel::ColumnName;
const bool isLastColumn = index.column() == EntityOutlinerListModel::ColumnLockToggle;
QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName);
@@ -183,7 +183,7 @@ namespace AzToolsFramework
return;
}
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AZ::EntityId entityId = GetEntityIdFromIndex(index);
const QTreeView* outlinerTreeView(qobject_cast<const QTreeView*>(option.widget));
const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2) - 1;
@@ -283,7 +283,7 @@ namespace AzToolsFramework
void PrefabUiHandler::PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const
{
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AZ::EntityId entityId = GetEntityIdFromIndex(index);
const QPoint offset = QPoint(-18, 3);
QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName);
const int iconSize = 16;
@@ -385,7 +385,7 @@ namespace AzToolsFramework
bool PrefabUiHandler::OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AZ::EntityId entityId = GetEntityIdFromIndex(index);
const QPoint offset = QPoint(-18, 3);
if (m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId))
@@ -411,7 +411,7 @@ namespace AzToolsFramework
void PrefabUiHandler::OnOutlinerItemCollapse(const QModelIndex& index) const
{
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
AZ::EntityId entityId = GetEntityIdFromIndex(index);
if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
@@ -420,8 +420,10 @@ namespace AzToolsFramework
}
}
bool PrefabUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const
bool PrefabUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const
{
AZ::EntityId entityId = GetEntityIdFromIndex(index);
if (!m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
// Focus on this prefab
@@ -43,8 +43,8 @@ namespace AzToolsFramework
const QModelIndex& index,
const QModelIndex& descendantIndex) const override;
bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override;
void OnOutlinerItemCollapse(const QModelIndex& index) const override;
bool OnEntityDoubleClick(AZ::EntityId entityId) const override;
protected:
Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
@@ -15,7 +15,7 @@ namespace UnitTest
// When no containers are in the way, the function will just return the entityId of the entity that was clicked.
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -29,7 +29,7 @@ namespace UnitTest
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -47,7 +47,7 @@ namespace UnitTest
m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -65,7 +65,7 @@ namespace UnitTest
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -85,7 +85,7 @@ namespace UnitTest
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -8,6 +8,7 @@
#include <Tests/FocusMode/EditorFocusModeFixture.h>
#include <AzCore/Component/TransformBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <Tests/BoundsTestComponent.h>
@@ -93,10 +94,13 @@ namespace UnitTest
entity->CreateComponent<UnitTest::BoundsTestComponent>();
entity->Activate();
// Move the CarEntity so it's out of the way.
AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition);
// Move the City so that it is in view
AZ::TransformBus::Event(m_entityMap[CityEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCityEntityPosition);
// Setup the camera so the Car entity is in view.
// Move the CarEntity so that it's not overlapping with the rest
AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCarEntityPosition);
// Setup the camera so the entities is in view.
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
@@ -113,4 +117,5 @@ namespace UnitTest
return entity->GetId();
}
} // namespace UnitTest
@@ -8,7 +8,6 @@
#pragma once
#include <AzCore/Component/TransformBus.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
@@ -38,9 +37,6 @@ namespace UnitTest
AzToolsFramework::EntityIdList GetSelectedEntities();
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
AzFramework::CameraState m_cameraState;
inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f);
inline static const char* CityEntityName = "City";
inline static const char* StreetEntityName = "Street";
@@ -49,7 +45,11 @@ namespace UnitTest
inline static const char* Passenger1EntityName = "Passenger1";
inline static const char* Passenger2EntityName = "Passenger2";
inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
AzFramework::CameraState m_cameraState;
inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f);
inline static AZ::Vector3 s_worldCityEntityPosition = AZ::Vector3(5.0f, 10.0f, 0.0f);
inline static AZ::Vector3 s_worldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
};
} // namespace UnitTest
@@ -45,5 +45,20 @@ namespace UnitTest
// Click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
}
void BoxSelectOnViewport()
{
// Calculate the position in screen space of where to begin and end the box select action
const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(-10.0f, 15.0f, 5.0f), m_cameraState);
const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(10.0f, 15.0f, -5.0f), m_cameraState);
// Perform a box select in the viewport
m_actionDispatcher->SetStickySelect(true)
->CameraState(m_cameraState)
->MousePosition(beginningPositionWorldBoxSelect)
->MouseLButtonDown()
->MousePosition(endingPositionWorldBoxSelect)
->MouseLButtonUp();
}
};
} // namespace UnitTest
@@ -13,7 +13,7 @@ namespace UnitTest
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnLevel)
{
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -27,7 +27,7 @@ namespace UnitTest
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -41,7 +41,7 @@ namespace UnitTest
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -55,7 +55,7 @@ namespace UnitTest
m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -68,10 +68,71 @@ namespace UnitTest
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
ClickAtWorldPositionOnViewport(s_worldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0);
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLevel)
{
// Do a box select that includes all entities in the fixture
BoxSelectOnViewport();
// Entities are selected
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_THAT(selectedEntitiesAfter,
UnorderedElementsAre(
m_entityMap[CityEntityName],
m_entityMap[StreetEntityName],
m_entityMap[CarEntityName],
m_entityMap[Passenger1EntityName],
m_entityMap[SportsCarEntityName],
m_entityMap[Passenger2EntityName]
)
);
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnChild)
{
// Set the focus on the Passenger1 Entity (child of the entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
// Do a box select that includes all entities in the fixture
BoxSelectOnViewport();
// Entities are selected
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_THAT(selectedEntitiesAfter,
UnorderedElementsAre(
m_entityMap[StreetEntityName],
m_entityMap[CarEntityName],
m_entityMap[Passenger1EntityName],
m_entityMap[SportsCarEntityName],
m_entityMap[Passenger2EntityName]
)
);
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLeaf)
{
// Set the focus on the Passenger1 Entity (child of the entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]);
// Do a box select that includes all entities in the fixture
BoxSelectOnViewport();
// Entities are selected
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_THAT(selectedEntitiesAfter,
UnorderedElementsAre(
m_entityMap[Passenger1EntityName]
)
);
}
} // namespace UnitTest