Initial commit of CreatePrefab work

This commit is contained in:
srikappa
2021-04-14 17:26:14 -07:00
parent 70c2d5ee40
commit a371edd07f
11 changed files with 281 additions and 90 deletions
@@ -279,18 +279,29 @@ namespace AzToolsFramework
AZStd::unique_ptr<Prefab::Instance> createdPrefabInstance =
m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath);
if (!instanceToParentUnder)
{
instanceToParentUnder = *m_rootInstance;
}
if (createdPrefabInstance)
{
if (!instanceToParentUnder)
{
instanceToParentUnder = *m_rootInstance;
}
Prefab::Instance& addedInstance = instanceToParentUnder->get().AddInstance(AZStd::move(createdPrefabInstance));
HandleEntitiesAdded({addedInstance.m_containerEntity.get()});
AZ::Entity* containerEntity = addedInstance.m_containerEntity.get();
containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({containerEntity});
HandleEntitiesAdded(entities);
// Update the template of the instance since we modified the entities of the instance by calling HandleEntitiesAdded.
Prefab::PrefabDom serializedInstance;
if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance))
{
m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance);
}
return addedInstance;
}
HandleEntitiesAdded(entities);
return AZStd::nullopt;
}
@@ -186,7 +186,7 @@ namespace AzToolsFramework
PlayInEditorData m_playInEditorData;
//////////////////////////////////////////////////////////////////////////
// PrefabSystemComponentInterface interface implementation
// PrefabEditorEntityOwnershipInterface implementation
Prefab::InstanceOptionalReference CreatePrefab(
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Prefab::Instance>>&& nestedPrefabInstances,
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
@@ -283,7 +283,7 @@ namespace AzToolsFramework
{
if (!m_instanceEntityMapper->RegisterEntityToInstance(entityId, *this))
{
AZ_Assert(false,
AZ_Error("Prefab", false,
"Prefab - Failed to register entity with id %s with a Prefab Instance derived from source asset %s "
"This entity is likely already registered. Check for a double add.",
entityId.ToString().c_str(),
@@ -15,6 +15,7 @@
#include <AzCore/Component/TickBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/TemplateInstanceMapperInterface.h>
@@ -117,6 +118,8 @@ namespace AzToolsFramework
currentTemplateId);
isUpdateSuccessful = false;
m_instancesUpdateQueue.pop();
continue;
}
}
@@ -139,9 +142,16 @@ namespace AzToolsFramework
}
m_instancesUpdateQueue.pop();
}
for (auto entityIdIterator = selectedEntityIds.begin(); entityIdIterator != selectedEntityIds.end(); entityIdIterator++)
{
AZ::Entity* entity = GetEntityById(*entityIdIterator);
if (entity == nullptr)
{
selectedEntityIds.erase(entityIdIterator--);
}
}
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
// Enable the Outliner
@@ -163,5 +173,50 @@ namespace AzToolsFramework
return isUpdateSuccessful;
}
Instance* InstanceUpdateExecutor::UniqueInstanceQueue::front()
{
return m_instancesQueue.front();
}
void InstanceUpdateExecutor::UniqueInstanceQueue::pop()
{
m_instancesSet.erase(m_instancesQueue.front());
m_instancesQueue.pop();
}
void InstanceUpdateExecutor::UniqueInstanceQueue::emplace(Instance* instance)
{
Instance* ancestorInstance = instance;
while (ancestorInstance != nullptr)
{
if (m_instancesSet.contains(ancestorInstance))
{
return;
}
auto parent = ancestorInstance->GetParentInstance();
if (parent.has_value())
{
ancestorInstance = &(parent->get());
}
else
{
ancestorInstance = nullptr;
}
}
// TODO - remove child instances too?
// Optimization.
m_instancesQueue.emplace(instance);
m_instancesSet.emplace(instance);
}
size_t InstanceUpdateExecutor::UniqueInstanceQueue::size()
{
return m_instancesQueue.size();
}
}
}
@@ -15,6 +15,7 @@
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/std/containers/queue.h>
#include <AzCore/std/containers/set.h>
#include <AzToolsFramework/Prefab/Instance/InstanceUpdateExecutorInterface.h>
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
@@ -45,6 +46,19 @@ namespace AzToolsFramework
PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr;
TemplateInstanceMapperInterface* m_templateInstanceMapperInterface = nullptr;
int m_instanceCountToUpdateInBatch = 0;
class UniqueInstanceQueue
{
public:
Instance* front();
void pop();
void emplace(Instance* instance);
size_t size();
private:
AZStd::queue<Instance*> m_instancesQueue;
AZStd::unordered_set<Instance*> m_instancesSet;
};
//UniqueInstanceQueue m_instancesUpdateQueue;
AZStd::queue<Instance*> m_instancesUpdateQueue;
bool m_updatingTemplateInstancesInQueue { false };
};
@@ -15,15 +15,16 @@
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Utils/TypeHash.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityIdMapper.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/Instance/InstanceToTemplateInterface.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
#include <AzToolsFramework/Prefab/PrefabUndo.h>
@@ -37,12 +38,14 @@ namespace AzToolsFramework
void PrefabPublicHandler::RegisterPrefabPublicHandlerInterface()
{
m_instanceEntityMapperInterface = AZ::Interface<InstanceEntityMapperInterface>::Get();
AZ_Assert(
m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface");
AZ_Assert(m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface");
m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get();
AZ_Assert(m_instanceToTemplateInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceToTemplateInterface");
m_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
AZ_Assert(m_prefabLoaderInterface, "Could not get PrefabLoaderInterface on PrefabPublicHandler construction.");
m_prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
AZ_Assert(m_prefabSystemComponentInterface, "Could not get PrefabSystemComponentInterface on PrefabPublicHandler construction.");
@@ -58,7 +61,7 @@ namespace AzToolsFramework
m_prefabUndoCache.Destroy();
}
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath)
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
{
// Retrieve entityList from entityIds
EntityList inputEntityList;
@@ -70,17 +73,14 @@ namespace AzToolsFramework
EntityList topLevelEntities;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
entitiesHaveCommonRoot,
&AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive,
inputEntityList,
commonRootEntityId,
&topLevelEntities
);
entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList,
commonRootEntityId, &topLevelEntities);
// Bail if entities don't share a common root
if (!entitiesHaveCommonRoot)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
}
AZ::Entity* commonRootEntity = nullptr;
@@ -91,58 +91,139 @@ namespace AzToolsFramework
// 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 : "
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;
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
InstanceOptionalReference instance;
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
// Initialize Undo Batch object
ScopedUndoBatch undoBatch("Create Prefab");
TemplateId commonRootOwningTemplateId = commonRootEntityOwningInstance->get().GetTemplateId();
PrefabDom commonRootInstanceDomBeforeCreate;
m_instanceToTemplateInterface->GenerateDomForInstance(
commonRootInstanceDomBeforeCreate, commonRootEntityOwningInstance->get());
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
{
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
}
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(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(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
if (!instance)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(A null instance is returned)."));
}
PrefabDom commonRootInstanceDomAfterCreate;
m_instanceToTemplateInterface->GenerateDomForInstance(
commonRootInstanceDomAfterCreate, commonRootEntityOwningInstance->get());
auto commonRootInstanceUndoNode = aznew PrefabUndoInstance("Undo Instance Node");
commonRootInstanceUndoNode->Capture(
commonRootInstanceDomBeforeCreate, commonRootInstanceDomAfterCreate, commonRootOwningTemplateId);
commonRootInstanceUndoNode->SetParent(undoBatch.GetUndoBatch());
commonRootInstanceUndoNode->Redo();
linkRemoveUndo->Redo();
AZ::EntityId containerEntityId = instance->get().GetContainerEntityId();
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
// Apply Transform changes as overrides
{
Prefab::PrefabDom containerEntityDomBefore;
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity);
AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero());
AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero());
// Set the transform (translation, rotation) of the container entity
GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation);
// Set container entity to be child of common root
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation);
PrefabDom containerEntityDomAfter;
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity);
PrefabDom patch;
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
auto linkAddUndo = aznew PrefabUndoInstanceLink("Undo Link Add Node");
linkAddUndo->Capture(
commonRootEntityOwningInstance->get().GetTemplateId(), instance->get().GetTemplateId(), instance->get().GetInstanceAlias(),
patch, InvalidLinkId);
linkAddUndo->SetParent(undoBatch.GetUndoBatch());
linkAddUndo->Redo();
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
}
// Change top level entities to be parented to the container entity
// Mark them as dirty so this change is correctly applied to the template
for (AZ::Entity* topLevelEntity : topLevelEntities)
{
m_prefabUndoCache.UpdateCache(topLevelEntity->GetId());
undoBatch.MarkEntityDirty(topLevelEntity->GetId());
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
}
/*
// Select Container Entity
{
auto selectionUndo = aznew SelectionCommand({containerEntityId}, "Select Prefab Container Entity");
selectionUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
}*/
}
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(PrefabEditorEntityOwnershipInterface unavailable)."));
}
// Save Template to file
m_prefabLoaderInterface->SaveTemplate(instance->get().GetTemplateId());
InstanceOptionalReference instance = prefabEditorEntityOwnershipInterface->CreatePrefab(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
if (!instance)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(A null instance is returned)."));
}
AZ::EntityId containerEntityId = instance->get().GetContainerEntityId();
AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero());
AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero());
// Set the transform (translation, rotation) of the container entity
GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation);
// Set container entity to be child of common root
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId);
// Assign the EditorPrefabComponent to the instance container
EntityCompositionRequests::AddComponentsOutcome outcome;
EntityCompositionRequestBus::BroadcastResult(
outcome, &EntityCompositionRequests::AddComponentsToEntities, EntityIdList{containerEntityId},
AZ::ComponentTypeList{azrtti_typeid<AzToolsFramework::Prefab::EditorPrefabComponent>()});
// Change top level entities to be parented to the container entity
for (AZ::Entity* topLevelEntity : topLevelEntities)
{
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
}
// This function does not support undo/redo yet, so clear the undo stack to prevent issues.
//AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::FlushUndo);
return AZ::Success();
}
@@ -174,14 +255,7 @@ namespace AzToolsFramework
AZStd::string("SavePrefab - Path error. Path could be invalid, or the prefab may not be loaded in this level."));
}
auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
if (prefabLoaderInterface == nullptr)
{
return AZ::Failure(AZStd::string(
"Could not save prefab - internal error (PrefabLoaderInterface unavailable)."));
}
if (!prefabLoaderInterface->SaveTemplate(templateId))
if (!m_prefabLoaderInterface->SaveTemplate(templateId))
{
return AZ::Failure(AZStd::string("Could not save prefab - internal error (Json write operation failure)."));
}
@@ -260,15 +334,15 @@ namespace AzToolsFramework
// Create Undo node on entities if they belong to an instance
InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
if (instanceOptionalReference.has_value())
if (instanceOptionalReference.has_value() && !IsInstanceContainerEntity(entityId))
{
PrefabDom beforeState;
m_prefabUndoCache.Retrieve(entityId, beforeState);
PrefabDom afterState;
AZ::Entity* entity = GetEntityById(entityId);
if (entity)
{
PrefabDom beforeState;
m_prefabUndoCache.Retrieve(entityId, beforeState);
m_instanceToTemplateInterface->GenerateDomForEntity(afterState, *entity);
PrefabDom patch;
@@ -287,7 +361,10 @@ namespace AzToolsFramework
// Update the cache
m_prefabUndoCache.Store(entityId, AZStd::move(afterState));
}
else
{
m_prefabUndoCache.PurgeCache(entityId);
}
}
}
@@ -27,8 +27,10 @@ namespace AzToolsFramework
namespace Prefab
{
class Instance;
class InstanceEntityMapperInterface;
class InstanceToTemplateInterface;
class PrefabLoaderInterface;
class PrefabSystemComponentInterface;
class PrefabPublicHandler final
@@ -42,7 +44,7 @@ namespace AzToolsFramework
void UnregisterPrefabPublicHandlerInterface();
// PrefabPublicInterface...
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath) override;
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 SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
@@ -74,6 +76,7 @@ namespace AzToolsFramework
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
PrefabLoaderInterface* m_prefabLoaderInterface = nullptr;
PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr;
// Caches entity states for undo/redo purposes
@@ -49,7 +49,7 @@ namespace AzToolsFramework
* @param filePath The path for the new prefab file.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath) = 0;
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) = 0;
/**
* Instantiate a prefab from a prefab file.
@@ -104,7 +104,6 @@ namespace AzToolsFramework
return nullptr;
}
AZStd::unique_ptr<Instance> newInstance = AZStd::make_unique<Instance>(AZStd::move(containerEntity));
for (AZ::Entity* entity : entities)
@@ -120,8 +119,11 @@ namespace AzToolsFramework
newInstance->AddInstance(AZStd::move(instance));
}
newInstance->SetTemplateSourcePath(relativeFilePath);
/*
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, EntityList{containerEntity->GetId()});
*/
newInstance->SetTemplateSourcePath(filePath);
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance);
if (newTemplateId == InvalidTemplateId)
@@ -157,11 +159,16 @@ namespace AzToolsFramework
void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom)
{
PrefabDom& templateDomToUpdate = FindTemplateDom(templateId);
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
auto templateRef = FindTemplate(templateId);
if (templateRef.has_value())
{
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
PropagateTemplateChanges(templateId);
PrefabDom& templateDomToUpdate = templateRef->get().GetPrefabDom();
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
{
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
templateRef->get().MarkAsDirty(true);
PropagateTemplateChanges(templateId);
}
}
}
@@ -615,7 +622,12 @@ namespace AzToolsFramework
instancesValue = memberFound->value;
}
instancesValue->get().AddMember(rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator());
// Only add the instance if it's not there already
if (instancesValue->get().FindMember(rapidjson::StringRef(instanceAlias.c_str())) == instancesValue->get().MemberEnd())
{
instancesValue->get().AddMember(
rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator());
}
Template& sourceTemplate = sourceTemplateRef->get();
@@ -628,9 +640,12 @@ namespace AzToolsFramework
newLink.GetLinkDom().AddMember(rapidjson::StringRef(PrefabDomUtils::SourceName),
rapidjson::StringRef(sourceTemplate.GetFilePath().c_str()), newLink.GetLinkDom().GetAllocator());
PrefabDom linkPatchCopy;
linkPatchCopy.CopyFrom(linkPatch->get(), newLink.GetLinkDom().GetAllocator());
if (linkPatch && linkPatch->get().IsArray() && !(linkPatch->get().Empty()))
{
m_instanceToTemplatePropagator.AddPatchesToLink(linkPatch.value(), newLink);
m_instanceToTemplatePropagator.AddPatchesToLink(linkPatchCopy, newLink);
}
//update the target template dom to have the proper values for the source template dom
@@ -24,6 +24,7 @@
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiInterface.h>
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
@@ -39,9 +40,12 @@ namespace AzToolsFramework
{
namespace Prefab
{
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr;
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab";
void PrefabUserSettings::Reflect(AZ::ReflectContext* context)
@@ -79,6 +83,13 @@ namespace AzToolsFramework
return;
}
s_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
if (s_prefabLoaderInterface == nullptr)
{
AZ_Assert(false, "Prefab - could not get PrefabLoaderInterface on PrefabIntegrationManager construction.");
return;
}
EditorContextMenuBus::Handler::BusConnect();
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
AZ::Interface<PrefabIntegrationInterface>::Register(this);
@@ -320,14 +331,15 @@ namespace AzToolsFramework
GenerateSuggestedFilenameFromEntities(prefabRootEntities, suggestedName);
if (!QueryUserForPrefabSaveLocation(suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
if (!QueryUserForPrefabSaveLocation(
suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
{
// User canceled prefab creation, or error prevented continuation.
return;
}
}
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath);
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
if (!createPrefabOutcome.IsSuccess())
{
@@ -29,6 +29,9 @@ namespace AzToolsFramework
{
namespace Prefab
{
class PrefabLoaderInterface;
//! Structure for saving/retrieving user settings related to prefab workflows.
class PrefabUserSettings
: public AZ::UserSettings
@@ -129,6 +132,7 @@ namespace AzToolsFramework
static EditorEntityUiInterface* s_editorEntityUiInterface;
static PrefabPublicInterface* s_prefabPublicInterface;
static PrefabEditInterface* s_prefabEditInterface;
static PrefabLoaderInterface* s_prefabLoaderInterface;
};
}
}