Propagation Optimization (#5355)
* Merge changes Signed-off-by: Mikhail Naumov <mnaumov@amazon.com> * removing leftover immediate flag Signed-off-by: Mikhail Naumov <mnaumov@amazon.com>
This commit is contained in:
+1
-1
@@ -49,7 +49,7 @@ namespace AzToolsFramework
|
||||
//! @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshes as part of propagation.
|
||||
//! Defaults to nullopt, which means that all instances will be refreshed.
|
||||
//! @return True if the template was patched correctly, false if the operation failed.
|
||||
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
|
||||
virtual void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) = 0;
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude)
|
||||
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId) override;
|
||||
|
||||
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
|
||||
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) override;
|
||||
|
||||
void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override;
|
||||
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ namespace AzToolsFramework
|
||||
AZ::Interface<InstanceUpdateExecutorInterface>::Unregister(this);
|
||||
}
|
||||
|
||||
void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude)
|
||||
void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
auto findInstancesResult =
|
||||
m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId);
|
||||
@@ -66,7 +66,7 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
Instance* instanceToExcludePtr = nullptr;
|
||||
const Instance* instanceToExcludePtr = nullptr;
|
||||
if (instanceToExclude.has_value())
|
||||
{
|
||||
instanceToExcludePtr = &(instanceToExclude->get());
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ namespace AzToolsFramework
|
||||
|
||||
explicit InstanceUpdateExecutor(int instanceCountToUpdateInBatch = 0);
|
||||
|
||||
void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
|
||||
void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) override;
|
||||
bool UpdateTemplateInstancesInQueue() override;
|
||||
virtual void RemoveTemplateInstanceFromQueue(const Instance* instance) override;
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ namespace AzToolsFramework
|
||||
virtual ~InstanceUpdateExecutorInterface() = default;
|
||||
|
||||
// Add all Instances of Template with given Id into a queue for updating them later.
|
||||
virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
|
||||
// Update Instances in the waiting queue.
|
||||
virtual bool UpdateTemplateInstancesInQueue() = 0;
|
||||
|
||||
@@ -777,7 +777,7 @@ namespace AzToolsFramework
|
||||
linkUpdate->SetParent(undoBatch);
|
||||
linkUpdate->Capture(patch, linkId);
|
||||
|
||||
linkUpdate->Redo(parentInstance);
|
||||
linkUpdate->Redo(parentInstance->get());
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::Internal_HandleEntityChange(
|
||||
@@ -788,8 +788,7 @@ namespace AzToolsFramework
|
||||
PrefabUndoEntityUpdate* state = aznew PrefabUndoEntityUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
|
||||
state->SetParent(undoBatch);
|
||||
state->Capture(beforeState, afterState, entityId);
|
||||
|
||||
state->Redo(instance);
|
||||
state->Redo(instance->get());
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::Internal_HandleInstanceChange(
|
||||
@@ -1167,6 +1166,60 @@ namespace AzToolsFramework
|
||||
|
||||
ScopedUndoBatch undoBatch("Delete Selected");
|
||||
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "Internal::DeleteEntities:UndoCaptureAndPurgeEntities");
|
||||
|
||||
Prefab::PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonOwningInstance->get());
|
||||
|
||||
if (deleteDescendants)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
AZStd::vector<Instance*> instances;
|
||||
|
||||
PrefabOperationResult retrieveEntitiesAndInstancesOutcome =
|
||||
RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
|
||||
|
||||
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
|
||||
{
|
||||
return AZStd::move(retrieveEntitiesAndInstancesOutcome);
|
||||
}
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
commonOwningInstance->get().DetachEntity(entity->GetId()).release();
|
||||
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, entity->GetId());
|
||||
}
|
||||
|
||||
for (auto& nestedInstance : instances)
|
||||
{
|
||||
AZStd::unique_ptr<Instance> outInstance =
|
||||
commonOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias());
|
||||
RemoveLink(outInstance, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
|
||||
outInstance.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AZ::EntityId entityId : entityIdsNoFocusContainer)
|
||||
{
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
// If this is the container entity, it actually represents the instance so get its owner
|
||||
if (owningInstance->get().GetContainerEntityId() == entityId)
|
||||
{
|
||||
auto instancePtr = commonOwningInstance->get().DetachNestedInstance(owningInstance->get().GetInstanceAlias());
|
||||
RemoveLink(instancePtr, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
|
||||
}
|
||||
else
|
||||
{
|
||||
commonOwningInstance->get().DetachEntity(entityId);
|
||||
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, entityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prefab::PrefabDom instanceDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomAfter, commonOwningInstance->get());
|
||||
|
||||
// In order to undo DeleteSelected, we have to create a selection command which selects the current selection
|
||||
// and then add the deletion as children.
|
||||
// Commands always execute themselves first and then their children (when going forwards)
|
||||
@@ -1174,81 +1227,22 @@ namespace AzToolsFramework
|
||||
EntityIdList selectedEntities;
|
||||
ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &ToolsApplicationRequests::GetSelectedEntities);
|
||||
SelectionCommand* selCommand = aznew SelectionCommand(selectedEntities, "Delete Entities");
|
||||
selCommand->SetParent(undoBatch.GetUndoBatch());
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "Internal::DeleteEntities:RunRedo");
|
||||
selCommand->RunRedo();
|
||||
|
||||
// We insert a "deselect all" command before we delete the entities. This ensures the delete operations aren't changing
|
||||
// selection state, which triggers expensive UI updates. By deselecting up front, we are able to do those expensive
|
||||
// UI updates once at the start instead of once for each entity.
|
||||
{
|
||||
EntityIdList deselection;
|
||||
SelectionCommand* deselectAllCommand = aznew SelectionCommand(deselection, "Deselect Entities");
|
||||
deselectAllCommand->SetParent(selCommand);
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "Internal::DeleteEntities:UndoCaptureAndPurgeEntities");
|
||||
|
||||
Prefab::PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonOwningInstance->get());
|
||||
|
||||
if (deleteDescendants)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
AZStd::vector<Instance*> instances;
|
||||
|
||||
PrefabOperationResult retrieveEntitiesAndInstancesOutcome =
|
||||
RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
|
||||
|
||||
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
|
||||
{
|
||||
return AZStd::move(retrieveEntitiesAndInstancesOutcome);
|
||||
}
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
commonOwningInstance->get().DetachEntity(entity->GetId()).release();
|
||||
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, entity->GetId());
|
||||
}
|
||||
|
||||
for (auto& nestedInstance : instances)
|
||||
{
|
||||
AZStd::unique_ptr<Instance> outInstance = commonOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias());
|
||||
RemoveLink(outInstance, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
|
||||
outInstance.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AZ::EntityId entityId : entityIdsNoFocusContainer)
|
||||
{
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
// If this is the container entity, it actually represents the instance so get its owner
|
||||
if (owningInstance->get().GetContainerEntityId() == entityId)
|
||||
{
|
||||
auto instancePtr = commonOwningInstance->get().DetachNestedInstance(owningInstance->get().GetInstanceAlias());
|
||||
RemoveLink(instancePtr, commonOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch());
|
||||
}
|
||||
else
|
||||
{
|
||||
commonOwningInstance->get().DetachEntity(entityId);
|
||||
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, entityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prefab::PrefabDom instanceDomAfter;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomAfter, commonOwningInstance->get());
|
||||
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance deletion");
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
|
||||
command->SetParent(selCommand);
|
||||
}
|
||||
|
||||
selCommand->SetParent(undoBatch.GetUndoBatch());
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "Internal::DeleteEntities:RunRedo");
|
||||
selCommand->RunRedo();
|
||||
}
|
||||
EntityIdList deselection;
|
||||
SelectionCommand* deselectAllCommand = aznew SelectionCommand(deselection, "Deselect Entities");
|
||||
deselectAllCommand->SetParent(undoBatch.GetUndoBatch());
|
||||
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance deletion");
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
|
||||
command->SetParent(undoBatch.GetUndoBatch());
|
||||
command->Redo(commonOwningInstance->get());
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
@@ -1338,7 +1332,7 @@ namespace AzToolsFramework
|
||||
command->SetParent(undoBatch.GetUndoBatch());
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "Internal::DetachPrefab:RunRedo");
|
||||
command->RunRedo();
|
||||
command->Redo(parentInstance);
|
||||
}
|
||||
|
||||
instancePtr->DetachNestedInstances(
|
||||
|
||||
@@ -159,11 +159,9 @@ namespace AzToolsFramework
|
||||
newInstance->SetTemplateId(newTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude)
|
||||
|
||||
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
UpdatePrefabInstances(templateId, instanceToExclude);
|
||||
|
||||
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
|
||||
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
|
||||
{
|
||||
@@ -174,6 +172,7 @@ namespace AzToolsFramework
|
||||
templateIdToLinkIdsIterator->second.end()));
|
||||
UpdateLinkedInstances(linkIdsToUpdateQueue);
|
||||
}
|
||||
UpdatePrefabInstances(templateId, instanceToExclude);
|
||||
}
|
||||
|
||||
void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom)
|
||||
@@ -191,7 +190,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabSystemComponent::UpdatePrefabInstances(TemplateId templateId, InstanceOptionalReference instanceToExclude)
|
||||
void PrefabSystemComponent::UpdatePrefabInstances(TemplateId templateId, InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
m_instanceUpdateExecutor.AddTemplateInstancesToQueue(templateId, instanceToExclude);
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace AzToolsFramework
|
||||
*/
|
||||
void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override;
|
||||
|
||||
void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
|
||||
void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) override;
|
||||
|
||||
/**
|
||||
* Updates all Instances owned by a Template.
|
||||
@@ -240,7 +240,7 @@ namespace AzToolsFramework
|
||||
* @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshed
|
||||
* as part of propagation.Defaults to nullopt, which means that all instances will be refreshed.
|
||||
*/
|
||||
void UpdatePrefabInstances(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt);
|
||||
void UpdatePrefabInstances(TemplateId templateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt);
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(PrefabSystemComponent);
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ namespace AzToolsFramework
|
||||
|
||||
virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0;
|
||||
virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0;
|
||||
virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
|
||||
virtual AZStd::unique_ptr<Instance> InstantiatePrefab(
|
||||
AZ::IO::PathView filePath, InstanceOptionalReference parent = AZStd::nullopt) = 0;
|
||||
|
||||
@@ -51,6 +51,10 @@ namespace AzToolsFramework
|
||||
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId);
|
||||
}
|
||||
|
||||
void PrefabUndoInstance::Redo(InstanceOptionalConstReference instance)
|
||||
{
|
||||
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, instance);
|
||||
}
|
||||
|
||||
//PrefabEntityUpdateUndo
|
||||
PrefabUndoEntityUpdate::PrefabUndoEntityUpdate(const AZStd::string& undoOperationName)
|
||||
@@ -110,10 +114,10 @@ namespace AzToolsFramework
|
||||
m_templateId);
|
||||
}
|
||||
|
||||
void PrefabUndoEntityUpdate::Redo(InstanceOptionalReference instanceToExclude)
|
||||
void PrefabUndoEntityUpdate::Redo(InstanceOptionalConstReference instance)
|
||||
{
|
||||
[[maybe_unused]] bool isPatchApplicationSuccessful =
|
||||
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, instanceToExclude);
|
||||
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, instance);
|
||||
|
||||
AZ_Error(
|
||||
"Prefab", isPatchApplicationSuccessful,
|
||||
@@ -310,12 +314,12 @@ namespace AzToolsFramework
|
||||
UpdateLink(m_linkDomNext);
|
||||
}
|
||||
|
||||
void PrefabUndoLinkUpdate::Redo(InstanceOptionalReference instanceToExclude)
|
||||
void PrefabUndoLinkUpdate::Redo(InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
UpdateLink(m_linkDomNext, instanceToExclude);
|
||||
}
|
||||
|
||||
void PrefabUndoLinkUpdate::UpdateLink(PrefabDom& linkDom, InstanceOptionalReference instanceToExclude)
|
||||
void PrefabUndoLinkUpdate::UpdateLink(PrefabDom& linkDom, InstanceOptionalConstReference instanceToExclude)
|
||||
{
|
||||
LinkReference link = m_prefabSystemComponentInterface->FindLink(m_linkId);
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace AzToolsFramework
|
||||
|
||||
void Undo() override;
|
||||
void Redo() override;
|
||||
void Redo(InstanceOptionalConstReference instance);
|
||||
};
|
||||
|
||||
//! handles entity updates, such as when the values on an entity change
|
||||
@@ -72,7 +73,7 @@ namespace AzToolsFramework
|
||||
void Undo() override;
|
||||
void Redo() override;
|
||||
//! Overload to allow to apply the change, but prevent instanceToExclude from being refreshed.
|
||||
void Redo(InstanceOptionalReference instanceToExclude);
|
||||
void Redo(InstanceOptionalConstReference instanceToExclude);
|
||||
|
||||
private:
|
||||
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
|
||||
@@ -137,10 +138,10 @@ namespace AzToolsFramework
|
||||
void Undo() override;
|
||||
void Redo() override;
|
||||
//! Overload to allow to apply the change, but prevent instanceToExclude from being refreshed.
|
||||
void Redo(InstanceOptionalReference instanceToExclude);
|
||||
void Redo(InstanceOptionalConstReference instanceToExclude);
|
||||
|
||||
private:
|
||||
void UpdateLink(PrefabDom& linkDom, InstanceOptionalReference instanceToExclude = AZStd::nullopt);
|
||||
void UpdateLink(PrefabDom& linkDom, InstanceOptionalConstReference instanceToExclude = AZStd::nullopt);
|
||||
|
||||
LinkId m_linkId;
|
||||
PrefabDom m_linkDomNext; //data for delete/update
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace AzToolsFramework
|
||||
PrefabUndoInstance* state = aznew Prefab::PrefabUndoInstance(undoMessage);
|
||||
state->Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, instance.GetTemplateId());
|
||||
state->SetParent(undoBatch);
|
||||
state->Redo();
|
||||
state->Redo(instance);
|
||||
}
|
||||
|
||||
LinkId CreateLink(
|
||||
|
||||
@@ -82,8 +82,8 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
auto transform = aznew AzToolsFramework::Components::TransformComponent;
|
||||
transform->SetParent(parentId);
|
||||
entity->AddComponent(transform);
|
||||
transform->SetParent(parentId);
|
||||
|
||||
entity->Activate();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user