Added couple of helper functions

This commit is contained in:
srikappa
2021-04-19 13:43:54 -07:00
parent f3ff5ec886
commit 65b2d9de1b
4 changed files with 87 additions and 64 deletions
@@ -63,53 +63,28 @@ namespace AzToolsFramework
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
{
// Retrieve entityList from entityIds
EntityList inputEntityList;
EntityIdListToEntityList(entityIds, inputEntityList);
// Find common root and top level entities
bool entitiesHaveCommonRoot = false;
EntityList inputEntityList, topLevelEntities;
AZ::EntityId commonRootEntityId;
EntityList topLevelEntities;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList,
commonRootEntityId, &topLevelEntities);
// Bail if entities don't share a common root
if (!entitiesHaveCommonRoot)
InstanceOptionalReference commonRootEntityOwningInstance;
PrefabOperationResult findCommonRootOutcome = FindCommonRootOwningInstance(
entityIds, inputEntityList, topLevelEntities, commonRootEntityId, commonRootEntityOwningInstance);
if (!findCommonRootOutcome.IsSuccess())
{
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
return findCommonRootOutcome;
}
AZ::Entity* commonRootEntity = nullptr;
if (commonRootEntityId.IsValid())
{
commonRootEntity = GetEntityById(commonRootEntityId);
}
// Retrieve the owning instance of the common root entity, which will be our new instance's parent instance.
InstanceOptionalReference commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId);
AZ_Assert(
commonRootEntityOwningInstance.has_value(),
"Failed to create prefab : "
"Couldn't get a valid owning instance for the common root entity of the enities provided");
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
InstanceOptionalReference instance;
InstanceOptionalReference instanceToCreate;
{
// Initialize Undo Batch object
ScopedUndoBatch undoBatch("Create Prefab");
TemplateId commonRootOwningTemplateId = commonRootEntityOwningInstance->get().GetTemplateId();
PrefabDom commonRootInstanceDomBeforeCreate;
m_instanceToTemplateInterface->GenerateDomForInstance(
commonRootInstanceDomBeforeCreate, commonRootEntityOwningInstance->get());
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
{
@@ -117,6 +92,14 @@ namespace AzToolsFramework
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
}
// When you move instances from another template, you have to remove the links and propagate changes to target template.
for (auto& nestedInstance : instances)
{
PrefabUndoHelpers::RemoveLink(
nestedInstance->GetTemplateId(), commonRootEntityOwningInstance->get().GetTemplateId(),
nestedInstance->GetInstanceAlias(), nestedInstance->GetLinkId(), undoBatch.GetUndoBatch());
}
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
@@ -124,35 +107,23 @@ namespace AzToolsFramework
"(PrefabEditorEntityOwnershipInterface unavailable)."));
}
// When you move instances from another template, you have to remove the links and propagate changes to target template.
auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Undo Link Remove Node");
for (auto& nestedInstance : instances)
{
PrefabDom emptyLinkDom;
linkRemoveUndo->Capture(
commonRootOwningTemplateId, nestedInstance->GetTemplateId(), nestedInstance->GetInstanceAlias(), emptyLinkDom,
nestedInstance->GetLinkId());
linkRemoveUndo->SetParent(undoBatch.GetUndoBatch());
}
// Create the Prefab
instance = prefabEditorEntityOwnershipInterface->CreatePrefab(
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
if (!instance)
if (!instanceToCreate)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(A null instance is returned)."));
}
PrefabUndoHelpers::UpdatePrefabInstance(
commonRootEntityOwningInstance->get(), "Undo detaching entity", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch());
commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch());
linkRemoveUndo->Redo();
AZ::EntityId containerEntityId = instance->get().GetContainerEntityId();
AddLink(topLevelEntities, instance->get(), commonRootEntityOwningInstance->get(), undoBatch.GetUndoBatch(), commonRootEntityId);
CreateLink(
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get(), undoBatch.GetUndoBatch(),
commonRootEntityId);
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
// Change top level entities to be parented to the container entity
// Mark them as dirty so this change is correctly applied to the template
@@ -172,12 +143,45 @@ namespace AzToolsFramework
}
// Save Template to file
m_prefabLoaderInterface->SaveTemplate(instance->get().GetTemplateId());
m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
return AZ::Success();
}
void PrefabPublicHandler::AddLink(
PrefabOperationResult PrefabPublicHandler::FindCommonRootOwningInstance(
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance)
{
// Retrieve entityList from entityIds
EntityIdListToEntityList(entityIds, inputEntityList);
// Find common root and top level entities
bool entitiesHaveCommonRoot = false;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList,
commonRootEntityId, &topLevelEntities);
// Bail if entities don't share a common root
if (!entitiesHaveCommonRoot)
{
return AZ::Failure(AZStd::string("Failed to create a prefab: Provided entities do not share a common root."));
}
// Retrieve the owning instance of the common root entity, which will be our new instance's parent instance.
commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId);
if (!commonRootEntityOwningInstance)
{
AZ_Assert(
false,
"Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided");
return AZ::Failure(AZStd::string(
"Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided"));
}
return AZ::Success();
}
void PrefabPublicHandler::CreateLink(
const EntityList& topLevelEntities, Instance& instanceToAdd, Instance& parentInstance, UndoSystem::URSequencePoint* undoBatch,
AZ::EntityId commonRootEntityId)
{
@@ -205,8 +209,8 @@ namespace AzToolsFramework
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
PrefabUndoHelpers::AddLink(
"Add Link", instanceToAdd.GetTemplateId(), parentInstance.GetTemplateId(), patch, instanceToAdd.GetInstanceAlias(),
PrefabUndoHelpers::CreateLink(
instanceToAdd.GetTemplateId(), parentInstance.GetTemplateId(), patch, instanceToAdd.GetInstanceAlias(),
undoBatch);
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
@@ -69,10 +69,14 @@ namespace AzToolsFramework
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
void AddLink(
void CreateLink(
const EntityList& topLevelEntities, Instance& instanceToAdd, Instance& parentInstance,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId);
PrefabOperationResult FindCommonRootOwningInstance(
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance);
static Instance* GetParentInstance(Instance* instance);
static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant);
static void GenerateContainerEntityTransform(const EntityList& topLevelEntities, AZ::Vector3& translation, AZ::Quaternion& rotation);
@@ -33,15 +33,27 @@ namespace AzToolsFramework
state->Redo();
}
void AddLink(
AZStd::string_view undoMessage, TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
void CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch)
{
auto linkAddUndo = aznew PrefabUndoInstanceLink(undoMessage);
auto linkAddUndo = aznew PrefabUndoInstanceLink("Create Link");
linkAddUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, patch, InvalidLinkId);
linkAddUndo->SetParent(undoBatch);
linkAddUndo->Redo();
}
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias,
LinkId linkId, UndoSystem::URSequencePoint* undoBatch)
{
auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Remove Link");
PrefabDom emptyLinkDom;
linkRemoveUndo->Capture(
targetTemplateId, sourceTemplateId, instanceAlias, emptyLinkDom, linkId);
linkRemoveUndo->SetParent(undoBatch);
linkRemoveUndo->Redo();
}
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -21,9 +21,12 @@ namespace AzToolsFramework
void UpdatePrefabInstance(
const Instance& instance, AZStd::string_view undoMessage, const PrefabDom& instanceDomBeforeUpdate,
UndoSystem::URSequencePoint* undoBatch);
void AddLink(
AZStd::string_view undoMessage, TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
void CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch);
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias,
LinkId linkId, UndoSystem::URSequencePoint* undoBatch);
}
} // namespace Prefab
} // namespace AzToolsFramework