Merge branch 'development' into LYN-5265_state_tracker_impl

This commit is contained in:
John
2021-10-06 11:59:35 +01:00
357 changed files with 5037 additions and 2141 deletions
@@ -47,14 +47,6 @@ namespace AzToolsFramework
//! Retrieve the absolute path for the Asset Database Location
virtual bool GetAbsoluteAssetDatabaseLocation(AZStd::string& /*result*/) { return false; }
//! Retrieve the absolute folder path to the current game's source assets (the ones that go into source control)
//! This may include the current mod path, if a mod is being edited by the editor
virtual const char* GetAbsoluteDevGameFolderPath() = 0;
//! Retrieve the absolute folder path to the current developer root ('dev'), which contains source artifacts
//! and is generally checked into source control.
virtual const char* GetAbsoluteDevRootFolderPath() = 0;
/// Convert a full source path like "c:\\dev\\gamename\\blah\\test.tga" into a relative product path.
/// asset paths never mention their alias and are relative to the asset cache root
@@ -27,6 +27,7 @@
#include <AzToolsFramework/ToolsComponents/EditorAssetMimeDataContainer.h>
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h>
#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/FocusMode/FocusModeSystemComponent.h>
@@ -251,6 +252,7 @@ namespace AzToolsFramework
azrtti_typeid<EditorEntityContextComponent>(),
azrtti_typeid<Components::EditorEntityUiSystemComponent>(),
azrtti_typeid<FocusModeSystemComponent>(),
azrtti_typeid<ContainerEntitySystemComponent>(),
azrtti_typeid<SliceMetadataEntityContextComponent>(),
azrtti_typeid<Prefab::PrefabSystemComponent>(),
azrtti_typeid<EditorEntityFixupComponent>(),
@@ -354,26 +354,6 @@ namespace AzToolsFramework
}
}
const char* AssetSystemComponent::GetAbsoluteDevGameFolderPath()
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
if (fileIO)
{
return fileIO->GetAlias("@devassets@");
}
return "";
}
const char* AssetSystemComponent::GetAbsoluteDevRootFolderPath()
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
if (fileIO)
{
return fileIO->GetAlias("@devroot@");
}
return "";
}
void AssetSystemComponent::OnSystemTick()
{
AssetSystemBus::ExecuteQueuedEvents();
@@ -56,8 +56,6 @@ namespace AzToolsFramework
//////////////////////////////////////////////////////////////////////////
// AzToolsFramework::AssetSystemRequestBus::Handler overrides
bool GetAbsoluteAssetDatabaseLocation(AZStd::string& result) override;
const char* GetAbsoluteDevGameFolderPath() override;
const char* GetAbsoluteDevRootFolderPath() override;
bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& outputPath) override;
bool GenerateRelativeSourcePath(
const AZStd::string& sourcePath, AZStd::string& outputPath, AZStd::string& watchFolder) override;
@@ -137,7 +137,7 @@ namespace AzToolsFramework
AssetEditorWidgetUserSettings::AssetEditorWidgetUserSettings()
{
char assetRoot[AZ_MAX_PATH_LEN] = { 0 };
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", assetRoot, AZ_MAX_PATH_LEN);
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@projectroot@", assetRoot, AZ_MAX_PATH_LEN);
m_lastSavePath = assetRoot;
}
@@ -16,6 +16,7 @@
#include <AzToolsFramework/AssetBundle/AssetBundleComponent.h>
#include <AzToolsFramework/Component/EditorComponentAPIComponent.h>
#include <AzToolsFramework/Component/EditorLevelComponentAPIComponent.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h>
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
#include <AzToolsFramework/Entity/EditorEntityFixupComponent.h>
@@ -70,6 +71,7 @@ namespace AzToolsFramework
Components::EditorSelectionAccentSystemComponent::CreateDescriptor(),
EditorEntityContextComponent::CreateDescriptor(),
EditorEntityFixupComponent::CreateDescriptor(),
ContainerEntitySystemComponent::CreateDescriptor(),
FocusModeSystemComponent::CreateDescriptor(),
SliceMetadataEntityContextComponent::CreateDescriptor(),
SliceRequestComponent::CreateDescriptor(),
@@ -0,0 +1,61 @@
/*
* 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
*
*/
#pragma once
#include <AzCore/Interface/Interface.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzToolsFramework
{
//! Outcome object that returns an error message in case of failure to allow caller to handle internal errors.
using ContainerEntityOperationResult = AZ::Outcome<void, AZStd::string>;
//! ContainerEntityInterface
//! An entity registered as Container is just like a regular entity when open. If its state is changed
//! to closed, all descendants of the entity will be treated as part of the entity itself. Selecting any
//! descendant will result in the container being selected, and descendants will be hidden until the
//! container is opened.
class ContainerEntityInterface
{
public:
AZ_RTTI(ContainerEntityInterface, "{0A877C3A-726C-4FD2-BAFE-A2B9F1DE78E4}");
//! Registers the entity as a container. The container will be closed by default.
//! @param entityId The entityId that will be registered as a container.
virtual ContainerEntityOperationResult RegisterEntityAsContainer(AZ::EntityId entityId) = 0;
//! Unregisters the entity as a container.
//! The system will retain the closed state in case the entity is registered again later, but
//! if queried the entity will no longer behave as a container.
//! @param entityId The entityId that will be unregistered as a container.
virtual ContainerEntityOperationResult UnregisterEntityAsContainer(AZ::EntityId entityId) = 0;
//! Returns whether the entity id provided is registered as a container.
virtual bool IsContainer(AZ::EntityId entityId) const = 0;
//! Sets the open state of the container entity provided.
//! @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;
//! 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
//! verifying whether the entityId is registered as a container beforehand, since the container's
//! open behavior is exactly the same as the one of a regular entity.
//! @return False if the entityId is registered as a container, and its state is closed. True otherwise.
virtual bool IsContainerOpen(AZ::EntityId entityId) const = 0;
//! Detects if one of the ancestors of entityId is a closed container entity.
//! @return The highest closed entity container id if any, or entityId otherwise.
virtual AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const = 0;
};
} // namespace AzToolsFramework
@@ -0,0 +1,41 @@
/*
* 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
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
#include <AzCore/EBus/EBus.h>
#include <AzFramework/Entity/EntityContext.h>
namespace AzToolsFramework
{
//! Used to notify changes of state for Container Entities.
class ContainerEntityNotifications
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AzFramework::EntityContextId;
//////////////////////////////////////////////////////////////////////////
//! Triggered when a container entity status changes.
//! @param entityId The entity whose status has changed.
//! @param open The open state the container was changed to.
virtual void OnContainerEntityStatusChanged([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] bool open) {}
protected:
~ContainerEntityNotifications() = default;
};
using ContainerEntityNotificationBus = AZ::EBus<ContainerEntityNotifications>;
} // namespace AzToolsFramework
@@ -0,0 +1,120 @@
/*
* 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
*
*/
#include <AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h>
#include <AzCore/Component/TransformBus.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityNotificationBus.h>
namespace AzToolsFramework
{
void ContainerEntitySystemComponent::Activate()
{
AZ::Interface<ContainerEntityInterface>::Register(this);
}
void ContainerEntitySystemComponent::Deactivate()
{
AZ::Interface<ContainerEntityInterface>::Unregister(this);
}
void ContainerEntitySystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
{
}
void ContainerEntitySystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("ContainerEntityService"));
}
ContainerEntityOperationResult ContainerEntitySystemComponent::RegisterEntityAsContainer(AZ::EntityId entityId)
{
if (IsContainer(entityId))
{
return AZ::Failure(AZStd::string(
"ContainerEntitySystemComponent error - trying to register entity as container twice."));
}
m_containers.insert(entityId);
return AZ::Success();
}
ContainerEntityOperationResult ContainerEntitySystemComponent::UnregisterEntityAsContainer(AZ::EntityId entityId)
{
if (!IsContainer(entityId))
{
return AZ::Failure(AZStd::string(
"ContainerEntitySystemComponent error - trying to unregister entity that is not a container."));
}
m_containers.erase(entityId);
return AZ::Success();
}
bool ContainerEntitySystemComponent::IsContainer(AZ::EntityId entityId) const
{
return m_containers.contains(entityId);
}
ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpenState(AZ::EntityId entityId, bool open)
{
if (!IsContainer(entityId))
{
return AZ::Failure(AZStd::string(
"ContainerEntitySystemComponent error - cannot set open state of entity that was not registered as container."));
}
if(open)
{
m_openContainers.insert(entityId);
}
else
{
m_openContainers.erase(entityId);
}
ContainerEntityNotificationBus::Broadcast(&ContainerEntityNotificationBus::Events::OnContainerEntityStatusChanged, entityId, open);
return AZ::Success();
}
bool ContainerEntitySystemComponent::IsContainerOpen(AZ::EntityId entityId) const
{
// If the entity is not a container, it should behave as open.
if(!m_containers.contains(entityId))
{
return true;
}
// If the entity is a container, return its state.
return m_openContainers.contains(entityId);
}
AZ::EntityId ContainerEntitySystemComponent::FindHighestSelectableEntity(AZ::EntityId entityId) const
{
AZ::EntityId highestSelectableEntityId = entityId;
// Go up the hierarchy until you hit the root
while (entityId.IsValid())
{
if (!IsContainerOpen(entityId))
{
// If one of the ancestors is a container and it's closed, keep track of its id.
// We only return of the higher closed container in the hierarchy.
highestSelectableEntityId = entityId;
}
AZ::TransformBus::EventResult(entityId, entityId, &AZ::TransformBus::Events::GetParentId);
}
return highestSelectableEntityId;
}
} // namespace AzToolsFramework
@@ -0,0 +1,54 @@
/*
* 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
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
namespace AzToolsFramework
{
//! System Component to track Container Entity registration and open state.
//! An entity registered as Container is just like a regular entity when open. If its state is changed
//! to closed, all descendants of the entity will be treated as part of the entity itself. Selecting any
//! descendant will result in the container being selected, and descendants will be hidden until the
//! container is opened.
class ContainerEntitySystemComponent final
: public AZ::Component
, private ContainerEntityInterface
{
public:
AZ_COMPONENT(ContainerEntitySystemComponent, "{74349759-B36B-44A6-B89F-F45D7111DD11}");
ContainerEntitySystemComponent() = default;
virtual ~ContainerEntitySystemComponent() = default;
// AZ::Component overrides ...
void Activate() override;
void Deactivate() override;
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
// ContainerEntityInterface overrides ...
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;
bool IsContainerOpen(AZ::EntityId entityId) const override;
AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const override;
private:
AZStd::unordered_set<AZ::EntityId> m_containers; //!< All entities in this set are containers.
AZStd::unordered_set<AZ::EntityId> m_openContainers; //!< All entities in this set are open containers.
};
} // namespace AzToolsFramework
@@ -39,7 +39,7 @@ namespace AzToolsFramework
// the TraceContextLogFormatter.
//
// Usage example:
// const char* gameFolder = m_context.pRC->GetSystemEnvironment()->pFileIO->GetAlias("@devassets@");
// const char* gameFolder = m_context.pRC->GetSystemEnvironment()->pFileIO->GetAlias("@projectroot@");
// AZ_TraceContext("Game folder", gameFolder);
//
// for (int i=0; i<subMeshCount; ++i)
@@ -66,7 +66,7 @@ namespace AzToolsFramework
StringFunc::Path::Join(resolveBuffer, "log", logDirectory);
fileIO->SetAlias("@log@", logDirectory.c_str());
fileIO->CreatePath("@root@");
fileIO->CreatePath("@products@");
fileIO->CreatePath("@user@");
fileIO->CreatePath("@log@");
@@ -8,6 +8,7 @@
#include <AzToolsFramework/Prefab/PrefabFocusHandler.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
@@ -35,6 +36,30 @@ namespace AzToolsFramework::Prefab
EditorEntityContextNotificationBus::Handler::BusDisconnect();
}
void PrefabFocusHandler::Initialize()
{
m_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
AZ_Assert(
m_containerEntityInterface,
"Prefab - PrefabFocusHandler - "
"Container Entity Interface could not be found. "
"Check that it is being correctly initialized.");
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
AZ_Assert(
m_focusModeInterface,
"Prefab - PrefabFocusHandler - "
"Focus Mode Interface could not be found. "
"Check that it is being correctly initialized.");
m_instanceEntityMapperInterface = AZ::Interface<InstanceEntityMapperInterface>::Get();
AZ_Assert(
m_instanceEntityMapperInterface,
"Prefab - PrefabFocusHandler - "
"Instance Entity Mapper Interface could not be found. "
"Check that it is being correctly initialized.");
}
PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId)
{
InstanceOptionalReference focusedInstance;
@@ -44,7 +69,7 @@ namespace AzToolsFramework::Prefab
PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipInterface =
AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if(!prefabEditorEntityOwnershipInterface)
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not focus on root prefab instance - internal error "
"(PrefabEditorEntityOwnershipInterface unavailable)."));
@@ -79,8 +104,16 @@ namespace AzToolsFramework::Prefab
return AZ::Failure(AZStd::string("Prefab Focus Handler: invalid instance to focus on."));
}
if (!m_isInitialized)
{
Initialize();
}
if (!m_focusedInstance.has_value() || &m_focusedInstance->get() != &focusedInstance->get())
{
// Close all container entities in the old path
CloseInstanceContainers(m_instanceFocusVector);
m_focusedInstance = focusedInstance;
m_focusedTemplateId = focusedInstance->get().GetTemplateId();
@@ -103,12 +136,14 @@ namespace AzToolsFramework::Prefab
}
// Focus on the descendants of the container entity
if (FocusModeInterface* focusModeInterface = AZ::Interface<FocusModeInterface>::Get())
{
focusModeInterface->SetFocusRoot(containerEntityId);
}
m_focusModeInterface->SetFocusRoot(containerEntityId);
// Refresh path variables
RefreshInstanceFocusList();
// Open all container entities in the new path
OpenInstanceContainers(m_instanceFocusVector);
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
}
@@ -156,6 +191,11 @@ namespace AzToolsFramework::Prefab
void PrefabFocusHandler::OnEntityStreamLoadSuccess()
{
if (!m_isInitialized)
{
Initialize();
}
// Focus on the root prefab (AZ::EntityId() will default to it)
FocusOnOwningPrefab(AZ::EntityId());
}
@@ -184,4 +224,26 @@ namespace AzToolsFramework::Prefab
}
}
void PrefabFocusHandler::OpenInstanceContainers(const AZStd::vector<InstanceOptionalReference>& instances) const
{
for (const InstanceOptionalReference& instance : instances)
{
if (instance.has_value())
{
m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), true);
}
}
}
void PrefabFocusHandler::CloseInstanceContainers(const AZStd::vector<InstanceOptionalReference>& instances) const
{
for (const InstanceOptionalReference& instance : instances)
{
if (instance.has_value())
{
m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), false);
}
}
}
} // namespace AzToolsFramework::Prefab
@@ -15,6 +15,12 @@
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/Template/Template.h>
namespace AzToolsFramework
{
class ContainerEntityInterface;
class FocusModeInterface;
}
namespace AzToolsFramework::Prefab
{
class InstanceEntityMapperInterface;
@@ -30,6 +36,8 @@ namespace AzToolsFramework::Prefab
PrefabFocusHandler();
~PrefabFocusHandler();
void Initialize();
// PrefabFocusInterface overrides ...
PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override;
PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override;
@@ -46,12 +54,19 @@ namespace AzToolsFramework::Prefab
PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance);
void RefreshInstanceFocusList();
void OpenInstanceContainers(const AZStd::vector<InstanceOptionalReference>& instances) const;
void CloseInstanceContainers(const AZStd::vector<InstanceOptionalReference>& instances) const;
InstanceOptionalReference m_focusedInstance;
TemplateId m_focusedTemplateId;
AZStd::vector<InstanceOptionalReference> m_instanceFocusVector;
AZ::IO::Path m_instanceFocusPath;
InstanceEntityMapperInterface* m_instanceEntityMapperInterface;
ContainerEntityInterface* m_containerEntityInterface = nullptr;
FocusModeInterface* m_focusModeInterface = nullptr;
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
bool m_isInitialized = false;
};
} // namespace AzToolsFramework::Prefab
@@ -8,6 +8,7 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/IO/FileOperations.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
@@ -78,13 +79,9 @@ namespace AzToolsFramework
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(entitiesAndDescendants,
&AzToolsFramework::ToolsApplicationRequestBus::Events::GatherEntitiesAndAllDescendents, AzToolsFramework::EntityIdList{ entityId });
// Retrieve the game folder so we can use that as a root with the passed in relative path
const char* gameFolder = nullptr;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gameFolder, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAbsoluteDevGameFolderPath);
// Join our relative path with the game folder to get a full path to the desired asset
AZStd::string assetFullPath;
AzFramework::StringFunc::Path::Join(gameFolder, assetPath, assetFullPath);
AZ::IO::FixedMaxPath assetFullPath = AZ::Utils::GetProjectPath();
assetFullPath /= assetPath;
// Call SliceUtilities::MakeNewSlice with all user input prompts disabled
bool success = AzToolsFramework::SliceUtilities::MakeNewSlice(entitiesAndDescendants,
@@ -718,7 +718,7 @@ namespace AzToolsFramework
if (!fullPathFound)
{
assetFullPath = AZStd::string::format("@devassets@/%s", sliceAssetPath.c_str());
assetFullPath = AZStd::string::format("@projectroot@/%s", sliceAssetPath.c_str());
}
return Commit(assetFullPath.c_str(), preSaveCallback, postSaveCallback, sliceCommitFlags);
@@ -1020,13 +1020,13 @@ namespace AzToolsFramework
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "File IO is not initialized.");
AZStd::string devAssetPath = fileIO->GetAlias("@devassets@");
AZStd::string devAssetPath = fileIO->GetAlias("@projectroot@");
AZStd::string userPath = fileIO->GetAlias("@user@");
AZStd::string tempPath = fullPath;
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, devAssetPath);
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, userPath);
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, tempPath);
AzFramework::StringFunc::Replace(tempPath, "@devassets@", devAssetPath.c_str());
AzFramework::StringFunc::Replace(tempPath, "@projectroot@", devAssetPath.c_str());
AzFramework::StringFunc::Replace(tempPath, devAssetPath.c_str(), userPath.c_str());
tempPath.append(".slicetemp");
@@ -378,11 +378,11 @@ namespace AzToolsFramework
// If this layer is being loaded, it won't have a level save dependency yet, so clear that flag.
m_mustSaveLevelWhenLayerSaves = false;
QString fullPathName = levelPakFile;
if (fullPathName.contains("@devassets@"))
if (fullPathName.contains("@projectroot@"))
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
fullPathName.replace("@devassets@", fileIO->GetAlias("@devassets@"));
fullPathName.replace("@projectroot@", fileIO->GetAlias("@projectroot@"));
}
QFileInfo fileNameInfo(fullPathName);
@@ -37,51 +37,71 @@ namespace AzToolsFramework
return m_handlerId;
}
QString EditorEntityUiHandlerBase::GenerateItemInfoString(AZ::EntityId /*entityId*/) const
QString EditorEntityUiHandlerBase::GenerateItemInfoString([[maybe_unused]] AZ::EntityId entityId) const
{
return QString();
}
QString EditorEntityUiHandlerBase::GenerateItemTooltip(AZ::EntityId /*entityId*/) const
QString EditorEntityUiHandlerBase::GenerateItemTooltip([[maybe_unused]] AZ::EntityId entityId) const
{
return QString();
}
QIcon EditorEntityUiHandlerBase::GenerateItemIcon(AZ::EntityId /*entityId*/) const
QIcon EditorEntityUiHandlerBase::GenerateItemIcon([[maybe_unused]] AZ::EntityId entityId) const
{
return QIcon();
}
bool EditorEntityUiHandlerBase::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const
bool EditorEntityUiHandlerBase::CanToggleLockVisibility([[maybe_unused]] AZ::EntityId entityId) const
{
return true;
}
bool EditorEntityUiHandlerBase::CanRename(AZ::EntityId /*entityId*/) const
bool EditorEntityUiHandlerBase::CanRename([[maybe_unused]] AZ::EntityId entityId) const
{
return true;
}
void EditorEntityUiHandlerBase::PaintItemBackground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
void EditorEntityUiHandlerBase::PaintItemBackground(
[[maybe_unused]] QPainter* painter,
[[maybe_unused]] const QStyleOptionViewItem& option,
[[maybe_unused]] const QModelIndex& index) const
{
}
void EditorEntityUiHandlerBase::PaintDescendantBackground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/,
const QModelIndex& /*descendantIndex*/) const
void EditorEntityUiHandlerBase::PaintDescendantBackground(
[[maybe_unused]] QPainter* painter,
[[maybe_unused]] const QStyleOptionViewItem& option,
[[maybe_unused]] const QModelIndex& index,
[[maybe_unused]] const QModelIndex& descendantIndex) const
{
}
void EditorEntityUiHandlerBase::PaintDescendantBranchBackground(QPainter* /*painter*/, const QTreeView* /*view*/, const QRect& /*rect*/,
const QModelIndex& /*index*/, const QModelIndex& /*descendantIndex*/) const
void EditorEntityUiHandlerBase::PaintDescendantBranchBackground(
[[maybe_unused]] QPainter* painter,
[[maybe_unused]] const QTreeView* view,
[[maybe_unused]] const QRect& rect,
[[maybe_unused]] const QModelIndex& index,
[[maybe_unused]] const QModelIndex& descendantIndex) const
{
}
void EditorEntityUiHandlerBase::PaintItemForeground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
void EditorEntityUiHandlerBase::PaintItemForeground(
[[maybe_unused]] QPainter* painter,
[[maybe_unused]] const QStyleOptionViewItem& option,
[[maybe_unused]] const QModelIndex& index) const
{
}
void EditorEntityUiHandlerBase::PaintDescendantForeground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/,
const QModelIndex& /*descendantIndex*/) const
void EditorEntityUiHandlerBase::PaintDescendantForeground(
[[maybe_unused]] QPainter* painter,
[[maybe_unused]] const QStyleOptionViewItem& option,
[[maybe_unused]] const QModelIndex& index,
[[maybe_unused]] const QModelIndex& descendantIndex) const
{
}
void EditorEntityUiHandlerBase::OnDoubleClick([[maybe_unused]] AZ::EntityId entityId) const
{
}
@@ -61,6 +61,9 @@ namespace AzToolsFramework
virtual void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const;
//! Triggered when the entity is double clicked in the Outliner.
virtual void OnDoubleClick(AZ::EntityId entityId) const;
private:
EditorEntityUiHandlerId m_handlerId = 0;
};
@@ -88,6 +88,7 @@ namespace AzToolsFramework
EntityOutlinerListModel::~EntityOutlinerListModel()
{
ContainerEntityNotificationBus::Handler::BusDisconnect();
EditorEntityInfoNotificationBus::Handler::BusDisconnect();
EditorEntityContextNotificationBus::Handler::BusDisconnect();
ToolsApplicationEvents::Bus::Handler::BusDisconnect();
@@ -105,6 +106,12 @@ namespace AzToolsFramework
EntityCompositionNotificationBus::Handler::BusConnect();
AZ::EntitySystemBus::Handler::BusConnect();
AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(
editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
ContainerEntityNotificationBus::Handler::BusConnect(editorEntityContextId);
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
AZ_Assert(m_editorEntityUiInterface != nullptr,
"EntityOutlinerListModel requires a EditorEntityUiInterface instance on Initialize.");
@@ -1333,12 +1340,26 @@ namespace AzToolsFramework
emit EnableSelectionUpdates(true);
}
void EntityOutlinerListModel::OnEntityRuntimeActivationChanged(AZ::EntityId entityId, bool activeOnStart)
void EntityOutlinerListModel::OnEntityRuntimeActivationChanged(AZ::EntityId entityId, [[maybe_unused]] bool activeOnStart)
{
AZ_UNUSED(activeOnStart);
QueueEntityUpdate(entityId);
}
void EntityOutlinerListModel::OnContainerEntityStatusChanged(AZ::EntityId entityId, [[maybe_unused]] bool open)
{
QModelIndex changedIndex = GetIndexFromEntity(entityId);
// Trigger a refresh of all direct children so that they can be shown or hidden appropriately.
int numChildren = rowCount(changedIndex);
if (numChildren > 0)
{
emit dataChanged(index(0, 0, changedIndex), index(numChildren - 1, ColumnCount - 1, changedIndex));
}
// Always expand containers
QueueEntityToExpand(entityId, true);
}
void EntityOutlinerListModel::OnEntityInfoUpdatedRemoveChildBegin([[maybe_unused]] AZ::EntityId parentId, [[maybe_unused]] AZ::EntityId childId)
{
//add/remove operations trigger selection change signals which assert and break undo/redo operations in progress in inspector etc.
@@ -17,6 +17,7 @@
#include <AzToolsFramework/API/EntityCompositionNotificationBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityNotificationBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/EditorEntityRuntimeActivationBus.h>
@@ -54,6 +55,7 @@ namespace AzToolsFramework
, private EntityCompositionNotificationBus::Handler
, private EditorEntityRuntimeActivationChangeNotificationBus::Handler
, private AZ::EntitySystemBus::Handler
, private ContainerEntityNotificationBus::Handler
{
Q_OBJECT;
@@ -216,6 +218,9 @@ namespace AzToolsFramework
// EditorEntityRuntimeActivationChangeNotificationBus::Handler
void OnEntityRuntimeActivationChanged(AZ::EntityId entityId, bool activeOnStart) override;
// ContainerEntityNotificationBus overrides ...
void OnContainerEntityStatusChanged(AZ::EntityId entityId, bool open) override;
// Drag/Drop of components from Component Palette.
bool dropMimeDataComponentPalette(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
@@ -11,6 +11,8 @@
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/Entity.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include "EntityOutlinerListModel.hxx"
namespace AzToolsFramework
@@ -19,6 +21,10 @@ namespace AzToolsFramework
EntityOutlinerSortFilterProxyModel::EntityOutlinerSortFilterProxyModel(QObject* pParent)
: QSortFilterProxyModel(pParent)
{
m_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
AZ_Assert(
m_containerEntityInterface != nullptr,
"EntityOutlinerContainerProxyModel requires a ContainerEntityInterface instance on construction.");
}
void EntityOutlinerSortFilterProxyModel::UpdateFilter()
@@ -26,8 +32,24 @@ namespace AzToolsFramework
invalidateFilter();
}
void EntityOutlinerSortFilterProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
{
QSortFilterProxyModel::setSourceModel(sourceModel);
m_listModel = qobject_cast<EntityOutlinerListModel*>(sourceModel);
AZ_Assert(m_listModel != nullptr, "EntityOutlinerContainerProxyModel requires an EntityOutlinerListModel as its source .");
}
bool EntityOutlinerSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
// Retrieve the entityId of the parent entity
AZ::EntityId parentEntityId = m_listModel->GetEntityFromIndex(sourceParent);
if(!m_containerEntityInterface->IsContainerOpen(parentEntityId))
{
return false;
}
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
QVariant visibilityData = sourceModel()->data(index, EntityOutlinerListModel::VisibilityRole);
return visibilityData.isValid() ? visibilityData.toBool() : true;
@@ -19,11 +19,12 @@
namespace AzToolsFramework
{
class ContainerEntityInterface;
class EntityOutlinerListModel;
/*!
* Enables the Outliner to filter entries based on search string.
* Enables the Outliner to do custom sorting on entries.
*/
//! Enables the Outliner to filter entries based on search string.
//! Enables the Outliner to do custom sorting on entries.
//! Enforces the correct rendering for container entities.
class EntityOutlinerSortFilterProxyModel
: public QSortFilterProxyModel
{
@@ -37,12 +38,15 @@ namespace AzToolsFramework
void UpdateFilter();
// Qt overrides
void setSourceModel(QAbstractItemModel* sourceModel) override;
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
void sort(int column, Qt::SortOrder order) override;
private:
QString m_filterName;
EntityOutlinerListModel* m_listModel = nullptr;
ContainerEntityInterface* m_containerEntityInterface = nullptr;
};
}
@@ -199,6 +199,7 @@ namespace AzToolsFramework
m_proxyModel = aznew EntityOutlinerSortFilterProxyModel(this);
m_proxyModel->setSourceModel(m_listModel);
m_gui->m_objectTree->setModel(m_proxyModel);
// Link up signals for informing the model of tree changes using the proxy as an intermediary
@@ -905,8 +906,12 @@ namespace AzToolsFramework
}
}
void EntityOutlinerWidget::OnTreeItemDoubleClicked(const QModelIndex& /*index*/)
void EntityOutlinerWidget::OnTreeItemDoubleClicked(const QModelIndex& index)
{
if (AZ::EntityId entityId = GetEntityIdFromIndex(index); auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId))
{
entityUiHandler->OnDoubleClick(entityId);
}
}
void EntityOutlinerWidget::OnTreeItemExpanded(const QModelIndex& index)
@@ -1150,7 +1155,7 @@ namespace AzToolsFramework
{
QTimer::singleShot(1, this, [this]() {
m_gui->m_objectTree->setUpdatesEnabled(true);
m_gui->m_objectTree->expand(m_proxyModel->index(0,0));
m_gui->m_objectTree->expandToDepth(0);
});
}
@@ -41,6 +41,7 @@ namespace AzToolsFramework
{
class EditorEntityUiInterface;
class EntityOutlinerListModel;
class EntityOutlinerContainerProxyModel;
class EntityOutlinerSortFilterProxyModel;
namespace EntityOutliner
@@ -119,6 +120,7 @@ namespace AzToolsFramework
Ui::EntityOutlinerWidgetUI* m_gui;
EntityOutlinerListModel* m_listModel;
EntityOutlinerContainerProxyModel* m_containerModel;
EntityOutlinerSortFilterProxyModel* m_proxyModel;
AZ::u64 m_selectionContextId;
AZStd::vector<AZ::EntityId> m_selectedEntityIds;
@@ -22,6 +22,7 @@
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
@@ -56,7 +57,7 @@ namespace AzToolsFramework
{
namespace Prefab
{
ContainerEntityInterface* PrefabIntegrationManager::s_containerEntityInterface = nullptr;
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
PrefabFocusInterface* PrefabIntegrationManager::s_prefabFocusInterface = nullptr;
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
@@ -89,6 +90,13 @@ namespace AzToolsFramework
PrefabIntegrationManager::PrefabIntegrationManager()
{
s_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
if (s_containerEntityInterface == nullptr)
{
AZ_Assert(false, "Prefab - could not get ContainerEntityInterface on PrefabIntegrationManager construction.");
return;
}
s_editorEntityUiInterface = AZ::Interface<EditorEntityUiInterface>::Get();
if (s_editorEntityUiInterface == nullptr)
{
@@ -307,7 +315,7 @@ namespace AzToolsFramework
// temporarily null after QFileDialogs close, which we need in order to
// be able to parent our message dialogs properly
QWidget* activeWindow = QApplication::activeWindow();
const AZStd::string prefabFilesPath = "@devassets@/Prefabs";
const AZStd::string prefabFilesPath = "@projectroot@/Prefabs";
// Remove Level entity if it's part of the list
@@ -1057,6 +1065,7 @@ namespace AzToolsFramework
void PrefabIntegrationManager::OnPrefabComponentActivate(AZ::EntityId entityId)
{
// Register entity to appropriate UI Handler for UI overrides
if (s_prefabPublicInterface->IsLevelInstanceContainerEntity(entityId))
{
s_editorEntityUiInterface->RegisterEntity(entityId, m_levelRootUiHandler.GetHandlerId());
@@ -1064,11 +1073,32 @@ namespace AzToolsFramework
else
{
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (prefabWipFeaturesEnabled)
{
// Register entity as a container
s_containerEntityInterface->RegisterEntityAsContainer(entityId);
}
}
}
void PrefabIntegrationManager::OnPrefabComponentDeactivate(AZ::EntityId entityId)
{
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (prefabWipFeaturesEnabled && !s_prefabPublicInterface->IsLevelInstanceContainerEntity(entityId))
{
// Unregister entity as a container
s_containerEntityInterface->UnregisterEntityAsContainer(entityId);
}
// Unregister entity from UI Handler
s_editorEntityUiInterface->UnregisterEntity(entityId);
}
@@ -26,6 +26,8 @@
namespace AzToolsFramework
{
class ContainerEntityInterface;
namespace Prefab
{
class PrefabFocusInterface;
@@ -134,6 +136,7 @@ namespace AzToolsFramework
static const AZStd::string s_prefabFileExtension;
static ContainerEntityInterface* s_containerEntityInterface;
static EditorEntityUiInterface* s_editorEntityUiInterface;
static PrefabFocusInterface* s_prefabFocusInterface;
static PrefabLoaderInterface* s_prefabLoaderInterface;
@@ -8,6 +8,8 @@
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx>
@@ -317,4 +319,17 @@ namespace AzToolsFramework
return Internal_GetLastVisibleChild(model, lastChild);
}
void PrefabUiHandler::OnDoubleClick(AZ::EntityId entityId) const
{
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (prefabWipFeaturesEnabled)
{
// Focus on this prefab
m_prefabFocusInterface->FocusOnOwningPrefab(entityId);
}
}
}
@@ -29,13 +29,14 @@ namespace AzToolsFramework
PrefabUiHandler();
~PrefabUiHandler() override = default;
// EditorEntityUiHandler...
// EditorEntityUiHandler overrides ...
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
QString GenerateItemTooltip(AZ::EntityId entityId) const override;
QIcon GenerateItemIcon(AZ::EntityId entityId) const override;
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const override;
void OnDoubleClick(AZ::EntityId entityId) const override;
private:
Prefab::PrefabFocusInterface* m_prefabFocusInterface = nullptr;
@@ -13,8 +13,9 @@
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <AzToolsFramework/API/EditorViewportIconDisplayInterface.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorEntityIconComponentBus.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
@@ -191,6 +192,14 @@ namespace AzToolsFramework
return AZ::EntityId();
}
// Container Entity support - if the entity that is being selected is part of a closed container,
// change the selection to the container instead.
ContainerEntityInterface* containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
if (containerEntityInterface)
{
return containerEntityInterface->FindHighestSelectableEntity(entityIdUnderCursor);
}
return entityIdUnderCursor;
}
@@ -116,6 +116,10 @@ set(FILES
Component/EditorLevelComponentAPIBus.h
Component/EditorLevelComponentAPIComponent.cpp
Component/EditorLevelComponentAPIComponent.h
ContainerEntity/ContainerEntityInterface.h
ContainerEntity/ContainerEntityNotificationBus.h
ContainerEntity/ContainerEntitySystemComponent.cpp
ContainerEntity/ContainerEntitySystemComponent.h
Editor/EditorContextMenuBus.h
Editor/EditorSettingsAPIBus.h
Entity/EditorEntityStartStatus.h
@@ -131,13 +131,13 @@ namespace UnitTest
m_app.reset(aznew ToolsTestApplication("ArchiveComponentTest"));
m_app->Start(AzFramework::Application::Descriptor());
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
{
fileIoBase->SetAlias("@assets@", m_tempDir.GetDirectory());
fileIoBase->SetAlias("@products@", m_tempDir.GetDirectory());
}
}
@@ -37,10 +37,10 @@ namespace // anonymous
bool Search(const AzToolsFramework::AssetFileInfoList& assetList, const AZ::Data::AssetId& assetId)
{
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
[&](AzToolsFramework::AssetFileInfo fileInfo)
{
return fileInfo.m_assetId == assetId;
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
[&](AzToolsFramework::AssetFileInfo fileInfo)
{
return fileInfo.m_assetId == assetId;
});
}
}
@@ -74,11 +74,11 @@ namespace UnitTest
m_application->Start(AzFramework::Application::Descriptor());
// By default @assets@ is setup to include the platform at the end. But this test is going to
// By default @products@ is setup to include the platform at the end. But this test is going to
// loop over platforms and it will be included as part of the relative path of the file.
// So the asset folder for these tests have to point to the cache project root folder, which
// doesn't include the platform.
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
for (int idx = 0; idx < s_totalAssets; idx++)
{
@@ -158,17 +158,17 @@ namespace UnitTest
m_assetRegistry->RegisterAssetDependency(assets[5], AZ::Data::ProductDependency(assets[6], 0));
m_assetRegistry->RegisterAssetDependency(assets[6], AZ::Data::ProductDependency(assets[7], 0));
// asset8 -> asset6
// asset8 -> asset6
m_assetRegistry->RegisterAssetDependency(assets[8], AZ::Data::ProductDependency(assets[6], 0));
// asset10 -> asset11
// asset10 -> asset11
m_assetRegistry->RegisterAssetDependency(assets[10], AZ::Data::ProductDependency(assets[11], 0));
// asset11 -> asset10
// asset11 -> asset10
m_assetRegistry->RegisterAssetDependency(assets[11], AZ::Data::ProductDependency(assets[10], 0));
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
@@ -203,10 +203,6 @@ namespace UnitTest
const AZStd::string engroot = AZ::Test::GetEngineRootPath();
AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engroot.c_str());
AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath());
assetRoot /= "Cache";
AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str());
}
void TearDown() override
@@ -219,7 +215,7 @@ namespace UnitTest
delete m_application;
}
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
{
auto foundIter = m_assetRegistry->m_assetIdToInfo.find(id);
if (foundIter != m_assetRegistry->m_assetIdToInfo.end())
@@ -540,7 +536,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList, assets[7]));
EXPECT_TRUE(Search(assetList, assets[8]));
// Removing the android flag from the asset should still produce the same result
// Removing the android flag from the asset should still produce the same result
m_assetSeedManager->RemoveSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC);
@@ -564,7 +560,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList, assets[3]));
EXPECT_TRUE(Search(assetList, assets[4]));
// Adding the android flag again to the asset
// Adding the android flag again to the asset
m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ANDROID_ID);
@@ -624,7 +620,7 @@ namespace UnitTest
EXPECT_EQ(assetList1.m_fileInfoList[0].m_assetId, assetList2.m_fileInfoList[0].m_assetId);
EXPECT_GE(assetList2.m_fileInfoList[0].m_modificationTime, assetList1.m_fileInfoList[0].m_modificationTime); // file mod time should change
// file hash should not change
for (int idx = 0; idx < 5; idx++)
{
@@ -680,7 +676,7 @@ namespace UnitTest
m_assetSeedManager->AddSeedAsset(assets[validFileIndex], AzFramework::PlatformFlags::Platform_PC, m_assetsPath[invalidFileIndex]);
const AzFramework::AssetSeedList& oldSeedList = m_assetSeedManager->GetAssetSeedList();
for (const auto& seedInfo : oldSeedList)
{
if (seedInfo.m_assetId == assets[validFileIndex])
@@ -18,8 +18,6 @@ namespace UnitTests
{
public:
MOCK_METHOD1(GetAbsoluteAssetDatabaseLocation, bool(AZStd::string&));
MOCK_METHOD0(GetAbsoluteDevGameFolderPath, const char* ());
MOCK_METHOD0(GetAbsoluteDevRootFolderPath, const char* ());
MOCK_METHOD2(GetRelativeProductPathFromFullSourceOrProductPath, bool(const AZStd::string& fullPath, AZStd::string& relativeProductPath));
MOCK_METHOD3(GenerateRelativeSourcePath,
bool(const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder));
@@ -181,8 +181,8 @@ namespace UnitTest
const char* dir = m_componentApplication->GetExecutableFolder();
m_localFileIO.SetAlias("@assets@", dir);
m_localFileIO.SetAlias("@devassets@", dir);
m_localFileIO.SetAlias("@products@", dir);
m_localFileIO.SetAlias("@projectroot@", dir);
}
void Destroy()
@@ -22,7 +22,7 @@
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <Utils/Utils.h>
namespace
namespace
{
static const int s_totalAssets = 12;
}
@@ -53,15 +53,15 @@ namespace UnitTest
m_application->Start(AzFramework::Application::Descriptor());
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
// By default @assets@ is setup to include the platform at the end. But this test is going to
// By default @products@ is setup to include the platform at the end. But this test is going to
// loop over all platforms and it will be included as part of the relative path of the file.
// So the asset folder for these tests have to point to the cache project root folder, which
// doesn't include the platform.
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
for (int platformNum = AzFramework::PlatformId::PC; platformNum < AzFramework::PlatformId::NumPlatformIds; ++platformNum)
{
@@ -142,8 +142,6 @@ namespace UnitTest
/*
* AssetSystemRequestBus
*/
const char* GetAbsoluteDevGameFolderPath() override { return ""; }
const char* GetAbsoluteDevRootFolderPath() override { return ""; }
bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) override { return false; }
bool GenerateRelativeSourcePath(
[[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath,