Merge branch 'development' into Prefabs/SpawnableEntityAlias

This commit is contained in:
AMZN-koppersr
2021-11-04 10:39:59 -07:00
506 changed files with 11274 additions and 4002 deletions
@@ -40,7 +40,7 @@ namespace AzToolsFramework
bool isDisabledInSimMode = false; ///< set to true if the view pane should not be openable from level editor menu when editor is in simulation mode.
bool showOnToolsToolbar = false; ///< set to true if the view pane should create a button on the tools toolbar to open/close the pane
QString toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
AZStd::string toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
};
} // namespace AzToolsFramework
@@ -426,6 +426,8 @@ namespace AzToolsFramework
->Property("showInMenu", BehaviorValueProperty(&ViewPaneOptions::showInMenu))
->Property("canHaveMultipleInstances", BehaviorValueProperty(&ViewPaneOptions::canHaveMultipleInstances))
->Property("isPreview", BehaviorValueProperty(&ViewPaneOptions::isPreview))
->Property("showOnToolsToolbar", BehaviorValueProperty(&ViewPaneOptions::showOnToolsToolbar))
->Property("toolbarIcon", BehaviorValueProperty(&ViewPaneOptions::toolbarIcon))
;
behaviorContext->EBus<EditorRequestBus>("EditorRequestBus")
@@ -102,7 +102,7 @@ namespace AzToolsFramework
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
AssetSystemBus::Handler::BusDisconnect();
m_assetBrowserModel.release();
m_assetBrowserModel.reset();
EntryCache::DestroyInstance();
}
@@ -26,8 +26,12 @@ namespace AzToolsFramework
AZ::Interface<ContainerEntityInterface>::Unregister(this);
}
void ContainerEntitySystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
void ContainerEntitySystemComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ContainerEntitySystemComponent, AZ::Component>()->Version(1);
}
}
void ContainerEntitySystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -47,8 +47,12 @@ namespace AzToolsFramework
AZ::Interface<FocusModeInterface>::Unregister(this);
}
void FocusModeSystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
void FocusModeSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<FocusModeSystemComponent, AZ::Component>()->Version(1);
}
}
void FocusModeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -210,8 +210,8 @@ namespace AzToolsFramework
m_enabled = enabled;
if (!enabled)
{
// Send an internal focus change event to reset our input state to fresh if we're disabled.
HandleFocusChange(nullptr);
// Clear input channels to reset our input state if we're disabled.
ClearInputChannels(nullptr);
}
}
@@ -246,7 +246,7 @@ namespace AzToolsFramework
if (eventType == QEvent::Type::MouseMove)
{
// clear override cursor when moving outside of the viewport
// Clear override cursor when moving outside of the viewport
const auto* mouseEvent = static_cast<const QMouseEvent*>(event);
if (m_overrideCursor && !m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(mouseEvent->globalPos())))
{
@@ -255,6 +255,13 @@ namespace AzToolsFramework
}
}
// If the application state changes (e.g. we have alt-tabbed or minimized the
// main editor window) then ensure all input channels are cleared
if (eventType == QEvent::ApplicationStateChange)
{
ClearInputChannels(event);
}
// Only accept mouse & key release events that originate from an object that is not our target widget,
// as we don't want to erroneously intercept user input meant for another component.
if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease)
@@ -264,9 +271,6 @@ namespace AzToolsFramework
if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut)
{
// If our focus changes, go ahead and reset all input devices.
HandleFocusChange(event);
// If we focus in on the source widget and the mouse is contained in its
// bounds, refresh the cached cursor position to ensure it is up to date (this
// ensures cursor positions are refreshed correctly with context menu focus changes)
@@ -451,7 +455,7 @@ namespace AzToolsFramework
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
}
void QtEventToAzInputMapper::HandleFocusChange(QEvent* event)
void QtEventToAzInputMapper::ClearInputChannels(QEvent* event)
{
for (auto& channelData : m_channels)
{
@@ -138,8 +138,9 @@ namespace AzToolsFramework
void HandleKeyEvent(QKeyEvent* keyEvent);
// Handles mouse wheel events.
void HandleWheelEvent(QWheelEvent* wheelEvent);
// Handles focus change events.
void HandleFocusChange(QEvent* event);
// Clear all input channels (set all channel states to 'ended').
void ClearInputChannels(QEvent* event);
// Populates m_keyMappings.
void InitializeKeyMappings();
@@ -12,11 +12,12 @@
#include <AzCore/Utils/TypeHash.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityIdMapper.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
@@ -565,6 +566,7 @@ namespace AzToolsFramework
parentId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
}
// If the parent entity isn't owned by a prefab instance, bail.
InstanceOptionalReference owningInstanceOfParentEntity = GetOwnerInstanceByEntityId(parentId);
if (!owningInstanceOfParentEntity)
{
@@ -572,6 +574,14 @@ namespace AzToolsFramework
"Cannot add entity because the owning instance of parent entity with id '%llu' could not be found.",
static_cast<AZ::u64>(parentId)));
}
// If the parent entity is a closed container, bail.
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get(); !containerEntityInterface->IsContainerOpen(parentId))
{
return AZ::Failure(AZStd::string::format(
"Cannot add entity because the parent entity (id '%llu') is a closed container entity.",
static_cast<AZ::u64>(parentId)));
}
EntityAlias entityAlias = Instance::GenerateEntityAlias();
@@ -129,7 +129,7 @@ namespace AzToolsFramework
ToastId ToastNotificationsView::CreateToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration)
{
AzQtComponents::ToastNotification* notification = aznew AzQtComponents::ToastNotification(parentWidget(), toastConfiguration);
AzQtComponents::ToastNotification* notification = new AzQtComponents::ToastNotification(this, toastConfiguration);
ToastId toastId = AZ::Entity::MakeId();
m_notifications[toastId] = notification;
@@ -43,6 +43,7 @@
#include <AzToolsFramework/API/ComponentEntityObjectBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserSourceDropBus.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
@@ -764,10 +765,21 @@ namespace AzToolsFramework
return canHandleData;
}
bool EntityOutlinerListModel::CanDropMimeDataAssets(const QMimeData* data, Qt::DropAction /*action*/, int /*row*/, int /*column*/, const QModelIndex& /*parent*/) const
bool EntityOutlinerListModel::CanDropMimeDataAssets(
const QMimeData* data,
[[maybe_unused]] Qt::DropAction action,
[[maybe_unused]] int row,
[[maybe_unused]] int column,
const QModelIndex& parent) const
{
using namespace AzToolsFramework;
// Disable dropping assets on closed container entities.
AZ::EntityId parentId = GetEntityFromIndex(parent);
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
!containerEntityInterface->IsContainerOpen(parentId))
{
return false;
}
if (data->hasFormat(AssetBrowser::AssetBrowserEntry::GetMimeType()))
{
return DecodeAssetMimeData(data);
@@ -788,8 +800,15 @@ namespace AzToolsFramework
return false;
}
// If the parent entity is a closed container, bail.
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
!containerEntityInterface->IsContainerOpen(assignParentId))
{
return false;
}
// Source Files
if (sourceFiles.size() > 0)
if (!sourceFiles.empty())
{
// Get position (center of viewport). If no viewport is available, (0,0,0) will be used.
AZ::Vector3 viewportCenterPosition = AZ::Vector3::CreateZero();
@@ -973,6 +992,12 @@ namespace AzToolsFramework
return false;
}
// If the new parent is a closed container, bail.
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get(); !containerEntityInterface->IsContainerOpen(newParentId))
{
return false;
}
// Ignore entities not owned by the editor context. It is assumed that all entities belong
// to the same context since multiple selection doesn't span across views.
for (const AZ::EntityId& entityId : selectedEntityIds)
@@ -1387,7 +1387,10 @@ namespace AzToolsFramework
QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
QPixmap pixmap;
stream >> pixmap;
GUI->SetBrowseButtonIcon(pixmap);
if (!pixmap.isNull())
{
GUI->SetBrowseButtonIcon(pixmap);
}
}
}
}
@@ -1417,6 +1420,8 @@ namespace AzToolsFramework
}
else if (attrib == AZ_CRC_CE("ThumbnailIcon"))
{
GUI->SetCustomThumbnailEnabled(false);
AZStd::string iconPath;
if (attrValue->Read<AZStd::string>(iconPath) && !iconPath.empty())
{
@@ -1434,8 +1439,11 @@ namespace AzToolsFramework
QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
QPixmap pixmap;
stream >> pixmap;
GUI->SetCustomThumbnailEnabled(true);
GUI->SetCustomThumbnailPixmap(pixmap);
if (!pixmap.isNull())
{
GUI->SetCustomThumbnailEnabled(true);
GUI->SetCustomThumbnailPixmap(pixmap);
}
}
}
}
@@ -67,16 +67,9 @@ namespace AzToolsFramework
void ThumbnailPropertyCtrl::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName)
{
if (m_customThumbnailEnabled)
{
ClearThumbnail();
}
else
{
m_key = key;
m_thumbnail->SetThumbnailKey(m_key, contextName);
m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName);
}
m_key = key;
m_thumbnail->SetThumbnailKey(m_key, contextName);
m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName);
UpdateVisibility();
}
@@ -80,8 +80,9 @@ namespace AzToolsFramework
private:
AZStd::string m_message; //!< Message to display for fading text.
float m_opacity = 1.0f; //!< The opacity of the invalid click message.
AzFramework::ScreenPoint m_invalidClickPosition; //!< The position to display the invalid click message.
float m_opacity = 0.0f; //!< The opacity of the invalid click message.
//! The position to display the invalid click message.
AzFramework::ScreenPoint m_invalidClickPosition = AzFramework::ScreenPoint(0, 0);
};
//! Interface to begin invalid click feedback (will run all added InvalidClick behaviors).
@@ -301,6 +301,7 @@ namespace AzToolsFramework::ViewportUi::Internal
HighlightBorderSize + ViewportUiOverlayMargin, HighlightBorderSize + ViewportUiOverlayMargin);
m_componentModeBorderText.setVisible(true);
m_componentModeBorderText.setText(borderTitle.c_str());
UpdateUiOverlayGeometry();
}
void ViewportUiDisplay::RemoveViewportBorder()
@@ -28,9 +28,12 @@ namespace UnitTest
return true;
}
void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
void BoundsTestComponent::Reflect(AZ::ReflectContext* context)
{
// noop
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<BoundsTestComponent, EditorComponentBase>()->Version(1);
}
}
void BoundsTestComponent::Activate()
@@ -42,5 +42,4 @@ namespace UnitTest
AZ::Aabb GetWorldBounds() override;
AZ::Aabb GetLocalBounds() override;
};
} // namespace UnitTest
@@ -0,0 +1,130 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#if defined(HAVE_BENCHMARK)
#include <Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h>
#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
namespace Benchmark
{
using BM_SpawnAllEntities = BM_Spawnable;
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, SingleEntitySpawnable_SpawnCallVariable)(::benchmark::State& state)
{
const uint64_t spawnAllEntitiesCallCount = aznumeric_cast<uint64_t>(state.range());
const uint64_t entityCountInSourcePrefab = 1;
SetUpSpawnableAsset(entityCountInSourcePrefab);
for (auto _ : state)
{
state.PauseTiming();
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
state.ResumeTiming();
for (uint64_t spwanableCounter = 0; spwanableCounter < spawnAllEntitiesCallCount; spwanableCounter++)
{
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
}
m_rootSpawnableInterface->ProcessSpawnableQueue();
// Destroy the ticket so that this queues a request to delete all the entities spawned with this ticket.
state.PauseTiming();
delete m_spawnTicket;
m_spawnTicket = nullptr;
// This will process the request to delete all entities spawned with the ticket
m_rootSpawnableInterface->ProcessSpawnableQueue();
state.ResumeTiming();
}
state.SetComplexityN(spawnAllEntitiesCallCount);
}
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, SingleEntitySpawnable_SpawnCallVariable)
->RangeMultiplier(10)
->Range(100, 10000)
->Unit(benchmark::kMillisecond)
->Complexity();
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, SingleSpawnCall_EntityCountVariable)(::benchmark::State& state)
{
const uint64_t entityCountInSpawnable = aznumeric_cast<uint64_t>(state.range());
SetUpSpawnableAsset(entityCountInSpawnable);
for (auto _ : state)
{
state.PauseTiming();
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
state.ResumeTiming();
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
m_rootSpawnableInterface->ProcessSpawnableQueue();
// Destroy the ticket so that this queues a request to delete all the entities spawned with this ticket.
state.PauseTiming();
delete m_spawnTicket;
m_spawnTicket = nullptr;
// This will process the request to delete all entities spawned with the ticket
m_rootSpawnableInterface->ProcessSpawnableQueue();
state.ResumeTiming();
}
state.SetComplexityN(entityCountInSpawnable);
}
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, SingleSpawnCall_EntityCountVariable)
->RangeMultiplier(10)
->Range(100, 10000)
->Unit(benchmark::kMillisecond)
->Complexity();
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, EntityCountVariable_SpawnCallCountVariable)(::benchmark::State& state)
{
const uint64_t entityCountInSpawnable = aznumeric_cast<uint64_t>(state.range(0));
const uint64_t spawnCallCount = aznumeric_cast<uint64_t>(state.range(1));
SetUpSpawnableAsset(entityCountInSpawnable);
for (auto _ : state)
{
state.PauseTiming();
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
state.ResumeTiming();
for (uint64_t spawnCallCounter = 0; spawnCallCounter < spawnCallCount; spawnCallCounter++)
{
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
}
m_rootSpawnableInterface->ProcessSpawnableQueue();
state.PauseTiming();
delete m_spawnTicket;
m_spawnTicket = nullptr;
m_rootSpawnableInterface->ProcessSpawnableQueue();
state.ResumeTiming();
}
state.SetComplexityN(entityCountInSpawnable * spawnCallCount);
}
// Provide ranges here to compare times for spawning the same number of entities by altering entityCountInSpawnable and spawnCallCount.
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, EntityCountVariable_SpawnCallCountVariable)
->Args({ 10, 100 })
->Args({ 100, 10 })
->Args({ 10, 1000 })
->Args({ 1000, 10 })
->Args({ 100, 1000 })
->Args({ 1000, 100 })
->Unit(benchmark::kMillisecond)
->Complexity();
} // namespace Benchmark
#endif
@@ -0,0 +1,69 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#if defined(HAVE_BENCHMARK)
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
#include <Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h>
namespace Benchmark
{
void BM_Spawnable::SetUp(const benchmark::State& state)
{
SetUpHelper(state);
}
void BM_Spawnable::SetUp(benchmark::State& state)
{
SetUpHelper(state);
}
void BM_Spawnable::SetUpHelper(const benchmark::State& state)
{
BM_Prefab::SetUp(state);
m_rootSpawnableInterface = AzFramework::RootSpawnableInterface::Get();
AZ_Assert(m_rootSpawnableInterface != nullptr, "RootSpawnableInterface isn't found.");
}
void BM_Spawnable::TearDown(const benchmark::State& state)
{
TearDownHelper(state);
}
void BM_Spawnable::TearDown(benchmark::State& state)
{
TearDownHelper(state);
}
void BM_Spawnable::TearDownHelper(const benchmark::State& state)
{
m_spawnableAsset.Release();
BM_Prefab::TearDown(state);
}
void BM_Spawnable::SetUpSpawnableAsset(uint64_t entityCount)
{
AZStd::vector<AZ::Entity*> entities;
entities.reserve(entityCount);
for (uint64_t i = 0; i < entityCount; i++)
{
entities.emplace_back(CreateEntity("Entity"));
}
AZStd::unique_ptr<Instance> instance = m_prefabSystemComponent->CreatePrefab(AZStd::move(entities), {}, m_pathString);
const PrefabDom& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId());
// Lifecycle of spawnable is managed by the asset that's created using it.
AzFramework::Spawnable* spawnable = new AzFramework::Spawnable(
AZ::Data::AssetId::CreateString("{612F2AB1-30DF-44BB-AFBE-17A85199F09E}:0"), AZ::Data::AssetData::AssetStatus::Ready);
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom);
m_spawnableAsset = AZ::Data::Asset<AzFramework::Spawnable>(spawnable, AZ::Data::AssetLoadBehavior::Default);
}
} // namespace Benchmark
#endif
@@ -0,0 +1,44 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#if defined(HAVE_BENCHMARK)
#pragma once
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
#include <Prefab/Benchmark/PrefabBenchmarkFixture.h>
namespace AzFramework
{
class EntitySpawnTicket;
class RootSpawnableDefinition;
}
namespace Benchmark
{
class BM_Spawnable
: public Benchmark::BM_Prefab
{
protected:
void SetUp(const benchmark::State& state) override;
void SetUp(benchmark::State& state) override;
void SetUpHelper(const benchmark::State& state);
void TearDown(const benchmark::State& state) override;
void TearDown(benchmark::State& state) override;
void TearDownHelper(const benchmark::State& state);
void SetUpSpawnableAsset(uint64_t entityCount);
AZ::Data::Asset<AzFramework::Spawnable> m_spawnableAsset;
AzFramework::EntitySpawnTicket* m_spawnTicket;
AzFramework::RootSpawnableDefinition* m_rootSpawnableInterface;
};
} // namespace Benchmark
#endif
@@ -60,6 +60,9 @@ set(FILES
Prefab/Benchmark/PrefabLoadBenchmarks.cpp
Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp
Prefab/Benchmark/SpawnableCreateBenchmarks.cpp
Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h
Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.cpp
Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp
Prefab/PrefabFocus/PrefabFocusTests.cpp
Prefab/MockPrefabFileIOActionValidator.cpp
Prefab/MockPrefabFileIOActionValidator.h