Merge branch 'main' into DetachPrefab
This commit is contained in:
+1
-1
@@ -124,7 +124,7 @@ namespace AzToolsFramework
|
||||
"PrefabLoaderInterface could not be found. It is required to load Prefab Instances");
|
||||
|
||||
// Make sure we have a relative path
|
||||
instance->m_templateSourcePath = loaderInterface->GetRelativePathToProject(instance->m_templateSourcePath);
|
||||
instance->m_templateSourcePath = loaderInterface->GenerateRelativePath(instance->m_templateSourcePath);
|
||||
|
||||
TemplateId templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(instance->GetTemplateSourcePath());
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/FileFunc/FileFunc.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
@@ -112,7 +114,7 @@ namespace AzToolsFramework
|
||||
return InvalidTemplateId;
|
||||
}
|
||||
|
||||
AZ::IO::Path relativePath = GetRelativePathToProject(originPath);
|
||||
AZ::IO::Path relativePath = GenerateRelativePath(originPath);
|
||||
|
||||
// Cyclical dependency detected if the prefab file is already part of the progressed
|
||||
// file path set.
|
||||
@@ -301,6 +303,45 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrefabLoader::SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath)
|
||||
{
|
||||
AZ_Assert(absolutePath.IsAbsolute(), "SaveTemplateToFile requires an absolute path for saving the initial prefab file.");
|
||||
|
||||
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
|
||||
if (!domAndFilepath)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that the absolute path provided to this matches the relative path saved in the template.
|
||||
// Otherwise, the saved prefab won't be able to be loaded.
|
||||
auto relativePath = GenerateRelativePath(absolutePath);
|
||||
if (relativePath != domAndFilepath->second)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"PrefabLoader::SaveTemplateToFile - "
|
||||
"Failed to save template '%s' to location '%.*s'."
|
||||
"Error: Relative path '%.*s' for location didn't match template name.",
|
||||
domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), AZ_STRING_ARG(relativePath.Native()));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, absolutePath);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"PrefabLoader::SaveTemplateToFile - "
|
||||
"Failed to save template '%s' to location '%.*s'."
|
||||
"Error: %s",
|
||||
domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), outcome.GetError().c_str());
|
||||
return false;
|
||||
}
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrefabLoader::SaveTemplateToString(TemplateId templateId, AZStd::string& output)
|
||||
{
|
||||
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
|
||||
@@ -385,21 +426,100 @@ namespace AzToolsFramework
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path).MakePreferred();
|
||||
if (pathWithOSSeparator.IsAbsolute())
|
||||
{
|
||||
// If an absolute path was passed in, just return it as-is.
|
||||
return path;
|
||||
}
|
||||
|
||||
return AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
|
||||
// A relative path was passed in, so try to turn it back into an absolute path.
|
||||
|
||||
AZ::IO::Path fullPath;
|
||||
|
||||
bool pathFound = false;
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
AZStd::string rootFolder;
|
||||
AZStd::string inputPath(path.Native());
|
||||
|
||||
// Given an input path that's expected to exist, try to look it up.
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
|
||||
inputPath.c_str(), assetInfo, rootFolder);
|
||||
|
||||
if (pathFound)
|
||||
{
|
||||
// The asset system provided us with a valid root folder and relative path, so return it.
|
||||
fullPath = AZ::IO::Path(rootFolder) / assetInfo.m_relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
|
||||
|
||||
// Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
|
||||
// the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
|
||||
// a unit test, so just execute the fallback logic without an error.
|
||||
[[maybe_unused]] bool assetProcessorReady = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
|
||||
|
||||
AZ_Error(
|
||||
"Prefab", !assetProcessorReady, "Full source path for '%.*s' could not be determined. Using fallback logic.",
|
||||
AZ_STRING_ARG(path.Native()));
|
||||
|
||||
// If a relative path was passed in, make it relative to the project root.
|
||||
fullPath = AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
|
||||
}
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
AZ::IO::Path PrefabLoader::GetRelativePathToProject(AZ::IO::PathView path)
|
||||
AZ::IO::Path PrefabLoader::GenerateRelativePath(AZ::IO::PathView path)
|
||||
{
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
|
||||
if (!pathWithOSSeparator.IsAbsolute())
|
||||
bool pathFound = false;
|
||||
|
||||
AZStd::string relativePath;
|
||||
AZStd::string rootFolder;
|
||||
AZ::IO::Path finalPath;
|
||||
|
||||
// The asset system allows for paths to be relative to multiple root folders, using a priority system.
|
||||
// This request will make the input path relative to the most appropriate, highest-priority root folder.
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, path.Native(),
|
||||
relativePath, rootFolder);
|
||||
|
||||
if (pathFound && !relativePath.empty())
|
||||
{
|
||||
return path;
|
||||
// A relative path was generated successfully, so return it.
|
||||
finalPath = relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
|
||||
|
||||
// Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
|
||||
// the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
|
||||
// a unit test, so just execute the fallback logic without an error.
|
||||
[[maybe_unused]] bool assetProcessorReady = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
|
||||
|
||||
AZ_Error("Prefab", !assetProcessorReady,
|
||||
"Relative source path for '%.*s' could not be determined. Using project path as relative root.",
|
||||
AZ_STRING_ARG(path.Native()));
|
||||
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
|
||||
|
||||
if (pathWithOSSeparator.IsAbsolute())
|
||||
{
|
||||
// If an absolute path was passed in, make it relative to the project path.
|
||||
finalPath = AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a relative path was passed in, just return it.
|
||||
finalPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
|
||||
return finalPath;
|
||||
}
|
||||
|
||||
AZ::IO::Path PrefabLoaderInterface::GeneratePath()
|
||||
|
||||
@@ -72,6 +72,16 @@ namespace AzToolsFramework
|
||||
*/
|
||||
bool SaveTemplate(TemplateId templateId) override;
|
||||
|
||||
/**
|
||||
* Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
|
||||
* Converts Prefab Template form into .prefab form by collapsing nested Template info
|
||||
* into a source path and patches.
|
||||
* @param templateId Id of the template to be saved
|
||||
* @param absolutePath Absolute path to save the file to
|
||||
* @return bool on whether the operation succeeded or not
|
||||
*/
|
||||
bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) override;
|
||||
|
||||
/**
|
||||
* Saves a Prefab Template into the provided output string.
|
||||
* Converts Prefab Template form into .prefab form by collapsing nested Template info
|
||||
@@ -91,9 +101,11 @@ namespace AzToolsFramework
|
||||
//! The path will always have the correct separator for the current OS
|
||||
AZ::IO::Path GetFullPath(AZ::IO::PathView path) override;
|
||||
|
||||
//! Converts path into a relative path to the project, this will be the paths in .prefab file.
|
||||
//! The path will always have '/' separator.
|
||||
AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) override;
|
||||
//! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
|
||||
//! with the engine.
|
||||
//! This path will be the path that appears in the .prefab file.
|
||||
//! The path will always use the '/' separator.
|
||||
AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) override;
|
||||
|
||||
//! Returns if the path is a valid path for a prefab
|
||||
static bool IsValidPrefabPath(AZ::IO::PathView path);
|
||||
|
||||
@@ -60,6 +60,16 @@ namespace AzToolsFramework
|
||||
*/
|
||||
virtual bool SaveTemplate(TemplateId templateId) = 0;
|
||||
|
||||
/**
|
||||
* Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
|
||||
* Converts Prefab Template form into .prefab form by collapsing nested Template info
|
||||
* into a source path and patches.
|
||||
* @param templateId Id of the template to be saved
|
||||
* @param absolutePath Absolute path to save the file to
|
||||
* @return bool on whether the operation succeeded or not
|
||||
*/
|
||||
virtual bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) = 0;
|
||||
|
||||
/**
|
||||
* Saves a Prefab Template into the provided output string.
|
||||
* Converts Prefab Template form into .prefab form by collapsing nested Template info
|
||||
@@ -74,9 +84,11 @@ namespace AzToolsFramework
|
||||
//! The path will always have the correct separator for the current OS
|
||||
virtual AZ::IO::Path GetFullPath(AZ::IO::PathView path) = 0;
|
||||
|
||||
//! Converts path into a relative path to the current project, this will be the paths in .prefab file.
|
||||
//! The path will always have '/' separator.
|
||||
virtual AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) = 0;
|
||||
//! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
|
||||
//! with the engine.
|
||||
//! This path will be the path that appears in the .prefab file.
|
||||
//! The path will always use the '/' separator.
|
||||
virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace AzToolsFramework
|
||||
m_prefabUndoCache.Destroy();
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView absolutePath)
|
||||
{
|
||||
EntityList inputEntityList, topLevelEntities;
|
||||
AZ::EntityId commonRootEntityId;
|
||||
@@ -77,6 +77,8 @@ namespace AzToolsFramework
|
||||
return findCommonRootOutcome;
|
||||
}
|
||||
|
||||
AZ_Assert(absolutePath.IsAbsolute(), "CreatePrefab requires an absolute path for saving the initial prefab file.");
|
||||
|
||||
InstanceOptionalReference instanceToCreate;
|
||||
{
|
||||
// Initialize Undo Batch object
|
||||
@@ -145,7 +147,8 @@ namespace AzToolsFramework
|
||||
|
||||
// Create the Prefab
|
||||
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
|
||||
entities, AZStd::move(instancePtrs), filePath, commonRootEntityOwningInstance);
|
||||
entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(absolutePath),
|
||||
commonRootEntityOwningInstance);
|
||||
|
||||
if (!instanceToCreate)
|
||||
{
|
||||
@@ -238,7 +241,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
// Save Template to file
|
||||
m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
|
||||
m_prefabLoaderInterface->SaveTemplateToFile(instanceToCreate->get().GetTemplateId(), absolutePath);
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
@@ -302,7 +305,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
//Detect whether this instantiation would produce a cyclical dependency
|
||||
auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
|
||||
auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath);
|
||||
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
|
||||
|
||||
if (templateId == InvalidTemplateId)
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace AzToolsFramework
|
||||
void UnregisterPrefabPublicHandlerInterface();
|
||||
|
||||
// PrefabPublicInterface...
|
||||
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) override;
|
||||
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView absolutePath) 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;
|
||||
|
||||
@@ -46,10 +46,10 @@ namespace AzToolsFramework
|
||||
* Create a prefab out of the entities provided, at the path provided.
|
||||
* Automatically detects descendants of entities, and discerns between entities and child instances.
|
||||
* @param entityIds The entities that should form the new prefab (along with their descendants).
|
||||
* @param filePath The path for the new prefab file.
|
||||
* @param filePath The absolute 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, AZ::IO::PathView filePath) = 0;
|
||||
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView absolutePath) = 0;
|
||||
|
||||
/**
|
||||
* Instantiate a prefab from a prefab file.
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace AzToolsFramework
|
||||
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);
|
||||
AZ::IO::Path relativeFilePath = m_prefabLoader.GenerateRelativePath(filePath);
|
||||
if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId)
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
|
||||
+2
-3
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzFramework/Spawnable/SpawnableAssetHandler.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
@@ -73,8 +73,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
uint32_t ProcessedObjectStore::BuildSubId(AZStd::string_view id)
|
||||
{
|
||||
AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size());
|
||||
return azlossy_caster(subIdHash.GetHash());
|
||||
return AzFramework::SpawnableAssetHandler::BuildSubId(id);
|
||||
}
|
||||
|
||||
const AZStd::string& ProcessedObjectStore::GetId() const
|
||||
|
||||
Reference in New Issue
Block a user