Merge pull request #226 from aws-lumberyard-dev/Prefab/Instantiate/Setup

KEYSTONE USE CASE | Instantiate Prefab
This commit is contained in:
AMZN-daimini
2021-04-23 09:23:31 -07:00
committed by GitHub
11 changed files with 131 additions and 14 deletions
@@ -31,11 +31,19 @@ namespace AzToolsFramework
//! /param entities The entities to put under the new prefab.
//! /param nestedPrefabInstances The nested prefab instances to put under the new prefab.
//! /param filePath The filepath corresponding to the prefab file to be created.
//! /param instanceToParentUnder The instance under which the newly created prefab instance is parented under.
//! /param instanceToParentUnder The instance the newly created prefab instance is parented under.
//! /return The optional reference to the prefab created.
virtual Prefab::InstanceOptionalReference CreatePrefab(
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Prefab::Instance>>&& nestedPrefabInstances,
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder = AZStd::nullopt) = 0;
//! Instantiate the prefab file provided.
//! /param filePath The filepath for the prefab file the instance should be created from.
//! /param instanceToParentUnder The instance the newly instantiated prefab instance is parented under.
//! /return The optional reference to the prefab instance.
virtual Prefab::InstanceOptionalReference InstantiatePrefab(
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder = AZStd::nullopt) = 0;
virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0;
virtual bool LoadFromStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) = 0;
@@ -19,6 +19,7 @@
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <AzToolsFramework/Prefab/PrefabLoader.h>
@@ -307,6 +308,26 @@ namespace AzToolsFramework
return AZStd::nullopt;
}
Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::InstantiatePrefab(
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder)
{
AZStd::unique_ptr<Prefab::Instance> createdPrefabInstance = m_prefabSystemComponent->InstantiatePrefab(filePath);
if (createdPrefabInstance)
{
if (!instanceToParentUnder)
{
instanceToParentUnder = *m_rootInstance;
}
Prefab::Instance& addedInstance = instanceToParentUnder->get().AddInstance(AZStd::move(createdPrefabInstance));
HandleEntitiesAdded({addedInstance.m_containerEntity.get()});
return addedInstance;
}
return AZStd::nullopt;
}
Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::GetRootPrefabInstance()
{
AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService.");
@@ -191,6 +191,9 @@ namespace AzToolsFramework
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Prefab::Instance>>&& nestedPrefabInstances,
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
Prefab::InstanceOptionalReference InstantiatePrefab(
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
Prefab::InstanceOptionalReference GetRootPrefabInstance() override;
//////////////////////////////////////////////////////////////////////////
@@ -161,6 +161,61 @@ namespace AzToolsFramework
return AZ::Success();
}
PrefabOperationResult PrefabPublicHandler::InstantiatePrefab(
AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position)
{
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not instantiate prefab - internal error "
"(PrefabEditorEntityOwnershipInterface unavailable)."));
}
InstanceOptionalReference instanceToParentUnder;
// Get parent entity and owning instance
if (parent.IsValid())
{
instanceToParentUnder = m_instanceEntityMapperInterface->FindOwningInstance(parent);
}
if (!instanceToParentUnder.has_value())
{
instanceToParentUnder = prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
parent = instanceToParentUnder->get().GetContainerEntityId();
}
{
// Initialize Undo Batch object
ScopedUndoBatch undoBatch("Instantiate Prefab");
PrefabDom instanceToParentUnderDomBeforeCreate;
m_instanceToTemplateInterface->GenerateDomForInstance(
instanceToParentUnderDomBeforeCreate, instanceToParentUnder->get());
// Instantiate the Prefab
auto instanceToCreate = prefabEditorEntityOwnershipInterface->InstantiatePrefab(filePath, instanceToParentUnder);
if (!instanceToCreate)
{
return AZ::Failure(AZStd::string("Could not instantiate the prefab provided - internal error "
"(A null instance is returned)."));
}
PrefabUndoHelpers::UpdatePrefabInstance(
instanceToParentUnder->get(), "Update prefab instance", instanceToParentUnderDomBeforeCreate, undoBatch.GetUndoBatch());
CreateLink({}, instanceToCreate->get(), instanceToParentUnder->get().GetTemplateId(),
undoBatch.GetUndoBatch(), parent);
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
// Apply position
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetWorldTranslation, position);
}
return AZ::Success();
}
PrefabOperationResult PrefabPublicHandler::FindCommonRootOwningInstance(
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance)
@@ -222,19 +277,16 @@ namespace AzToolsFramework
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
PrefabUndoHelpers::CreateLink(
LinkId linkId = PrefabUndoHelpers::CreateLink(
sourceInstance.GetTemplateId(), targetTemplateId, patch, sourceInstance.GetInstanceAlias(),
undoBatch);
sourceInstance.SetLinkId(linkId);
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
}
PrefabOperationResult PrefabPublicHandler::InstantiatePrefab(AZStd::string_view /*filePath*/, AZ::EntityId /*parent*/, AZ::Vector3 /*position*/)
{
return AZ::Failure(AZStd::string("Prefab - InstantiatePrefab is yet to be implemented."));
}
PrefabOperationResult PrefabPublicHandler::SavePrefab(AZ::IO::Path filePath)
{
auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str());
@@ -322,9 +374,9 @@ namespace AzToolsFramework
AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch)
{
// Create Undo node on entities if they belong to an instance
InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
if (instanceOptionalReference.has_value())
if (owningInstance.has_value())
{
PrefabDom afterState;
AZ::Entity* entity = GetEntityById(entityId);
@@ -45,7 +45,7 @@ namespace AzToolsFramework
// PrefabPublicInterface...
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
@@ -58,7 +58,7 @@ namespace AzToolsFramework
* @param position The position in world space the prefab should be instantiated in.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
virtual PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) = 0;
virtual PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) = 0;
/**
* Saves changes to prefab to disk.
@@ -261,6 +261,29 @@ namespace AzToolsFramework
}
}
AZStd::unique_ptr<Instance> PrefabSystemComponent::InstantiatePrefab(AZ::IO::PathView filePath)
{
// Retrieve the template id for the source prefab filepath
Prefab::TemplateId templateId = GetTemplateIdFromFilePath(filePath);
if (templateId == Prefab::InvalidTemplateId)
{
// Load the template from the file
templateId = m_prefabLoader.LoadTemplateFromFile(filePath);
}
if (templateId == Prefab::InvalidTemplateId)
{
AZ_Error("Prefab", false,
"Could not load template from path %s during InstantiatePrefab. Unable to proceed",
filePath);
return nullptr;
}
return InstantiatePrefab(templateId);
}
AZStd::unique_ptr<Instance> PrefabSystemComponent::InstantiatePrefab(const TemplateId& templateId)
{
TemplateReference instantiatingTemplate = FindTemplate(templateId);
@@ -115,9 +115,16 @@ namespace AzToolsFramework
*/
void RemoveAllTemplates() override;
/**
* Generates a new Prefab Instance based on the Template whose source is stored in filepath.
* @param filePath the path to the prefab source file containing the template being instantiated.
* @return A unique_ptr to the newly instantiated instance. Null if operation failed.
*/
AZStd::unique_ptr<Instance> InstantiatePrefab(AZ::IO::PathView filePath) override;
/**
* Generates a new Prefab Instance based on the Template referenced by templateId
* @param templateId the id of the template being instantiated
* @param templateId the id of the template being instantiated.
* @return A unique_ptr to the newly instantiated instance. Null if operation failed.
*/
AZStd::unique_ptr<Instance> InstantiatePrefab(const TemplateId& templateId) override;
@@ -58,6 +58,7 @@ namespace AzToolsFramework
virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0;
virtual void PropagateTemplateChanges(TemplateId templateId) = 0;
virtual AZStd::unique_ptr<Instance> InstantiatePrefab(AZ::IO::PathView filePath) = 0;
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,
@@ -33,7 +33,7 @@ namespace AzToolsFramework
state->Redo();
}
void CreateLink(
LinkId CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch)
{
@@ -41,6 +41,8 @@ namespace AzToolsFramework
linkAddUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, patch, InvalidLinkId);
linkAddUndo->SetParent(undoBatch);
linkAddUndo->Redo();
return linkAddUndo->GetLinkId();
}
void RemoveLink(
@@ -21,7 +21,7 @@ namespace AzToolsFramework
void UpdatePrefabInstance(
const Instance& instance, AZStd::string_view undoMessage, const PrefabDom& instanceDomBeforeUpdate,
UndoSystem::URSequencePoint* undoBatch);
void CreateLink(
LinkId CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch);
void RemoveLink(