4ee2f341dc
* Fix several Prefab outliner ordering issues This change does a few things to address instability in entity order when prefabs are enabled: - Changes ordering behavior on entity add to always be "insert after the last selected sibling of the new entity, or at the end if there is no selected sibling" - Adds some logic to ensure selection stays frozen during prefab propagation to allow this behavior to be used - Alters delta generation in `PrefabPublicHandler::CreateEntity` to use the template instead of reserializing the DOM - this avoids a whole bunch of patching issues caused by EditorEntitySortComponent doing post-hoc order fix-up and should generally be safer/faster as we're producing patches for the actual target for those patches - Because the duplicate action is DOM-driven, and there's some thorniness around making changes that will affect the template during propagation, this adds `PrefabPublicHandler::AddNewEntityToSortOrder` to directly patch the DOM for the duplicate case Two bits of this come from patches from the incredibly helpful @AMZN-daimini - Alters `PrefabPublicHandler::GenerateUndoNodesForEntityChangeAndUpdateCache` behavior for determining what's an override: we now check to see if we're part of the current focused instance but *not* owned by the focus instance directly. This lets entity order for nested prefabs get saved to the owning prefab instead of as an override. I'm putting this up for discussion without a feature flag gating it, but we may wish to make this a toggle or disable it outright for stabilization (in which case entity order won't be saved to the owning prefab) - Adds a custom serializer for EditorEntitySortComponent. This isn't strictly necessary now, but it was very useful for debugging and ended up receiving much more manual testing its migration path and save/load path more than I've tested without using the serializer. Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Add missing serializers Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Address some review feedback Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Generate patch in `PrefabPublicHandler::CreateEntity` using the instance's fully evaluated template in-memory Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Fix up comment Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Fix Linux build Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Try to make test less timing dependent (haven't been able to repro failure locally) Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Fix another build issue Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Fix unit test failures Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * Fix a duplicate issue with sanitization that was causing sporadic test failure (thanks, test!) Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com> * One more Linux fix... Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
205 lines
11 KiB
C++
205 lines
11 KiB
C++
/*
|
|
* 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
|
|
*
|
|
*/
|
|
|
|
#ifndef AZTOOLSFRAMEWORK_TOOLSAPPLICATION_H
|
|
#define AZTOOLSFRAMEWORK_TOOLSAPPLICATION_H
|
|
|
|
#include <AzCore/base.h>
|
|
#include <AzFramework/Application/Application.h>
|
|
#include <AzFramework/Asset/SimpleAsset.h>
|
|
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
|
#include <AzToolsFramework/API/EditorEntityAPI.h>
|
|
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
|
#include <AzToolsFramework/Commands/PreemptiveUndoCache.h>
|
|
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
|
|
|
#pragma once
|
|
|
|
namespace AzToolsFramework
|
|
{
|
|
namespace UndoSystem
|
|
{
|
|
class UndoCacheInterface;
|
|
}
|
|
|
|
class ToolsApplication
|
|
: public AzFramework::Application
|
|
, public ToolsApplicationRequests::Bus::Handler
|
|
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
|
{
|
|
public:
|
|
AZ_RTTI(ToolsApplication, "{2895561E-BE90-4CC3-8370-DD46FCF74C01}", AzFramework::Application);
|
|
AZ_CLASS_ALLOCATOR(ToolsApplication, AZ::SystemAllocator, 0);
|
|
|
|
ToolsApplication(int* argc = nullptr, char*** argv = nullptr);
|
|
~ToolsApplication();
|
|
|
|
void Stop() override;
|
|
void CreateReflectionManager() override;
|
|
void Reflect(AZ::ReflectContext* context) override;
|
|
|
|
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
|
|
|
|
AzToolsFramework::ToolsApplicationRequests::ResolveToolPathOutcome ResolveConfigToolsPath(const char* toolApplicationName) const override;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AzFramework::Application
|
|
void Start(const Descriptor& descriptor, const StartupParameters& startupParameters = StartupParameters()) override;
|
|
|
|
protected:
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AzFramework::Application
|
|
void StartCommon(AZ::Entity* systemEntity) override;
|
|
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
|
|
bool AddEntity(AZ::Entity* entity) override;
|
|
bool RemoveEntity(AZ::Entity* entity) override;
|
|
const char* GetCurrentConfigurationName() const override;
|
|
void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AzFramework::ApplicationRequests::Bus overrides ...
|
|
void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ToolsApplicationRequests::Bus::Handler
|
|
void PreExportEntity(AZ::Entity& source, AZ::Entity& target) override;
|
|
void PostExportEntity(AZ::Entity& source, AZ::Entity& target) override;
|
|
|
|
void MarkEntitySelected(AZ::EntityId entityId) override;
|
|
void MarkEntitiesSelected(const EntityIdList& entitiesToSelect) override;
|
|
|
|
void MarkEntityDeselected(AZ::EntityId entityId) override;
|
|
void MarkEntitiesDeselected(const EntityIdList& entitiesToDeselect) override;
|
|
|
|
void SetEntityHighlighted(AZ::EntityId entityId, bool highlighted) override;
|
|
|
|
void AddDirtyEntity(AZ::EntityId entityId) override;
|
|
int RemoveDirtyEntity(AZ::EntityId entityId) override;
|
|
void ClearDirtyEntities() override;
|
|
bool IsDuringUndoRedo() override { return m_isDuringUndoRedo; }
|
|
void UndoPressed() override;
|
|
void RedoPressed() override;
|
|
void FlushUndo() override;
|
|
void FlushRedo() override;
|
|
UndoSystem::URSequencePoint* BeginUndoBatch(const char* label) override;
|
|
UndoSystem::URSequencePoint* ResumeUndoBatch(UndoSystem::URSequencePoint* token, const char* label) override;
|
|
void EndUndoBatch() override;
|
|
|
|
bool IsEntityEditable(AZ::EntityId entityId) override;
|
|
bool AreEntitiesEditable(const EntityIdList& entityIds) override;
|
|
|
|
void CheckoutPressed() override;
|
|
SourceControlFileInfo GetSceneSourceControlInfo() override;
|
|
|
|
bool AreAnyEntitiesSelected() override { return !m_selectedEntities.empty(); }
|
|
int GetSelectedEntitiesCount() override { return static_cast<int>(m_selectedEntities.size()); }
|
|
const EntityIdList& GetSelectedEntities() override { return m_selectedEntities; }
|
|
const EntityIdList& GetHighlightedEntities() override { return m_highlightedEntities; }
|
|
void SetSelectedEntities(const EntityIdList& selectedEntities) override;
|
|
bool IsSelectable(const AZ::EntityId& entityId) override;
|
|
bool IsSelected(const AZ::EntityId& entityId) override;
|
|
bool IsSliceRootEntity(const AZ::EntityId& entityId) override;
|
|
|
|
UndoSystem::UndoStack* GetUndoStack() override { return m_undoStack; }
|
|
UndoSystem::URSequencePoint* GetCurrentUndoBatch() override { return m_currentBatchUndo; }
|
|
PreemptiveUndoCache* GetUndoCache() override { return &m_undoCache; }
|
|
|
|
EntityIdSet GatherEntitiesAndAllDescendents(const EntityIdList& inputEntities) override;
|
|
|
|
AZ::EntityId CreateNewEntity(AZ::EntityId parentId = AZ::EntityId()) override;
|
|
AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& pos, AZ::EntityId parentId = AZ::EntityId()) override;
|
|
AZ::EntityId GetExistingEntity(AZ::u64 id) override;
|
|
bool EntityExists(AZ::EntityId id) override;
|
|
void DeleteSelected() override;
|
|
void DeleteEntityById(AZ::EntityId entityId) override;
|
|
void DeleteEntities(const EntityIdList& entities) override;
|
|
void DeleteEntityAndAllDescendants(AZ::EntityId entityId) override;
|
|
void DeleteEntitiesAndAllDescendants(const EntityIdList& entities) override;
|
|
|
|
bool DetachEntities(const AZStd::vector<AZ::EntityId>& entitiesToDetach, AZStd::vector<AZStd::pair<AZ::EntityId, AZ::SliceComponent::EntityRestoreInfo>>& restoreInfos) override;
|
|
|
|
/**
|
|
* Detaches the supplied subslices from their owning slice instance
|
|
* @param subsliceRootList A list of SliceInstanceAddresses paired with a mapping from the sub slices asset entityId's to the owing slice instance's live entityIds
|
|
See SliceComponent::GetMappingBetweenSubsliceAndSourceInstanceEntityIds for a helper to acquire this mapping
|
|
* @param restoreInfos A list of EntityRestoreInfo's to be filled with information on how to restore the entities in the subslices back to their original state before this operation
|
|
* @return Returns true on operation success, false otherwise
|
|
*/
|
|
bool DetachSubsliceInstances(const AZ::SliceComponent::SliceInstanceEntityIdRemapList& subsliceRootList,
|
|
AZStd::vector<AZStd::pair<AZ::EntityId, AZ::SliceComponent::EntityRestoreInfo>>& restoreInfos) override;
|
|
|
|
bool FindCommonRoot(const EntityIdSet& entitiesToBeChecked, AZ::EntityId& commonRootEntityId, EntityIdList* topLevelEntities = nullptr) override;
|
|
bool FindCommonRootInactive(const EntityList& entitiesToBeChecked, AZ::EntityId& commonRootEntityId, EntityList* topLevelEntities = nullptr) override;
|
|
void FindTopLevelEntityIdsInactive(const EntityIdList& entityIdsToCheck, EntityIdList& topLevelEntityIds) override;
|
|
AZ::SliceComponent::SliceInstanceAddress FindCommonSliceInstanceAddress(const EntityIdList& entityIds) override;
|
|
AZ::EntityId GetRootEntityIdOfSliceInstance(AZ::SliceComponent::SliceInstanceAddress sliceAddress) override;
|
|
AZ::EntityId GetCurrentLevelEntityId() override;
|
|
|
|
bool RequestEditForFileBlocking(const char* assetPath, const char* progressMessage, const RequestEditProgressCallback& progressCallback) override;
|
|
bool CheckSourceControlConnectionAndRequestEditForFileBlocking(const char* assetPath, const char* progressMessage, const RequestEditProgressCallback& progressCallback) override;
|
|
void RequestEditForFile(const char* assetPath, RequestEditResultCallback resultCallback) override;
|
|
void CheckSourceControlConnectionAndRequestEditForFile(const char* assetPath, RequestEditResultCallback resultCallback) override;
|
|
|
|
void EnterEditorIsolationMode() override;
|
|
void ExitEditorIsolationMode() override;
|
|
bool IsEditorInIsolationMode() override;
|
|
|
|
void CreateAndAddEntityFromComponentTags(const AZStd::vector<AZ::Crc32>& requiredTags, const char* entityName) override;
|
|
|
|
/* Open 3D Engine INTERNAL USE ONLY. */
|
|
void RunRedoSeparately(UndoSystem::URSequencePoint* redoCommand) override;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AzFramework::SimpleAssetRequests::Bus::Handler
|
|
struct PathAssetEntry
|
|
{
|
|
explicit PathAssetEntry(const char* path)
|
|
: m_path(path) {}
|
|
explicit PathAssetEntry(AZStd::string&& path)
|
|
: m_path(AZStd::move(path)) {}
|
|
AZStd::string m_path;
|
|
};
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PrefabPublicNotificationBus::Handler
|
|
|
|
void OnPrefabInstancePropagationBegin() override;
|
|
void OnPrefabInstancePropagationEnd() override;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CreateUndosForDirtyEntities();
|
|
void ConsistencyCheckUndoCache();
|
|
AZ::Aabb m_selectionBounds;
|
|
EntityIdList m_selectedEntities;
|
|
EntityIdList m_highlightedEntities;
|
|
UndoSystem::UndoStack* m_undoStack;
|
|
UndoSystem::URSequencePoint* m_currentBatchUndo;
|
|
AZStd::unordered_set<AZ::EntityId> m_dirtyEntities;
|
|
PreemptiveUndoCache m_undoCache;
|
|
bool m_isDuringUndoRedo;
|
|
bool m_isInIsolationMode;
|
|
EntityIdSet m_isolatedEntityIdSet;
|
|
bool m_freezeSelectionUpdates = false;
|
|
|
|
EditorEntityAPI* m_editorEntityAPI = nullptr;
|
|
|
|
EditorEntityManager m_editorEntityManager;
|
|
|
|
UndoSystem::UndoCacheInterface* m_undoCacheInterface = nullptr;
|
|
};
|
|
} // namespace AzToolsFramework
|
|
|
|
#endif // AZTOOLSFRAMEWORK_TOOLSAPPLICATION_H
|