Merge branch 'development' into LYN-5265_state_tracker_impl
This commit is contained in:
@@ -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(),
|
||||
|
||||
+61
@@ -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
|
||||
+41
@@ -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
|
||||
+120
@@ -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
|
||||
+54
@@ -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");
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+33
-13
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -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;
|
||||
};
|
||||
|
||||
+23
-2
@@ -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.
|
||||
|
||||
+5
@@ -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);
|
||||
|
||||
|
||||
+22
@@ -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;
|
||||
|
||||
+8
-4
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+7
-2
@@ -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;
|
||||
|
||||
+32
-2
@@ -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;
|
||||
|
||||
+10
-1
@@ -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)
|
||||
{
|
||||
|
||||
-2
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user