Merge pull request #260 from aws-lumberyard-dev/Prefab/CreatePrefab
Added undo and redo support for nested prefab creation
This commit is contained in:
+1
-1
@@ -279,7 +279,7 @@ namespace AzToolsFramework
|
||||
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder)
|
||||
{
|
||||
AZStd::unique_ptr<Prefab::Instance> createdPrefabInstance =
|
||||
m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath);
|
||||
m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath, nullptr, false);
|
||||
|
||||
if (createdPrefabInstance)
|
||||
{
|
||||
|
||||
@@ -321,7 +321,6 @@ namespace AzToolsFramework
|
||||
removedNestedInstance = AZStd::move(nestedInstanceIterator->second);
|
||||
|
||||
removedNestedInstance->m_parent = nullptr;
|
||||
removedNestedInstance->m_alias = InstanceAlias();
|
||||
|
||||
m_nestedInstances.erase(instanceAlias);
|
||||
}
|
||||
@@ -396,6 +395,14 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback)
|
||||
{
|
||||
for (auto& [instanceAlias, instance] : m_nestedInstances)
|
||||
{
|
||||
callback(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
for (auto& [entityAlias, entity] : m_entities)
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace AzToolsFramework
|
||||
void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback);
|
||||
void GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
void GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
void GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback);
|
||||
|
||||
/**
|
||||
* Gets the alias for a given EnitityId in the Instance DOM.
|
||||
|
||||
@@ -101,6 +101,10 @@ namespace AzToolsFramework
|
||||
nestedInstance->GetInstanceAlias(), nestedInstance->GetLinkId(), undoBatch.GetUndoBatch());
|
||||
}
|
||||
|
||||
PrefabUndoHelpers::UpdatePrefabInstance(
|
||||
commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate,
|
||||
undoBatch.GetUndoBatch());
|
||||
|
||||
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
|
||||
if (!prefabEditorEntityOwnershipInterface)
|
||||
{
|
||||
@@ -118,13 +122,21 @@ namespace AzToolsFramework
|
||||
"(A null instance is returned)."));
|
||||
}
|
||||
|
||||
PrefabUndoHelpers::UpdatePrefabInstance(
|
||||
commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch());
|
||||
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
|
||||
|
||||
instanceToCreate->get().GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
|
||||
AZ_Assert(nestedInstance, "Invalid nested instance found in the new prefab created.");
|
||||
EntityOptionalReference nestedInstanceContainerEntity = nestedInstance->GetContainerEntity();
|
||||
AZ_Assert(
|
||||
nestedInstanceContainerEntity, "Invalid container entity found for the nested instance used in prefab creation.");
|
||||
CreateLink(
|
||||
{&nestedInstanceContainerEntity->get()}, *nestedInstance, instanceToCreate->get().GetTemplateId(),
|
||||
undoBatch.GetUndoBatch(), containerEntityId);
|
||||
});
|
||||
|
||||
CreateLink(
|
||||
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), 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
|
||||
@@ -225,19 +237,7 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::SavePrefab(AZ::IO::Path filePath)
|
||||
{
|
||||
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
||||
if (!prefabSystemComponentInterface)
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Prefab - PrefabPublicHandler - "
|
||||
"Prefab System Component Interface could not be found. "
|
||||
"Check that it is being correctly initialized.");
|
||||
return AZ::Failure(
|
||||
AZStd::string("SavePrefab - Internal error (Prefab System Component Interface could not be found)."));
|
||||
}
|
||||
|
||||
auto templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str());
|
||||
auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str());
|
||||
|
||||
if (templateId == InvalidTemplateId)
|
||||
{
|
||||
@@ -438,26 +438,14 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabRequestResult PrefabPublicHandler::HasUnsavedChanges(AZ::IO::Path prefabFilePath) const
|
||||
{
|
||||
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
||||
if (!prefabSystemComponentInterface)
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"Prefab - PrefabPublicHandler - "
|
||||
"Prefab System Component Interface could not be found. "
|
||||
"Check that it is being correctly initialized.");
|
||||
return AZ::Failure(
|
||||
AZStd::string("HasUnsavedChanges - Internal error (Prefab System Component Interface could not be found)."));
|
||||
}
|
||||
|
||||
auto templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(prefabFilePath.c_str());
|
||||
auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(prefabFilePath.c_str());
|
||||
|
||||
if (templateId == InvalidTemplateId)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("HasUnsavedChanges - Path error. Path could be invalid, or the prefab may not be loaded in this level."));
|
||||
}
|
||||
|
||||
return AZ::Success(prefabSystemComponentInterface->IsTemplateDirty(templateId));
|
||||
return AZ::Success(m_prefabSystemComponentInterface->IsTemplateDirty(templateId));
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::DeleteEntitiesInInstance(const EntityIdList& entityIds)
|
||||
|
||||
@@ -91,8 +91,9 @@ namespace AzToolsFramework
|
||||
m_instanceUpdateExecutor.UpdateTemplateInstancesInQueue();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Instance> PrefabSystemComponent::CreatePrefab(const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume,
|
||||
AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity)
|
||||
AZStd::unique_ptr<Instance> PrefabSystemComponent::CreatePrefab(
|
||||
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume,
|
||||
AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity, bool shouldCreateLinks)
|
||||
{
|
||||
AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath);
|
||||
if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId)
|
||||
@@ -123,7 +124,7 @@ namespace AzToolsFramework
|
||||
newInstance->SetTemplateSourcePath(relativeFilePath);
|
||||
newInstance->SetContainerEntityName(relativeFilePath.Stem().Native());
|
||||
|
||||
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance);
|
||||
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance, shouldCreateLinks);
|
||||
if (newTemplateId == InvalidTemplateId)
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
@@ -289,7 +290,7 @@ namespace AzToolsFramework
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
TemplateId PrefabSystemComponent::CreateTemplateFromInstance(Instance& instance)
|
||||
TemplateId PrefabSystemComponent::CreateTemplateFromInstance(Instance& instance, bool shouldCreateLinks)
|
||||
{
|
||||
// We will register the template to match the path the instance has
|
||||
const AZ::IO::Path& templateSourcePath = instance.GetTemplateSourcePath();
|
||||
@@ -323,14 +324,15 @@ namespace AzToolsFramework
|
||||
return InvalidTemplateId;
|
||||
}
|
||||
|
||||
if (!GenerateLinksForNewTemplate(newTemplateId, instance))
|
||||
if (shouldCreateLinks)
|
||||
{
|
||||
// Clear new template and any links associated with it
|
||||
RemoveTemplate(newTemplateId);
|
||||
|
||||
return InvalidTemplateId;
|
||||
if (!GenerateLinksForNewTemplate(newTemplateId, instance))
|
||||
{
|
||||
// Clear new template and any links associated with it
|
||||
RemoveTemplate(newTemplateId);
|
||||
return InvalidTemplateId;
|
||||
}
|
||||
}
|
||||
|
||||
return newTemplateId;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,17 +187,22 @@ namespace AzToolsFramework
|
||||
* @param entities A vector of entities that will be used in the new instance. May be empty
|
||||
* @param instances A vector of Prefab Instances that will be nested in the new instance, will be consumed and moved.
|
||||
* May be empty
|
||||
* @param filePath the path to associate the template of the new instance to
|
||||
* @param filePath the path to associate the template of the new instance to.
|
||||
* @param containerEntity The container entity for the prefab to be created. It will be created if a nullptr is provided.
|
||||
* @param shouldCreateLinks The flag indicating if links should be created between the templates of the instance
|
||||
* and its nested instances.
|
||||
* @return A pointer to the newly created instance. nullptr on failure
|
||||
*/
|
||||
AZStd::unique_ptr<Instance> CreatePrefab(const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume,
|
||||
AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr) override;
|
||||
AZStd::unique_ptr<Instance> CreatePrefab(
|
||||
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume,
|
||||
AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr,
|
||||
bool ShouldCreateLinks = true) override;
|
||||
|
||||
PrefabDom& FindTemplateDom(TemplateId templateId) override;
|
||||
|
||||
/**
|
||||
* Updates a template with the given updated DOM.
|
||||
*
|
||||
*
|
||||
* @param templateId The id of the template to update.
|
||||
* @param updatedDom The DOM to update the template with.
|
||||
*/
|
||||
@@ -260,9 +265,11 @@ namespace AzToolsFramework
|
||||
/**
|
||||
* Takes a prefab instance and generates a new Prefab Template
|
||||
* along with any new Prefab Links representing any of the nested instances present
|
||||
* @param instance The instance used to generate the new Template
|
||||
* @param instance The instance used to generate the new Template.
|
||||
* @param shouldCreateLinks The flag indicating if links should be created between the templates of the instance
|
||||
* and its nested instances.
|
||||
*/
|
||||
TemplateId CreateTemplateFromInstance(Instance& instance);
|
||||
TemplateId CreateTemplateFromInstance(Instance& instance, bool shouldCreateLinks);
|
||||
|
||||
/**
|
||||
* Connect two templates with given link, and a nested instance value iterator
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ namespace AzToolsFramework
|
||||
virtual AZStd::unique_ptr<Instance> InstantiatePrefab(const TemplateId& templateId) = 0;
|
||||
virtual AZStd::unique_ptr<Instance> CreatePrefab(const AZStd::vector<AZ::Entity*>& entities,
|
||||
AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, AZ::IO::PathView filePath,
|
||||
AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr) = 0;
|
||||
AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr, bool ShouldCreateLinks = true) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user