Integrating latest from github/staging
Integrating up through commit 5e1bdae
This commit is contained in:
@@ -12,11 +12,12 @@
|
||||
|
||||
#include "native/AssetManager/AssetCatalog.h"
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/AssetDatabaseBus.h>
|
||||
#include <AzFramework/FileTag/FileTagBus.h>
|
||||
#include <AzFramework/FileTag/FileTag.h>
|
||||
#include <AzToolsFramework/API/AssetDatabaseBus.h>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include "PathDependencyManager.h"
|
||||
@@ -45,14 +46,12 @@ namespace AssetProcessor
|
||||
m_absoluteDevFolderPath[0] = 0;
|
||||
m_absoluteDevGameFolderPath[0] = 0;
|
||||
|
||||
AZStd::string appRoot;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot);
|
||||
azstrcpy(m_absoluteDevFolderPath, AZ_MAX_PATH_LEN, appRoot.c_str());
|
||||
|
||||
AZStd::string gameFolderPath;
|
||||
AzFramework::StringFunc::Path::Join(appRoot.c_str(), AssetUtilities::ComputeGameName().toUtf8().constData(), gameFolderPath);
|
||||
azstrcpy(m_absoluteDevGameFolderPath, AZ_MAX_PATH_LEN, gameFolderPath.c_str());
|
||||
AZStd::string engineRoot;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
|
||||
azstrcpy(m_absoluteDevFolderPath, AZ_MAX_PATH_LEN, engineRoot.c_str());
|
||||
|
||||
AZStd::string gameFolderPath{AssetUtilities::ComputeProjectPath().toUtf8().constData()};
|
||||
azstrcpy(m_absoluteDevGameFolderPath, AZ_MAX_PATH_LEN, gameFolderPath.c_str());
|
||||
|
||||
AssetUtilities::ComputeProjectCacheRoot(m_cacheRootDir);
|
||||
|
||||
@@ -340,9 +339,13 @@ namespace AssetProcessor
|
||||
}
|
||||
else
|
||||
{
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
AZ::SettingsRegistryInterface::FixedValueString cacheRootFolder;
|
||||
settingsRegistry->Get(cacheRootFolder, AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder);
|
||||
|
||||
QString tempRegistryFile = QString("%1/%2").arg(workSpace).arg("assetcatalog.xml.tmp");
|
||||
QString platformGameDir = QString("%1/%2/").arg(m_cacheRoot.absoluteFilePath(platform)).arg(AssetUtilities::ComputeGameName().toLower());
|
||||
QString actualRegistryFile = QString("%1%2").arg(platformGameDir).arg("assetcatalog.xml");
|
||||
QString platformCacheDir = QString::fromUtf8(cacheRootFolder.c_str(), aznumeric_cast<int>(cacheRootFolder.size()));
|
||||
QString actualRegistryFile = QString("%1/%2").arg(platformCacheDir).arg("assetcatalog.xml");
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Creating asset catalog: %s --> %s\n", tempRegistryFile.toUtf8().constData(), actualRegistryFile.toUtf8().constData());
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
@@ -352,12 +355,12 @@ namespace AssetProcessor
|
||||
AZ::IO::FileIOBase::GetInstance()->Close(fileHandle);
|
||||
|
||||
// Make sure that the destination folder of the registry file exists
|
||||
QDir registryDir(platformGameDir);
|
||||
QDir registryDir(platformCacheDir);
|
||||
if (!registryDir.exists())
|
||||
{
|
||||
QString absPath = registryDir.absolutePath();
|
||||
bool makeDirResult = AZ::IO::SystemFile::CreateDir(absPath.toUtf8().constData());
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, makeDirResult, "Failed create folder %s", platformGameDir.toUtf8().constData());
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, makeDirResult, "Failed create folder %s", platformCacheDir.toUtf8().constData());
|
||||
}
|
||||
|
||||
// if we succeeded in doing this, then use "rename" to move the file over the previous copy.
|
||||
@@ -488,9 +491,7 @@ namespace AssetProcessor
|
||||
AZ::Data::AssetId assetId(combined.m_sourceGuid, combined.m_subID);
|
||||
|
||||
// relative file path is gotten by removing the platform and game from the product name
|
||||
QString relativeProductPath = combined.m_productName.c_str();
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove PLATFORM and an extra slash
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove GAMENAME and an extra slash
|
||||
QString relativeProductPath = AssetUtilities::StripAssetPlatform(combined.m_productName);
|
||||
QString fullProductPath = m_cacheRoot.absoluteFilePath(combined.m_productName.c_str());
|
||||
|
||||
AZ::Data::AssetInfo info;
|
||||
@@ -1133,31 +1134,17 @@ namespace AssetProcessor
|
||||
return assetInfo;
|
||||
}
|
||||
|
||||
bool ConvertDatabaseProductPathToProductFileName(QString dbPath, QString& productFileName)
|
||||
bool ConvertDatabaseProductPathToProductFilename(AZStd::string_view dbPath, QString& productFileName)
|
||||
{
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
bool result = false;
|
||||
int gameNameIndex = dbPath.indexOf(gameName, 0, Qt::CaseInsensitive);
|
||||
if (gameNameIndex != -1)
|
||||
// Always strip the leading directory from the product path
|
||||
// The leading directory can be either an asset platform path or a subfolder
|
||||
AZ::StringFunc::TokenizeNext(dbPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
|
||||
if (!dbPath.empty())
|
||||
{
|
||||
//we will now remove the gameName and the native separator to get the assetId
|
||||
dbPath.remove(0, gameNameIndex + gameName.length() + 1); // adding one for the native separator also
|
||||
result = true;
|
||||
productFileName = QString::fromUtf8(dbPath.data(), aznumeric_cast<int>(dbPath.size()));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we will just remove the platform and the native separator to get the assetId
|
||||
int separatorIndex = dbPath.indexOf("/");
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
dbPath.remove(0, separatorIndex + 1); // adding one for the native separator
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
productFileName = dbPath;
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssetCatalog::ProcessGetRelativeProductPathFromFullSourceOrProductPathRequest(const AZStd::string& fullPath, AZStd::string& relativeProductPath)
|
||||
@@ -1166,7 +1153,7 @@ namespace AssetProcessor
|
||||
QString normalizedSourceOrProductPath = AssetUtilities::NormalizeFilePath(sourceOrProductPath);
|
||||
|
||||
QString productFileName;
|
||||
int resultCode = 0;
|
||||
bool resultCode = false;
|
||||
QDir inputPath(normalizedSourceOrProductPath);
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "ProcessGetRelativeProductPath: %s...\n", sourceOrProductPath.toUtf8().constData());
|
||||
@@ -1175,7 +1162,7 @@ namespace AssetProcessor
|
||||
{
|
||||
//if the path coming in is already a relative path,we just send it back
|
||||
productFileName = sourceOrProductPath;
|
||||
resultCode = 1;
|
||||
resultCode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1196,7 +1183,7 @@ namespace AssetProcessor
|
||||
// Now after removing the cache root,normalizedInputAssetPath can either be $Platform/$Game/xxx/yyy or something like $Platform/zzz
|
||||
// and the corresponding assetId have to be either xxx/yyy or zzz
|
||||
|
||||
resultCode = ConvertDatabaseProductPathToProductFileName(normalizedSourceOrProductPath, productFileName);
|
||||
resultCode = ConvertDatabaseProductPathToProductFilename(normalizedSourceOrProductPath.toUtf8().data(), productFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1224,12 +1211,12 @@ namespace AssetProcessor
|
||||
|
||||
if (m_db->GetProductsBySourceName(relativeName, products))
|
||||
{
|
||||
resultCode = ConvertDatabaseProductPathToProductFileName(products[0].m_productName.c_str(), productFileName);
|
||||
resultCode = ConvertDatabaseProductPathToProductFilename(products[0].m_productName, productFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
productFileName = relativeName;
|
||||
resultCode = 1;
|
||||
resultCode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1242,7 +1229,6 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
relativeProductPath = productFileName.toUtf8().data();
|
||||
|
||||
}
|
||||
|
||||
void AssetCatalog::ProcessGetFullSourcePathFromRelativeProductPathRequest(const AZStd::string& relPath, AZStd::string& fullSourcePath)
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace AssetProcessor
|
||||
PathDependencyManager::PathDependencyManager(AZStd::shared_ptr<AssetDatabaseConnection> stateData, PlatformConfiguration* platformConfig)
|
||||
: m_stateData(stateData), m_platformConfig(platformConfig)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PathDependencyManager::SaveUnresolvedDependenciesToDatabase(AssetBuilderSDK::ProductPathDependencySet& unresolvedDependencies, const AzToolsFramework::AssetDatabase::ProductDatabaseEntry& productEntry, const AZStd::string& platform)
|
||||
@@ -55,7 +55,7 @@ namespace AssetProcessor
|
||||
// other problems. This string says that something went wrong in this function.
|
||||
AZStd::string("INVALID_PATH"),
|
||||
dependencyType);
|
||||
|
||||
|
||||
AZStd::string path = AssetUtilities::NormalizeFilePath(unresolvedPathDep.m_dependencyPath.c_str()).toUtf8().constData();
|
||||
bool isExactDependency = IsExactDependency(path);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace AssetProcessor
|
||||
dependencyContainer.push_back(placeholderDependency);
|
||||
}
|
||||
|
||||
if(!m_stateData->UpdateProductDependencies(dependencyContainer))
|
||||
if (!m_stateData->UpdateProductDependencies(dependencyContainer))
|
||||
{
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Failed to save unresolved dependencies to database for product %d (%s)",
|
||||
productEntry.m_productID, productEntry.m_productName.c_str());
|
||||
@@ -111,8 +111,8 @@ namespace AssetProcessor
|
||||
const DependencyProductMap& excludedPathDependencyIds = handleProductDependencies ? exclusionMaps.m_productPathDependencyIds : exclusionMaps.m_sourcePathDependencyIds;
|
||||
const DependencyProductMap& excludedWildcardPathDependencyIds = handleProductDependencies ? exclusionMaps.m_wildcardProductPathDependencyIds : exclusionMaps.m_wildcardSourcePathDependencyIds;
|
||||
|
||||
// strip path of /<platform>/<project>/
|
||||
AZStd::string strippedPath = handleProductDependencies ? StripPlatformAndProject(assetName) : sourceEntry.m_sourceName;
|
||||
// strip asset platform from path
|
||||
AZStd::string strippedPath = handleProductDependencies ? AssetUtilities::StripAssetPlatform(assetName).toUtf8().constData() : sourceEntry.m_sourceName;
|
||||
SanitizeForDatabase(strippedPath);
|
||||
|
||||
auto unresolvedIter = excludedPathDependencyIds.find(ExcludedDependenciesSymbol + strippedPath);
|
||||
@@ -137,13 +137,6 @@ namespace AssetProcessor
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string PathDependencyManager::StripPlatformAndProject(AZStd::string_view productName)
|
||||
{
|
||||
auto nextSlash = productName.find('/'); // platform/
|
||||
nextSlash = productName.find('/', nextSlash + 1) + 1; // project/
|
||||
return productName.substr(nextSlash, productName.size() - nextSlash);
|
||||
}
|
||||
|
||||
PathDependencyManager::DependencyProductMap& PathDependencyManager::SelectMap(MapSet& mapSet, bool wildcard, AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry::DependencyType type)
|
||||
{
|
||||
const bool isSource = type == AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry::DependencyType::ProductDep_SourceFile;
|
||||
@@ -193,7 +186,7 @@ namespace AssetProcessor
|
||||
|
||||
void PathDependencyManager::NotifyResolvedDependencies(const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencyContainer) const
|
||||
{
|
||||
if(!m_dependencyResolvedCallback)
|
||||
if (!m_dependencyResolvedCallback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -226,7 +219,7 @@ namespace AssetProcessor
|
||||
const bool isExactDependency = IsExactDependency(productDependencyDatabaseEntry.m_unresolvedPath);
|
||||
AZ::s64 dependencyId = isExactDependency ? productDependencyDatabaseEntry.m_productDependencyID : AzToolsFramework::AssetDatabase::InvalidEntryId;
|
||||
|
||||
if(isSourceDependency && !isExactDependency && matchedPath == sourceNameWithScanFolder)
|
||||
if (isSourceDependency && !isExactDependency && matchedPath == sourceNameWithScanFolder)
|
||||
{
|
||||
// Since we did a search for the source 2 different ways, filter one out
|
||||
// Scanfolder-prefixes are only for exact dependencies
|
||||
@@ -239,14 +232,14 @@ namespace AssetProcessor
|
||||
AZStd::vector<AZStd::pair<DependencyProductIdInfo, bool>> exclusions; // bool = is exact dependency
|
||||
GetMatchedExclusions(sourceEntry, matchedProduct, exclusions, productDependencyDatabaseEntry.m_dependencyType, exclusionMaps);
|
||||
|
||||
if(!exclusions.empty())
|
||||
if (!exclusions.empty())
|
||||
{
|
||||
bool isExclusionForThisProduct = false;
|
||||
bool isExclusionExact = false;
|
||||
|
||||
for (const auto& exclusionPair : exclusions)
|
||||
{
|
||||
if(exclusionPair.first.m_productId == productDependencyDatabaseEntry.m_productPK && exclusionPair.first.m_platform == productDependencyDatabaseEntry.m_platform)
|
||||
if (exclusionPair.first.m_productId == productDependencyDatabaseEntry.m_productPK && exclusionPair.first.m_platform == productDependencyDatabaseEntry.m_platform)
|
||||
{
|
||||
isExclusionExact = exclusionPair.second;
|
||||
isExclusionForThisProduct = true;
|
||||
@@ -254,7 +247,7 @@ namespace AssetProcessor
|
||||
}
|
||||
}
|
||||
|
||||
if(isExclusionForThisProduct)
|
||||
if (isExclusionForThisProduct)
|
||||
{
|
||||
if (isExactDependency && isExclusionExact)
|
||||
{
|
||||
@@ -314,8 +307,8 @@ namespace AssetProcessor
|
||||
{
|
||||
const AZStd::string& productName = productEntry.m_productName;
|
||||
|
||||
// strip path of /<platform>/<project>/
|
||||
AZStd::string strippedPath = StripPlatformAndProject(productName);
|
||||
// strip path of the <platform>/
|
||||
AZStd::string strippedPath = AssetUtilities::StripAssetPlatform(productName).toUtf8().constData();
|
||||
SanitizeForDatabase(strippedPath);
|
||||
|
||||
searchPaths.push_back(strippedPath);
|
||||
@@ -347,7 +340,7 @@ namespace AssetProcessor
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer matchedProducts;
|
||||
|
||||
// Figure out the list of products to work with, for a source match, use all the products, otherwise just use the matched products
|
||||
if(isSourceDependency)
|
||||
if (isSourceDependency)
|
||||
{
|
||||
matchedProducts = products;
|
||||
}
|
||||
@@ -357,11 +350,11 @@ namespace AssetProcessor
|
||||
{
|
||||
const AZStd::string& productName = productEntry.m_productName;
|
||||
|
||||
// strip path of /<platform>/<project>/
|
||||
AZStd::string strippedPath = StripPlatformAndProject(productName);
|
||||
// strip path of the leading asset platform /<platform>
|
||||
AZStd::string strippedPath = AssetUtilities::StripAssetPlatform(productName).toUtf8().constData();
|
||||
SanitizeForDatabase(strippedPath);
|
||||
|
||||
if(strippedPath == matchedPath)
|
||||
if (strippedPath == matchedPath)
|
||||
{
|
||||
matchedProducts.push_back(productEntry);
|
||||
}
|
||||
@@ -373,7 +366,7 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
// Save everything to the db
|
||||
if(!m_stateData->UpdateProductDependencies(dependencyContainer))
|
||||
if (!m_stateData->UpdateProductDependencies(dependencyContainer))
|
||||
{
|
||||
AZ_Error("PathDependencyManager", false, "Failed to update product dependencies");
|
||||
}
|
||||
@@ -386,7 +379,7 @@ namespace AssetProcessor
|
||||
|
||||
void CleanupPathDependency(AssetBuilderSDK::ProductPathDependency& pathDependency)
|
||||
{
|
||||
if(pathDependency.m_dependencyType == AssetBuilderSDK::ProductPathDependencyType::SourceFile)
|
||||
if (pathDependency.m_dependencyType == AssetBuilderSDK::ProductPathDependencyType::SourceFile)
|
||||
{
|
||||
// Nothing to cleanup if the dependency type was already pointing at source.
|
||||
return;
|
||||
@@ -411,7 +404,7 @@ namespace AssetProcessor
|
||||
{
|
||||
const AZ::Data::ProductDependencyInfo::ProductDependencyFlags productDependencyFlags =
|
||||
AZ::Data::ProductDependencyInfo::CreateFlags(AZ::Data::AssetLoadBehavior::NoLoad);
|
||||
const QString gameName = AssetUtilities::ComputeGameName();
|
||||
|
||||
AZStd::vector<AssetBuilderSDK::ProductDependency> excludedDeps;
|
||||
|
||||
// Check the path dependency set and find any conflict (include and exclude the same path dependency)
|
||||
@@ -458,9 +451,8 @@ namespace AssetProcessor
|
||||
{
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer productInfoContainer;
|
||||
QString productNameWithPlatform = QString("%1%2%3").arg(platform.c_str(), AZ_CORRECT_DATABASE_SEPARATOR_STRING, dependencyPathSearch.c_str());
|
||||
QString productNameWithPlatformAndGameName = QString("%1%2%3%2%4").arg(platform.c_str(), AZ_CORRECT_DATABASE_SEPARATOR_STRING, gameName, dependencyPathSearch.c_str());
|
||||
|
||||
if (AzFramework::StringFunc::Equal(productNameWithPlatformAndGameName.toUtf8().data(), productName.c_str()))
|
||||
if (AzFramework::StringFunc::Equal(productNameWithPlatform.toUtf8().data(), productName.c_str()))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false,
|
||||
"Invalid dependency: Product Asset ( %s ) has listed itself as one of its own Product Dependencies.",
|
||||
@@ -471,18 +463,15 @@ namespace AssetProcessor
|
||||
|
||||
if (isExactDependency)
|
||||
{
|
||||
m_stateData->GetProductsByProductName(productNameWithPlatformAndGameName, productInfoContainer);
|
||||
// Not all products will be in the game subfolder.
|
||||
// Items in dev, like bootstrap.cfg, end up in just the root platform folder.
|
||||
// These two checks search for products in both location.
|
||||
// Example: If a path dependency was just "bootstrap.cfg" in SamplesProject on PC, this would search both
|
||||
// "cache/SamplesProject/pc/bootstrap.cfg" and "cache/SamplesProject/pc/SamplesProject/bootstrap.cfg".
|
||||
// Search for products in the cache platform folder
|
||||
// Example: If a path dependency is "test1.asset" in SamplesProject on PC, this would search
|
||||
// "SamplesProject/Cache/pc/test1.asset"
|
||||
m_stateData->GetProductsByProductName(productNameWithPlatform, productInfoContainer);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stateData->GetProductsLikeProductName(productNameWithPlatformAndGameName, AzToolsFramework::AssetDatabase::AssetDatabaseConnection::LikeType::Raw, productInfoContainer);
|
||||
m_stateData->GetProductsLikeProductName(productNameWithPlatform, AzToolsFramework::AssetDatabase::AssetDatabaseConnection::LikeType::Raw, productInfoContainer);
|
||||
}
|
||||
|
||||
// See if path matches any product files
|
||||
|
||||
@@ -76,9 +76,6 @@ namespace AssetProcessor
|
||||
/// Returns false if a path contains wildcards, true otherwise
|
||||
static bool IsExactDependency(AZStd::string_view path);
|
||||
|
||||
/// Removes /platform/project/ from the start of a product path
|
||||
static AZStd::string StripPlatformAndProject(AZStd::string_view relativeProductPath);
|
||||
|
||||
/// Prefixes the scanFolderId to the relativePath
|
||||
AZStd::string ToScanFolderPrefixedPath(int scanFolderId, const char* relativePath) const;
|
||||
|
||||
|
||||
@@ -67,8 +67,7 @@ namespace AssetProcessor
|
||||
if (AssetUtilities::ComputeAssetRoot(assetRoot))
|
||||
{
|
||||
azstrcpy(m_absoluteDevFolderPath, AZ_MAX_PATH_LEN, assetRoot.absolutePath().toUtf8().constData());
|
||||
QString absoluteDevGameFolderPath = assetRoot.absoluteFilePath(AssetUtilities::ComputeGameName());
|
||||
azstrcpy(m_absoluteDevGameFolderPath, AZ_MAX_PATH_LEN, absoluteDevGameFolderPath.toUtf8().constData());
|
||||
azstrcpy(m_absoluteDevGameFolderPath, AZ_MAX_PATH_LEN, AssetUtilities::ComputeProjectPath().toUtf8().constData());
|
||||
}
|
||||
|
||||
using namespace AZStd::placeholders;
|
||||
@@ -1067,7 +1066,7 @@ namespace AssetProcessor
|
||||
AZStd::vector<AZStd::vector<AZ::u32> > newLegacySubIDs; // each product has a vector of legacy subids;
|
||||
for (const AssetBuilderSDK::JobProduct& product : processedAsset.m_response.m_outputProducts)
|
||||
{
|
||||
// prior products, if present, will be in the form "platform/game/subfolders/productfile", convert
|
||||
// prior products, if present, will be in the form "platform/subfolders/productfile", convert
|
||||
// our new products to the same thing by removing the cache root
|
||||
QString newProductName = product.m_productFileName.c_str();
|
||||
newProductName = AssetUtilities::NormalizeFilePath(newProductName);
|
||||
@@ -1093,7 +1092,8 @@ namespace AssetProcessor
|
||||
//This is the legacy product guid, its only use is for backward compatibility as before the asset id's guid was created off of the relative product name.
|
||||
// Right now when we query for an asset guid we first match on the source guid which is correct and secondarily match on the product guid. Eventually this will go away.
|
||||
newProductName = newProductName.right(newProductName.length() - newProductName.indexOf('/') - 1); // remove PLATFORM and an extra slash
|
||||
newProductName = newProductName.right(newProductName.length() - newProductName.indexOf('/') - 1); // remove GAMENAME and an extra slash
|
||||
// Strip the <asset_platform> from the front of a relative product path
|
||||
newProductName = AssetUtilities::StripAssetPlatform(newProductName.toUtf8().constData());
|
||||
newProduct.m_legacyGuid = AZ::Uuid::CreateName(newProductName.toUtf8().constData());
|
||||
|
||||
//push back the new product into the new products list
|
||||
@@ -1115,7 +1115,7 @@ namespace AssetProcessor
|
||||
// we need to delete these product files from the disk as they no longer exist and inform everyone we did so
|
||||
for (const auto& priorProduct : priorProducts)
|
||||
{
|
||||
// product name will be in the form "platform/game/relativeProductPath"
|
||||
// product name will be in the form "platform/relativeProductPath"
|
||||
// and will always already be a lowercase string, because its relative to the cache.
|
||||
QString productName = priorProduct.m_productName.c_str();
|
||||
|
||||
@@ -1123,10 +1123,8 @@ namespace AssetProcessor
|
||||
// this is case sensitive since it refers to a real location on disk.
|
||||
QString fullProductPath = m_cacheRootDir.absoluteFilePath(productName);
|
||||
|
||||
// relative file path is gotten by removing the platform and game from the product name
|
||||
QString relativeProductPath = productName;
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove PLATFORM and an extra slash
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove GAMENAME and an extra slash
|
||||
// Strip the <asset_platform> from the front of a relative product path
|
||||
QString relativeProductPath = AssetUtilities::StripAssetPlatform(priorProduct.m_productName);
|
||||
|
||||
AZ::Data::AssetId assetId(source.m_sourceGuid, priorProduct.m_subID);
|
||||
|
||||
@@ -1302,16 +1300,15 @@ namespace AssetProcessor
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntry& newProduct = pair.first;
|
||||
AZStd::vector<AZ::u32>& subIds = newLegacySubIDs[productIdx];
|
||||
|
||||
// product name will be in the form "platform/game/relativeProductPath"
|
||||
// product name will be in the form "platform/relativeProductPath"
|
||||
QString productName = QString::fromUtf8(newProduct.m_productName.c_str());
|
||||
|
||||
// the full file path is gotten by adding the product name to the cache root
|
||||
QString fullProductPath = m_cacheRootDir.absoluteFilePath(productName);
|
||||
|
||||
// relative file path is gotten by removing the platform and game from the product name
|
||||
QString relativeProductPath = productName;
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove PLATFORM and an extra slash
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // remove GAMENAME and an extra slash
|
||||
// Strip the <asset_platform> from the front of a relative product path
|
||||
QString relativeProductPath = AssetUtilities::StripAssetPlatform(productName.toUtf8().constData());
|
||||
|
||||
AssetNotificationMessage message(relativeProductPath.toUtf8().constData(), AssetNotificationMessage::AssetChanged, newProduct.m_assetType, processedAsset.m_entry.m_platformInfo.m_identifier.c_str());
|
||||
AZ::Data::AssetId assetId(source.m_sourceGuid, newProduct.m_subID);
|
||||
@@ -1572,10 +1569,10 @@ namespace AssetProcessor
|
||||
// this might be interesting, but only if its a known product!
|
||||
// the dictionary in statedata stores only the relative path, not the platform.
|
||||
// which means right now we have, for example
|
||||
// d:/game/root/Cache/SamplesProject/IOS/SamplesProject/textures/favorite.tga
|
||||
// ^^^^^^^^^^^^ engine root
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cache root
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ platform root
|
||||
// d:/SamplesProject/Cache/ios/textures/favorite.tga
|
||||
// ^^^^^^^^^ projectroot
|
||||
// ^^^^^^^^^^^^^^^^^^^^^ cache root
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^ platform root
|
||||
{
|
||||
QMutexLocker locker(&m_processingJobMutex);
|
||||
auto found = m_processingProductInfoList.find(fullProductFile.toUtf8().constData());
|
||||
@@ -1596,7 +1593,7 @@ namespace AssetProcessor
|
||||
QString relativeProductFile = m_cacheRootDir.relativeFilePath(fullProductFile);
|
||||
|
||||
//platform
|
||||
QString platform = relativeProductFile;// currently <platform>/<gamename>/<relative_asset_path>
|
||||
QString platform = relativeProductFile;// currently <platform>/<relative_asset_path>
|
||||
platform = platform.left(platform.indexOf('/')); // also consume the extra slash - remove PLATFORM
|
||||
|
||||
//we are going to force the processor to re process the source file associated with this product
|
||||
@@ -1652,11 +1649,8 @@ namespace AssetProcessor
|
||||
}
|
||||
}
|
||||
|
||||
// currently <platform>/<gamename>/<relative_asset_path>
|
||||
// remove PLATFORM and GAMENAME so that we only have the relative asset path which should match the db
|
||||
QString relativePath(relativeProductFile);
|
||||
relativePath = relativePath.right(relativePath.length() - relativePath.indexOf('/') - 1); // also consume the extra slash - remove PLATFORM
|
||||
relativePath = relativePath.right(relativePath.length() - relativePath.indexOf('/') - 1); // also consume the extra slash - remove GAMENAME
|
||||
// Strip the <asset_platform> from the front of a relative product path
|
||||
QString relativePath = AssetUtilities::StripAssetPlatform(relativeProductFile.toUtf8().constData());
|
||||
|
||||
//set the fingerprint on the job that made this product
|
||||
for (auto& job : jobs)
|
||||
@@ -1687,9 +1681,9 @@ namespace AssetProcessor
|
||||
{
|
||||
bool successfullyRemoved = true;
|
||||
// delete the products.
|
||||
// products have names like "pc/SamplesProject/textures/blah.dds" and do include platform roots!
|
||||
// products have names like "pc/textures/blah.dds" and do include platform roots!
|
||||
// this means the actual full path is something like
|
||||
// [cache root] / [platform] / [product name]
|
||||
// [cache root] / [platform]
|
||||
for (const auto& product : products)
|
||||
{
|
||||
//get the source for this product
|
||||
@@ -1700,9 +1694,7 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
QString fullProductPath = m_cacheRootDir.absoluteFilePath(product.m_productName.c_str());
|
||||
QString relativeProductPath(product.m_productName.c_str());
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // also consume the extra slash - remove PLATFORM
|
||||
relativeProductPath = relativeProductPath.right(relativeProductPath.length() - relativeProductPath.indexOf('/') - 1); // also consume the extra slash - remove GAMENAME
|
||||
QString relativeProductPath(AssetUtilities::StripAssetPlatform(product.m_productName));
|
||||
QFileInfo productFileInfo(fullProductPath);
|
||||
if (productFileInfo.exists())
|
||||
{
|
||||
@@ -2144,15 +2136,7 @@ namespace AssetProcessor
|
||||
pathRel = QString();
|
||||
}
|
||||
|
||||
if (jobDetails.m_scanFolder->IsRoot())
|
||||
{
|
||||
// stuff which is found in the root continues to go to the root, rather than GAMENAME folder...
|
||||
lowerCasePath += pathRel;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowerCasePath += "/" + AssetUtilities::ComputeGameName() + pathRel;
|
||||
}
|
||||
lowerCasePath += pathRel;
|
||||
|
||||
lowerCasePath = lowerCasePath.toLower();
|
||||
jobDetails.m_destinationPath = m_cacheRootDir.absoluteFilePath(lowerCasePath);
|
||||
@@ -3471,8 +3455,16 @@ namespace AssetProcessor
|
||||
AssetProcessor::BuilderConfigurationRequestBus::Broadcast(&AssetProcessor::BuilderConfigurationRequests::UpdateJobDescriptor, jobDescriptor.m_jobKey, jobDescriptor);
|
||||
|
||||
const AssetBuilderSDK::PlatformInfo* const infoForPlatform = m_platformConfig->GetPlatformByIdentifier(jobDescriptor.GetPlatformIdentifier().c_str());
|
||||
AZ_Assert(infoForPlatform, "Somehow, a platform for a job was created in createjobs which cannot be found in the list of enabled platforms.");
|
||||
if (infoForPlatform)
|
||||
|
||||
if (!infoForPlatform)
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, infoForPlatform,
|
||||
"CODE BUG: Builder %s emitted jobs for a platform that isn't enabled (%s). This job will be "
|
||||
"discarded. Builders should check the input list of platforms and only emit jobs for platforms "
|
||||
"in that list", builderInfo.m_name.c_str(), jobDescriptor.GetPlatformIdentifier().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
JobDetails newJob;
|
||||
newJob.m_assetBuilderDesc = builderInfo;
|
||||
@@ -4614,7 +4606,7 @@ namespace AssetProcessor
|
||||
QString metaDataFileName;
|
||||
QDir assetRoot;
|
||||
AssetUtilities::ComputeAssetRoot(assetRoot);
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString projectPath = AssetUtilities::ComputeProjectPath();
|
||||
QString fullPathToFile(absolutePathToFileToCheck);
|
||||
|
||||
if (!m_cachedMetaFilesExistMap)
|
||||
@@ -4624,7 +4616,7 @@ namespace AssetProcessor
|
||||
for (int idx = 0; idx < m_platformConfig->MetaDataFileTypesCount(); idx++)
|
||||
{
|
||||
QPair<QString, QString> metaDataFileType = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
QString fullMetaPath = assetRoot.filePath(gameName + "/" + metaDataFileType.first);
|
||||
QString fullMetaPath = QDir(projectPath).filePath(metaDataFileType.first);
|
||||
if (QFileInfo::exists(fullMetaPath))
|
||||
{
|
||||
m_metaFilesWhichActuallyExistOnDisk.insert(metaDataFileType.first);
|
||||
@@ -4644,7 +4636,7 @@ namespace AssetProcessor
|
||||
|
||||
if (m_metaFilesWhichActuallyExistOnDisk.find(metaDataFileType.first) != m_metaFilesWhichActuallyExistOnDisk.end())
|
||||
{
|
||||
QString fullMetaPath = assetRoot.filePath(gameName + "/" + metaDataFileType.first);
|
||||
QString fullMetaPath = QDir(projectPath).filePath(metaDataFileType.first);
|
||||
metaDataFileName = fullMetaPath;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#include "native/utilities/assetUtils.h"
|
||||
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
using namespace AZ::IO;
|
||||
@@ -114,20 +117,20 @@ void FileServer::ConnectionAdded(unsigned int connId, Connection* connection)
|
||||
{
|
||||
projectCacheRoot = QDir(projectCacheRoot.absoluteFilePath(assetPlatform));
|
||||
}
|
||||
fileIO->SetAlias("@root@", projectCacheRoot.absolutePath().toUtf8().data());
|
||||
const char* projectCachePath = projectCacheRoot.absolutePath().toUtf8().data();
|
||||
fileIO->SetAlias("@assets@", projectCachePath);
|
||||
fileIO->SetAlias("@root@", projectCachePath);
|
||||
|
||||
QString userDir = projectCacheRoot.absoluteFilePath("user");
|
||||
userDir = QDir::toNativeSeparators(userDir);
|
||||
fileIO->SetAlias("@user@", userDir.toUtf8().data());
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
AZ::IO::Path projectUserPath;
|
||||
settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
fileIO->SetAlias("@user@", projectUserPath.c_str());
|
||||
|
||||
QString logDir = QDir(userDir).absoluteFilePath("log");
|
||||
logDir = QDir::toNativeSeparators(logDir);
|
||||
fileIO->SetAlias("@log@", logDir.toUtf8().data());
|
||||
AZ::IO::Path logUserPath = projectUserPath / "log";
|
||||
fileIO->SetAlias("@log@", logUserPath.c_str());
|
||||
}
|
||||
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString gameDir = projectCacheRoot.absoluteFilePath(gameName);
|
||||
gameDir = QDir::toNativeSeparators(gameDir);
|
||||
fileIO->SetAlias("@assets@", gameDir.toUtf8().data());
|
||||
|
||||
// note that the cache folder is auto-created only upon first use of VFS.
|
||||
}
|
||||
@@ -145,13 +148,20 @@ void FileServer::EnsureCacheFolderExists(int connId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fileIO->GetAlias("@cache@"))
|
||||
if (fileIO->GetAlias("@usercache@"))
|
||||
{
|
||||
// already created.
|
||||
return;
|
||||
}
|
||||
|
||||
QString cacheDir = QDir(fileIO->GetAlias("@user@")).absoluteFilePath("cache");
|
||||
AZ::IO::FixedMaxPath cacheUserPath;
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry->Get(cacheUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
|
||||
{
|
||||
cacheUserPath /= "Cache";
|
||||
}
|
||||
|
||||
auto cacheDir = QString::fromUtf8(cacheUserPath.c_str(), aznumeric_cast<int>(cacheUserPath.Native().size()));
|
||||
cacheDir = QDir::toNativeSeparators(cacheDir);
|
||||
// the Cache-dir is special in that we don't allow sharing of cache dirs for multiple running
|
||||
// apps of the same platform at the same time.
|
||||
@@ -207,7 +217,7 @@ void FileServer::EnsureCacheFolderExists(int connId)
|
||||
}
|
||||
#endif
|
||||
|
||||
fileIO->SetAlias("@cache@", cacheDir.toUtf8().data());
|
||||
fileIO->SetAlias("@usercache@", cacheDir.toUtf8().data());
|
||||
}
|
||||
|
||||
void FileServer::ConnectionRemoved(unsigned int connId)
|
||||
@@ -944,7 +954,7 @@ void FileServer::ProcessFileTreeRequest(unsigned int connId, unsigned int, unsig
|
||||
}
|
||||
|
||||
auto fileIO = m_fileIOs[connId];
|
||||
|
||||
|
||||
FileTreeResponse::FileList files;
|
||||
FileTreeResponse::FolderList folders;
|
||||
|
||||
@@ -954,10 +964,10 @@ void FileServer::ProcessFileTreeRequest(unsigned int connId, unsigned int, unsig
|
||||
folders.push_back("@assets@");
|
||||
untestedFolders.push_back("@assets@");
|
||||
}
|
||||
if (fileIO->IsDirectory("@cache@"))
|
||||
if (fileIO->IsDirectory("@usercache@"))
|
||||
{
|
||||
folders.push_back("@cache@");
|
||||
untestedFolders.push_back("@cache@");
|
||||
folders.push_back("@usercache@");
|
||||
untestedFolders.push_back("@usercache@");
|
||||
}
|
||||
if (fileIO->IsDirectory("@user@"))
|
||||
{
|
||||
@@ -976,7 +986,7 @@ void FileServer::ProcessFileTreeRequest(unsigned int connId, unsigned int, unsig
|
||||
}
|
||||
|
||||
AZ::IO::Result res = ResultCode::Success;
|
||||
|
||||
|
||||
while (untestedFolders.size() && res == ResultCode::Success)
|
||||
{
|
||||
AZ::OSString folderName = untestedFolders.back();
|
||||
@@ -1006,9 +1016,9 @@ void FileServer::ProcessFileTreeRequest(unsigned int connId, unsigned int, unsig
|
||||
}
|
||||
|
||||
uint32_t resultCode = static_cast<uint32_t>(res.GetResultCode());
|
||||
|
||||
|
||||
FileTreeResponse response(resultCode, files, folders);
|
||||
|
||||
|
||||
Send(connId, serial, response);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <native/InternalBuilders/SettingsRegistryBuilder.h>
|
||||
#include <native/utilities/PlatformConfiguration.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
@@ -210,6 +212,8 @@ namespace AssetProcessor
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
||||
|
||||
AZStd::vector<AZStd::string> excludes = ReadExcludesFromRegistry();
|
||||
// Exclude the AssetProcessor settings from the game regsitry
|
||||
excludes.emplace_back(AssetProcessor::AssetProcessorSettingsKey);
|
||||
|
||||
AZStd::vector<char> scratchBuffer;
|
||||
scratchBuffer.reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
||||
@@ -228,19 +232,16 @@ namespace AssetProcessor
|
||||
};
|
||||
|
||||
// Add the project specific specializations
|
||||
if (auto settingsRegistry = AZ::Interface<AZ::SettingsRegistryInterface>::Get(); settingsRegistry)
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
if (!projectName.empty())
|
||||
{
|
||||
auto projectKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/sys_game_folder", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
|
||||
if (AZ::SettingsRegistryInterface::FixedValueString projectName; settingsRegistry->Get(projectName, projectKey))
|
||||
for (AZ::SettingsRegistryInterface::Specializations& specialization : specializations)
|
||||
{
|
||||
for (AZ::SettingsRegistryInterface::Specializations& specialization : specializations)
|
||||
{
|
||||
specialization.Append(projectName);
|
||||
// The Game Launcher normally has a build target name of <ProjectName>Launcher
|
||||
// Add that as a specialization to pick up the gem dependencies files that are specialized
|
||||
// on a the Game Launcher target if the asset platform isn't "server"
|
||||
specialization.Append(projectName + launcherType);
|
||||
}
|
||||
specialization.Append(projectName);
|
||||
// The Game Launcher normally has a build target name of <ProjectName>Launcher
|
||||
// Add that as a specialization to pick up the gem dependencies files that are specialized
|
||||
// on a the Game Launcher target if the asset platform isn't "server"
|
||||
specialization.Append(projectName + launcherType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,8 +256,9 @@ namespace AssetProcessor
|
||||
for (AZStd::string_view platform : platformCodes)
|
||||
{
|
||||
AZ::u32 productSubID = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(platform)); // Deliberately ignoring half the bits.
|
||||
for (size_t i = 0; i < AZ_ARRAY_SIZE(specializations); ++i)
|
||||
for (size_t i = 0; i < AZStd::size(specializations); ++i)
|
||||
{
|
||||
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
|
||||
if (m_isShuttingDown)
|
||||
{
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
|
||||
@@ -269,12 +271,12 @@ namespace AssetProcessor
|
||||
if (auto settingsRegistry = AZ::Interface<AZ::SettingsRegistryInterface>::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
AZStd::array settingsToCopy{
|
||||
AZStd::string::format("%s/sys_game_folder", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey),
|
||||
AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey),
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_BinaryFolder},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_SourceGameFolder},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder},
|
||||
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_CacheGameFolder}
|
||||
};
|
||||
|
||||
for (const auto& settingsKey : settingsToCopy)
|
||||
@@ -288,14 +290,14 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(registry);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, platform, specializations[i], &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, platform, specializations[i], &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, platform, specializations[i], &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, platform, specialization, &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, platform, specialization, &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, platform, specialization, &scratchBuffer);
|
||||
|
||||
// Merge the Developer User settings registry only in non-release builds
|
||||
if (!specializations->Contains("release"))
|
||||
if (!specialization.Contains("release"))
|
||||
{
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_DevRegistry(registry, platform, specializations[i], &scratchBuffer);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_UserRegistry(registry, platform, specialization, &scratchBuffer);
|
||||
}
|
||||
|
||||
AZ::ComponentApplicationBus::Broadcast([®istry](AZ::ComponentApplicationRequests* appRequests)
|
||||
@@ -314,7 +316,7 @@ namespace AssetProcessor
|
||||
return;
|
||||
}
|
||||
|
||||
outputPath += specializations[i].GetSpecialization(0); // Append configuration
|
||||
outputPath += specialization.GetSpecialization(0); // Append configuration
|
||||
outputPath += '.';
|
||||
outputPath += platform;
|
||||
outputPath += ".setreg";
|
||||
|
||||
@@ -506,7 +506,7 @@ void ConnectionManager::AddAddressToAllowedList(QString address)
|
||||
UpdateAllowedListFromBootStrap();
|
||||
while (m_allowedListAddresses.removeOne(address)) {}
|
||||
m_allowedListAddresses << address;
|
||||
AssetUtilities::WriteAllowedlistToBootstrap(m_allowedListAddresses);
|
||||
AssetUtilities::WriteAllowedlistToSettingsRegistry(m_allowedListAddresses);
|
||||
Q_EMIT SyncAllowedListAndRejectedList(m_allowedListAddresses, m_rejectedAddresses);
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ void ConnectionManager::RemoveAddressFromAllowedList(QString address)
|
||||
{
|
||||
UpdateAllowedListFromBootStrap();
|
||||
while (m_allowedListAddresses.removeOne(address)) {}
|
||||
AssetUtilities::WriteAllowedlistToBootstrap(m_allowedListAddresses);
|
||||
AssetUtilities::WriteAllowedlistToSettingsRegistry(m_allowedListAddresses);
|
||||
Q_EMIT SyncAllowedListAndRejectedList(m_allowedListAddresses, m_rejectedAddresses);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,9 +235,9 @@ bool ConnectionWorker::NegotiateDirect(bool initiate)
|
||||
using namespace AzFramework::AssetSystem;
|
||||
|
||||
AZStd::string azBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForAppRoot, azBranchToken);
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForEngineRoot, azBranchToken);
|
||||
QString branchToken(azBranchToken.c_str());
|
||||
QString projectName = AssetUtilities::ComputeGameName();
|
||||
QString projectName = AssetUtilities::ComputeProjectName();
|
||||
|
||||
NegotiationMessage myInfo;
|
||||
|
||||
@@ -316,7 +316,7 @@ bool ConnectionWorker::NegotiateDirect(bool initiate)
|
||||
QString incomingBranchToken(engineInfo.m_negotiationInfoMap[NegotiationInfo_BranchIndentifier].c_str());
|
||||
if (QString::compare(incomingBranchToken, branchToken, Qt::CaseInsensitive) != 0)
|
||||
{
|
||||
//if we are here it means that the editor/game which is negotiating is running on a different branch
|
||||
// if we are here it means that the editor/game which is negotiating is running on a different branch
|
||||
// note that it could have just read nothing from the engine or a repeat packet, in that case, discard it silently and try again.
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "ConnectionWorker::NegotiateDirect: branch token mismatch from %s - %p - %s vs %s\n", engineInfo.m_identifier.c_str(), this, incomingBranchToken.toUtf8().data(), branchToken.toUtf8().data());
|
||||
AssetProcessor::MessageInfoBus::Broadcast(&AssetProcessor::MessageInfoBus::Events::NegotiationFailed);
|
||||
@@ -325,7 +325,7 @@ bool ConnectionWorker::NegotiateDirect(bool initiate)
|
||||
}
|
||||
|
||||
QString incomingProjectName(engineInfo.m_negotiationInfoMap[NegotiationInfo_ProjectName].c_str());
|
||||
// Do a case-insensitive compare for the project name because some (case-sensitive) platforms will blower-case the incoming project name
|
||||
// Do a case-insensitive compare for the project name because some (case-sensitive) platforms will lower-case the incoming project name
|
||||
if(QString::compare(incomingProjectName, projectName, Qt::CaseInsensitive) != 0)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "ConnectionWorker::NegotiateDirect: project name mismatch from %s - %p - %s vs %s\n", engineInfo.m_identifier.c_str(), this, incomingProjectName.toUtf8().constData(), projectName.toUtf8().constData());
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include <AzToolsFramework/Process/ProcessCommunicator.h>
|
||||
#include <AzToolsFramework/Process/ProcessWatcher.h>
|
||||
#include <AzFramework/Process/ProcessCommunicator.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
|
||||
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
@@ -164,7 +164,7 @@ namespace AssetProcessor
|
||||
// build the command line:
|
||||
QString commandString = NativeLegacyRCCompiler::BuildCommand(inputFile, watchFolder, platformIdentifier, params, dest);
|
||||
|
||||
AzToolsFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
|
||||
// while it might be tempting to set the executable in processLaunchInfo.m_processExecutableString, it turns out that RC.EXE
|
||||
// won't work if you do that because it assumes the first command line param is the exe name, which is not the case if you do it that way...
|
||||
@@ -173,12 +173,12 @@ namespace AssetProcessor
|
||||
processLaunchInfo.m_commandlineParameters = QString(formatter).arg(m_rcExecutableFullPath).arg(commandString).toUtf8().data();
|
||||
processLaunchInfo.m_showWindow = false;
|
||||
processLaunchInfo.m_workingDirectory = m_systemRoot.absolutePath().toUtf8().data();
|
||||
processLaunchInfo.m_processPriority = AzToolsFramework::PROCESSPRIORITY_IDLE;
|
||||
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_IDLE;
|
||||
|
||||
AZ_TracePrintf("RC Builder", "Executing RC.EXE: '%s' ...\n", processLaunchInfo.m_commandlineParameters.c_str());
|
||||
AZ_TracePrintf("Rc Builder", "Executing RC.EXE with working directory: '%s' ...\n", processLaunchInfo.m_workingDirectory.c_str());
|
||||
|
||||
AzToolsFramework::ProcessWatcher* watcher = AzToolsFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzToolsFramework::COMMUNICATOR_TYPE_STDINOUT);
|
||||
AzFramework::ProcessWatcher* watcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT);
|
||||
|
||||
if (!watcher)
|
||||
{
|
||||
@@ -256,18 +256,16 @@ namespace AssetProcessor
|
||||
QString cmdLine;
|
||||
if (!dest.isEmpty())
|
||||
{
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString projectName = AssetUtilities::ComputeProjectName();
|
||||
QString projectPath = AssetUtilities::ComputeProjectPath();
|
||||
|
||||
int portNumber = 0;
|
||||
ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort);
|
||||
|
||||
QDir assetRoot;
|
||||
AssetUtilities::ComputeAssetRoot(assetRoot);
|
||||
QString gameRoot = assetRoot.absoluteFilePath(AssetUtilities::ComputeGameName());
|
||||
AZStd::string appBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForAppRoot, appBranchToken);
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForEngineRoot, appBranchToken);
|
||||
cmdLine = QString("\"%1\" /p=%2 %3 /unattended=true /gameroot=\"%4\" /watchfolder=\"%6\" /targetroot=\"%5\" /logprefix=\"%5/\" /port=%7 /gamesubdirectory=\"%8\" /branchtoken=\"%9\"");
|
||||
cmdLine = cmdLine.arg(inputFile, platformIdentifier, params, gameRoot, dest, watchFolder).arg(portNumber).arg(gameName).arg(appBranchToken.c_str());
|
||||
cmdLine = cmdLine.arg(inputFile, platformIdentifier, params, projectPath, dest, watchFolder).arg(portNumber).arg(projectName).arg(appBranchToken.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzToolsFramework/API/AssetDatabaseBus.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
@@ -44,7 +45,7 @@ namespace AssetProcessor
|
||||
public:
|
||||
AssetCatalogForUnitTest(QObject* parent, AssetProcessor::PlatformConfiguration* platformConfiguration)
|
||||
: AssetCatalog(parent, platformConfiguration) {}
|
||||
|
||||
|
||||
// prevent automatic save on shutdown, no point in doing that in unit test mode, just wastes time.
|
||||
virtual ~AssetCatalogForUnitTest()
|
||||
{
|
||||
@@ -68,7 +69,7 @@ namespace AssetProcessor
|
||||
: public ScopedAllocatorSetupFixture
|
||||
{
|
||||
protected:
|
||||
|
||||
|
||||
// store all data we create here so that it can be destroyed on shutdown before we remove allocators
|
||||
struct DataMembers
|
||||
{
|
||||
@@ -89,7 +90,7 @@ namespace AssetProcessor
|
||||
int argc = 0;
|
||||
DataMembers() : coreApp(argc, nullptr)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -108,23 +109,28 @@ namespace AssetProcessor
|
||||
m_systemEntity = m_app->Create(desc);
|
||||
|
||||
m_data = azcreate(DataMembers, ());
|
||||
|
||||
|
||||
AssetUtilities::ComputeAssetRoot(m_data->m_priorAssetRoot);
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
|
||||
// the canonicalization of the path here is to get around the fact that on some platforms
|
||||
// the "temporary" folder location could be junctioned into some other folder and getting "QDir::current()"
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
m_data->m_temporarySourceDir = QDir(m_data->m_temporaryDir.path());
|
||||
QString canonicalTempDirPath = AssetUtilities::NormalizeDirectoryPath(m_data->m_temporarySourceDir.canonicalPath());
|
||||
m_data->m_temporarySourceDir = QDir(canonicalTempDirPath);
|
||||
m_data->m_scopedDir.Setup(m_data->m_temporarySourceDir.path());
|
||||
m_data->m_gameName = AssetUtilities::ComputeGameName("SamplesProject"); // uses the above file.
|
||||
m_data->m_gameName = AssetUtilities::ComputeProjectName("SamplesProject"); // uses the above file.
|
||||
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
QDir newRoot; // throwaway dummy var - we just want to invoke the below function
|
||||
AssetUtilities::ComputeAssetRoot(newRoot, &m_data->m_temporarySourceDir);
|
||||
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
auto cacheRootKey =
|
||||
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_cache_path";
|
||||
settingsRegistry->Set(cacheRootKey, m_data->m_temporarySourceDir.absoluteFilePath("Cache").toUtf8().constData());
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*settingsRegistry);
|
||||
AssetUtilities::ComputeProjectCacheRoot(m_data->m_cacheRootDir);
|
||||
QString normalizedCacheRoot = AssetUtilities::NormalizeDirectoryPath(m_data->m_cacheRootDir.absolutePath());
|
||||
m_data->m_cacheRootDir = QDir(normalizedCacheRoot);
|
||||
@@ -181,7 +187,7 @@ namespace AssetProcessor
|
||||
|
||||
m_data->m_databaseLocationListener.BusConnect();
|
||||
m_data->m_dbConn.OpenDatabase();
|
||||
|
||||
|
||||
BuildConfig(m_data->m_temporarySourceDir, &(m_data->m_dbConn), m_data->m_config);
|
||||
m_data->m_assetCatalog.reset(new AssetCatalogForUnitTest(nullptr, &(m_data->m_config)));
|
||||
}
|
||||
@@ -331,7 +337,7 @@ namespace AssetProcessor
|
||||
{
|
||||
bool relPathfound = false;
|
||||
AZStd::string relPath;
|
||||
AZStd::string fullPath(fileToCheck.toStdString().c_str());
|
||||
AZStd::string fullPath(fileToCheck.toUtf8().constData());
|
||||
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(relPathfound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath, fullPath, relPath);
|
||||
|
||||
@@ -356,7 +362,7 @@ namespace AssetProcessor
|
||||
{
|
||||
bool fullPathfound = false;
|
||||
AZStd::string fullPath;
|
||||
AZStd::string relPath(fileToCheck.toStdString().c_str());
|
||||
AZStd::string relPath(fileToCheck.toUtf8().constData());
|
||||
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathfound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetFullSourcePathFromRelativeProductPath, relPath, fullPath);
|
||||
|
||||
@@ -419,7 +425,7 @@ namespace AssetProcessor
|
||||
ASSERT_EQ(m_data->m_absorber.m_numAssertsAbsorbed, 2);
|
||||
// reset the absorber before we leave this assert-test, so that it doesn't cause failure of the test itself
|
||||
m_data->m_absorber.Clear();
|
||||
|
||||
|
||||
ASSERT_TRUE(TestGetRelativeProductPath("", false, { "" }));
|
||||
ASSERT_TRUE(TestGetFullSourcePath("", m_data->m_temporarySourceDir, false, ""));
|
||||
}
|
||||
@@ -444,75 +450,76 @@ namespace AssetProcessor
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_WithGameName_ReturnsFileInGameFolder)
|
||||
{
|
||||
// feed it a product path with gamename and a platform name, returns it without gamename
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName + "/aaa/basefile.txt");
|
||||
// feed it a product path with a platform name, returns it
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/aaa/basefile.txt");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_WithoutGameName_ReturnsFileInRootFolder)
|
||||
{
|
||||
// feed it a product path without gamename, just the file name since its supposed to be a root file
|
||||
// feed it a product path, just the file name since its supposed to be a root file
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/basefile.txt");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "basefile.txt" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_BadCasingInPlatform_ReturnsRelativePath)
|
||||
{
|
||||
// feed it a product path with gamename but poor casing (test 1: the pc platform is not matching case)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("Pc/" + m_data->m_gameName + "/aaa/basefile.txt");
|
||||
// feed it a product path but with poor casing (test 1: the pc platform is not matching case)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("Pc") + "/aaa/basefile.txt");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_BadCasingInGameName_ReturnsRelativePath)
|
||||
{
|
||||
//feed it a product path with gamename but poor casing (test 2: the gameName is not matching case)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toUpper() + "/aaa/basefile.txt");
|
||||
//feed it a product path but with poor casing (test 2: the gameName is not matching case)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/aaa/basefile.txt");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_FolderName_ReturnsFolderNameOnly)
|
||||
{
|
||||
// feed it a product path that resolves to a directory name instead of a file. GameName is 'incorrect' (upper)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toUpper() + "/aaa");
|
||||
// feed it a product path that resolves to a directory name instead of a file.
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/aaa");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_FolderNameExtraSlash_ReturnsFolderNameOnlyNoExtraSlash)
|
||||
{
|
||||
// make sure it doesn't keep any trailing slashes. GameName is 'incorrect' (upper)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toUpper() + "/aaa/"); // extra trailing slash
|
||||
// make sure it doesn't keep any trailing slashes.
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/aaa/"); // extra trailing slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa" })); // the API should never result in a trailing slash
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_FolderNameExtraWrongWaySlash_ReturnsFolderNameOnlyNoExtraWrongSlash)
|
||||
{
|
||||
// make sure it doesn't keep any trailing slashes. GameName is 'incorrect' (upper)
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toUpper() + "/aaa\\"); // extra trailing wrongway slash
|
||||
// make sure it doesn't keep any trailing slashes.
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/aaa\\"); // extra trailing wrongway slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa" })); // the API should never result in a trailing slash
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_RelativeDirectoryNameWhichDoesNotExist_ReturnsFolderNameOnly)
|
||||
{
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toLower() + "/nonexistantfolder"); // extra trailing wrongway slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "nonexistantfolder" }));
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/nonexistantfolder"); // extra trailing wrongway slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "nonexistantfolder" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_RelativeDirectoryNameWhichDoesNotExistWithExtraSlash_ReturnsFolderNameOnly)
|
||||
{
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toLower() + "/nonexistantfolder/"); // extra trailing wrongway slash
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/nonexistantfolder/"); // extra trailing wrongway slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "nonexistantfolder" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_RelativeDirectoryNameWhichDoesNotExistWithExtraWrongWaySlash_ReturnsFolderNameOnly)
|
||||
{
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc\\" + m_data->m_gameName.toLower() + "\\nonexistantfolder\\"); // extra trailing wrongway slash
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "\\nonexistantfolder\\"); // extra trailing wrongway slash
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "nonexistantfolder" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_RelativePathToSourceFile_ReturnsProductFilePath)
|
||||
{
|
||||
QString fileToCheck = m_data->m_temporarySourceDir.absoluteFilePath("subfolder3/BaseFile.txt");
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "basefilez.arc2", "basefileaz.azm2", "basefile.arc2", "basefile.azm2" }));
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "basefilez.arc2", "basefileaz.azm2",
|
||||
"basefile.arc2", "basefile.azm2" }));
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestWithProducts, GetRelativeProductPathFromFullSourceOrProductPath_RelativePathToSourceFile_BadCasing_ReturnsProductFilePath)
|
||||
@@ -533,9 +540,9 @@ namespace AssetProcessor
|
||||
// ----- Test the ProcessGetFullAssetPath function on product files
|
||||
{
|
||||
QStringList pcouts;
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc/") + m_data->m_gameName + "/subfolder3/randomfileoutput.random"));
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc/") + m_data->m_gameName + "/subfolder3/randomfileoutput.random1"));
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc/") + m_data->m_gameName + "/subfolder3/randomfileoutput.random2"));
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc") + "/subfolder3/randomfileoutput.random"));
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc") + "/subfolder3/randomfileoutput.random1"));
|
||||
pcouts.push_back(m_data->m_cacheRootDir.filePath(QString("pc") + "/subfolder3/randomfileoutput.random2"));
|
||||
|
||||
AZ::s64 jobId;
|
||||
ASSERT_TRUE(AddSourceAndJob("subfolder3", "somerandomfile.random", &(m_data->m_dbConn), jobId));
|
||||
@@ -591,32 +598,32 @@ namespace AssetProcessor
|
||||
QString fileToCheck = "@somerandomalias@/subfolder3/randomfileoutput.random1";
|
||||
EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, m_data->m_temporarySourceDir, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AssetCatalogTest_GetFullSourcePath, InvalidAliasMissingSeperator_ReturnsAbsolutePathToSource)
|
||||
{
|
||||
//feed it a path with some random alias and asset id but no separator
|
||||
QString fileToCheck = "@somerandomalias@subfolder3/randomfileoutput.random1";
|
||||
EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, m_data->m_temporarySourceDir, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AssetCatalogTest_GetFullSourcePath, InvalidSourcePathContainingCacheAlias_ReturnsAbsolutePathToSource)
|
||||
{
|
||||
//feed it a path with alias and input name
|
||||
QString fileToCheck = "@assets@/somerandomfile.random";
|
||||
EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, m_data->m_temporarySourceDir, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AssetCatalogTest_GetFullSourcePath, AbsolutePathToCache_ReturnsAbsolutePathToSource)
|
||||
{
|
||||
//feed it an absolute path with cacheroot
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath("pc/" + m_data->m_gameName.toLower() + "/subfolder3/randomfileoutput.random1");
|
||||
QString fileToCheck = m_data->m_cacheRootDir.filePath(QString("pc") + "/subfolder3/randomfileoutput.random1");
|
||||
EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, m_data->m_temporarySourceDir, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(AssetCatalogTest_GetFullSourcePath, ProductNameIncludingPlatformAndGameName_ReturnsAbsolutePathToSource)
|
||||
{
|
||||
//feed it a productName directly
|
||||
QString fileToCheck = "pc/" + m_data->m_gameName + "/subfolder3/randomfileoutput.random1";
|
||||
QString fileToCheck = QString("pc") + "/subfolder3/randomfileoutput.random1";
|
||||
EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, m_data->m_temporarySourceDir, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
@@ -624,7 +631,7 @@ namespace AssetProcessor
|
||||
: public AssetCatalogTest
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
struct AssetCatalogTest_AssetInfo_DataMembers
|
||||
{
|
||||
AssetId m_assetA = AssetId(Uuid::CreateRandom(), 0);
|
||||
@@ -650,7 +657,7 @@ namespace AssetProcessor
|
||||
|
||||
AzFramework::StringFunc::Path::Join(m_customDataMembers->m_subfolder1AbsolutePath.c_str(), m_customDataMembers->m_assetASourceRelPath.c_str(), m_customDataMembers->m_assetAFullPath);
|
||||
CreateDummyFile(QString::fromUtf8(m_customDataMembers->m_assetAFullPath.c_str()), m_customDataMembers->m_assetTestString.c_str());
|
||||
|
||||
|
||||
AzFramework::StringFunc::Path::Join(m_data->m_cacheRootDir.absolutePath().toUtf8().constData(), m_customDataMembers->m_assetAProductRelPath.c_str(), m_customDataMembers->m_assetAProductFullPath);
|
||||
CreateDummyFile(QString::fromUtf8(m_customDataMembers->m_assetAProductFullPath.c_str()), m_customDataMembers->m_productTestString.c_str());
|
||||
}
|
||||
@@ -724,7 +731,7 @@ namespace AssetProcessor
|
||||
return true;
|
||||
};
|
||||
|
||||
void TearDown() override
|
||||
void TearDown() override
|
||||
{
|
||||
azdestroy(m_customDataMembers);
|
||||
AssetCatalogTest::TearDown();
|
||||
@@ -848,7 +855,7 @@ namespace AssetProcessor
|
||||
using namespace AzFramework::AssetSystem;
|
||||
|
||||
PlatformConfiguration config;
|
||||
|
||||
|
||||
config.EnablePlatform(AssetBuilderSDK::PlatformInfo("pc", { "test" }));
|
||||
|
||||
{
|
||||
@@ -1060,7 +1067,7 @@ namespace AssetProcessor
|
||||
productDependency.m_dependencySourceGuid = m_sourceFileWithDifferentProductsPerPlatform;
|
||||
productDependency.m_unresolvedPath = AZStd::string();
|
||||
|
||||
QString platformGameDir = QDir(cacheRoot.absoluteFilePath(productDependency.m_platform.c_str())).filePath(AssetUtilities::ComputeGameName().toLower());
|
||||
QString platformGameDir = QDir(cacheRoot.absoluteFilePath(productDependency.m_platform.c_str())).filePath(AssetUtilities::ComputeProjectName().toLower());
|
||||
QString assetCatalogFile = QDir(platformGameDir).filePath("assetcatalog.xml");
|
||||
QFileInfo fileInfo(assetCatalogFile);
|
||||
|
||||
@@ -1071,7 +1078,7 @@ namespace AssetProcessor
|
||||
// process all events
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents);
|
||||
|
||||
// This ensures that no save catalog event was queued when we resolve dependency
|
||||
// This ensures that no save catalog event was queued when we resolve dependency
|
||||
EXPECT_FALSE(fileInfo.exists());
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace AssetProcessorMessagesTests
|
||||
m_batchApplicationManager->BeforeRun();
|
||||
|
||||
// Override Game Name to be "SamplesProject"
|
||||
AssetUtilities::ComputeGameName("SamplesProject", true);
|
||||
AssetUtilities::ComputeProjectName("SamplesProject", true);
|
||||
|
||||
m_batchApplicationManager->m_platformConfiguration = new PlatformConfiguration();
|
||||
m_batchApplicationManager->InitAssetProcessorManager();
|
||||
@@ -144,7 +144,7 @@ namespace AssetProcessorMessagesTests
|
||||
RunNetworkRequest([]()
|
||||
{
|
||||
AZStd::string appBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForAppRoot, appBranchToken);
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForEngineRoot, appBranchToken);
|
||||
|
||||
AzFramework::AssetSystem::ConnectionSettings connectionSettings;
|
||||
connectionSettings.m_assetProcessorIp = "127.0.0.1";
|
||||
|
||||
@@ -181,9 +181,11 @@ namespace UnitTests
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/file.foo")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/File.bar")));
|
||||
|
||||
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr); // The API requires the old instance to be destroyed first
|
||||
AZ::IO::FileIOBase::SetInstance(new AZ::IO::LocalFileIO());
|
||||
if (AZ::IO::FileIOBase::GetInstance() == nullptr)
|
||||
{
|
||||
m_localFileIo = AZStd::make_unique<AZ::IO::LocalFileIO>();
|
||||
AZ::IO::FileIOBase::SetInstance(m_localFileIo.get());
|
||||
}
|
||||
|
||||
m_data->m_reporter = AZStd::make_unique<SourceFileRelocator>(m_data->m_connection, &m_data->m_platformConfig);
|
||||
|
||||
@@ -204,6 +206,12 @@ namespace UnitTests
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (AZ::IO::FileIOBase::GetInstance() == m_localFileIo.get())
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr);
|
||||
}
|
||||
m_localFileIo.reset();
|
||||
|
||||
AZ::JobContext::SetGlobalContext(nullptr);
|
||||
delete m_data->m_jobContext;
|
||||
delete m_data->m_jobManager;
|
||||
@@ -405,6 +413,7 @@ namespace UnitTests
|
||||
// we store the above data in a unique_ptr so that its memory can be cleared during TearDown() in one call, before we destroy the memory
|
||||
// allocator, reducing the chance of missing or forgetting to destroy one in the future.
|
||||
AZStd::unique_ptr<StaticData> m_data;
|
||||
AZStd::unique_ptr<AZ::IO::LocalFileIO> m_localFileIo;
|
||||
};
|
||||
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_SingleFile_Succeeds)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "AssetProcessorManagerTest.h"
|
||||
#include "native/AssetManager/PathDependencyManager.h"
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzToolsFramework/ToolsFileUtils/ToolsFileUtils.h>
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
@@ -41,7 +42,7 @@ public:
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDifferentTypes_BasicTest);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse_BasicTest);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_MissingFiles_ReturnsNoPathWithPlaceholders);
|
||||
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_BeforeComputingDirtiness_AllDirty);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_EmptyDatabase_AllDirty);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_SameAsLastTime_NoneDirty);
|
||||
@@ -206,6 +207,12 @@ void AssetProcessorManagerTest::SetUp()
|
||||
m_scopeDir->Setup(m_tempDir.path());
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto registry = AZ::SettingsRegistry::Get();
|
||||
auto cacheRootKey =
|
||||
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_cache_path";
|
||||
registry->Set(cacheRootKey, tempPath.absoluteFilePath("Cache").toUtf8().constData());
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
|
||||
|
||||
m_data->m_databaseLocationListener.BusConnect();
|
||||
|
||||
// in other unit tests we may open the database called ":memory:" to use an in-memory database instead of one on disk.
|
||||
@@ -220,7 +227,7 @@ void AssetProcessorManagerTest::SetUp()
|
||||
SetArgReferee<0>(m_data->m_databaseLocation),
|
||||
Return(true)));
|
||||
|
||||
m_gameName = AssetUtilities::ComputeGameName("SamplesProject", true);
|
||||
m_gameName = AssetUtilities::ComputeProjectName("SamplesProject", true);
|
||||
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
QDir newRoot;
|
||||
@@ -230,7 +237,6 @@ void AssetProcessorManagerTest::SetUp()
|
||||
AssetUtilities::ComputeProjectCacheRoot(cacheRoot);
|
||||
QString normalizedCacheRoot = AssetUtilities::NormalizeDirectoryPath(cacheRoot.absolutePath());
|
||||
|
||||
QString normalizedDirPathCheck = AssetUtilities::NormalizeDirectoryPath(QDir::current().absoluteFilePath("Cache/" + m_gameName));
|
||||
m_normalizedCacheRootDir.setPath(normalizedCacheRoot);
|
||||
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/assetProcessorManagerTest.txt"));
|
||||
@@ -357,7 +363,7 @@ TEST_F(AssetProcessorManagerTest, UnitTestForGettingJobInfoBySourceUUIDSuccess)
|
||||
TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToDatabase)
|
||||
{
|
||||
// This tests the JobDiagnosticTracker: Warnings/errors reported to it should be recorded in the database when AssetProcessed is fired and able to be retrieved when querying job status
|
||||
|
||||
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
@@ -471,7 +477,7 @@ TEST_F(AssetProcessorManagerTest, UnitTestForOutPutPrefix)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
m_isIdling = false;
|
||||
// tell the APM about the files:
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, tempPath.absoluteFilePath("subfolder2/test.txt")));
|
||||
@@ -626,10 +632,10 @@ TEST_F(AssetProcessorManagerTest, BuilderDirtiness_EmptyDatabase_AllDirty)
|
||||
|
||||
MockBuilderResponder mockBuilderResponder;
|
||||
mockBuilderResponder.BusConnect();
|
||||
|
||||
|
||||
mockBuilderResponder.AddBuilder("builder1", { AssetBuilderSDK::AssetBuilderPattern("*.egg", AssetBuilderPattern::Wildcard) }, AZ::Uuid::CreateRandom(), 1, "fingerprint1");
|
||||
mockBuilderResponder.AddBuilder("builder2", { AssetBuilderSDK::AssetBuilderPattern("*.foo", AssetBuilderPattern::Wildcard) }, AZ::Uuid::CreateRandom(), 1, "fingerprint2");
|
||||
|
||||
|
||||
m_assetProcessorManager->ComputeBuilderDirty();
|
||||
|
||||
EXPECT_TRUE(m_assetProcessorManager->m_anyBuilderChange);
|
||||
@@ -666,7 +672,7 @@ TEST_F(AssetProcessorManagerTest, BuilderDirtiness_SameAsLastTime_NoneDirty)
|
||||
mockBuilderResponder.BusDisconnect();
|
||||
}
|
||||
|
||||
// when a new builder appears, the new builder should be dirty,
|
||||
// when a new builder appears, the new builder should be dirty,
|
||||
TEST_F(AssetProcessorManagerTest, BuilderDirtiness_MoreThanLastTime_NewOneIsDirty)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
@@ -677,13 +683,13 @@ TEST_F(AssetProcessorManagerTest, BuilderDirtiness_MoreThanLastTime_NewOneIsDirt
|
||||
mockBuilderResponder.BusConnect();
|
||||
|
||||
mockBuilderResponder.AddBuilder("builder1", { AssetBuilderSDK::AssetBuilderPattern("*.egg", AssetBuilderPattern::Wildcard) }, AZ::Uuid::CreateRandom(), 1, "fingerprint1");
|
||||
|
||||
|
||||
m_assetProcessorManager->ComputeBuilderDirty();
|
||||
|
||||
mockBuilderResponder.AddBuilder("builder2", { AssetBuilderSDK::AssetBuilderPattern("*.foo", AssetBuilderPattern::Wildcard) }, AZ::Uuid::CreateRandom(), 1, "fingerprint2");
|
||||
|
||||
m_assetProcessorManager->ComputeBuilderDirty();
|
||||
|
||||
|
||||
// one new builder should have been dirty:
|
||||
EXPECT_TRUE(m_assetProcessorManager->m_anyBuilderChange);
|
||||
EXPECT_TRUE(m_assetProcessorManager->m_buildersAddedOrRemoved);
|
||||
@@ -892,7 +898,7 @@ TEST_F(AssetProcessorManagerTest, BuilderDirtiness_NewAnalysisFingerprint_IsNotA
|
||||
TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_BasicTest)
|
||||
{
|
||||
using SourceFileDependencyEntry = AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
|
||||
|
||||
|
||||
// A depends on B, which depends on both C and D
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
@@ -941,7 +947,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_BasicTe
|
||||
|
||||
dependencies.clear();
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("b.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, false);
|
||||
EXPECT_EQ(dependencies.size(), 3); // b depends on c, and d
|
||||
EXPECT_EQ(dependencies.size(), 3); // b depends on c, and d
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/b.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/c.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/d.txt").toUtf8().constData()), dependencies.end());
|
||||
@@ -961,7 +967,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDif
|
||||
{
|
||||
// test to make sure that different TYPES of dependencies work as expected.
|
||||
using SourceFileDependencyEntry = AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
|
||||
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/a.txt"), QString("tempdata\n"));
|
||||
@@ -998,7 +1004,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDif
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("a.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, false);
|
||||
// note that a depends on b, c, and d - with the latter two being indirect.
|
||||
// however, since b's dependency on C is via JOB, and we're asking for SOURCE only, we should not see C.
|
||||
EXPECT_EQ(dependencies.size(), 3);
|
||||
EXPECT_EQ(dependencies.size(), 3);
|
||||
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/a.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/b.txt").toUtf8().constData()), dependencies.end());
|
||||
@@ -1007,7 +1013,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDif
|
||||
dependencies.clear();
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("b.txt", dependencies, SourceFileDependencyEntry::DEP_JobToJob, false);
|
||||
// b depends on c, and d - but we're asking for job dependencies only, so we should not get anything except C and B
|
||||
EXPECT_EQ(dependencies.size(), 2);
|
||||
EXPECT_EQ(dependencies.size(), 2);
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/b.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/c.txt").toUtf8().constData()), dependencies.end());
|
||||
|
||||
@@ -1063,13 +1069,13 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse
|
||||
AssetProcessor::SourceFilesForFingerprintingContainer dependencies;
|
||||
// sanity: what Depends on a? the only result should be a itself.
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("a.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, true /*reverse*/);
|
||||
EXPECT_EQ(dependencies.size(), 1);
|
||||
EXPECT_EQ(dependencies.size(), 1);
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/a.txt").toUtf8().constData()), dependencies.end());
|
||||
|
||||
dependencies.clear();
|
||||
// what depends on d? b and a should (indirectly)
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("d.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, true);
|
||||
EXPECT_EQ(dependencies.size(), 3);
|
||||
EXPECT_EQ(dependencies.size(), 3);
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/a.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/b.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/d.txt").toUtf8().constData()), dependencies.end());
|
||||
@@ -1077,7 +1083,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse
|
||||
// what depends on c? b and a should.
|
||||
dependencies.clear();
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("c.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, true);
|
||||
EXPECT_EQ(dependencies.size(), 3); // b depends on c, and d
|
||||
EXPECT_EQ(dependencies.size(), 3); // b depends on c, and d
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/c.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/b.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/a.txt").toUtf8().constData()), dependencies.end());
|
||||
@@ -1092,7 +1098,7 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/c.txt").toUtf8().constData()), dependencies.end());
|
||||
}
|
||||
|
||||
// since we need these files to still produce a 0-based fingerprint, we need them to
|
||||
// since we need these files to still produce a 0-based fingerprint, we need them to
|
||||
// still do a best guess at absolute path, when they are missing.
|
||||
TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_MissingFiles_ReturnsNoPathWithPlaceholders)
|
||||
{
|
||||
@@ -1131,13 +1137,13 @@ TEST_F(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Missing
|
||||
AssetProcessor::SourceFilesForFingerprintingContainer dependencies;
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("a.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, false);
|
||||
EXPECT_EQ(dependencies.size(), 2); // a depends on b, c, and d - with the latter two being indirect.
|
||||
|
||||
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/a.txt").toUtf8().constData()), dependencies.end());
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/d.txt").toUtf8().constData()), dependencies.end());
|
||||
|
||||
dependencies.clear();
|
||||
m_assetProcessorManager->QueryAbsolutePathDependenciesRecursive("b.txt", dependencies, SourceFileDependencyEntry::DEP_SourceToSource, false);
|
||||
EXPECT_EQ(dependencies.size(), 1); // b depends on c, and d
|
||||
EXPECT_EQ(dependencies.size(), 1); // b depends on c, and d
|
||||
EXPECT_NE(dependencies.find(tempPath.absoluteFilePath("subfolder1/d.txt").toUtf8().constData()), dependencies.end());
|
||||
|
||||
// eliminate b --> c
|
||||
@@ -1161,7 +1167,7 @@ TEST_F(AssetProcessorManagerTest, BuilderSDK_API_CreateJobs_HasValidParameters_W
|
||||
|
||||
m_isIdling = false;
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absPath));
|
||||
|
||||
|
||||
// wait for AP to become idle.
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
@@ -1189,10 +1195,10 @@ TEST_F(AssetProcessorManagerTest, BuilderSDK_API_CreateJobs_HasValidParameters_W
|
||||
UnitTestUtils::CreateDummyFile(absPath);
|
||||
|
||||
m_mockApplicationManager->ResetMockBuilderCreateJobCalls();
|
||||
|
||||
|
||||
m_isIdling = false;
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absPath));
|
||||
|
||||
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
ASSERT_EQ(m_mockApplicationManager->GetMockBuilderCreateJobCalls(), 1);
|
||||
@@ -1461,14 +1467,14 @@ bool PathDependencyTest::ProcessAsset(TestAsset& asset, const OutputAssetSet& ou
|
||||
{
|
||||
ProcessJobResponse processJobResponse;
|
||||
processJobResponse.m_resultCode = ProcessJobResult_Success;
|
||||
|
||||
|
||||
for (const char* outputExtension : outputSet)
|
||||
{
|
||||
if(jobSet >= capturedDetails.size() || capturedDetails[jobSet].m_destinationPath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QString outputAssetPath = QDir(capturedDetails[jobSet].m_destinationPath).absoluteFilePath(QString(asset.m_name.c_str()) + outputExtension);
|
||||
|
||||
UnitTestUtils::CreateDummyFile(outputAssetPath, "this is a test output asset");
|
||||
@@ -1508,7 +1514,7 @@ bool SearchDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDataba
|
||||
void VerifyDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer, AZStd::initializer_list<AZ::Data::AssetId> assetIds, AZStd::initializer_list<const char*> unresolvedPaths = {})
|
||||
{
|
||||
EXPECT_EQ(dependencyContainer.size(), assetIds.size() + unresolvedPaths.size());
|
||||
|
||||
|
||||
for (const AZ::Data::AssetId& assetId : assetIds)
|
||||
{
|
||||
bool found = false;
|
||||
@@ -1635,19 +1641,19 @@ TEST_F(PathDependencyTest, NoLongerProcessedFile_IsRemoved)
|
||||
{
|
||||
details = message;
|
||||
});
|
||||
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
QString absPath(tempPath.absoluteFilePath("subfolder1/test1.txt"));
|
||||
|
||||
TestAsset testAsset("test1");
|
||||
|
||||
|
||||
ASSERT_TRUE(ProcessAsset(testAsset, { {".asset1"} }));
|
||||
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer products;
|
||||
m_sharedConnection->GetProductsBySourceName("test1.txt", products);
|
||||
|
||||
ASSERT_EQ(products.size(), 1);
|
||||
ASSERT_TRUE(QFile::exists(m_normalizedCacheRootDir.absoluteFilePath("pc/samplesproject/test1.asset1").toUtf8().constData()));
|
||||
ASSERT_TRUE(QFile::exists(m_normalizedCacheRootDir.absoluteFilePath("pc/test1.asset1").toUtf8().constData()));
|
||||
|
||||
m_mockApplicationManager->UnRegisterAllBuilders();
|
||||
|
||||
@@ -1723,15 +1729,15 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_DeferredPathResolution)
|
||||
AZStd::vector<TestAsset> dependencySources = { "dep1", "dep2" };
|
||||
// Start with mixed casing.
|
||||
ProductPathDependencySet dependencies = { {"Dep1.txt", AssetBuilderSDK::ProductPathDependencyType::SourceFile}, {"DEP2.asset2", AssetBuilderSDK::ProductPathDependencyType::ProductFile}, {"dep2.asset3", AssetBuilderSDK::ProductPathDependencyType::ProductFile} }; // Test depending on a source asset, and on a subset of product assets
|
||||
|
||||
|
||||
TestAsset mainFile("test_text");
|
||||
ASSERT_TRUE(ProcessAsset(mainFile, { { ".asset" }, {} }, dependencies));
|
||||
|
||||
|
||||
// ---------- Verify that we have unresolved path in ProductDependencies table ----------
|
||||
AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer;
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
ASSERT_EQ(dependencyContainer.size(), dependencies.size());
|
||||
|
||||
|
||||
// All dependencies are stored lowercase in the database. Make the expected dependencies lowercase here to match that.
|
||||
for(auto& dependency : dependencies)
|
||||
{
|
||||
@@ -1752,12 +1758,12 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_DeferredPathResolution)
|
||||
{
|
||||
ASSERT_TRUE(ProcessAsset(dependency, { { ".asset1", ".asset2" }, { ".asset3" } }, {}));
|
||||
}
|
||||
|
||||
|
||||
// ---------- Verify that path has been found and resolved ----------
|
||||
dependencyContainer.clear();
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
|
||||
VerifyDependencies(dependencyContainer,
|
||||
VerifyDependencies(dependencyContainer,
|
||||
{
|
||||
dependencySources[0].m_products[0],
|
||||
dependencySources[0].m_products[1],
|
||||
@@ -1780,19 +1786,19 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_DeferredPathResolutionAlreadyReso
|
||||
// create dependees
|
||||
TestAsset dep1("dep1");
|
||||
TestAsset dep2("deP2"); // random casing to make sure the search is case-insensitive
|
||||
|
||||
|
||||
ASSERT_TRUE(ProcessAsset(dep1, { {".asset1"}, {".asset2"} }));
|
||||
ASSERT_TRUE(ProcessAsset(dep2, { {".asset1", ".asset2"}, {".asset3"} }));
|
||||
|
||||
|
||||
// -------- Make main test asset, with dependencies on products we just created -----
|
||||
TestAsset primaryFile("test_text");
|
||||
ASSERT_TRUE(ProcessAsset(primaryFile, { { ".asset" }, {} }, { {"dep1.txt", ProductPathDependencyType::SourceFile}, {"DEP2.asset2", ProductPathDependencyType::ProductFile}, {"Dep2.asset3", ProductPathDependencyType::ProductFile} }));
|
||||
|
||||
|
||||
// ---------- Verify that the dependency was recorded, and did not keep the path after resolution ----------
|
||||
AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer;
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
|
||||
VerifyDependencies(dependencyContainer,
|
||||
VerifyDependencies(dependencyContainer,
|
||||
{
|
||||
dep1.m_products[0],
|
||||
dep1.m_products[1],
|
||||
@@ -1887,13 +1893,13 @@ TEST_F(PathDependencyTest, WildcardDependencies_Existing_ResolveCorrectly)
|
||||
|
||||
bool result = ProcessAsset(dep1, { {".asset1"}, {".asset2"} });
|
||||
ASSERT_TRUE(result) << "Failed to Process Assets";
|
||||
|
||||
|
||||
result = ProcessAsset(dep2, { {".asset1", ".asset2"}, {".asset3"} });
|
||||
ASSERT_TRUE(result) << "Failed to Process Assets";
|
||||
|
||||
|
||||
result = ProcessAsset(dep3, { {".asset1", ".asset2"}, {".asset3"} });
|
||||
ASSERT_TRUE(result) << "Failed to Process Assets";
|
||||
|
||||
|
||||
result = ProcessAsset(dep4, { {".asset1"}, {".asset3"} }); // This product will match on both dependencies, this will check to make sure we don't get duplicates
|
||||
ASSERT_TRUE(result) << "Failed to Process Assets";
|
||||
|
||||
@@ -1906,7 +1912,7 @@ TEST_F(PathDependencyTest, WildcardDependencies_Existing_ResolveCorrectly)
|
||||
AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer;
|
||||
result = m_sharedConnection->GetProductDependencies(dependencyContainer);
|
||||
ASSERT_TRUE(result)<< "Failed to Get Product Dependencies";
|
||||
|
||||
|
||||
VerifyDependencies(dependencyContainer,
|
||||
{
|
||||
dep1.m_products[0],
|
||||
@@ -2054,14 +2060,14 @@ TEST_F(PathDependencyTest, WildcardDependencies_Deferred_ResolveCorrectly)
|
||||
AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer;
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
|
||||
VerifyDependencies(dependencyContainer,
|
||||
VerifyDependencies(dependencyContainer,
|
||||
{
|
||||
dep1.m_products[0],
|
||||
dep1.m_products[1],
|
||||
dep2.m_products[2],
|
||||
dep3.m_products[2],
|
||||
dep4.m_products[0]
|
||||
},
|
||||
},
|
||||
{ "*p1.txt", "*.asset3" }
|
||||
);
|
||||
}
|
||||
@@ -2204,14 +2210,14 @@ void PathDependencyTest::RunWildcardTest(bool useCorrectDatabaseSeparator, Asset
|
||||
ASSERT_TRUE(ProcessAsset(matchingDepDeeperFolderMixedSlashes, { {".asset"}, {} })) << "Failed to Process " << matchingDepDeeperFolderMixedSlashes.m_name.c_str();
|
||||
ASSERT_TRUE(ProcessAsset(notMatchingDepInSubfolder, { {".asset"}, {} })) << "Failed to Process " << notMatchingDepInSubfolder.m_name.c_str();
|
||||
}
|
||||
|
||||
|
||||
// -------- Make main test asset, with dependencies on products we just created -----
|
||||
TestAsset primaryFile("test_text");
|
||||
const char* databaseSeparator = useCorrectDatabaseSeparator ? AZ_CORRECT_DATABASE_SEPARATOR_STRING : AZ_WRONG_DATABASE_SEPARATOR_STRING;
|
||||
|
||||
|
||||
AZStd::string extension = (pathDependencyType == ProductPathDependencyType::SourceFile) ? "txt" : "asset";
|
||||
AZStd::string wildcardString = AZStd::string::format("*testFolder%s*.%s", databaseSeparator, extension.c_str());
|
||||
|
||||
|
||||
ASSERT_TRUE(ProcessAsset(primaryFile, { { ".asset" }, {} }, { {wildcardString.c_str(), pathDependencyType}, })) << "Failed to Process " << primaryFile.m_name.c_str();
|
||||
|
||||
if (!buildDependenciesFirst)
|
||||
@@ -2354,7 +2360,7 @@ TEST_F(PathDependencyTest, AbsoluteDependencies_Deferred_ResolveCorrectly)
|
||||
// -------- Make main test asset, with dependencies on products that don't exist yet -----
|
||||
TestAsset primaryFile("test_text");
|
||||
ASSERT_TRUE(ProcessAsset(primaryFile, { { ".asset" }, {} },
|
||||
{
|
||||
{
|
||||
{absPathDep1.toUtf8().constData(), ProductPathDependencyType::SourceFile},
|
||||
{absPathDep2.toUtf8().constData(), ProductPathDependencyType::SourceFile},
|
||||
{absPathDep3.toUtf8().constData(), ProductPathDependencyType::SourceFile},
|
||||
@@ -2418,7 +2424,7 @@ TEST_F(PathDependencyTest, ChangeDependencies_Existing_ResolveCorrectly)
|
||||
|
||||
// Update again with different dependencies
|
||||
ASSERT_TRUE(ProcessAsset(primaryFile, { {".asset"} , {} }, { {absPath.toUtf8().constData(), ProductPathDependencyType::SourceFile} }));
|
||||
|
||||
|
||||
// ---------- Verify that the dependency was recorded, and did not keep the path after resolution ----------
|
||||
dependencyContainer.clear();
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
@@ -2582,7 +2588,7 @@ TEST_F(PathDependencyTest, SourceFileDependencyWithPrefix_Deferred_ResolvesCorre
|
||||
AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer;
|
||||
ASSERT_TRUE(m_sharedConnection->GetProductDependencies(dependencyContainer));
|
||||
|
||||
VerifyDependencies(dependencyContainer,
|
||||
VerifyDependencies(dependencyContainer,
|
||||
{
|
||||
dep2.m_products[0],
|
||||
dep2.m_products[1],
|
||||
@@ -2834,7 +2840,7 @@ TEST_F(AssetProcessorManagerTest, AssetProcessedImpl_DifferentProductDependencie
|
||||
// and correctly stored the results into the dependency table.
|
||||
|
||||
//-------------------------------- EVALUATION PHASE -------------------------
|
||||
// at this point, the AP will have filed the asset away in its database and we can now validate that it actually
|
||||
// at this point, the AP will have filed the asset away in its database and we can now validate that it actually
|
||||
// did it correctly.
|
||||
// We expect to see two dependencies in the dependency table, each with the correct dependency, no duplicates, no lost data.
|
||||
AssetDatabaseConnection* sharedConnection = m_assetProcessorManager->m_stateData.get();
|
||||
@@ -2856,7 +2862,7 @@ TEST_F(AssetProcessorManagerTest, AssetProcessedImpl_DifferentProductDependencie
|
||||
// this also asserts uniqueness.
|
||||
ASSERT_EQ(countFound, 2);
|
||||
ASSERT_EQ(capturedTableEntries.size(), countFound); // if they were not unique asset IDs, they would have collapsed on top of each other.
|
||||
|
||||
|
||||
// make sure both assetIds are present:
|
||||
ASSERT_NE(capturedTableEntries.find(expectedIdOfProductA), capturedTableEntries.end());
|
||||
ASSERT_NE(capturedTableEntries.find(expectedIdOfProductB), capturedTableEntries.end());
|
||||
@@ -2927,7 +2933,7 @@ TEST_F(AssetProcessorManagerTest, AssessDeletedFile_OnJobInFlight_IsIgnored)
|
||||
m_isIdling = false;
|
||||
m_assetProcessorManager->AssetProcessed(capturedDetails.m_jobEntry, response);
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
|
||||
// at this point, everything should be up to date and ready for the test - there should be one source in the database
|
||||
// with numOutputsToSimulate products.
|
||||
// now, we simulate a job running to process the asset again, by modifying the timestamp on the file to be at least one second later.
|
||||
@@ -2959,7 +2965,7 @@ TEST_F(AssetProcessorManagerTest, AssessDeletedFile_OnJobInFlight_IsIgnored)
|
||||
ASSERT_FALSE(capturedDetails.m_destinationPath.isEmpty());
|
||||
// ----------------------------- TEST BEGINS HERE -----------------------------
|
||||
// simulte a very slow computer processing the file one output at a time and feeding file change notifies:
|
||||
|
||||
|
||||
// FROM THIS POINT ON we should see no new job create / cancellation or anything since we're just going to be messing with the cache.
|
||||
bool gotUnexpectedAssetToProcess = false;
|
||||
connection = QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::AssetToProcess, [&gotUnexpectedAssetToProcess](JobDetails /*jobDetails*/)
|
||||
@@ -2994,7 +3000,7 @@ TEST_F(AssetProcessorManagerTest, AssessDeletedFile_OnJobInFlight_IsIgnored)
|
||||
|
||||
QString fileNameToGenerate = QString("test%1.txt").arg(outputIdx);
|
||||
QString filePathToGenerate = QDir(capturedDetails.m_destinationPath).absoluteFilePath(fileNameToGenerate);
|
||||
|
||||
|
||||
JobProduct product(filePathToGenerate.toUtf8().constData(), AZ::Uuid::CreateRandom(), static_cast<AZ::u32>(outputIdx));
|
||||
response.m_outputProducts.push_back(product);
|
||||
|
||||
@@ -3005,7 +3011,7 @@ TEST_F(AssetProcessorManagerTest, AssessDeletedFile_OnJobInFlight_IsIgnored)
|
||||
// simulate the file watcher showing the deletion occuring:
|
||||
notifyAPM("AssessDeletedFile", filePathToGenerate, shouldBlockAndWaitThisTime);
|
||||
UnitTestUtils::CreateDummyFile(filePathToGenerate, "an output");
|
||||
|
||||
|
||||
// let the APM go for a significant amount of time so that it simulates a slow thread copying a large file with lots of events about it pouring in.
|
||||
for (int repeatLoop = 0; repeatLoop < 100; ++repeatLoop)
|
||||
{
|
||||
@@ -3020,7 +3026,7 @@ TEST_F(AssetProcessorManagerTest, AssessDeletedFile_OnJobInFlight_IsIgnored)
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, QString(filePathToGenerate)));
|
||||
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents, 1);
|
||||
ASSERT_FALSE(gotUnexpectedAssetToProcess);
|
||||
|
||||
|
||||
// now tell it to stop ignoring the cache delete and let it do the next one.
|
||||
EBUS_EVENT(AssetProcessor::ProcessingJobInfoBus, EndCacheFileUpdate, filePathToGenerate.toUtf8().data(), false);
|
||||
|
||||
@@ -3075,7 +3081,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_BasicTest
|
||||
// each file we will take a different approach to publishing: rel path, and UUID:
|
||||
job.m_sourceFileDependencies.push_back(AZStd::make_pair<AZ::Uuid, AssetBuilderSDK::SourceFileDependency>(dummyBuilderUUID, { "a.txt", AZ::Uuid::CreateNull() }));
|
||||
job.m_sourceFileDependencies.push_back(AZStd::make_pair<AZ::Uuid, AssetBuilderSDK::SourceFileDependency>(dummyBuilderUUID, { "", uuidOfB }));
|
||||
|
||||
|
||||
// it is currently assumed that the only fields that we care about in JobDetails is the builder busId and the job dependencies themselves:
|
||||
JobDetails newDetails;
|
||||
newDetails.m_assetBuilderDesc.m_busId = dummyBuilderUUID;
|
||||
@@ -3267,7 +3273,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFi
|
||||
// this indirectly verifies the QueryAbsolutePathDependenciesRecursive function also but it has its own dedicated tests, above.
|
||||
AssetProcessor::SourceFilesForFingerprintingContainer deps;
|
||||
m_assetProcessorManager.get()->QueryAbsolutePathDependenciesRecursive(QString::fromUtf8("assetProcessorManagerTest.txt"), deps, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceToSource, false);
|
||||
|
||||
|
||||
// we should find all of the deps, but not the placeholders.
|
||||
|
||||
EXPECT_EQ(deps.size(), 2);
|
||||
@@ -3453,7 +3459,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFi
|
||||
EXPECT_EQ(deps.size(), 2);
|
||||
EXPECT_NE(deps.find(absPath.toUtf8().constData()), deps.end());
|
||||
EXPECT_NE(deps.find(dependsOnFile1_Job.toUtf8().constData()), deps.end()); // c
|
||||
|
||||
|
||||
// in addition, we expect to have the original file that depends on B appear in the analysis queue, since something it depends on appeared:
|
||||
QString normalizedSourcePath = AssetUtilities::NormalizeFilePath(absPath);
|
||||
EXPECT_TRUE(m_assetProcessorManager->m_alreadyActiveFiles.contains(normalizedSourcePath));
|
||||
@@ -4407,7 +4413,7 @@ TEST_F(AssetProcessorManagerTest, SourceFileProcessFailure_ClearsFingerprint)
|
||||
|
||||
ASSERT_TRUE(found);
|
||||
ASSERT_NE(source.m_analysisFingerprint, "");
|
||||
|
||||
|
||||
// Modify the file and run it through AP again, but this time signal a failure
|
||||
|
||||
{
|
||||
@@ -4655,12 +4661,12 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesFor
|
||||
// Enable the features we're testing
|
||||
m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
|
||||
AssetUtilities::SetUseFileHashOverride(true, true);
|
||||
|
||||
|
||||
// Enable es3 platform after the initial SetUp has already processed the files for pc
|
||||
QDir tempPath(m_tempDir.path());
|
||||
AssetBuilderSDK::PlatformInfo es3Platform("es3", { "host", "renderer" });
|
||||
m_config->EnablePlatform(es3Platform, true);
|
||||
|
||||
|
||||
// There's no way to remove scanfolders and adding a new one after enabling the platform will cause the pc assets to build as well, which we don't want
|
||||
// Instead we'll just const cast the vector and modify the enabled platforms for the scanfolder
|
||||
auto& platforms = const_cast<AZStd::vector<AssetBuilderSDK::PlatformInfo>&>(m_config->GetScanFolderAt(0).GetPlatforms());
|
||||
@@ -4743,7 +4749,7 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
|
||||
SetFileContents(m_data->m_absolutePath[1].toUtf8().constData(), "hello world");
|
||||
|
||||
|
||||
// Enable the features we're testing
|
||||
m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
|
||||
AssetUtilities::SetUseFileHashOverride(true, true);
|
||||
@@ -4861,7 +4867,7 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_DeleteFile)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
|
||||
} while (m_data->m_deletedSources.size() < m_data->m_relativePathFromWatchFolder[0].size() && timer.elapsed() < 5000);
|
||||
|
||||
|
||||
ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 0);
|
||||
ASSERT_EQ(m_data->m_processResults.size(), 0);
|
||||
ASSERT_THAT(m_data->m_deletedSources, testing::ElementsAre(m_data->m_relativePathFromWatchFolder[0]));
|
||||
@@ -4885,7 +4891,7 @@ TEST_F(ModtimeScanningTest, ReprocessRequest_SourceWithDependency_BothWillProces
|
||||
|
||||
using SourceFileDependencyEntry = AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
|
||||
|
||||
SourceFileDependencyEntry newEntry1;
|
||||
SourceFileDependencyEntry newEntry1;
|
||||
newEntry1.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
|
||||
newEntry1.m_builderGuid = AZ::Uuid::CreateRandom();
|
||||
newEntry1.m_source = m_data->m_absolutePath[0].toUtf8().constData();
|
||||
@@ -4953,7 +4959,7 @@ void MockBuilderInfoHandler::CreateJobs(const AssetBuilderSDK::CreateJobsRequest
|
||||
|
||||
if (!m_jobDependencyFilePath.isEmpty())
|
||||
{
|
||||
jobDescriptor.m_jobDependencyList.push_back(AssetBuilderSDK::JobDependency("Mock Job", "pc", AssetBuilderSDK::JobDependencyType::Order,
|
||||
jobDescriptor.m_jobDependencyList.push_back(AssetBuilderSDK::JobDependency("Mock Job", "pc", AssetBuilderSDK::JobDependencyType::Order,
|
||||
AssetBuilderSDK::SourceFileDependency(m_jobDependencyFilePath.toUtf8().constData(), AZ::Uuid::CreateNull())));
|
||||
}
|
||||
|
||||
@@ -5127,7 +5133,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_WildcardM
|
||||
m_assetProcessorManager.get()->m_stateData->QueryDependsOnSourceBySourceDependency("wildcardTest.txt", nullptr, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, callbackFunction);
|
||||
EXPECT_EQ(wildcardDeps.size(), 2);
|
||||
|
||||
// The database should have the wildcard record and the individual dependency on b and c at this point, now we add new files
|
||||
// The database should have the wildcard record and the individual dependency on b and c at this point, now we add new files
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(dependsOnFileb1_Source, QString("tempdata\n")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(dependsOnFilec1_Job, QString("tempdata\n")));
|
||||
|
||||
@@ -5307,7 +5313,7 @@ TEST_F(DuplicateProductsTest, SameSource_MultipleBuilder_DuplicateProductJobs_Em
|
||||
QDir tempPath(m_tempDir.path());
|
||||
QString sourceFile;
|
||||
AZStd::vector<JobDetails> jobDetails;
|
||||
|
||||
|
||||
ProcessJobResponse response;
|
||||
SetupDuplicateProductsTest(sourceFile, tempPath, productFile, jobDetails, response, false, "txt");
|
||||
|
||||
@@ -5397,7 +5403,7 @@ void JobDependencyTest::SetUp()
|
||||
m_data->m_mockBuilderInfoHandler.BusConnect();
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
|
||||
QString watchFolderPath = tempPath.absoluteFilePath("subfolder1");
|
||||
const ScanFolderInfo* scanFolder = m_config->GetScanFolderByPath(watchFolderPath);
|
||||
|
||||
@@ -5460,7 +5466,7 @@ TEST_F(JobDependencyTest, JobDependency_ThatWasJustRun_IsFound)
|
||||
TEST_F(JobDependencyTest, JobDependency_ThatHasNotRun_IsNotFound)
|
||||
{
|
||||
AZStd::vector<JobDetails> capturedDetails;
|
||||
|
||||
|
||||
capturedDetails.clear();
|
||||
m_data->m_mockBuilderInfoHandler.m_jobDependencyFilePath = "c.txt";
|
||||
CaptureJobs(capturedDetails, "subfolder1/b.txt");
|
||||
@@ -5654,7 +5660,7 @@ TEST_F(ChainJobDependencyTest, TestChainDependency_Multi)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
|
||||
} while (finishedJobs.size() < capturedDetails.size() && timer.elapsed() < 5000);
|
||||
|
||||
|
||||
ASSERT_EQ(finishedJobs.size(), capturedDetails.size());
|
||||
|
||||
// Test that the jobs completed in the correct order (captureDetails has the correct ordering)
|
||||
@@ -5775,7 +5781,7 @@ TEST_F(DeleteTest, DeleteFolderSharedAcrossTwoScanFolders_CorrectFileAndFolderAr
|
||||
QDir tempPath(m_tempDir.path());
|
||||
QString absPath(tempPath.absoluteFilePath("subfolder1/textures"));
|
||||
QDir(absPath).removeRecursively();
|
||||
|
||||
|
||||
AZStd::vector<AZStd::string> deletedFolders;
|
||||
QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::SourceFolderDeleted, [&deletedFolders](QString file)
|
||||
{
|
||||
|
||||
+95
-67
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
const char TestAppRoot[] = ":/testdata";
|
||||
const char TestAppRoot[] = "@exefolder@/testdata";
|
||||
const char EmptyDummyProjectName[] = "EmptyDummyProject";
|
||||
const char DummyProjectName[] = "DummyProject";
|
||||
|
||||
@@ -54,10 +54,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BadPlatform)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_broken_badplatform";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_badplatform");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
}
|
||||
|
||||
@@ -67,10 +69,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoPlatform)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_broken_noplatform";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noplatform");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
}
|
||||
|
||||
@@ -79,10 +83,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoScanFolders)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_broken_noscans";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noscans");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
}
|
||||
|
||||
@@ -91,10 +97,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BrokenRecognizers)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_broken_recognizers";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_recognizers");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
}
|
||||
|
||||
@@ -103,10 +111,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
// verify the data.
|
||||
@@ -127,42 +137,43 @@ TEST_F(PlatformConfigurationUnitTests, TestReadScanFolderRoot_FromSettingsRegist
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
ASSERT_NE(nullptr, settingsRegistry);
|
||||
|
||||
AZ::SettingsRegistryInterface::Specializations apSpecializations;
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(*settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, apSpecializations);
|
||||
|
||||
struct ScanFolderVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
QTemporaryDir tempEngineRoot;
|
||||
QDir tempPath(tempEngineRoot.path());
|
||||
QString testScanFolderSetregPath = tempPath.absoluteFilePath("test.setreg");
|
||||
UnitTestUtils::CreateDummyFile(testScanFolderSetregPath, QString(R"({ "Amazon":
|
||||
{
|
||||
void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value)
|
||||
"AssetProcessor":
|
||||
{
|
||||
if (valueName == "recursive")
|
||||
{
|
||||
m_isRecursive = value != 0;
|
||||
}
|
||||
else if (valueName == "order")
|
||||
{
|
||||
m_scanOrder = value;
|
||||
"Settings":
|
||||
{
|
||||
"ScanFolder SettingsRegistryTest":
|
||||
{
|
||||
"watch": "_TestPath",
|
||||
"recursive": false,
|
||||
"order": 20000
|
||||
}
|
||||
}
|
||||
}
|
||||
void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value)
|
||||
{
|
||||
if (valueName == "watch")
|
||||
{
|
||||
m_watchPath = value;
|
||||
}
|
||||
}
|
||||
AZ::SettingsRegistryInterface::FixedValueString m_watchPath;
|
||||
bool m_isRecursive{};
|
||||
int m_scanOrder{};
|
||||
};
|
||||
}
|
||||
}\n)"));
|
||||
|
||||
ScanFolderVisitor scanFolderVisitor;
|
||||
EXPECT_TRUE(settingsRegistry->Visit(scanFolderVisitor, "/Amazon/AssetProcessor/Settings/ScanFolder Root"));
|
||||
EXPECT_TRUE(AssetProcessor::PlatformConfiguration::MergeConfigFileToSettingsRegistry(*settingsRegistry, testScanFolderSetregPath.toUtf8().data()));
|
||||
|
||||
AZStd::string watchPath;
|
||||
bool recurseScanFolder{ true };
|
||||
AZ::s64 scanOrder{};
|
||||
|
||||
EXPECT_TRUE(settingsRegistry->Get(watchPath, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
|
||||
+ "/ScanFolder SettingsRegistryTest/watch"));
|
||||
EXPECT_TRUE(settingsRegistry->Get(recurseScanFolder, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
|
||||
+ "/ScanFolder SettingsRegistryTest/recursive"));
|
||||
EXPECT_TRUE(settingsRegistry->Get(scanOrder, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
|
||||
+ "/ScanFolder SettingsRegistryTest/order"));
|
||||
|
||||
// These test values come from the <dev_root>/Engine/Registry/AssetProcessorPlatformConfig.setreg file
|
||||
EXPECT_STREQ("@ROOT@", scanFolderVisitor.m_watchPath.c_str());
|
||||
EXPECT_FALSE(scanFolderVisitor.m_isRecursive);
|
||||
EXPECT_EQ(10000, scanFolderVisitor.m_scanOrder);
|
||||
EXPECT_STREQ("_TestPath", watchPath.c_str());
|
||||
EXPECT_FALSE(recurseScanFolder);
|
||||
EXPECT_EQ(20000, scanOrder);
|
||||
}
|
||||
|
||||
|
||||
@@ -340,34 +351,36 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
AssetUtilities::ComputeProjectName(EmptyDummyProjectName, true);
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderCount(), 3); // the two, and then the one that has the same data as prior but different identifier.
|
||||
QString scanName = AssetUtilities::ComputeGameName() + " Scan Folder";
|
||||
QString scanName = AssetUtilities::ComputeProjectPath() + " Scan Folder";
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetDisplayName(), scanName);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetOutputPrefix(), QString());
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).RecurseSubFolders(), true);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetOrder(), 0);
|
||||
// its important that this does NOT change and this makes sure the old way of doing it (case-sensitive name) persists
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetPortableKey(), QString("from-ini-file-Game"));
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetPortableKey(), QString("Game"));
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).GetDisplayName(), QString("FeatureTests"));
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).GetOutputPrefix(), QString("featuretestsoutputfolder")); // to prove its not related to display name
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).RecurseSubFolders(), false);
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).GetOrder(), 5000);
|
||||
// this proves that the featuretests name is used instead of the output prefix
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).GetPortableKey(), QString("from-ini-file-FeatureTests"));
|
||||
ASSERT_EQ(config.GetScanFolderAt(1).GetPortableKey(), QString("FeatureTests"));
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetDisplayName(), QString("FeatureTests2"));
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetOutputPrefix(), QString("featuretestsoutputfolder")); // to prove its not related to display name
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).RecurseSubFolders(), false);
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetOrder(), 6000);
|
||||
// this proves that the featuretests name is used instead of the output prefix
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetPortableKey(), QString("from-ini-file-FeatureTests2"));
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetPortableKey(), QString("FeatureTests2"));
|
||||
}
|
||||
|
||||
TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderPlatformSpecific)
|
||||
@@ -375,10 +388,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular_platform_scanfolder";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular_platform_scanfolder");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderCount(), 5);
|
||||
@@ -419,10 +434,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
ASSERT_TRUE(config.IsFileExcluded("blahblah/$tmp_01.test"));
|
||||
@@ -446,10 +463,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
|
||||
const char* platformWhichIsNotCurrentPlatform = "pc";
|
||||
#endif
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
|
||||
@@ -519,11 +538,13 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, DummyProjectName, false, false));
|
||||
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), DummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
|
||||
@@ -565,7 +586,7 @@ TEST_F(PlatformConfigurationUnitTests, Test_GemHandling)
|
||||
QTemporaryDir tempEngineRoot;
|
||||
QDir tempPath(tempEngineRoot.path());
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
AssetUtilities::ComputeGameName("SamplesProject", true);
|
||||
AssetUtilities::ComputeProjectName("SamplesProject", true);
|
||||
|
||||
QDir computedEngineRoot;
|
||||
ASSERT_TRUE(AssetUtilities::ComputeAssetRoot(computedEngineRoot, &tempPath));
|
||||
@@ -576,9 +597,11 @@ TEST_F(PlatformConfigurationUnitTests, Test_GemHandling)
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("Gems/LyShine/AssetProcessorGemConfig.ini"), ";nothing to see here"));
|
||||
|
||||
// note that it is expected that the gems system gives us absolute paths.
|
||||
AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> fakeGems;
|
||||
fakeGems.push_back({ "LyShine", "Gems/LyShine", tempPath.absoluteFilePath("Gems/LyShine").toUtf8().constData(), "0fefab3f13364722b2eab3b96ce2bf20", true, false });// true = pretend this is a game gem.
|
||||
fakeGems.push_back({ "LmbrCentral", "Gems/LmbrCentral/v2", tempPath.absoluteFilePath("Gems/LmbrCentral/v2").toUtf8().constData(), "ff06785f7145416b9d46fde39098cb0c", false, false });
|
||||
AZStd::vector<AzFramework::GemInfo> fakeGems;
|
||||
fakeGems.emplace_back("LyShine");// true = pretend this is a game gem.
|
||||
fakeGems.back().m_absoluteSourcePaths.push_back(tempPath.absoluteFilePath("Gems/LyShine").toUtf8().constData());
|
||||
fakeGems.emplace_back("LmbrCentral");
|
||||
fakeGems.back().m_absoluteSourcePaths.push_back(tempPath.absoluteFilePath("Gems/LmbrCentral/v2").toUtf8().constData());
|
||||
|
||||
// reading gems via the Gems System is already to be tested in the actual Gems API tests.
|
||||
// to avoid trying to load those DLLs we avoid calling the actual ReadGems function
|
||||
@@ -593,8 +616,7 @@ TEST_F(PlatformConfigurationUnitTests, Test_GemHandling)
|
||||
EXPECT_TRUE(config.GetScanFolderAt(0).GetOutputPrefix().isEmpty());
|
||||
EXPECT_TRUE(config.GetScanFolderAt(0).RecurseSubFolders());
|
||||
// the first one is a game gem, so its order should be above 1 but below 100.
|
||||
EXPECT_GE(config.GetScanFolderAt(0).GetOrder(), 1);
|
||||
EXPECT_LE(config.GetScanFolderAt(0).GetOrder(), 100);
|
||||
EXPECT_GE(config.GetScanFolderAt(0).GetOrder(), 100);
|
||||
EXPECT_EQ(0, config.GetScanFolderAt(0).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive));
|
||||
|
||||
// for each gem, there are currently 1 scan folder, the gem assets folder, with no output prefix
|
||||
@@ -618,15 +640,17 @@ TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes)
|
||||
ASSERT_TRUE(QString::compare(config.GetMetaDataFileTypeAt(1).second, "zzzz", Qt::CaseInsensitive) == 0);
|
||||
}
|
||||
|
||||
TEST_F(PlatformConfigurationUnitTests, ReadCheckSever_FromConfig_Valid)
|
||||
TEST_F(PlatformConfigurationUnitTests, ReadCheckServer_FromConfig_Valid)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
const char* configRoot = ":/testdata/config_regular";
|
||||
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot, TestAppRoot, EmptyDummyProjectName, false, false));
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
|
||||
@@ -642,7 +666,11 @@ TEST_F(PlatformConfigurationUnitTests, PlatformConfigFile_IsPresent_Found)
|
||||
QTemporaryDir tempEngineRoot;
|
||||
QDir tempPath(tempEngineRoot.path());
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
AssetUtilities::ComputeGameName("SamplesProject", true);
|
||||
AssetUtilities::ComputeProjectName("SamplesProject", true);
|
||||
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
ASSERT_NE(nullptr, settingsRegistry);
|
||||
settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder, tempPath.absolutePath().toUtf8().constData());
|
||||
|
||||
QDir computedEngineRoot;
|
||||
ASSERT_TRUE(AssetUtilities::ComputeAssetRoot(computedEngineRoot, &tempPath));
|
||||
@@ -655,7 +683,7 @@ TEST_F(PlatformConfigurationUnitTests, PlatformConfigFile_IsPresent_Found)
|
||||
platformConfigPath.append("TestPlatform/");
|
||||
platformConfigPath.append(AssetProcessor::AssetProcessorPlatformConfigFileName);
|
||||
|
||||
QStringList platformConfigList;
|
||||
AZStd::vector<AZ::IO::Path> platformConfigList;
|
||||
ASSERT_FALSE(config.AddPlatformConfigFilePaths(platformConfigList));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath(platformConfigPath), ";nothing to see here"));
|
||||
ASSERT_TRUE(config.AddPlatformConfigFilePaths(platformConfigList));
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <QHash>
|
||||
|
||||
#include "native/tests/AssetProcessorTest.h"
|
||||
#include <native/utilities/PlatformConfiguration.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
@@ -519,11 +521,18 @@ TEST_F(AssetUtilitiesTest, GetServerAddress_ReadFromConfig_Valid)
|
||||
QTemporaryDir tempDir;
|
||||
QDir tempPath(tempDir.path());
|
||||
QString assetServerAddress("T:/AssetServerCacheDummyFolder");
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("AssetProcessorPlatformConfig.ini"), QString("[Server]\ncacheServerAddress=%1\n").arg(assetServerAddress));
|
||||
QString assetProcesorPlatformConfigPath = tempPath.absoluteFilePath("AssetProcessorPlatformConfig.ini");
|
||||
UnitTestUtils::CreateDummyFile(assetProcesorPlatformConfigPath, QString("[Server]\ncacheServerAddress=%1\n").arg(assetServerAddress));
|
||||
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
QDir newRoot;
|
||||
AssetUtilities::ComputeEngineRoot(newRoot, &tempPath);
|
||||
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
AZ::SettingsRegistryMergeUtils::ConfigParserSettings configParserSettings;
|
||||
configParserSettings.m_registryRootPointerPath = AssetProcessor::AssetProcessorSettingsKey;
|
||||
AssetProcessor::PlatformConfiguration::MergeConfigFileToSettingsRegistry(*settingsRegistry,
|
||||
assetProcesorPlatformConfigPath.toUtf8().data());
|
||||
QString assetServerAddressReturned = AssetUtilities::ServerAddress();
|
||||
EXPECT_STREQ(assetServerAddressReturned.toUtf8().data(), assetServerAddress.toUtf8().data());
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ void MainWindow::Activate()
|
||||
|
||||
ui->projectLabel->setText(QStringLiteral("%1: %2")
|
||||
.arg(tr("Project"))
|
||||
.arg(m_guiApplicationManager->GetGameName()));
|
||||
.arg(QDir{m_guiApplicationManager->GetProjectPath()}.absolutePath()));
|
||||
|
||||
ui->rootLabel->setText(QStringLiteral("%1: %2")
|
||||
.arg(tr("Root"))
|
||||
|
||||
@@ -1,655 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#if defined(UNIT_TEST)
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
#include "AssetCatalogUnitTests.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/Asset/AssetProcessorMessages.h>
|
||||
|
||||
#include <AzToolsFramework/Asset/AssetProcessorMessages.h>
|
||||
#include <native/AssetManager/assetProcessorManager.h>
|
||||
#include <native/utilities/PlatformConfiguration.h>
|
||||
#include <native/utilities/AssetBuilderInfo.h>
|
||||
#include <native/AssetManager/assetScanFolderInfo.h>
|
||||
#include <native/utilities/assetUtils.h>
|
||||
#include <native/resourcecompiler/RCBuilder.h>
|
||||
#include <native/assetprocessor.h>
|
||||
|
||||
#include <QTemporaryDir>
|
||||
#include <QString>
|
||||
#include <QCoreApplication>
|
||||
#include <QSet>
|
||||
#include <QList>
|
||||
#include <QTime>
|
||||
#include <QThread>
|
||||
#include <QPair>
|
||||
#include <AzToolsFramework/API/AssetDatabaseBus.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
using namespace UnitTestUtils;
|
||||
using namespace AzFramework::AssetSystem;
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AzToolsFramework::AssetDatabase;
|
||||
|
||||
REGISTER_UNIT_TEST(AssetCatalogUnitTests)
|
||||
REGISTER_UNIT_TEST(AssetCatalogUnitTests_AssetInfo)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// a utility class to redirect the location the database is stored to a different location so that we don't
|
||||
// touch real data during unit tests.
|
||||
class FakeDatabaseLocationListener
|
||||
: protected AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler
|
||||
{
|
||||
public:
|
||||
FakeDatabaseLocationListener(const char* desiredLocation, const char* assetPath)
|
||||
: m_location(desiredLocation)
|
||||
, m_assetPath(assetPath)
|
||||
{
|
||||
AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler::BusConnect();
|
||||
}
|
||||
~FakeDatabaseLocationListener()
|
||||
{
|
||||
AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
protected:
|
||||
// IMPLEMENTATION OF -------------- AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Listener
|
||||
bool GetAssetDatabaseLocation(AZStd::string& location) override
|
||||
{
|
||||
location = m_location;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
private:
|
||||
AZStd::string m_location;
|
||||
AZStd::string m_assetPath;
|
||||
};
|
||||
|
||||
// Adds a scan folder to the config and to the database
|
||||
void AddScanFolder(const ScanFolderInfo& scanFolderInfo, PlatformConfiguration& config, AssetDatabaseConnection* dbConn)
|
||||
{
|
||||
config.AddScanFolder(scanFolderInfo);
|
||||
ScanFolderDatabaseEntry newScanFolder(
|
||||
scanFolderInfo.ScanPath().toStdString().c_str(),
|
||||
scanFolderInfo.GetDisplayName().toStdString().c_str(),
|
||||
scanFolderInfo.GetPortableKey().toStdString().c_str(),
|
||||
scanFolderInfo.GetOutputPrefix().toStdString().c_str(),
|
||||
scanFolderInfo.IsRoot());
|
||||
dbConn->SetScanFolder(newScanFolder);
|
||||
}
|
||||
|
||||
void BuildConfig(const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config)
|
||||
{
|
||||
config.EnablePlatform({ "pc" ,{ "desktop", "renderer" } }, true);
|
||||
config.EnablePlatform({ "es3" ,{ "mobile", "renderer" } }, true);
|
||||
config.EnablePlatform({ "fandango" ,{ "console", "renderer" } }, false);
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms;
|
||||
config.PopulatePlatformsForScanFolder(platforms);
|
||||
// PATH DisplayName PortKey outputfolder root recurse platforms order
|
||||
AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder4"), "subfolder4", "subfolder4", "", false, false, platforms, -6), config, dbConn); // subfolder 4 overrides subfolder3
|
||||
AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder3"), "subfolder3", "subfolder3", "", false, false, platforms, -5), config, dbConn); // subfolder 3 overrides subfolder2
|
||||
AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder2"), "subfolder2", "subfolder2", "", false, true, platforms, -2), config, dbConn); // subfolder 2 overrides subfolder1
|
||||
AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder1"), "subfolder1", "subfolder1", "editor", false, true, platforms, -1), config, dbConn); // subfolder1 overrides root
|
||||
AddScanFolder(ScanFolderInfo(tempPath.absolutePath(), "temp", "tempfolder", "", true, false, platforms, 0), config, dbConn); // add the root
|
||||
|
||||
config.AddMetaDataType("exportsettings", QString());
|
||||
|
||||
AZ::Uuid buildIDRcLegacy;
|
||||
BUILDER_ID_RC.GetUuid(buildIDRcLegacy);
|
||||
|
||||
AssetRecognizer rec;
|
||||
AssetPlatformSpec specpc;
|
||||
AssetPlatformSpec speces3;
|
||||
|
||||
speces3.m_extraRCParams = "somerandomparam";
|
||||
rec.m_name = "random files";
|
||||
rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.random", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
config.AddRecognizer(rec);
|
||||
|
||||
specpc.m_extraRCParams = ""; // blank must work
|
||||
speces3.m_extraRCParams = "testextraparams";
|
||||
|
||||
const char* builderTxt1Name = "txt files";
|
||||
rec.m_name = builderTxt1Name;
|
||||
rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
rec.m_platformSpecs.insert("es3", speces3);
|
||||
|
||||
config.AddRecognizer(rec);
|
||||
|
||||
// Ignore recognizer
|
||||
AssetPlatformSpec ignore_spec;
|
||||
ignore_spec.m_extraRCParams = "skip";
|
||||
AssetRecognizer ignore_rec;
|
||||
ignore_rec.m_name = "ignore files";
|
||||
ignore_rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.ignore", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
ignore_rec.m_platformSpecs.insert("pc", specpc);
|
||||
ignore_rec.m_platformSpecs.insert("es3", ignore_spec);
|
||||
config.AddRecognizer(ignore_rec);
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/savebackup\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
config.AddExcludeRecognizer(excludeRecogniser);
|
||||
}
|
||||
|
||||
// Adds a source file and job entry to the database, jobId is output
|
||||
bool AddSourceAndJob(const char* scanFolder, const char* sourceRelPath, AssetDatabaseConnection* dbConn, AZ::s64& jobId, AZ::Uuid assetId = AZ::Uuid::CreateRandom())
|
||||
{
|
||||
ScanFolderDatabaseEntry scanFolderEntry;
|
||||
bool result = dbConn->GetScanFolderByPortableKey(scanFolder, scanFolderEntry);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceDatabaseEntry sourceEntry(scanFolderEntry.m_scanFolderID, sourceRelPath, assetId, "fingerprint");
|
||||
dbConn->SetSource(sourceEntry);
|
||||
|
||||
JobDatabaseEntry jobEntry(sourceEntry.m_sourceID, "test", 1234, "pc", assetId, AzToolsFramework::AssetSystem::JobStatus::Completed, 12345);
|
||||
dbConn->SetJob(jobEntry);
|
||||
|
||||
jobId = jobEntry.m_jobID;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Calls the GetRelativeProductPathFromFullSourceOrProductPath function and checks the return results, returning true if it matches both of the expected results
|
||||
bool TestGetRelativeProductPath(const QString fileToCheck, bool expectedToFind, AZStd::initializer_list<const char*> expectedPaths)
|
||||
{
|
||||
bool relPathfound = false;
|
||||
AZStd::string relPath;
|
||||
AZStd::string fullPath(fileToCheck.toStdString().c_str());
|
||||
|
||||
EBUS_EVENT_RESULT(relPathfound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullPath, relPath);
|
||||
|
||||
if (relPathfound != expectedToFind)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& path : expectedPaths)
|
||||
{
|
||||
if (relPath == path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calls the GetFullSourcePathFromRelativeProductPath function and checks the return results, returning true if it matches both of the expected results
|
||||
bool TestGetFullSourcePath(const QString& fileToCheck, const QDir& tempPath, bool expectToFind, const char* expectedPath)
|
||||
{
|
||||
bool fullPathfound = false;
|
||||
AZStd::string fullPath;
|
||||
AZStd::string relPath(fileToCheck.toStdString().c_str());
|
||||
|
||||
EBUS_EVENT_RESULT(fullPathfound, AzToolsFramework::AssetSystemRequestBus, GetFullSourcePathFromRelativeProductPath, relPath, fullPath);
|
||||
|
||||
if (fullPathfound != expectToFind)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString output(fullPath.c_str());
|
||||
output.remove(0, tempPath.path().length() + 1); //adding one for the native separator
|
||||
|
||||
return (output == expectedPath);
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
void AssetCatalogUnitTests::StartTest()
|
||||
{
|
||||
QDir oldRoot;
|
||||
AssetUtilities::ComputeAssetRoot(oldRoot);
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
|
||||
// the canonicalization of the path here is to get around the fact that on some platforms
|
||||
// the "temporary" folder location could be junctioned into some other folder and getting "QDir::current()"
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
QTemporaryDir dir;
|
||||
QDir tempPath(dir.path());
|
||||
QString canonicalTempDirPath = AssetUtilities::NormalizeDirectoryPath(tempPath.canonicalPath());
|
||||
UnitTestUtils::ScopedDir changeDir(canonicalTempDirPath);
|
||||
tempPath = QDir(canonicalTempDirPath);
|
||||
NetworkRequestID requestId(1, 1);
|
||||
|
||||
FakeDatabaseLocationListener listener(tempPath.filePath("statedatabase.sqlite").toUtf8().constData(), "displayString");
|
||||
|
||||
AZStd::unique_ptr<AssetDatabaseConnection> dbConn = AZStd::make_unique<AssetDatabaseConnection>();
|
||||
dbConn->OpenDatabase();
|
||||
|
||||
CreateDummyFile(tempPath.absoluteFilePath("bootstrap.cfg"), QString("sys_game_folder=SamplesProject\n"));
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
QDir newRoot;
|
||||
AssetUtilities::ComputeAssetRoot(newRoot, &tempPath);
|
||||
|
||||
UNIT_TEST_EXPECT_FALSE(gameName.isEmpty());
|
||||
// should create cache folder in the root, and read everything from there.
|
||||
|
||||
QSet<QString> expectedFiles;
|
||||
// set up some interesting files:
|
||||
expectedFiles << tempPath.absoluteFilePath("rootfile2.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder1/rootfile1.txt"); // note: Must override the actual root file
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder1/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/ccc/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder2/aaa/bbb/ccc/ddd/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/BaseFile.txt"); // note the case upper here
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder8/a/b/c/test.txt");
|
||||
|
||||
// subfolder3 is not recursive so none of these should show up in any scan or override check
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/aaa/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/aaa/bbb/basefile.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/aaa/bbb/ccc/basefile.txt");
|
||||
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/uniquefile.txt"); // only exists in subfolder3
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/uniquefile.ignore"); // only exists in subfolder3
|
||||
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/rootfile3.txt"); // must override rootfile3 in root
|
||||
expectedFiles << tempPath.absoluteFilePath("rootfile1.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("rootfile3.txt");
|
||||
expectedFiles << tempPath.absoluteFilePath("unrecognised.file"); // a file that should not be recognised
|
||||
expectedFiles << tempPath.absoluteFilePath("unrecognised2.file"); // a file that should not be recognised
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder1/test/test.format"); // a file that should be recognised
|
||||
expectedFiles << tempPath.absoluteFilePath("test.format"); // a file that should NOT be recognised
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/somefile.xxx");
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/savebackup/test.txt");//file that should be excluded
|
||||
expectedFiles << tempPath.absoluteFilePath("subfolder3/somerandomfile.random");
|
||||
|
||||
for (const QString& expect : expectedFiles)
|
||||
{
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(expect));
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Created file %s with msecs %llu\n", expect.toUtf8().constData(),
|
||||
QFileInfo(expect).lastModified().toMSecsSinceEpoch());
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
QThread::msleep(35); // give at least some milliseconds so that the files never share the same timestamp exactly
|
||||
#else
|
||||
// on platforms such as mac, the file time resolution is only a second :(
|
||||
QThread::msleep(1001);
|
||||
#endif
|
||||
}
|
||||
|
||||
PlatformConfiguration config;
|
||||
BuildConfig(tempPath, dbConn.get(), config);
|
||||
|
||||
AssetCatalog assetCatalog(nullptr, &config);
|
||||
QDir cacheRoot;
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::ComputeProjectCacheRoot(cacheRoot));
|
||||
QString normalizedCacheRoot = AssetUtilities::NormalizeDirectoryPath(cacheRoot.absolutePath());
|
||||
|
||||
// make sure it picked up the one in the current folder
|
||||
|
||||
QString normalizedDirPathCheck = AssetUtilities::NormalizeDirectoryPath(tempPath.absoluteFilePath("Cache/" + gameName));
|
||||
UNIT_TEST_EXPECT_TRUE(normalizedCacheRoot == normalizedDirPathCheck);
|
||||
QDir normalizedCacheRootDir(normalizedCacheRoot);
|
||||
|
||||
// ----- Test the get asset path functions, which given a full path to an asset, checks the mappings and turns it into an Asset ID ---
|
||||
{
|
||||
// sanity check - make sure it does not crash or misbehave when given empty names
|
||||
QString fileToCheck = "";
|
||||
{
|
||||
UnitTestUtils::AssertAbsorber absorb;
|
||||
// empty requests should generate an assert.
|
||||
GetRelativeProductPathFromFullSourceOrProductPathRequest request(fileToCheck.toUtf8().constData());
|
||||
UNIT_TEST_EXPECT_TRUE(absorb.m_numAssertsAbsorbed == 1);
|
||||
GetFullSourcePathFromRelativeProductPathRequest sourceRequest(fileToCheck.toUtf8().constData());
|
||||
UNIT_TEST_EXPECT_TRUE(absorb.m_numAssertsAbsorbed == 2);
|
||||
}
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath("", false, {""}));
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath("", tempPath, false, ""));
|
||||
|
||||
// Add a source file with 4 products
|
||||
{
|
||||
AZ::s64 jobId;
|
||||
bool result = AddSourceAndJob("subfolder3", "BaseFile.txt", dbConn.get(), jobId);
|
||||
UNIT_TEST_EXPECT_TRUE(result);
|
||||
|
||||
AZ::u32 productSubId = 0;
|
||||
for (auto& relativeProductPath : { "subfolder3/basefilez.arc2", "subfolder3/basefileaz.azm2", "subfolder3/basefile.arc2", "subfolder3/basefile.azm2" })
|
||||
{
|
||||
ProductDatabaseEntry newProduct(jobId, productSubId++, cacheRoot.relativeFilePath(relativeProductPath).toStdString().c_str(), AZ::Data::AssetType::CreateRandom());
|
||||
dbConn->SetProduct(newProduct);
|
||||
}
|
||||
}
|
||||
|
||||
// GetRelativeProductPathFromFullSourceOrProductPath has 4 code paths:
|
||||
// 1) Relative input paths are returned straight away
|
||||
// 2) Paths inside the cache folder are transformed to product paths, no database involvement
|
||||
// 3) Source files that have a product return the product path
|
||||
// 4) Source files that don't have a product return the source file's relative path since that is the path a product might have
|
||||
|
||||
// Failure case
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
fileToCheck = "d:\\test.txt";
|
||||
#else
|
||||
fileToCheck = "/test.txt"; // rooted
|
||||
#endif
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, false, { fileToCheck.toStdString().c_str() }));
|
||||
|
||||
// (Case 1) feed it a relative path
|
||||
fileToCheck = "\test.txt";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "\test.txt" }));
|
||||
|
||||
// (Case 2) feed it a product path with gamename
|
||||
fileToCheck = normalizedCacheRootDir.filePath("pc/" + gameName + "/aaa/basefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
|
||||
// (Case 2) feed it a product path without gamename
|
||||
fileToCheck = normalizedCacheRootDir.filePath("pc/basefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "basefile.txt" }));
|
||||
|
||||
// (Case 2) feed it a product path with gamename but poor casing (test 1: the pc platform is not matching case)
|
||||
fileToCheck = normalizedCacheRootDir.filePath("Pc/" + gameName + "/aaa/basefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
|
||||
// (Case 2) feed it a product path with gamename but poor casing (test 2: the gameName is not matching case)
|
||||
fileToCheck = normalizedCacheRootDir.filePath("pc/" + gameName.toUpper() + "/aaa/basefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
|
||||
// (Case 2) feed it a product path that resolves to a directory name instead of a file.
|
||||
fileToCheck = normalizedCacheRootDir.filePath("pc/" + gameName.toUpper() + "/aaa");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa" }));
|
||||
|
||||
// Case 3
|
||||
fileToCheck = tempPath.absoluteFilePath("subfolder3/BaseFile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "basefilez.arc2", "basefileaz.azm2", "basefile.arc2", "basefile.azm2" }));
|
||||
|
||||
// Case 4
|
||||
fileToCheck = tempPath.absoluteFilePath("subfolder2/aaa/basefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
|
||||
// ----- Test the ProcessGetFullAssetPath function
|
||||
{
|
||||
QStringList pcouts;
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random2"));
|
||||
|
||||
AZ::s64 jobId;
|
||||
bool result = AddSourceAndJob("subfolder3", "somerandomfile.random", dbConn.get(), jobId);
|
||||
UNIT_TEST_EXPECT_TRUE(result);
|
||||
|
||||
AZ::u32 productSubID = 0;
|
||||
for (auto& product : pcouts)
|
||||
{
|
||||
ProductDatabaseEntry newProduct(jobId, productSubID++, cacheRoot.relativeFilePath(product).toStdString().c_str(), AZ::Data::AssetType::CreateRandom());
|
||||
dbConn->SetProduct(newProduct);
|
||||
}
|
||||
}
|
||||
|
||||
//feed it an relative product, and expect a full, absolute source file path in return.
|
||||
fileToCheck = "subfolder3/randomfileoutput.random1";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it another relative product
|
||||
fileToCheck = "subfolder3/randomfileoutput.random2";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it the same relative product with different separators
|
||||
fileToCheck = "subfolder3\\randomfileoutput.random2";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it a full path
|
||||
fileToCheck = tempPath.filePath("somefolder/somefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "somefolder/somefile.txt"));
|
||||
|
||||
//feed it a path with alias and asset id
|
||||
fileToCheck = "@assets@/subfolder3/randomfileoutput.random1";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it a path with some random alias and asset id
|
||||
fileToCheck = "@somerandomalias@/subfolder3/randomfileoutput.random1";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it a path with some random alias and asset id but no separator
|
||||
fileToCheck = "@somerandomalias@subfolder3/randomfileoutput.random1";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it a path with alias and input name
|
||||
fileToCheck = "@assets@/somerandomfile.random";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it an absolute path with cacheroot
|
||||
fileToCheck = normalizedCacheRootDir.filePath("pc/" + gameName + "/subfolder3/randomfileoutput.random1");
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
|
||||
//feed it a productName directly
|
||||
fileToCheck = "pc/" + gameName + "/subfolder3/randomfileoutput.random1";
|
||||
UNIT_TEST_EXPECT_TRUE(TestGetFullSourcePath(fileToCheck, tempPath, true, "subfolder3/somerandomfile.random"));
|
||||
}
|
||||
|
||||
Q_EMIT UnitTestPassed();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AssetCatalogUnitTests_AssetInfo::StartTest()
|
||||
{
|
||||
using namespace AZ::Data;
|
||||
using namespace AzToolsFramework;
|
||||
|
||||
// the canonicalization of the path here is to get around the fact that on some platforms
|
||||
// the "temporary" folder location could be junctioned into some other folder and getting "QDir::current()"
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
QTemporaryDir dir;
|
||||
QDir tempPath(dir.path());
|
||||
QString canonicalTempDirPath = AssetUtilities::NormalizeDirectoryPath(tempPath.canonicalPath());
|
||||
UnitTestUtils::ScopedDir changeDir(canonicalTempDirPath);
|
||||
tempPath = QDir(canonicalTempDirPath);
|
||||
|
||||
CreateDummyFile(tempPath.absoluteFilePath("bootstrap.cfg"), QString("sys_game_folder=SamplesProject\n"));
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
QDir newRoot;
|
||||
AssetUtilities::ComputeAssetRoot(newRoot, &tempPath);
|
||||
QDir cacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(cacheRoot);
|
||||
AZStd::string cacheRootPath = cacheRoot.absolutePath().toStdString().c_str();
|
||||
|
||||
FakeDatabaseLocationListener listener(tempPath.filePath("statedatabase.sqlite").toUtf8().constData(), "displayString");
|
||||
|
||||
AZStd::unique_ptr<AssetDatabaseConnection> dbConn = AZStd::make_unique<AssetDatabaseConnection>();
|
||||
dbConn->OpenDatabase();
|
||||
|
||||
PlatformConfiguration config;
|
||||
BuildConfig(tempPath, dbConn.get(), config);
|
||||
|
||||
AssetCatalog assetCatalog(nullptr, &config);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssetId assetA(AZ::Uuid::CreateRandom(), 0);
|
||||
AZ::Uuid assetALegacyUuid = AZ::Uuid::CreateRandom();
|
||||
AssetType assetAType = AssetType::CreateRandom();
|
||||
AZStd::string assetAFileFilter = "*.source";
|
||||
AZStd::string subfolder1AbsolutePath = tempPath.absoluteFilePath("subfolder1").toStdString().c_str();
|
||||
AZStd::string assetASourceRelPath = "assetA.source";
|
||||
AZStd::string assetASourceDatabasePath = "editor/assetA.source";
|
||||
AZStd::string assetAProductRelPath = "editor/assetA.product";
|
||||
|
||||
AZStd::string assetAFullPath;
|
||||
AzFramework::StringFunc::Path::Join(subfolder1AbsolutePath.c_str(), assetASourceRelPath.c_str(), assetAFullPath);
|
||||
CreateDummyFile(QString::fromUtf8(assetAFullPath.c_str()), "Its the Asset A"); // 15 bytes of data
|
||||
|
||||
AZStd::string assetAProductFullPath;
|
||||
AzFramework::StringFunc::Path::Join(cacheRootPath.c_str(), assetAProductRelPath.c_str(), assetAProductFullPath);
|
||||
CreateDummyFile(QString::fromUtf8(assetAProductFullPath.c_str()), "Its a product A"); // 15 bytes of data
|
||||
|
||||
auto getAssetInfoById = [assetA, assetAType, subfolder1AbsolutePath](bool expectedResult, AZStd::string expectedRelPath, AZStd::string expectedRootPath, AssetType assetType) -> bool
|
||||
{
|
||||
bool result = false;
|
||||
AssetInfo assetInfo;
|
||||
AZStd::string rootPath;
|
||||
AssetSystemRequestBus::BroadcastResult(result, &AssetSystem::AssetSystemRequest::GetAssetInfoById, assetA, assetType, assetInfo, rootPath);
|
||||
|
||||
if (result != expectedResult)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expectedResult)
|
||||
{
|
||||
return (assetInfo.m_assetId == assetA)
|
||||
&& (assetInfo.m_assetType == assetAType)
|
||||
&& (assetInfo.m_relativePath == expectedRelPath)
|
||||
&& (assetInfo.m_sizeBytes == 15)
|
||||
&& (rootPath == expectedRootPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto getAssetInfoByIdPair = [&](bool expectedResult, AZStd::string expectedRelPath, AZStd::string expectedRootPath) -> bool
|
||||
{
|
||||
// First test without providing the assetType
|
||||
bool result = getAssetInfoById(expectedResult, expectedRelPath, expectedRootPath, AssetType::CreateNull());
|
||||
|
||||
// If successful, test again, this time providing the assetType
|
||||
if (result)
|
||||
{
|
||||
result = getAssetInfoById(expectedResult, expectedRelPath, expectedRootPath, assetAType);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
auto getSourceInfoBySourcePath = [](bool expectedResult, AZStd::string sourcePath, AZ::Uuid expectedUuid, AZStd::string expectedRelPath, AZStd::string expectedRootPath, AZ::Data::AssetType expectedType = AZ::Data::s_invalidAssetType) -> bool
|
||||
{
|
||||
bool result = false;
|
||||
AssetInfo assetInfo;
|
||||
AZStd::string rootPath;
|
||||
AssetSystemRequestBus::BroadcastResult(result, &AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, sourcePath.c_str(), assetInfo, rootPath);
|
||||
|
||||
if (result != expectedResult)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expectedResult)
|
||||
{
|
||||
return (assetInfo.m_assetId == expectedUuid)
|
||||
&& (assetInfo.m_assetType == expectedType)
|
||||
&& (assetInfo.m_relativePath == expectedRelPath)
|
||||
&& (assetInfo.m_sizeBytes == 15)
|
||||
&& (rootPath == expectedRootPath)
|
||||
;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
//Test 1: Asset not in database
|
||||
UNIT_TEST_EXPECT_TRUE(getAssetInfoByIdPair(false, "", ""));
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(false, "", AZ::Uuid::CreateNull(), "", ""));
|
||||
|
||||
// Add asset to database
|
||||
AZ::s64 jobId;
|
||||
UNIT_TEST_EXPECT_TRUE(AddSourceAndJob("subfolder1", assetASourceDatabasePath.c_str(), dbConn.get(), jobId, assetA.m_guid));
|
||||
ProductDatabaseEntry newProductEntry(jobId, 0, assetAProductRelPath.c_str(), assetAType);
|
||||
dbConn->SetProduct(newProductEntry);
|
||||
|
||||
// Test 2: Asset in database, not registered as source asset
|
||||
// note that when asking for products, a performance improvement causes the catalog to use its REGISTRY
|
||||
// rather than the database to ask for products, so to set this up the registry must be present and must have the asset registered within it
|
||||
AzFramework::AssetSystem::AssetNotificationMessage message(assetAProductRelPath.c_str(), AssetNotificationMessage::AssetChanged, assetAType);
|
||||
message.m_sizeBytes = 15;
|
||||
message.m_assetId = AZ::Data::AssetId(assetA.m_guid, 0);
|
||||
assetCatalog.OnAssetMessage("pc", message);
|
||||
|
||||
// also of note: When looking up products, you don't get a root path since they are all in the cache.
|
||||
// its important here that we specifically get an empty root path.
|
||||
UNIT_TEST_EXPECT_TRUE(getAssetInfoByIdPair(true, assetAProductRelPath, ""));
|
||||
|
||||
// this call has to work with full and relative path.
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetASourceRelPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str()));
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetAFullPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str()));
|
||||
|
||||
dbConn->RemoveProductsByJobID(jobId);
|
||||
|
||||
// similar to the above, because its not the DB that is used for products, we have to inform the catalog that its gone
|
||||
message.m_type = AssetNotificationMessage::AssetRemoved;
|
||||
assetCatalog.OnAssetMessage("pc", message);
|
||||
|
||||
// Add to queue
|
||||
assetCatalog.OnSourceQueued(assetA.m_guid, assetALegacyUuid, subfolder1AbsolutePath.c_str(), assetASourceRelPath.c_str());
|
||||
|
||||
//Test 3: Asset in queue, not registered as source asset
|
||||
UNIT_TEST_EXPECT_TRUE(getAssetInfoByIdPair(false, "", ""));
|
||||
|
||||
// this call should STILL work even after the above call to "OnSourceQueued" since its explicitly asking for the source details.
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetASourceRelPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str()));
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetAFullPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str()));
|
||||
|
||||
// Register as source type
|
||||
// note that once this call has been made, ALL REQUESTS for this type of asset should always include an appropriate type (non zero)
|
||||
ToolsAssetSystemBus::Broadcast(&ToolsAssetSystemRequests::RegisterSourceAssetType, assetAType, assetAFileFilter.c_str());
|
||||
|
||||
//Test 4: Asset in queue, registered as source asset
|
||||
UNIT_TEST_EXPECT_TRUE(getAssetInfoByIdPair(true, assetASourceRelPath, subfolder1AbsolutePath));
|
||||
|
||||
// these calls are identical to the two above, but should continue to work even though we have registered the asset type as a source asset type.
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetASourceRelPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str(), assetAType));
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetAFullPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str(), assetAType));
|
||||
|
||||
// Remove from queue
|
||||
assetCatalog.OnSourceFinished(assetA.m_guid, assetALegacyUuid);
|
||||
|
||||
// Add asset to database
|
||||
ProductDatabaseEntry assetAEntry(jobId, 0, assetAProductRelPath.c_str(), assetAType);
|
||||
dbConn->SetProduct(assetAEntry);
|
||||
|
||||
//Test 5: Asset in database, registered as source asset
|
||||
UNIT_TEST_EXPECT_TRUE(getAssetInfoByIdPair(true, assetASourceRelPath, subfolder1AbsolutePath));
|
||||
|
||||
// at this point the details about the asset in question is no longer in memory, only the database. However, these calls should continue find the
|
||||
// information, because the system is supposed check both the database AND the in-memory queue in the to find the info being requested.
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetASourceRelPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str(), assetAType));
|
||||
UNIT_TEST_EXPECT_TRUE(getSourceInfoBySourcePath(true, assetAFullPath.c_str(), assetA.m_guid, assetASourceRelPath.c_str(), subfolder1AbsolutePath.c_str(), assetAType));
|
||||
|
||||
Q_EMIT UnitTestPassed();
|
||||
}
|
||||
|
||||
#include <native/unittests/moc_AssetCatalogUnitTests.cpp>
|
||||
} // namespace AssetProcessor
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "AssetProcessorManagerUnitTests.h"
|
||||
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
#include "MockApplicationManager.h"
|
||||
#include "native/FileWatcher/FileWatcher.h"
|
||||
@@ -56,7 +56,7 @@ namespace AssetProcessor
|
||||
using GetFullSourcePathFromRelativeProductPathResponse = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathResponse;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
REGISTER_UNIT_TEST(AssetProcessorManagerUnitTests_ScanFolders)
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace AssetProcessor
|
||||
AssetUtilities::ComputeAssetRoot(oldRoot);
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
FileWatcher fileWatcher;
|
||||
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::temp().exists());
|
||||
QString tmpDirPath = AssetUtilities::NormalizeDirectoryPath(QDir::tempPath());
|
||||
|
||||
@@ -153,8 +153,7 @@ namespace AssetProcessor
|
||||
UnitTestUtils::ScopedDir changeDir(canonicalTempDirPath);
|
||||
NetworkRequestID requestId(1, 1);
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName(AssetProcessorManagerTestGameProject);
|
||||
QString gameName = AssetUtilities::ComputeProjectName(AssetProcessorManagerTestGameProject);
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
@@ -162,6 +161,13 @@ namespace AssetProcessor
|
||||
AssetUtilities::ComputeAssetRoot(newRoot, &tempPath);
|
||||
|
||||
// create a dummy file in the cache folder, so the folder structure gets created
|
||||
// Override the cache folder to be the within the temporary directory
|
||||
auto projectCacheRootKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
settingsRegistry->Set(projectCacheRootKey, tempPath.absoluteFilePath("Cache").toUtf8().data());
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*settingsRegistry);
|
||||
}
|
||||
QDir projectCacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
|
||||
CreateDummyFile(projectCacheRoot.absoluteFilePath("placeholder.txt"));
|
||||
@@ -343,7 +349,7 @@ namespace AssetProcessor
|
||||
|
||||
// make sure it picked up the one in the cache and not for example the real working folder
|
||||
|
||||
QString normalizedDirPathCheck = AssetUtilities::NormalizeDirectoryPath(QDir(canonicalTempDirPath).absoluteFilePath("Cache/" + gameName));
|
||||
QString normalizedDirPathCheck = AssetUtilities::NormalizeDirectoryPath(QDir(canonicalTempDirPath).absoluteFilePath("Cache"));
|
||||
UNIT_TEST_EXPECT_TRUE(normalizedCacheRoot == normalizedDirPathCheck);
|
||||
QDir normalizedCacheRootDir(normalizedCacheRoot);
|
||||
|
||||
@@ -441,7 +447,7 @@ namespace AssetProcessor
|
||||
QString relativePathFromWatchFolder = "uniquefile.txt";
|
||||
QString watchFolderPath = tempPath.absoluteFilePath("subfolder3");
|
||||
QString absolutePath = AssetUtilities::NormalizeFilePath(watchFolderPath + "/" + relativePathFromWatchFolder);
|
||||
|
||||
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
@@ -469,7 +475,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_watchFolderPath == AssetUtilities::NormalizeFilePath(watchFolderPath));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_pathRelativeToWatchFolder == "uniquefile.txt");
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_databaseSourceName == "uniquefile.txt");
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()) + "/" + gameName.toLower());
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()));
|
||||
platformFolder = AssetUtilities::NormalizeDirectoryPath(platformFolder);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_destinationPath.startsWith(platformFolder));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_computedFingerprint != 0);
|
||||
@@ -659,8 +665,8 @@ namespace AssetProcessor
|
||||
|
||||
|
||||
QStringList es3outs;
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefile.arc1"));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefile.arc2"));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc1")));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc2")));
|
||||
|
||||
// feed it the messages its waiting for (create the files)
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products."));
|
||||
@@ -790,7 +796,7 @@ namespace AssetProcessor
|
||||
assetMessages.clear();
|
||||
|
||||
es3outs.clear();
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefile.azm"));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.azm")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products."));
|
||||
|
||||
//Invoke Asset Processed for es3 platform , txt files2 job description
|
||||
@@ -815,7 +821,7 @@ namespace AssetProcessor
|
||||
assetMessages.clear();
|
||||
|
||||
QStringList pcouts;
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc1")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "products."));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -843,7 +849,7 @@ namespace AssetProcessor
|
||||
assetMessages.clear();
|
||||
|
||||
pcouts.clear();
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.azm"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.azm")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "products."));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -1012,7 +1018,7 @@ namespace AssetProcessor
|
||||
{
|
||||
QString processFile1 = processResults[checkIdx].m_jobEntry.GetAbsoluteSourcePath();
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::NormalizeFilePath(processFile1) == AssetUtilities::NormalizeFilePath(absolutePath));
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()) + "/" + gameName.toLower());
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()));
|
||||
platformFolder = AssetUtilities::NormalizeDirectoryPath(platformFolder);
|
||||
processFile1 = processResults[checkIdx].m_destinationPath;
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1.startsWith(platformFolder));
|
||||
@@ -1029,12 +1035,12 @@ namespace AssetProcessor
|
||||
QStringList pcouts2;
|
||||
es3outs.clear();
|
||||
pcouts.clear();
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefilea.arc1"));
|
||||
es3outs2.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefilea.azm"));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefilea.arc1")));
|
||||
es3outs2.push_back(cacheRoot.filePath(QString("es3/basefilea.azm")));
|
||||
// note that the ES3 outs have changed
|
||||
// but the pc outs are still the same.
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc1"));
|
||||
pcouts2.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.azm"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc1")));
|
||||
pcouts2.push_back(cacheRoot.filePath(QString("pc/basefile.azm")));
|
||||
|
||||
// feed it the messages its waiting for (create the files)
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile."));
|
||||
@@ -1155,7 +1161,7 @@ namespace AssetProcessor
|
||||
{
|
||||
QString processFile1 = processResults[checkIdx].m_jobEntry.GetAbsoluteSourcePath();
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::NormalizeFilePath(processFile1) == AssetUtilities::NormalizeFilePath(absolutePath));
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()) + "/" + gameName.toLower());
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()));
|
||||
platformFolder = AssetUtilities::NormalizeDirectoryPath(platformFolder);
|
||||
processFile1 = processResults[checkIdx].m_destinationPath;
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1.startsWith(platformFolder));
|
||||
@@ -1261,7 +1267,7 @@ namespace AssetProcessor
|
||||
// 4 * file claimed for the produce file to be able to update it safely.
|
||||
// 4 * file released for the produce file so it's free for other tools to use it again.
|
||||
UNIT_TEST_EXPECT_TRUE(payloadList.size() == 9);
|
||||
unsigned int messageLoadCount = 0;
|
||||
unsigned int messageLoadCount = 0;
|
||||
for (auto payload : payloadList)
|
||||
{
|
||||
if (payload.first == SourceFileNotificationMessage::MessageType)
|
||||
@@ -1487,9 +1493,9 @@ namespace AssetProcessor
|
||||
|
||||
pcouts.clear();
|
||||
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/subfolder3/randomfileoutput.random2"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/subfolder3/randomfileoutput.random")));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/subfolder3/randomfileoutput.random1")));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/subfolder3/randomfileoutput.random2")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "products."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[1], "products."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[2], "products."));
|
||||
@@ -1535,12 +1541,12 @@ namespace AssetProcessor
|
||||
es3outs2.clear();
|
||||
pcouts.clear();
|
||||
pcouts2.clear();
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefilez.arc2"));
|
||||
es3outs2.push_back(cacheRoot.filePath(QString("es3/") + gameName + "/basefileaz.azm2"));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefilez.arc2")));
|
||||
es3outs2.push_back(cacheRoot.filePath(QString("es3/basefileaz.azm2")));
|
||||
// note that the ES3 outs have changed
|
||||
// but the pc outs are still the same.
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc2"));
|
||||
pcouts2.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.azm2"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc2")));
|
||||
pcouts2.push_back(cacheRoot.filePath(QString("pc/basefile.azm2")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile."));
|
||||
@@ -1629,7 +1635,7 @@ namespace AssetProcessor
|
||||
{
|
||||
QString processFile1 = processResults[checkIdx].m_jobEntry.GetAbsoluteSourcePath();
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1 == expectedReplacementInputFile);
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()) + "/" + gameName.toLower());
|
||||
QString platformFolder = cacheRoot.filePath(QString::fromUtf8(processResults[checkIdx].m_jobEntry.m_platformInfo.m_identifier.c_str()));
|
||||
platformFolder = AssetUtilities::NormalizeDirectoryPath(platformFolder);
|
||||
processFile1 = processResults[checkIdx].m_destinationPath;
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1.startsWith(platformFolder));
|
||||
@@ -1951,13 +1957,13 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
|
||||
|
||||
// it now believes that there are a whole bunch of assets in subfolder1/done_renaming and they resulted in
|
||||
// a whole bunch of files to have been created in the asset cache, listed in processresults, and they exist in outputscreated...
|
||||
// rename the output folder:
|
||||
|
||||
QString originalCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/" + gameName.toLower() + "/done_renaming";
|
||||
QString newCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/" + gameName.toLower() + "/renamed_again";
|
||||
QString originalCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/done_renaming";
|
||||
QString newCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/renamed_again";
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(renamer.rename(originalCacheFolderName, newCacheFolderName));
|
||||
|
||||
@@ -2017,8 +2023,8 @@ namespace AssetProcessor
|
||||
|
||||
// setup complete. now RENAME that folder.
|
||||
|
||||
originalCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/" + gameName.toLower() + "/rename_this_secondly";
|
||||
newCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/" + gameName.toLower() + "/done_renaming_again";
|
||||
originalCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/rename_this_secondly";
|
||||
newCacheFolderName = normalizedCacheRootDir.absoluteFilePath("pc") + "/done_renaming_again";
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(renamer.rename(originalCacheFolderName, newCacheFolderName));
|
||||
|
||||
@@ -2305,8 +2311,7 @@ namespace AssetProcessor
|
||||
UnitTestUtils::ScopedDir changeDir(dir.path());
|
||||
QDir tempPath(dir.path());
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName(AssetProcessorManagerTestGameProject);
|
||||
QString gameName = AssetUtilities::ComputeProjectName(AssetProcessorManagerTestGameProject);
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
@@ -2382,8 +2387,8 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_jobKey.compare(processResults[1].m_jobEntry.m_jobKey) != 0);
|
||||
|
||||
QStringList pcouts;
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc2"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc1")));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc2")));
|
||||
|
||||
// Create the product files for the first job
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "product1"));
|
||||
@@ -2416,7 +2421,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::NormalizeFilePath(changedInputResults[0].first) == AssetUtilities::NormalizeFilePath(sourceFile));
|
||||
|
||||
pcouts.clear();
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/basefile.arc3"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc3")));
|
||||
// Create the product files for the second job
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "product1"));
|
||||
|
||||
@@ -2515,9 +2520,7 @@ namespace AssetProcessor
|
||||
UnitTestUtils::ScopedDir changeDir(dir.path());
|
||||
QDir tempPath(dir.path());
|
||||
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName(AssetProcessorManagerTestGameProject);
|
||||
QString gameName = AssetUtilities::ComputeProjectName(AssetProcessorManagerTestGameProject);
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
@@ -2745,7 +2748,7 @@ namespace AssetProcessor
|
||||
}
|
||||
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
|
||||
};
|
||||
|
||||
|
||||
AssetProcessor::AssetBuilderInfoBus::Handler::BusConnect();
|
||||
QDir oldRoot;
|
||||
AssetUtilities::ComputeAssetRoot(oldRoot);
|
||||
@@ -2757,8 +2760,7 @@ namespace AssetProcessor
|
||||
UnitTestUtils::ScopedDir changeDir(dir.path());
|
||||
QDir tempPath(dir.path());
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName(AssetProcessorManagerTestGameProject);
|
||||
QString gameName = AssetUtilities::ComputeProjectName(AssetProcessorManagerTestGameProject);
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
@@ -2803,11 +2805,11 @@ namespace AssetProcessor
|
||||
QDir cacheRoot;
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::ComputeProjectCacheRoot(cacheRoot));
|
||||
|
||||
QString productFileAPath = cacheRoot.filePath(QString("pc/") + gameName + "/FileAProduct.txt");
|
||||
QString productFileBPath = cacheRoot.filePath(QString("pc/") + gameName + "/FileBProduct1.txt");
|
||||
QString product2FileBPath = cacheRoot.filePath(QString("pc/") + gameName + "/FileBProduct2.txt");
|
||||
QString productFileCPath = cacheRoot.filePath(QString("pc/") + gameName + "/FileCProduct.txt");
|
||||
QString product2FileCPath = cacheRoot.filePath(QString("pc/") + gameName + "/FileCProduct2.txt");
|
||||
QString productFileAPath = cacheRoot.filePath(QString("pc/FileAProduct.txt"));
|
||||
QString productFileBPath = cacheRoot.filePath(QString("pc/FileBProduct1.txt"));
|
||||
QString product2FileBPath = cacheRoot.filePath(QString("pc/FileBProduct2.txt"));
|
||||
QString productFileCPath = cacheRoot.filePath(QString("pc/FileCProduct.txt"));
|
||||
QString product2FileCPath = cacheRoot.filePath(QString("pc/FileCProduct2.txt"));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(sourceFileAPath, ""));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(sourceFileBPath, ""));
|
||||
@@ -2817,7 +2819,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(product2FileBPath, "product"));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(productFileCPath, "product"));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(product2FileCPath, "product"));
|
||||
|
||||
|
||||
// Analyze FileA
|
||||
QMetaObject::invokeMethod(&apm, "AssessAddedFile", Qt::QueuedConnection, Q_ARG(QString, sourceFileAPath));
|
||||
|
||||
@@ -2927,7 +2929,7 @@ namespace AssetProcessor
|
||||
{
|
||||
// Ensure that we are processing the right FileB job
|
||||
UNIT_TEST_EXPECT_TRUE(QString(jobDetail.m_jobEntry.m_jobKey).compare("yyy") == 0);
|
||||
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(product2FileBPath.toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, jobDetail.m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
@@ -2981,7 +2983,7 @@ namespace AssetProcessor
|
||||
|
||||
processResults.clear();
|
||||
// Modify fingerprint of Job("FileA", "xxx", "pc") and analyze FileA again,
|
||||
changeJobAFingerprint = false; // This will revert back the changes in the extra info used for fingerprinting of this job
|
||||
changeJobAFingerprint = false; // This will revert back the changes in the extra info used for fingerprinting of this job
|
||||
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, sourceFileAPath));
|
||||
|
||||
@@ -3001,7 +3003,7 @@ namespace AssetProcessor
|
||||
{
|
||||
// Verify FileB jobinfo
|
||||
UNIT_TEST_EXPECT_TRUE(QString(jobDetail.m_jobEntry.m_jobKey).compare("yyy") == 0);
|
||||
|
||||
|
||||
}
|
||||
else if (QString(jobDetail.m_jobEntry.m_pathRelativeToWatchFolder).endsWith("FileC.txt"))
|
||||
{
|
||||
@@ -3011,14 +3013,14 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
|
||||
// Since one of the FileC job("FileC.txt","zzz") have emitted a job dependency on a FileB job("FileB.txt", "yyy")
|
||||
// which also have a job dependency on a FileA job("FileA.txt", "xxx") therefore deleting File A source file should
|
||||
// Since one of the FileC job("FileC.txt","zzz") have emitted a job dependency on a FileB job("FileB.txt", "yyy")
|
||||
// which also have a job dependency on a FileA job("FileA.txt", "xxx") therefore deleting File A source file should
|
||||
// cause both jobs (File B and File C) to be processed again.
|
||||
|
||||
|
||||
processResults.clear();
|
||||
|
||||
QFile::remove(sourceFileAPath);
|
||||
|
||||
|
||||
QMetaObject::invokeMethod(&apm, "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, sourceFileAPath));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
@@ -3053,7 +3055,7 @@ namespace AssetProcessor
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
|
||||
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 3);
|
||||
|
||||
for (JobDetails& jobDetail : processResults)
|
||||
@@ -3091,15 +3093,14 @@ namespace AssetProcessor
|
||||
|
||||
// the canonicalization of the path here is to get around the fact that on some platforms
|
||||
// the "temporary" folder location could be junctioned into some other folder and getting "QDir::current()"
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
// and other similar functions may actually return a different string but still be referring to the same folder
|
||||
QTemporaryDir dir;
|
||||
QDir tempPath(dir.path());
|
||||
QString canonicalTempDirPath = AssetUtilities::NormalizeDirectoryPath(tempPath.canonicalPath());
|
||||
UnitTestUtils::ScopedDir changeDir(canonicalTempDirPath);
|
||||
tempPath = QDir(canonicalTempDirPath);
|
||||
|
||||
// system is already actually initialized, along with gEnv, so this will always return that game name.
|
||||
QString gameName = AssetUtilities::ComputeGameName(AssetProcessorManagerTestGameProject);
|
||||
QString gameName = AssetUtilities::ComputeProjectName(AssetProcessorManagerTestGameProject);
|
||||
|
||||
// update the engine root
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
@@ -3116,7 +3117,7 @@ namespace AssetProcessor
|
||||
|
||||
// note: the crux of this test is that we ar redirecting output into the cache at a different location instead of default.
|
||||
// so our scan folder has a "redirected" folder.
|
||||
config.AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder1"), "subfolder1", "subfolder1", "redirected", false, true, platforms, -1));
|
||||
config.AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder1"), "subfolder1", "subfolder1", "redirected", false, true, platforms, -1));
|
||||
|
||||
AssetProcessorManager_Test apm(&config);
|
||||
|
||||
@@ -3173,7 +3174,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_watchFolderPath == tempPath.filePath("subfolder1"));
|
||||
|
||||
QStringList pcouts;
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/redirected/basefile.arc1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/redirected/basefile.arc1")));
|
||||
|
||||
// Create the product files for the first job
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "product1"));
|
||||
@@ -3230,7 +3231,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_databaseSourceName == "redirected/basefile.foo");
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_watchFolderPath == tempPath.absoluteFilePath("subfolder1"));
|
||||
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/redirected/basefile.arc1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/redirected/basefile.arc1")));
|
||||
|
||||
// Create the product files for the first job
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "product1"));
|
||||
@@ -3260,7 +3261,7 @@ namespace AssetProcessor
|
||||
assetMessages.clear();
|
||||
changedInputResults.clear();
|
||||
|
||||
QString deletedProductPath = cacheRoot.filePath(QString("pc/") + gameName + "/redirected/basefile.arc1");
|
||||
QString deletedProductPath = cacheRoot.filePath(QString("pc/redirected/basefile.arc1"));
|
||||
|
||||
QFile::remove(deletedProductPath);
|
||||
|
||||
@@ -3279,7 +3280,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_databaseSourceName == "redirected/basefile.foo");
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_watchFolderPath == tempPath.absoluteFilePath("subfolder1"));
|
||||
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/") + gameName + "/redirected/basefile.arc1"));
|
||||
pcouts.push_back(cacheRoot.filePath(QString("pc/redirected/basefile.arc1")));
|
||||
|
||||
// Create the product files for the first job
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "product1"));
|
||||
|
||||
@@ -78,9 +78,8 @@ void AssetProcessorServerUnitTest::RunFirstPartOfUnitTestsForAssetProcessorServe
|
||||
|
||||
void AssetProcessorServerUnitTest::RunAssetProcessorConnectionStressTest(bool failNegotiation)
|
||||
{
|
||||
AZStd::string azAppRoot = AZStd::string(QDir::current().absolutePath().toUtf8().constData());
|
||||
AZStd::string azBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForAppRoot, azBranchToken);
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForEngineRoot, azBranchToken);
|
||||
|
||||
QString branchToken(azBranchToken.c_str());
|
||||
|
||||
@@ -99,7 +98,7 @@ void AssetProcessorServerUnitTest::RunAssetProcessorConnectionStressTest(bool fa
|
||||
for (int idx = 0; idx < NUMBER_OF_TRIES; ++idx)
|
||||
{
|
||||
AzFramework::AssetSystem::AssetProcessorConnection connection;
|
||||
connection.Configure(branchToken.toUtf8().data(), "pc", "UNITTEST", AssetUtilities::ComputeGameName().toUtf8().constData()); // UNITTEST identifier will skip the processID validation during negotiation
|
||||
connection.Configure(branchToken.toUtf8().data(), "pc", "UNITTEST", AssetUtilities::ComputeProjectName().toUtf8().constData()); // UNITTEST identifier will skip the processID validation during negotiation
|
||||
connection.Connect("127.0.0.1", FEATURE_TEST_LISTEN_PORT);
|
||||
while (!connection.IsConnected() && !connection.NegotiationFailed())
|
||||
{
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace UnitTestUtils
|
||||
|
||||
m_localFileIO->SetAlias("@assets@", (newDir + QString("/ALIAS/assets")).toUtf8().constData());
|
||||
m_localFileIO->SetAlias("@log@", (newDir + QString("/ALIAS/logs")).toUtf8().constData());
|
||||
m_localFileIO->SetAlias("@cache@", (newDir + QString("/ALIAS/cache")).toUtf8().constData());
|
||||
m_localFileIO->SetAlias("@usercache@", (newDir + QString("/ALIAS/cache")).toUtf8().constData());
|
||||
m_localFileIO->SetAlias("@user@", (newDir + QString("/ALIAS/user")).toUtf8().constData());
|
||||
m_localFileIO->SetAlias("@root@", (newDir + QString("/ALIAS/root")).toUtf8().constData());
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ using namespace AssetProcessor;
|
||||
namespace AssetProcessor
|
||||
{
|
||||
const char* const TEST_BOOTSTRAP_DATA =
|
||||
"sys_game_folder = TestProject \r\n\
|
||||
"project_path = TestProject \r\n\
|
||||
assets = pc \r\n\
|
||||
-- ip and port of the asset processor.Only if you need to change defaults \r\n\
|
||||
-- remote_ip = 127.0.0.1 \r\n\
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "native/utilities/ApplicationManager.h"
|
||||
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
@@ -83,7 +84,7 @@ namespace AssetProcessor
|
||||
// we are in a job thread - return early to make it so that the global log file does not get this message
|
||||
// there will also be a log listener in the actual job log thread which will get the message too, and that one
|
||||
// will write it to the individual log.
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
AzFramework::LogComponent::OutputMessage(severity, window, message);
|
||||
@@ -119,29 +120,14 @@ AssetProcessorAZApplication::AssetProcessorAZApplication(int* argc, char*** argv
|
||||
*AZ::SettingsRegistry::Get(), AssetProcessorBuildTarget::GetBuildTargetName());
|
||||
|
||||
// Adding the PreModuleLoad event to the AssetProcessor application for logging when a gem loads
|
||||
m_preModuleLoadHandler = AZ::ModuleManagerRequests::PreModuleLoadEvent::Handler{ []([[maybe_unused]] AZStd::string_view modulePath)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Loading (Gem) Module '%.*s'...\n", aznumeric_cast<int>(modulePath.size()), modulePath.data());
|
||||
} };
|
||||
m_preModuleLoadHandler = AZ::ModuleManagerRequests::PreModuleLoadEvent::Handler{
|
||||
[]([[maybe_unused]] AZStd::string_view modulePath)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Loading (Gem) Module '%.*s'...\n", aznumeric_cast<int>(modulePath.size()), modulePath.data());
|
||||
}
|
||||
};
|
||||
|
||||
m_preModuleLoadHandler.Connect(m_moduleManager->m_preModuleLoadEvent);
|
||||
|
||||
// Override the /Amazon/AzCore/Bootstrap/sys_game_folder entry in the Settings Registry using the -gamefolder parameter
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (m_commandLine.GetNumSwitchValues("gamefolder") > 0)
|
||||
{
|
||||
const AZStd::string& gameFolderOverride = m_commandLine.GetSwitchValue("gamefolder", 0);
|
||||
auto gameFolderCommandLineOverride = AZStd::string::format("--regset=%s/sys_game_folder=%s", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
|
||||
gameFolderOverride.c_str());
|
||||
|
||||
AZ::CommandLine::ParamContainer commandLineArgs;
|
||||
m_commandLine.Dump(commandLineArgs);
|
||||
commandLineArgs.emplace_back(gameFolderCommandLineOverride);
|
||||
m_commandLine.Parse(commandLineArgs);
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*settingsRegistry, m_commandLine, false);
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*settingsRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::ComponentTypeList AssetProcessorAZApplication::GetRequiredSystemComponents() const
|
||||
@@ -155,7 +141,7 @@ AZ::ComponentTypeList AssetProcessorAZApplication::GetRequiredSystemComponents()
|
||||
|| *iter == AZ::Uuid("{624a7be2-3c7e-4119-aee2-1db2bdb6cc89}") // ScriptDebugAgent
|
||||
|| *iter == AZ::Uuid("{CAF3A025-FAC9-4537-B99E-0A800A9326DF}") // InputSystemComponent
|
||||
|| *iter == azrtti_typeid<AssetProcessor::ToolsAssetCatalogComponent>()
|
||||
)
|
||||
)
|
||||
{
|
||||
// AP does not require the above components to be active
|
||||
iter = components.erase(iter);
|
||||
@@ -274,7 +260,7 @@ void ApplicationManager::GetExternalBuilderFileList(QStringList& externalBuilder
|
||||
|
||||
if (externalBuilderModules.empty())
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "AssetProcessor was unable to locate any builders\n");
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "AssetProcessor was unable to locate any external builders\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,9 +270,16 @@ QDir ApplicationManager::GetSystemRoot() const
|
||||
{
|
||||
return m_systemRoot;
|
||||
}
|
||||
QString ApplicationManager::GetGameName() const
|
||||
QString ApplicationManager::GetProjectPath() const
|
||||
{
|
||||
return m_gameName;
|
||||
auto projectPath = AZ::Utils::GetProjectPath();
|
||||
if (!projectPath.empty())
|
||||
{
|
||||
return QString::fromUtf8(projectPath.c_str(), aznumeric_cast<int>(projectPath.size()));
|
||||
}
|
||||
|
||||
AZ_Warning("AssetUtils", false, "Unable to obtain the Project Path from the settings registry.");
|
||||
return {};
|
||||
}
|
||||
|
||||
QCoreApplication* ApplicationManager::GetQtApplication()
|
||||
@@ -451,7 +444,7 @@ void ApplicationManager::PopulateApplicationDependencies()
|
||||
m_filesOfInterest.push_back(applicationPath);
|
||||
|
||||
// add some known-dependent files (this can be removed when they are no longer a dependency)
|
||||
// Note that its not necessary for any of these files to actually exist. It is considered a "change" if they
|
||||
// Note that its not necessary for any of these files to actually exist. It is considered a "change" if they
|
||||
// change their file modtime, or if they go from existing to not existing, or if they go from not existing, to existing.
|
||||
// any of those should cause AP to drop.
|
||||
for (const QString& pathName : { "CrySystem",
|
||||
@@ -475,11 +468,10 @@ void ApplicationManager::PopulateApplicationDependencies()
|
||||
QDir assetRoot;
|
||||
AssetUtilities::ComputeAssetRoot(assetRoot);
|
||||
|
||||
QString globalConfigPath = assetRoot.filePath("AssetProcessorPlatformConfig.ini");
|
||||
QString globalConfigPath = assetRoot.filePath("AssetProcessorPlatformConfig.setreg");
|
||||
m_filesOfInterest.push_back(globalConfigPath);
|
||||
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString gamePlatformConfigPath = assetRoot.filePath(gameName + "/AssetProcessorGamePlatformConfig.ini");
|
||||
QString gamePlatformConfigPath = QDir(AssetUtilities::ComputeProjectPath()).filePath("AssetProcessorGamePlatformConfig.setreg");
|
||||
m_filesOfInterest.push_back(gamePlatformConfigPath);
|
||||
|
||||
// add app modules
|
||||
@@ -510,43 +502,14 @@ void ApplicationManager::PopulateApplicationDependencies()
|
||||
}
|
||||
}
|
||||
|
||||
bool ApplicationManager::StartAZFramework(QString appRootOverride)
|
||||
bool ApplicationManager::StartAZFramework()
|
||||
{
|
||||
AzFramework::Application::Descriptor appDescriptor;
|
||||
AZ::ComponentApplication::StartupParameters params;
|
||||
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString projectName = AssetUtilities::ComputeProjectName();
|
||||
AZ::SettingsRegistryInterface& registry = *AZ::SettingsRegistry::Get();
|
||||
// Add the supplied gameName as specialization key in the registry
|
||||
if (!gameName.isEmpty())
|
||||
{
|
||||
auto gameNameSpecialization = QString("%1/%2").arg(AZ::SettingsRegistryMergeUtils::SpecializationsRootKey).arg(gameName);
|
||||
QByteArray specializationByteArray = gameNameSpecialization.toUtf8();
|
||||
registry.Set(AZStd::string_view(specializationByteArray.data(), specializationByteArray.size()), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the project name as a registry specialization
|
||||
auto projectKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/sys_game_folder", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
|
||||
if (AZ::SettingsRegistryInterface::FixedValueString bootstrapProjectName; registry.Get(bootstrapProjectName, projectKey) && !bootstrapProjectName.empty())
|
||||
{
|
||||
registry.Set(AZ::SettingsRegistryInterface::FixedValueString::format("%s/%s",
|
||||
AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, bootstrapProjectName.c_str()),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
// The application will live in a bin folder one level up from the app root.
|
||||
static char s_storageForRootPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
if (!appRootOverride.isEmpty())
|
||||
{
|
||||
azstrcpy(s_storageForRootPath, AZ_MAX_PATH_LEN, appRootOverride.toUtf8().data());
|
||||
params.m_appRootOverride = s_storageForRootPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
params.m_appRootOverride = nullptr;
|
||||
}
|
||||
// Prevent loading of gems in the Create method of the ComponentApplication
|
||||
params.m_loadDynamicModules = false;
|
||||
|
||||
@@ -556,31 +519,27 @@ bool ApplicationManager::StartAZFramework(QString appRootOverride)
|
||||
AZ::Debug::Trace::HandleExceptions(true);
|
||||
|
||||
m_frameworkApp.Start(appDescriptor, params);
|
||||
|
||||
|
||||
//Registering all the Components
|
||||
m_frameworkApp.RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor());
|
||||
|
||||
|
||||
|
||||
Reflect();
|
||||
|
||||
QDir engineRoot;
|
||||
AssetUtilities::ComputeEngineRoot(engineRoot);
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@devroot@", engineRoot.absolutePath().toUtf8().data());
|
||||
|
||||
const AzFramework::CommandLine* commandLine = nullptr;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
|
||||
if (commandLine && commandLine->HasSwitch("logDir"))
|
||||
{
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@log@", commandLine->GetSwitchValue("logDir", 0).c_str());
|
||||
}
|
||||
else
|
||||
else if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
char executableDirectory[AZ_MAX_PATH_LEN];
|
||||
if (AZ::Utils::GetExecutableDirectory(executableDirectory, AZStd::size(executableDirectory)) == AZ::Utils::ExecutablePathResult::Success)
|
||||
{
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@log@", executableDirectory);
|
||||
}
|
||||
AZ::IO::Path projectUserPath;
|
||||
settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
|
||||
AZ::IO::Path logUserPath = projectUserPath / "log";
|
||||
auto fileIo = AZ::IO::FileIOBase::GetInstance();
|
||||
fileIo->SetAlias("@log@", logUserPath.c_str());
|
||||
}
|
||||
m_entity = aznew AZ::Entity("Application Entity");
|
||||
if (m_entity)
|
||||
@@ -622,7 +581,6 @@ bool ApplicationManager::ActivateModules()
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Cannot compute the asset root folder. Is AssetProcessor being run from the appropriate folder?");
|
||||
return false;
|
||||
}
|
||||
assetRoot.cd(AssetUtilities::ComputeGameName());
|
||||
|
||||
m_frameworkApp.LoadDynamicModules();
|
||||
return true;
|
||||
@@ -633,89 +591,13 @@ void ApplicationManager::addRunningThread(AssetProcessor::ThreadWorker* thread)
|
||||
m_runningThreads.push_back(thread);
|
||||
}
|
||||
|
||||
QString ApplicationManager::ParseOptionAppRootArgument()
|
||||
{
|
||||
AZ_Assert(m_qApp!=nullptr,"m_qApp not initialized. QT application must be created before this call.")
|
||||
// Parse any parameters.
|
||||
static const char* app_root_parameter = "app-root";
|
||||
static const char* app_root_parameter_desc = "Optional external path outside of the current engine to set as the application root.";
|
||||
QCommandLineOption appRootPathOption(QString(app_root_parameter), tr(app_root_parameter_desc), QString("path"));
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Asset Processor");
|
||||
parser.addOption(appRootPathOption);
|
||||
parser.parse(m_qApp->arguments());
|
||||
|
||||
QString appRootArgValue = parser.value(appRootPathOption);
|
||||
appRootArgValue.remove(QChar('\"'));
|
||||
return appRootArgValue.trimmed();
|
||||
}
|
||||
|
||||
bool ApplicationManager::ValidateExternalAppRoot(QString appRootPath) const
|
||||
{
|
||||
static const char* bootstrap_cfg_name = "bootstrap.cfg";
|
||||
|
||||
QDir testAppRootPath(appRootPath);
|
||||
|
||||
// Make sure the path exists
|
||||
if (!testAppRootPath.exists())
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, testAppRootPath.exists(), "Invalid Application Root path override (--app-root): %s. Directory does not exist.\n", appRootPath.toUtf8().data());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the path contains bootstrap.cfg
|
||||
if (!testAppRootPath.exists(bootstrap_cfg_name))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, testAppRootPath.exists(), "Invalid Application Root path override (--app-root): %s. Directory does not contain %s.\n", appRootPath.toUtf8().data(), bootstrap_cfg_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we can read the 'sys_game_folder' settings from bootstrap.cfg
|
||||
QSettings settings(testAppRootPath.absoluteFilePath(bootstrap_cfg_name), QSettings::Format::IniFormat);
|
||||
static const char* sysGameFolderKeyName = "sys_game_folder";
|
||||
auto sysGameFolderSettings = settings.value(sysGameFolderKeyName);
|
||||
if (!sysGameFolderSettings.isValid() || sysGameFolderSettings.isNull())
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, testAppRootPath.exists(), "Invalid Application Root path override (--app-root): %s. %s in the path is not valid.\n", appRootPath.toUtf8().data(), bootstrap_cfg_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the 'sys_game_folder' value in the external bootstrap.cfg points to a valid subfolder in that path
|
||||
QString sysGameFolder = sysGameFolderSettings.toString();
|
||||
QDir gameFolderPath(appRootPath);
|
||||
if (!gameFolderPath.cd(sysGameFolder))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, testAppRootPath.exists(), "Invalid Application Root path override (--app-root): %s. Configured Game folder %s in the path is not valid.\n", appRootPath.toUtf8().data(), sysGameFolder.toUtf8().data());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ApplicationManager::BeforeRunStatus ApplicationManager::BeforeRun()
|
||||
{
|
||||
// Create the Qt Application
|
||||
CreateQtApplication();
|
||||
|
||||
// Calculate the override app root path if provided and validate it before passing it along
|
||||
QString overrideAppRootPath = ParseOptionAppRootArgument();
|
||||
|
||||
if (!overrideAppRootPath.isEmpty())
|
||||
{
|
||||
if (ValidateExternalAppRoot(overrideAppRootPath))
|
||||
{
|
||||
QDir overrideAppRoot(overrideAppRootPath);
|
||||
QDir resultAppRoot;
|
||||
AssetUtilities::ComputeAssetRoot(resultAppRoot, &overrideAppRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Invalid override app root folder '%s'.", overrideAppRootPath.toUtf8().data());
|
||||
return ApplicationManager::BeforeRunStatus::Status_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
if (!StartAZFramework(overrideAppRootPath))
|
||||
if (!StartAZFramework())
|
||||
{
|
||||
return ApplicationManager::BeforeRunStatus::Status_Failure;
|
||||
}
|
||||
@@ -742,14 +624,13 @@ bool ApplicationManager::Activate()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_gameName = AssetUtilities::ComputeGameName();
|
||||
|
||||
if (m_gameName.isEmpty())
|
||||
auto projectName = AssetUtilities::ComputeProjectName();
|
||||
if (projectName.isEmpty())
|
||||
{
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Unable to detect name of current game project. Is bootstrap.cfg appropriately configured?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// the following controls what registry keys (or on mac or linux what entries in home folder) are used
|
||||
// so they should not be translated!
|
||||
qApp->setOrganizationName(GetOrganizationName());
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
QCoreApplication* GetQtApplication();
|
||||
|
||||
QDir GetSystemRoot() const;
|
||||
QString GetGameName() const;
|
||||
QString GetProjectPath() const;
|
||||
|
||||
void RegisterComponentDescriptor(const AZ::ComponentDescriptor* descriptor);
|
||||
|
||||
@@ -163,9 +163,7 @@ protected:
|
||||
virtual const char* GetLogBaseName() = 0;
|
||||
virtual RegistryCheckInstructions PopupRegistryProblemsMessage(QString warningText) = 0;
|
||||
private:
|
||||
bool StartAZFramework(QString appRootOverride);
|
||||
bool ValidateExternalAppRoot(QString appRootPath) const;
|
||||
QString ParseOptionAppRootArgument();
|
||||
bool StartAZFramework();
|
||||
|
||||
// QuitPair - Object pointer and "is ready" boolean pair.
|
||||
typedef QPair<QObject*, bool> QuitPair;
|
||||
@@ -178,7 +176,6 @@ private:
|
||||
bool m_needRestart = false;
|
||||
bool m_queuedCheckQuit = false;
|
||||
QDir m_systemRoot;
|
||||
QString m_gameName;
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
|
||||
};
|
||||
|
||||
@@ -337,13 +337,13 @@ bool ApplicationManagerBase::InitPlatformConfiguration()
|
||||
m_platformConfiguration = new AssetProcessor::PlatformConfiguration();
|
||||
QDir assetRoot;
|
||||
AssetUtilities::ComputeAssetRoot(assetRoot);
|
||||
return m_platformConfiguration->InitializeFromConfigFiles(GetSystemRoot().absolutePath(), assetRoot.absolutePath(), GetGameName());
|
||||
return m_platformConfiguration->InitializeFromConfigFiles(GetSystemRoot().absolutePath(), assetRoot.absolutePath(), GetProjectPath());
|
||||
}
|
||||
|
||||
bool ApplicationManagerBase::InitBuilderConfiguration()
|
||||
{
|
||||
m_builderConfig = AZStd::make_unique<AssetProcessor::BuilderConfigurationManager>();
|
||||
QString configFile = GetSystemRoot().absoluteFilePath(GetGameName() + "/" + AssetProcessor::BuilderConfigFile);
|
||||
QString configFile = QDir(GetProjectPath()).absoluteFilePath(AssetProcessor::BuilderConfigFile);
|
||||
|
||||
if (!QFile::exists(configFile))
|
||||
{
|
||||
@@ -1193,7 +1193,8 @@ bool ApplicationManagerBase::Activate()
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "AssetProcessor will process assets from gameproject %s.\n", AssetUtilities::ComputeGameName().toUtf8().data());
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel,
|
||||
"AssetProcessor will process assets from project root %s.\n", AssetUtilities::ComputeProjectPath().toUtf8().data());
|
||||
|
||||
// Shutdown if the disk has less than 128MB of free space
|
||||
if (!CheckSufficientDiskSpace(projectCache.absolutePath(), 128 * 1024 * 1024, true))
|
||||
@@ -1219,7 +1220,7 @@ bool ApplicationManagerBase::Activate()
|
||||
|
||||
if (!InitPlatformConfiguration())
|
||||
{
|
||||
AZ_Error("AssetProcessor", false, "Failed to Initialize from AssetProcessorPlatformConfig.ini - check the log files in the logs/ subfolder for more information.");
|
||||
AZ_Error("AssetProcessor", false, "Failed to Initialize from AssetProcessorPlatformConfig.setreg - check the log files in the logs/ subfolder for more information.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1401,7 +1402,7 @@ bool ApplicationManagerBase::InitializeExternalBuilders()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationManagerBase::WaitForBuilderExit(AzToolsFramework::ProcessWatcher* processWatcher, AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds)
|
||||
bool ApplicationManagerBase::WaitForBuilderExit(AzFramework::ProcessWatcher* processWatcher, AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds)
|
||||
{
|
||||
AZ::u32 exitCode = 0;
|
||||
bool finishedOK = false;
|
||||
|
||||
@@ -177,7 +177,7 @@ protected:
|
||||
|
||||
AssetProcessor::AssetCatalog* GetAssetCatalog() const { return m_assetCatalog; }
|
||||
|
||||
static bool WaitForBuilderExit(AzToolsFramework::ProcessWatcher* processWatcher, AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds);
|
||||
static bool WaitForBuilderExit(AzFramework::ProcessWatcher* processWatcher, AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds);
|
||||
|
||||
ApplicationServer* m_applicationServer = nullptr;
|
||||
ConnectionManager* m_connectionManager = nullptr;
|
||||
|
||||
@@ -142,10 +142,6 @@ namespace AssetProcessor
|
||||
|
||||
bool Builder::Start()
|
||||
{
|
||||
// Get the app root to locate the builders
|
||||
AZStd::string appRootString;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(appRootString, &AzFramework::ApplicationRequests::GetAppRoot);
|
||||
|
||||
// Get the current BinXXX folder based on the current running AP
|
||||
QString applicationDir = QCoreApplication::instance()->applicationDirPath();
|
||||
|
||||
@@ -190,24 +186,26 @@ namespace AssetProcessor
|
||||
QDir projectCacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
|
||||
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
|
||||
AZStd::string appRootString;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(appRootString, &AzFramework::ApplicationRequests::GetAppRoot);
|
||||
QDir appRoot(QString(appRootString.c_str()));
|
||||
QString gameRoot = appRoot.absoluteFilePath(gameName);
|
||||
QString gameName = AssetUtilities::ComputeProjectName();
|
||||
QString projectPath = AssetUtilities::ComputeProjectPath();
|
||||
QDir engineRoot;
|
||||
AssetUtilities::ComputeEngineRoot(engineRoot);
|
||||
|
||||
int portNumber = 0;
|
||||
ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort);
|
||||
|
||||
AZStd::string params;
|
||||
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
params = AZStd::string::format(R"(-task=%s -id="%s" -gamename="%s" -gamecache="%s" -gameroot="%s" -port %d)",
|
||||
task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(), gameRoot.toUtf8().constData(), portNumber);
|
||||
#else
|
||||
params = AZStd::string::format(R"(-task=%s -id="%s" -gamename="\"%s\"" -gamecache="\"%s\"" -gameroot="\"%s\"" -port %d)",
|
||||
task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(), gameRoot.toUtf8().constData(), portNumber);
|
||||
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
params = AZStd::string::format(
|
||||
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)", task,
|
||||
builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
|
||||
#else
|
||||
params = AZStd::string::format(
|
||||
R"(-task=%s -id="%s" -project-name="\"%s\"" -project-cache-path="\"%s\"" -project-path="\"%s\"" -engine-path="\"%s\"" -port %d)",
|
||||
task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
|
||||
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
if (moduleFilePath && moduleFilePath[0])
|
||||
{
|
||||
@@ -230,17 +228,17 @@ namespace AssetProcessor
|
||||
return params;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::ProcessWatcher> Builder::LaunchProcess(const char* fullExePath, const AZStd::string& params) const
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> Builder::LaunchProcess(const char* fullExePath, const AZStd::string& params) const
|
||||
{
|
||||
AzToolsFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
processLaunchInfo.m_processExecutableString = fullExePath;
|
||||
processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" %s", fullExePath, params.c_str());
|
||||
processLaunchInfo.m_showWindow = false;
|
||||
processLaunchInfo.m_processPriority = AzToolsFramework::ProcessPriority::PROCESSPRIORITY_IDLE;
|
||||
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_IDLE;
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Executing AssetBuilder with parameters: %s\n", processLaunchInfo.m_commandlineParameters.c_str());
|
||||
|
||||
auto processWatcher = AZStd::unique_ptr<AzToolsFramework::ProcessWatcher>(AzToolsFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzToolsFramework::COMMUNICATOR_TYPE_STDINOUT));
|
||||
auto processWatcher = AZStd::unique_ptr<AzFramework::ProcessWatcher>(AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT));
|
||||
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, processWatcher, "Failed to start %s", fullExePath);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzToolsFramework/Process/ProcessWatcher.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <QString>
|
||||
@@ -108,7 +108,7 @@ namespace AssetProcessor
|
||||
void SetConnection(AZ::u32 connId);
|
||||
|
||||
AZStd::string BuildParams(const char* task, const char* moduleFilePath, const AZStd::string& builderGuid, const AZStd::string& jobDescriptionFile, const AZStd::string& jobResponseFile) const;
|
||||
AZStd::unique_ptr<AzToolsFramework::ProcessWatcher> LaunchProcess(const char* fullExePath, const AZStd::string& params) const;
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> LaunchProcess(const char* fullExePath, const AZStd::string& params) const;
|
||||
|
||||
//! Waits for the builder exe to send the job response and pumps stdout/err
|
||||
BuilderRunJobOutcome WaitForBuilderResponse(AssetBuilderSDK::JobCancelListener* jobCancelListener, AZ::u32 processTimeoutLimitInSeconds, AZStd::binary_semaphore* waitEvent) const;
|
||||
@@ -128,7 +128,7 @@ namespace AssetProcessor
|
||||
AZStd::binary_semaphore m_connectionEvent;
|
||||
|
||||
//! Optional process watcher
|
||||
AZStd::unique_ptr<AzToolsFramework::ProcessWatcher> m_processWatcher = nullptr;
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> m_processWatcher = nullptr;
|
||||
|
||||
//! Optional communicator, only available if we have a process watcher
|
||||
AZStd::unique_ptr<CommunicatorTracePrinter> m_tracePrinter = nullptr;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "CommunicatorTracePrinter.h"
|
||||
|
||||
CommunicatorTracePrinter::CommunicatorTracePrinter(AzToolsFramework::ProcessCommunicator* communicator, const char* window) :
|
||||
CommunicatorTracePrinter::CommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window) :
|
||||
m_communicator(communicator),
|
||||
m_window(window)
|
||||
{
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzToolsFramework/Process/ProcessCommunicator.h>
|
||||
#include <AzFramework/Process/ProcessCommunicator.h>
|
||||
|
||||
//! CommunicatorTracePrinter listens to stderr and stdout of a running process and writes its output to the AZ_Trace system
|
||||
//! Importantly, it does not do any blocking operations.
|
||||
class CommunicatorTracePrinter
|
||||
{
|
||||
public:
|
||||
CommunicatorTracePrinter(AzToolsFramework::ProcessCommunicator* communicator, const char* window);
|
||||
CommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window);
|
||||
~CommunicatorTracePrinter();
|
||||
|
||||
// call this periodically to drain the buffers and write them.
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
|
||||
private:
|
||||
AZStd::string m_window;
|
||||
AzToolsFramework::ProcessCommunicator* m_communicator;
|
||||
AzFramework::ProcessCommunicator* m_communicator;
|
||||
char m_streamBuffer[128];
|
||||
AZStd::string m_stringBeingConcatenated;
|
||||
AZStd::string m_errorStringBeingConcatenated;
|
||||
|
||||
@@ -130,37 +130,36 @@ ApplicationManager::BeforeRunStatus GUIApplicationManager::BeforeRun()
|
||||
m_qtFileWatcher.addPath(assetDbPath);
|
||||
|
||||
// if our Gems file changes, make sure we watch that, too.
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
QString gemsConfigFile = devRoot.filePath(gameName + "/gems.json");
|
||||
|
||||
m_qtFileWatcher.addPath(gemsConfigFile);
|
||||
QString projectPath = AssetUtilities::ComputeProjectPath();
|
||||
|
||||
QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::fileChanged, this, &GUIApplicationManager::FileChanged);
|
||||
QObject::connect(&m_qtFileWatcher, &QFileSystemWatcher::directoryChanged, this, &GUIApplicationManager::DirectoryChanged);
|
||||
|
||||
// Register a notifier for when the sys_game_folder property changes within the SettingsRegistry
|
||||
// Register a notifier for when the project_path property changes within the SettingsRegistry
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
auto onBootStrapGameFolderChanged = [this, cachedGameName = gameName](AZStd::string_view path, AZ::SettingsRegistryInterface::Type type)
|
||||
// Needs to be updated to project_path.
|
||||
auto OnProjectPathChanged = [this, cachedProjectPath = projectPath](AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
constexpr auto projectKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
|
||||
+ "/sys_game_folder";
|
||||
if (projectKey == path && type == AZ::SettingsRegistryInterface::Type::String)
|
||||
constexpr auto projectPathKey =
|
||||
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
|
||||
+ "/project_path";
|
||||
if (projectPathKey == path)
|
||||
{
|
||||
auto registry = AZ::SettingsRegistry::Get();
|
||||
AZ::SettingsRegistryInterface::FixedValueString newGameName;
|
||||
if (registry->Get(newGameName, path))
|
||||
AZ::SettingsRegistryInterface::FixedValueString newProjectPath;
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry && registry->Get(newProjectPath, path))
|
||||
{
|
||||
// we only have to quit if the actual project name has changed, not if just the bootstrap has changed.
|
||||
if (cachedGameName.compare(newGameName.c_str()) != 0)
|
||||
// we only have to quit if the project path has changed, not if just the bootstrap has changed.
|
||||
if (cachedProjectPath.compare(newProjectPath.c_str()) != 0)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Bootstrap.cfg Game Name changed from %s to %s. Quitting\n", cachedGameName.toUtf8().constData(), newGameName.c_str());
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "bootstrap.cfg Project Path changed from %s to %s. Quitting\n",
|
||||
cachedProjectPath.toUtf8().constData(), newProjectPath.c_str());
|
||||
QMetaObject::invokeMethod(this, "QuitRequested", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
m_bootstrapGameFolderChangedHandler = settingsRegistry->RegisterNotifier(AZStd::move(onBootStrapGameFolderChanged));
|
||||
m_bootstrapGameFolderChangedHandler = settingsRegistry->RegisterNotifier(AZStd::move(OnProjectPathChanged));
|
||||
}
|
||||
|
||||
return ApplicationManager::BeforeRunStatus::Status_Success;
|
||||
@@ -189,8 +188,13 @@ bool GUIApplicationManager::Run()
|
||||
qRegisterMetaType<AZ::u32>("AZ::u32");
|
||||
qRegisterMetaType<AZ::Uuid>("AZ::Uuid");
|
||||
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
AzQtComponents::StyleManager* styleManager = new AzQtComponents::StyleManager(qApp);
|
||||
styleManager->Initialize(qApp);
|
||||
styleManager->initialize(qApp, engineRootPath);
|
||||
|
||||
QDir engineRoot;
|
||||
AssetUtilities::ComputeAssetRoot(engineRoot);
|
||||
@@ -198,7 +202,8 @@ bool GUIApplicationManager::Run()
|
||||
AzQtComponents::StyleManager::addSearchPaths(
|
||||
QStringLiteral("style"),
|
||||
engineRoot.filePath(QStringLiteral("Code/Tools/AssetProcessor/native/ui/style")),
|
||||
QStringLiteral(":/AssetProcessor/style"));
|
||||
QStringLiteral(":/AssetProcessor/style"),
|
||||
engineRootPath);
|
||||
|
||||
m_mainWindow = new MainWindow(this);
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper(
|
||||
@@ -485,7 +490,7 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
|
||||
QVariant settingValue = loader.value("Game Projects/enabled_game_projects");
|
||||
QStringList compiledProjects = settingValue.toStringList();
|
||||
|
||||
if(compiledProjects.isEmpty())
|
||||
if (compiledProjects.isEmpty())
|
||||
{
|
||||
QByteArray byteArray;
|
||||
QFile jsonFile;
|
||||
@@ -497,12 +502,12 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
|
||||
QJsonObject settingsObject = QJsonDocument::fromJson(byteArray).object();
|
||||
QJsonArray projectsArray = settingsObject["Game Projects"].toArray();
|
||||
|
||||
if(!projectsArray.isEmpty())
|
||||
if (!projectsArray.isEmpty())
|
||||
{
|
||||
auto projectObject = projectsArray[0].toObject();
|
||||
QString projects = projectObject["default_value"].toString();
|
||||
|
||||
if(!projects.isEmpty())
|
||||
if (!projects.isEmpty())
|
||||
{
|
||||
compiledProjects = projects.split(',');
|
||||
usingDefaults = true;
|
||||
@@ -515,13 +520,13 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
|
||||
compiledProjects[i] = compiledProjects[i].trimmed();
|
||||
}
|
||||
|
||||
QString enabledProject = AssetUtilities::ComputeGameName();
|
||||
QString enabledProject = AssetUtilities::ComputeProjectName();
|
||||
|
||||
if(!compiledProjects.contains(enabledProject))
|
||||
if (!compiledProjects.contains(enabledProject))
|
||||
{
|
||||
QString projectSourceLine;
|
||||
|
||||
if(usingDefaults)
|
||||
if (usingDefaults)
|
||||
{
|
||||
projectSourceLine = QString("The currently compiled projects according to the defaults in %1 are '%2'").arg(defaultSettingsFile);
|
||||
}
|
||||
@@ -531,7 +536,6 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
|
||||
}
|
||||
|
||||
projectSourceLine = projectSourceLine.arg(compiledProjects.join(", "));
|
||||
|
||||
friendlyErrorMessage = QString("An error occurred while loading gems.\n"
|
||||
"The enabled game project is not in the list of compiled projects.\n"
|
||||
"Please configure the enabled project to be compiled and rebuild or change the enabled project.\n"
|
||||
@@ -539,13 +543,12 @@ bool GUIApplicationManager::OnError(const char* /*window*/, const char* message)
|
||||
"%2\n"
|
||||
"Full error text:\n"
|
||||
"%3"
|
||||
).arg(enabledProject).arg(projectSourceLine).arg(message).arg(AssetUtilities::GameFolderOverrideParameter);
|
||||
).arg(enabledProject).arg(projectSourceLine).arg(message).arg(AssetUtilities::ProjectPathOverrideParameter);
|
||||
}
|
||||
}
|
||||
|
||||
if(friendlyErrorMessage.isEmpty())
|
||||
if (friendlyErrorMessage.isEmpty())
|
||||
{
|
||||
|
||||
friendlyErrorMessage = QString("An error occurred while loading gems.\n"
|
||||
"This can happen when new gems are added to a project, but those gems need to be built in order to function.\n"
|
||||
"This can also happen when switching to a different project, one which uses gems which are not yet built.\n"
|
||||
@@ -631,34 +634,18 @@ void GUIApplicationManager::CreateQtApplication()
|
||||
m_qApp = new QApplication(*m_frameworkApp.GetArgC(), *m_frameworkApp.GetArgV());
|
||||
}
|
||||
|
||||
void GUIApplicationManager::DirectoryChanged(QString path)
|
||||
void GUIApplicationManager::DirectoryChanged([[maybe_unused]] QString path)
|
||||
{
|
||||
AZ_UNUSED(path);
|
||||
QDir devRoot = ApplicationManager::GetSystemRoot();
|
||||
QString cacheRoot = devRoot.filePath("Cache");
|
||||
if (!QDir(cacheRoot).exists())
|
||||
QDir projectCacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
|
||||
if (!projectCacheRoot.exists() || !projectCacheRoot.exists("assetdb.sqlite"))
|
||||
{
|
||||
//Cache directory is removed we need to restart
|
||||
// If either the Cache directory or database file has been removed, we need to restart
|
||||
QTimer::singleShot(200, this, [this]()
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "Restart", Qt::QueuedConnection);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
QDir projectCacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
|
||||
QString assetDbPath = projectCacheRoot.filePath("assetdb.sqlite");
|
||||
|
||||
if (!QFile::exists(assetDbPath))
|
||||
{
|
||||
// even if cache directory exists but the the database file is missing we need to restart
|
||||
QTimer::singleShot(200, this, [this]()
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "Restart", Qt::QueuedConnection);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUIApplicationManager::FileChanged(QString path)
|
||||
@@ -696,70 +683,6 @@ void GUIApplicationManager::FileChanged(QString path)
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (AssetUtilities::NormalizeFilePath(path).endsWith("gems.json", Qt::CaseInsensitive))
|
||||
{
|
||||
AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> oldGemsList = GetPlatformConfiguration()->GetGemsInformation();
|
||||
AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> newGemsList;
|
||||
QDir assetRoot;
|
||||
AssetUtilities::ComputeAssetRoot(assetRoot);
|
||||
AzToolsFramework::AssetUtils::GetGemsInfo(GetSystemRoot().absolutePath().toUtf8().constData(), assetRoot.absolutePath().toUtf8().constData(), GetGameName().toUtf8().constData(), newGemsList);
|
||||
|
||||
for (auto oldGemIter = oldGemsList.begin(); oldGemIter != oldGemsList.end();)
|
||||
{
|
||||
bool gemMatch = false;
|
||||
for (auto newGemIter = newGemsList.begin(); newGemIter != newGemsList.end();)
|
||||
{
|
||||
if (AzFramework::StringFunc::Equal(oldGemIter->m_identifier.c_str(), newGemIter->m_identifier.c_str()))
|
||||
{
|
||||
gemMatch = true;
|
||||
newGemIter = newGemsList.erase(newGemIter);
|
||||
break;
|
||||
}
|
||||
newGemIter++;
|
||||
}
|
||||
|
||||
if (gemMatch)
|
||||
{
|
||||
oldGemIter = oldGemsList.erase(oldGemIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldGemIter++;
|
||||
}
|
||||
}
|
||||
|
||||
// oldGemslist should contain the list of gems that got removed and newGemsList should contain the list of gems that were added to the project
|
||||
// if the project requires to be built again then we will quit otherwise we can restart
|
||||
bool exitApp = false;
|
||||
for (const AzToolsFramework::AssetUtils::GemInfo& gemInfo : newGemsList)
|
||||
{
|
||||
if (!gemInfo.m_assetOnly)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Gem %s was added to the project and require building. Quitting\n", gemInfo.m_gemName.c_str());
|
||||
exitApp = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (exitApp)
|
||||
{
|
||||
QuitRequested();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldGemsList.size() || newGemsList.size())
|
||||
{
|
||||
if (oldGemsList.size())
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Gem(s) were removed from the project. Restarting\n");
|
||||
}
|
||||
else if (newGemsList.size())
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Assets only gem(s) were added to the project. Restarting\n");
|
||||
}
|
||||
QMetaObject::invokeMethod(this, "Restart", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GUIApplicationManager::InitApplicationServer()
|
||||
|
||||
@@ -20,43 +20,48 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "native/AssetDatabase/AssetDatabase.h"
|
||||
#include "native/assetprocessor.h"
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/FileTag/FileTagBus.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/FileTag/FileTag.h>
|
||||
#include <AzFramework/FileTag/FileTagBus.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
const char* EngineFolder = "Engine";
|
||||
|
||||
AZStd::string GetXMLDependenciesFile(const AZStd::string& fullPath, const AZStd::vector<AzToolsFramework::AssetUtils::GemInfo>& gemInfoList, AZStd::string& tokenName)
|
||||
AZStd::string GetXMLDependenciesFile(const AZStd::string& fullPath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AZStd::string& tokenName)
|
||||
{
|
||||
AZStd::string xmlDependenciesFileFullPath;
|
||||
AZ::IO::Path xmlDependenciesFileFullPath;
|
||||
tokenName = EngineFolder;
|
||||
for (const AzToolsFramework::AssetUtils::GemInfo& gemElement : gemInfoList)
|
||||
for (const AzFramework::GemInfo& gemElement : gemInfoList)
|
||||
{
|
||||
if (AzFramework::StringFunc::StartsWith(fullPath.c_str(), gemElement.m_absoluteFilePath.c_str()) || AzFramework::StringFunc::Equal(gemElement.m_absoluteFilePath.c_str(), fullPath.c_str()))
|
||||
for (const AZ::IO::Path& absoluteSourcePath : gemElement.m_absoluteSourcePaths)
|
||||
{
|
||||
AZStd::string fileName = AZStd::string::format("%s_Dependencies.xml", gemElement.m_gemName.c_str());
|
||||
AzFramework::StringFunc::Path::ConstructFull(gemElement.m_absoluteFilePath.c_str(), AzToolsFramework::AssetUtils::GemInfo::GetGemAssetFolder().c_str(), fileName.c_str() , "xml", xmlDependenciesFileFullPath);
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Exists(xmlDependenciesFileFullPath.c_str()))
|
||||
if (AZ::StringFunc::StartsWith(fullPath, absoluteSourcePath.Native()) || AZ::StringFunc::Equal(absoluteSourcePath.Native(), fullPath))
|
||||
{
|
||||
tokenName = gemElement.m_gemName;
|
||||
return xmlDependenciesFileFullPath;
|
||||
xmlDependenciesFileFullPath /= AzFramework::GemInfo::GetGemAssetFolder();
|
||||
xmlDependenciesFileFullPath /= AZStd::string::format("%s_Dependencies.xml", gemElement.m_gemName.c_str());;
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Exists(xmlDependenciesFileFullPath.c_str()))
|
||||
{
|
||||
tokenName = gemElement.m_gemName;
|
||||
return xmlDependenciesFileFullPath.Native();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we are here than either the %gemName%_Dependencies.xml file does not exists or the user inputted path is not inside a gems folder,
|
||||
// in both the cases we will return the engine dependencies file
|
||||
const char* devRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
|
||||
AzFramework::StringFunc::Path::ConstructFull(devRoot, EngineFolder, "Engine_Dependencies.xml", "xml", xmlDependenciesFileFullPath);
|
||||
xmlDependenciesFileFullPath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
|
||||
xmlDependenciesFileFullPath /= EngineFolder;
|
||||
xmlDependenciesFileFullPath /= "Engine_Dependencies.xml";
|
||||
|
||||
return xmlDependenciesFileFullPath;
|
||||
return xmlDependenciesFileFullPath.Native();
|
||||
}
|
||||
|
||||
const int MissingDependencyScanner::DefaultMaxScanIteration = 800;
|
||||
@@ -731,7 +736,7 @@ namespace AssetProcessor
|
||||
}
|
||||
}
|
||||
|
||||
bool MissingDependencyScanner::PopulateRulesForScanFolder(const AZStd::string& scanFolderPath, const AZStd::vector<AzToolsFramework::AssetUtils::GemInfo>& gemInfoList, AZStd::string& dependencyTokenName)
|
||||
bool MissingDependencyScanner::PopulateRulesForScanFolder(const AZStd::string& scanFolderPath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AZStd::string& dependencyTokenName)
|
||||
{
|
||||
AZStd::string xmlDependenciesFullFilePath = GetXMLDependenciesFile(scanFolderPath, gemInfoList, dependencyTokenName);
|
||||
if (xmlDependenciesFullFilePath.empty())
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace AssetProcessor
|
||||
|
||||
void RegisterSpecializedScanner(AZStd::shared_ptr<SpecializedDependencyScanner> scanner);
|
||||
|
||||
bool PopulateRulesForScanFolder(const AZStd::string& scanFolderPath, const AZStd::vector<AzToolsFramework::AssetUtils::GemInfo>& gemInfoList, AZStd::string& dependencyTokenName);
|
||||
bool PopulateRulesForScanFolder(const AZStd::string& scanFolderPath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AZStd::string& dependencyTokenName);
|
||||
|
||||
protected:
|
||||
bool RunScan(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@
|
||||
#include <QVector>
|
||||
#include <QSet>
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <native/utilities/assetUtils.h>
|
||||
#include <native/AssetManager/assetScanFolderInfo.h>
|
||||
@@ -29,10 +30,15 @@
|
||||
#include <AzToolsFramework/Asset/AssetUtils.h>
|
||||
#endif
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class SettingsRegistryInterface;
|
||||
}
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
inline constexpr const char* AssetProcessorSettingsKey{ "/Amazon/AssetProcessor/Settings" };
|
||||
class PlatformConfiguration;
|
||||
class ScanFolderInfo;
|
||||
extern const char AssetConfigPlatformDir[];
|
||||
@@ -105,6 +111,73 @@ namespace AssetProcessor
|
||||
virtual const ExcludeRecognizerContainer& GetExcludeAssetRecognizerContainer() const = 0;
|
||||
};
|
||||
|
||||
//! Visitor for reading the "/Amazon/AssetProcessor/Settings/ScanFolder *" entries from the Settings Registry
|
||||
//! Expects the key to path to the visitor to be "/Amazon/AssetProcessor/Settings"
|
||||
struct ScanFolderVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName,
|
||||
AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override;
|
||||
|
||||
struct ScanFolderInfo
|
||||
{
|
||||
AZStd::string m_scanFolderIdentifier;
|
||||
AZStd::string m_scanFolderDisplayName;
|
||||
AZ::IO::Path m_watchPath{ AZ::IO::PosixPathSeparator };
|
||||
AZStd::vector<AZStd::string> m_includeIdentifiers;
|
||||
AZStd::vector<AZStd::string> m_excludeIdentifiers;
|
||||
AZStd::string m_outputPrefix;
|
||||
int m_scanOrder{};
|
||||
bool m_isRecursive{};
|
||||
};
|
||||
AZStd::vector<ScanFolderInfo> m_scanFolderInfos;
|
||||
private:
|
||||
AZStd::stack<AZStd::string> m_scanFolderStack;
|
||||
};
|
||||
|
||||
struct ExcludeVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName,
|
||||
AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override;
|
||||
|
||||
AZStd::vector<ExcludeAssetRecognizer> m_excludeAssetRecognizers;
|
||||
private:
|
||||
AZStd::stack<AZStd::string> m_excludeNameStack;
|
||||
};
|
||||
|
||||
struct RCVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
RCVisitor(const AZ::SettingsRegistryInterface& settingsRegistry, const AZStd::vector<AssetBuilderSDK::PlatformInfo>& enabledPlatforms)
|
||||
: m_registry(settingsRegistry)
|
||||
, m_enabledPlatforms(enabledPlatforms)
|
||||
{
|
||||
}
|
||||
AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName,
|
||||
AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value) override;
|
||||
void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override;
|
||||
|
||||
struct RCAssetRecognizer
|
||||
{
|
||||
AssetRecognizer m_recognizer;
|
||||
AZStd::string m_defaultParams;
|
||||
bool m_ignore{};
|
||||
};
|
||||
AZStd::vector<RCAssetRecognizer> m_assetRecognizers;
|
||||
private:
|
||||
void ApplyParamsOverrides(AZStd::string_view path);
|
||||
|
||||
AZStd::stack<AZStd::string> m_rcNameStack;
|
||||
const AZ::SettingsRegistryInterface& m_registry;
|
||||
const AZStd::vector<AssetBuilderSDK::PlatformInfo>& m_enabledPlatforms;
|
||||
};
|
||||
|
||||
/** Reads the platform ini configuration file to determine
|
||||
* platforms for which assets needs to be build
|
||||
*/
|
||||
@@ -127,22 +200,23 @@ namespace AssetProcessor
|
||||
* Note that order of the config files is relevant - later files override settings in
|
||||
* files that are earlier.
|
||||
**/
|
||||
bool InitializeFromConfigFiles(QString absoluteSystemRoot, QString absoluteAssetRoot, QString gameName, bool addPlatformConfigs = true, bool addGemsConfigs = true);
|
||||
bool InitializeFromConfigFiles(const QString& absoluteSystemRoot, const QString& absoluteAssetRoot, const QString& projectPath, bool addPlatformConfigs = true, bool addGemsConfigs = true);
|
||||
|
||||
QString PlatformName(unsigned int platformCrc) const;
|
||||
QString RendererName(unsigned int rendererCrc) const;
|
||||
//! Merge an AssetProcessor*Config.ini path to the Settings Registry
|
||||
//! The settings are anchored underneath the AssetProcessor::AssetProcessorSettingsKey JSON pointer
|
||||
static bool MergeConfigFileToSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry, const AZ::IO::PathView& filePathView);
|
||||
|
||||
const AZStd::vector<AssetBuilderSDK::PlatformInfo>& GetEnabledPlatforms() const;
|
||||
const AssetBuilderSDK::PlatformInfo* const GetPlatformByIdentifier(const char* identifier) const;
|
||||
|
||||
//! Add AssetProcessor config files from platform specific folders
|
||||
bool AddPlatformConfigFilePaths(QStringList& configList);
|
||||
bool AddPlatformConfigFilePaths(AZStd::vector<AZ::IO::Path>& configList);
|
||||
|
||||
int MetaDataFileTypesCount() const { return m_metaDataFileTypes.count(); }
|
||||
// Metadata file types are (meta file extension, original file extension - or blank if its tacked on the end instead of replacing).
|
||||
// so for example if its
|
||||
// blah.tif + blah.tif.metadata, then its ("metadata", "")
|
||||
// but if its blah.tif + blah.metadata (rplacing tif, data is lost) then its ("metadata", "tif")
|
||||
// but if its blah.tif + blah.metadata (replacing tif, data is lost) then its ("metadata", "tif")
|
||||
QPair<QString, QString> GetMetaDataFileTypeAt(int pos) const;
|
||||
|
||||
// Metadata extensions can also be a real file, to create a dependency on file types if a specific file changes
|
||||
@@ -160,7 +234,7 @@ namespace AssetProcessor
|
||||
int GetScanFolderCount() const;
|
||||
|
||||
//! Return the gems info list
|
||||
AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> GetGemsInformation() const;
|
||||
AZStd::vector<AzFramework::GemInfo> GetGemsInformation() const;
|
||||
|
||||
//! Retrieve the scan folder at a given index.
|
||||
AssetProcessor::ScanFolderInfo& GetScanFolderAt(int index);
|
||||
@@ -249,18 +323,18 @@ namespace AssetProcessor
|
||||
protected:
|
||||
|
||||
// call this first, to populate the list of platform informations
|
||||
void ReadPlatformInfosFromConfigFile(QString fileSource);
|
||||
void ReadPlatformInfosFromSettingsRegistry();
|
||||
// call this next, in order to find out what platforms are enabled
|
||||
void PopulateEnabledPlatforms(QStringList configFiles);
|
||||
// finaly, call this, in order to delete the platforminfos for non-enabled platforms
|
||||
void PopulateEnabledPlatforms();
|
||||
// finally, call this, in order to delete the platforminfos for non-enabled platforms
|
||||
void FinalizeEnabledPlatforms();
|
||||
|
||||
// iterate over all the gems and add their folders to the "scan folders" list as appropriate.
|
||||
void AddGemScanFolders(const AZStd::vector<AzToolsFramework::AssetUtils::GemInfo>& gemInfoList);
|
||||
void AddGemScanFolders(const AZStd::vector<AzFramework::GemInfo>& gemInfoList);
|
||||
|
||||
void ReadEnabledPlatformsFromConfigFile(QString fileSource);
|
||||
bool ReadRecognizersFromConfigFile(QString fileSource, bool skipScanFolders = false, QStringList scanFolderPatterns = QStringList() );
|
||||
void ReadMetaDataFromConfigFile(QString fileSource);
|
||||
void ReadEnabledPlatformsFromSettingsRegistry();
|
||||
bool ReadRecognizersFromSettingsRegistry(const QString& assetRoot, bool skipScanFolders = false, QStringList scanFolderPatterns = QStringList() );
|
||||
void ReadMetaDataFromSettingsRegistry();
|
||||
|
||||
private:
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> m_enabledPlatforms;
|
||||
@@ -269,15 +343,13 @@ namespace AssetProcessor
|
||||
AZStd::vector<AssetProcessor::ScanFolderInfo> m_scanFolders;
|
||||
QList<QPair<QString, QString> > m_metaDataFileTypes;
|
||||
QSet<QString> m_metaDataRealFiles;
|
||||
AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> m_gemInfoList;
|
||||
AZStd::vector<AzFramework::GemInfo> m_gemInfoList;
|
||||
|
||||
int m_minJobs = 1;
|
||||
int m_maxJobs = 3;
|
||||
|
||||
// used only during file read, keeps the total running list of all the enabled platforms from all config files and command lines
|
||||
QStringList m_tempEnabledPlatforms;
|
||||
|
||||
bool ReadRecognizerFromConfig(AssetRecognizer& target, QSettings& loader); // assumes the group is already selected
|
||||
AZStd::vector<AZStd::string> m_tempEnabledPlatforms;
|
||||
|
||||
///! if non-empty, fatalError contains the error that occurred during read.
|
||||
///! it will be printed out to the log when
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <QElapsedTimer>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTextStream>
|
||||
#include <QSettings>
|
||||
#include <QTimeZone>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
@@ -38,7 +37,9 @@
|
||||
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
#include <AzToolsFramework/UI/Logging/LogLine.h>
|
||||
#include <xxhash/xxhash.h>
|
||||
|
||||
@@ -77,7 +78,7 @@ namespace AssetUtilsInternal
|
||||
{
|
||||
if (waitTimeInSeconds < 0)
|
||||
{
|
||||
AZ_Warning("Asset Processor", waitTimeInSeconds >= 0, "Invalid timeout specified by the user")
|
||||
AZ_Warning("Asset Processor", waitTimeInSeconds >= 0, "Invalid timeout specified by the user");
|
||||
waitTimeInSeconds = 0;
|
||||
}
|
||||
bool failureOccurredOnce = false; // used for logging.
|
||||
@@ -152,12 +153,64 @@ namespace AssetUtilsInternal
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DumpAssetProcessorUserSettingsToFile(AZ::SettingsRegistryInterface& settingsRegistry,
|
||||
const AZ::IO::FixedMaxPath& setregPath)
|
||||
{
|
||||
// The AssetProcessor settings are currently under the Bootstrap object(This may change in the future
|
||||
constexpr AZStd::string_view AssetProcessorUserSettingsRootKey = AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey;
|
||||
AZStd::string apSettingsJson;
|
||||
AZ::IO::ByteContainerStream apSettingsStream(&apSettingsJson);
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::DumperSettings apDumperSettings;
|
||||
apDumperSettings.m_prettifyOutput = true;
|
||||
apDumperSettings.m_includeFilter = [&AssetProcessorUserSettingsRootKey](AZStd::string_view path)
|
||||
{
|
||||
// The AssetUtils only updates the following keys in the registry
|
||||
// Dump them all out to the setreg file
|
||||
auto allowedListKey = AZ::SettingsRegistryInterface::FixedValueString(AssetProcessorUserSettingsRootKey)
|
||||
+ "/allowed_list";
|
||||
auto branchTokenKey = AZ::SettingsRegistryInterface::FixedValueString(AssetProcessorUserSettingsRootKey)
|
||||
+ "/assetProcessor_branch_token";
|
||||
// The objects leading up to the keys to dump must be included in order the keys to be dumped
|
||||
return allowedListKey.starts_with(path.substr(0, allowedListKey.size()))
|
||||
|| branchTokenKey.starts_with(path.substr(0, branchTokenKey.size()));
|
||||
};
|
||||
apDumperSettings.m_jsonPointerPrefix = AssetProcessorUserSettingsRootKey;
|
||||
|
||||
if (AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(settingsRegistry, AssetProcessorUserSettingsRootKey,
|
||||
apSettingsStream, apDumperSettings))
|
||||
{
|
||||
|
||||
constexpr auto modeFlags = AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE
|
||||
| AZ::IO::SystemFile::SF_OPEN_CREATE_PATH;
|
||||
if (AZ::IO::SystemFile apSetregFile; apSetregFile.Open(setregPath.c_str(), modeFlags))
|
||||
{
|
||||
size_t bytesWritten = apSetregFile.Write(apSettingsJson.data(), apSettingsJson.size());
|
||||
return bytesWritten == apSettingsJson.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Unable to open AssetProcessor user setreg file (%s)\n", setregPath.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Dump of AssetProcessor User Settings failed at JSON pointer %.*s \n",
|
||||
aznumeric_cast<int>(AssetProcessorUserSettingsRootKey.size()), AssetProcessorUserSettingsRootKey.data());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
namespace AssetUtilities
|
||||
{
|
||||
constexpr AZStd::string_view AssetProcessorUserSetregRelPath = "user/Registry/asset_processor.setreg";
|
||||
|
||||
// do not place Qt objects in global scope, they allocate and refcount threaded data.
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_gameName;
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_projectPath;
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_projectName;
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_assetRoot;
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_assetServerAddress;
|
||||
AZ::SettingsRegistryInterface::FixedValueString s_cachedEngineRoot;
|
||||
@@ -191,7 +244,7 @@ namespace AssetUtilities
|
||||
|
||||
void ResetGameName()
|
||||
{
|
||||
s_gameName = {};
|
||||
s_projectName = {};
|
||||
}
|
||||
|
||||
bool CopyDirectory(QDir source, QDir destination)
|
||||
@@ -245,7 +298,7 @@ namespace AssetUtilities
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ComputeAssetRoot(QDir& root, const QDir* appRootOverride)
|
||||
bool ComputeAssetRoot(QDir& root, const QDir* rootOverride)
|
||||
{
|
||||
if (!s_assetRoot.empty())
|
||||
{
|
||||
@@ -253,10 +306,10 @@ namespace AssetUtilities
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use the appRoot if supplied is supplied and not an empty string
|
||||
if (appRootOverride && !appRootOverride->path().isEmpty())
|
||||
// Use the override if supplied and not an empty string
|
||||
if (rootOverride && !rootOverride->path().isEmpty())
|
||||
{
|
||||
root = *appRootOverride;
|
||||
root = *rootOverride;
|
||||
s_assetRoot = root.absolutePath().toUtf8().constData();
|
||||
return true;
|
||||
}
|
||||
@@ -288,7 +341,7 @@ namespace AssetUtilities
|
||||
return true;
|
||||
}
|
||||
|
||||
// The EngineRootFolder Key has not been found in the SettingsRegistry, log an warning about
|
||||
// The EngineRootFolder Key has not been found in the SettingsRegistry
|
||||
auto engineRootError = AZ::SettingsRegistryInterface::FixedValueString::format("The EngineRootFolder is not set in the SettingsRegistry at key %s.",
|
||||
AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
AssetProcessor::MessageInfoBus::Broadcast(&AssetProcessor::MessageInfoBusTraits::OnErrorMessage, engineRootError.c_str());
|
||||
@@ -296,7 +349,7 @@ namespace AssetUtilities
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Get the engine root folder
|
||||
//! Get the external engine root folder if the engine is external to the current root folder.
|
||||
//! If the current root folder is also the engine folder, then this behaves the same as ComputeEngineRoot
|
||||
bool ComputeEngineRoot(QDir& root, const QDir* engineRootOverride)
|
||||
{
|
||||
@@ -312,6 +365,7 @@ namespace AssetUtilities
|
||||
AssetUtilities::ComputeAssetRoot(root, engineRootOverride);
|
||||
}
|
||||
|
||||
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
// Use the engineRootOverride if supplied and not empty
|
||||
if (engineRootOverride && !engineRootOverride->path().isEmpty())
|
||||
{
|
||||
@@ -320,11 +374,11 @@ namespace AssetUtilities
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString engineRootFolder;
|
||||
if (settingsRegistry->Get(engineRootFolder, AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
@@ -336,7 +390,7 @@ namespace AssetUtilities
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MakeFileWritable(QString fileName)
|
||||
bool MakeFileWritable(const QString& fileName)
|
||||
{
|
||||
#if defined WIN32
|
||||
DWORD fileAttributes = GetFileAttributesA(fileName.toUtf8());
|
||||
@@ -386,7 +440,7 @@ namespace AssetUtilities
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CheckCanLock(QString fileName)
|
||||
bool CheckCanLock(const QString& fileName)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
AZStd::wstring usableFileName;
|
||||
@@ -419,42 +473,55 @@ namespace AssetUtilities
|
||||
#endif
|
||||
}
|
||||
|
||||
QString ComputeGameName(QString gameNameOverride, bool force)
|
||||
QString ComputeProjectName(QString gameNameOverride, bool force)
|
||||
{
|
||||
if (force || s_gameName.empty())
|
||||
if (force || s_projectName.empty())
|
||||
{
|
||||
// if its been specified on the command line, then ignore bootstrap:
|
||||
// Override Game Name if a non-empty override string has been supplied
|
||||
if (!gameNameOverride.isEmpty())
|
||||
{
|
||||
s_projectName = gameNameOverride.toUtf8().constData();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_projectName = AZ::Utils::GetProjectName();
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromUtf8(s_projectName.c_str(), aznumeric_cast<int>(s_projectName.size()));
|
||||
}
|
||||
|
||||
QString ComputeProjectPath()
|
||||
{
|
||||
if (s_projectPath.empty())
|
||||
{
|
||||
// Check command-line args first
|
||||
QStringList args = QCoreApplication::arguments();
|
||||
for (QString arg : args)
|
||||
{
|
||||
if (arg.contains(QString("/%1=").arg(GameFolderOverrideParameter), Qt::CaseInsensitive) || arg.contains(QString("--%1=").arg(GameFolderOverrideParameter), Qt::CaseInsensitive))
|
||||
if (arg.contains(QString("/%1=").arg(ProjectPathOverrideParameter), Qt::CaseInsensitive)
|
||||
|| arg.contains(QString("--%1=").arg(ProjectPathOverrideParameter), Qt::CaseInsensitive))
|
||||
{
|
||||
QString rawValueString = arg.split("=")[1].trimmed();
|
||||
if (!rawValueString.isEmpty())
|
||||
{
|
||||
s_gameName = rawValueString.toUtf8().constData();
|
||||
return rawValueString;
|
||||
QDir path(rawValueString);
|
||||
if (path.isAbsolute())
|
||||
{
|
||||
s_projectPath = rawValueString.toUtf8().constData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override Game Name if a non-empty override string has been supplied
|
||||
if (!gameNameOverride.isEmpty())
|
||||
{
|
||||
s_gameName = gameNameOverride.toUtf8().constData();
|
||||
}
|
||||
else
|
||||
{
|
||||
QDir engineRoot;
|
||||
if (!AssetUtilities::ComputeEngineRoot(engineRoot))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
s_gameName = ReadGameNameFromSettingsRegistry(engineRoot.absolutePath()).toUtf8().constData();
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromUtf8(s_gameName.c_str(), aznumeric_cast<int>(s_gameName.size()));
|
||||
if (s_projectPath.empty())
|
||||
{
|
||||
s_projectPath = AZ::Utils::GetProjectPath();
|
||||
}
|
||||
|
||||
return QString::fromUtf8(s_projectPath.c_str(), aznumeric_cast<int>(s_projectPath.size()));
|
||||
}
|
||||
|
||||
bool InServerMode()
|
||||
@@ -479,7 +546,7 @@ namespace AssetUtilities
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false, "Invalid server address, please check the AssetProcessorPlatformConfig.ini file \
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false, "Invalid server address, please check the AssetProcessorPlatformConfig.setreg file \
|
||||
to ensure that the address is correct. Asset Processor won't be running in server mode.");
|
||||
}
|
||||
|
||||
@@ -517,19 +584,18 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
}
|
||||
}
|
||||
|
||||
QDir engineRoot;
|
||||
ComputeEngineRoot(engineRoot);
|
||||
QString rootConfigFile = engineRoot.absoluteFilePath("AssetProcessorPlatformConfig.ini");
|
||||
|
||||
if (QFile::exists(rootConfigFile))
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry)
|
||||
{
|
||||
QString address;
|
||||
QSettings loader(rootConfigFile, QSettings::IniFormat);
|
||||
loader.beginGroup("Server");
|
||||
address = loader.value("cacheServerAddress", QString()).toString();
|
||||
loader.endGroup();
|
||||
s_assetServerAddress = address.toUtf8().constData();
|
||||
return address;
|
||||
AZStd::string address;
|
||||
if (settingsRegistry->Get(address, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
|
||||
+ "/Server/cacheServerAddress"))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Server Address: %s\n", address.c_str());
|
||||
}
|
||||
s_assetServerAddress = address;
|
||||
|
||||
return QString::fromUtf8(address.data(), aznumeric_cast<int>(address.size()));
|
||||
}
|
||||
|
||||
return QString();
|
||||
@@ -549,18 +615,12 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return *s_fileHashSetting;
|
||||
}
|
||||
|
||||
QDir engineRoot;
|
||||
ComputeEngineRoot(engineRoot);
|
||||
QString rootConfigFile = engineRoot.absoluteFilePath("AssetProcessorPlatformConfig.ini");
|
||||
|
||||
if (QFile::exists(rootConfigFile))
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry)
|
||||
{
|
||||
bool curValue;
|
||||
QSettings loader(rootConfigFile, QSettings::IniFormat);
|
||||
loader.beginGroup("Fingerprinting");
|
||||
curValue = loader.value("UseFileHashing", true).toBool();
|
||||
loader.endGroup();
|
||||
|
||||
bool curValue = true;
|
||||
settingsRegistry->Get(curValue, AZ::SettingsRegistryInterface::FixedValueString(AssetProcessor::AssetProcessorSettingsKey)
|
||||
+ "/Fingerprinting/UseFileHashing");
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "UseFileHashing: %s\n", curValue ? "True" : "False");
|
||||
s_fileHashSetting = curValue;
|
||||
|
||||
@@ -573,46 +633,8 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return *s_fileHashSetting;
|
||||
}
|
||||
|
||||
QString ReadGameNameFromSettingsRegistry(QString initialFolder /*= QString()*/)
|
||||
QString ReadAllowedlistFromSettingsRegistry([[maybe_unused]] QString initialFolder)
|
||||
{
|
||||
if (initialFolder.isEmpty())
|
||||
{
|
||||
QDir engineRoot;
|
||||
if (!AssetUtilities::ComputeEngineRoot(engineRoot))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
initialFolder = engineRoot.absolutePath();
|
||||
}
|
||||
|
||||
constexpr size_t BufferSize = AZ_ARRAY_SIZE(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + AZStd::char_traits<char>::length("/sys_game_folder");
|
||||
AZStd::fixed_string<BufferSize> projectKey{ AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey };
|
||||
projectKey += "/sys_game_folder";
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry && settingsRegistry->Get(projectName, projectKey))
|
||||
{
|
||||
return QString::fromUtf8(projectName.c_str(), aznumeric_cast<int>(projectName.size()));
|
||||
}
|
||||
|
||||
AZ_Warning("AssetUtils", false, "Unable to find the Project Name(sys_game_folder) key in the settings registry");
|
||||
return {};
|
||||
}
|
||||
|
||||
QString ReadAllowedlistFromSettingsRegistry(QString initialFolder /*= QString()*/)
|
||||
{
|
||||
if (initialFolder.isEmpty())
|
||||
{
|
||||
QDir assetRoot;
|
||||
if (!AssetUtilities::ComputeAssetRoot(assetRoot))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
initialFolder = assetRoot.absolutePath();
|
||||
}
|
||||
|
||||
constexpr size_t BufferSize = AZ_ARRAY_SIZE(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + AZStd::char_traits<char>::length("/allowed_list");
|
||||
AZStd::fixed_string<BufferSize> allowedListKey{ AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey };
|
||||
allowedListKey += "/allowed_list";
|
||||
@@ -626,18 +648,8 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return {};
|
||||
}
|
||||
|
||||
QString ReadRemoteIpFromSettingsRegistry(QString initialFolder /*= QString()*/)
|
||||
QString ReadRemoteIpFromSettingsRegistry([[maybe_unused]] QString initialFolder)
|
||||
{
|
||||
if (initialFolder.isEmpty())
|
||||
{
|
||||
QDir engineRoot;
|
||||
if (!AssetUtilities::ComputeEngineRoot(engineRoot))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
initialFolder = engineRoot.absolutePath();
|
||||
}
|
||||
constexpr size_t BufferSize = AZ_ARRAY_SIZE(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + AZStd::char_traits<char>::length("/remote_ip");
|
||||
AZStd::fixed_string<BufferSize> remoteIpKey{ AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey };
|
||||
remoteIpKey += "/remote_ip";
|
||||
@@ -651,159 +663,44 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return {};
|
||||
}
|
||||
|
||||
bool WriteAllowedlistToBootstrap(QStringList newAllowedList)
|
||||
bool WriteAllowedlistToSettingsRegistry(const QStringList& newAllowedList)
|
||||
{
|
||||
QDir assetRoot;
|
||||
ComputeAssetRoot(assetRoot);
|
||||
QString bootstrapFilename = assetRoot.filePath("bootstrap.cfg");
|
||||
QFile bootstrapFile(bootstrapFilename);
|
||||
AZ::IO::FixedMaxPath assetProcessorUserSetregPath = AZ::Utils::GetProjectPath();
|
||||
assetProcessorUserSetregPath /= AssetProcessorUserSetregRelPath;
|
||||
|
||||
// do not alter the branch file unless we are able to obtain an exclusive lock. Other apps (such as NPP) may actually write 0 bytes first, then slowly spool out the remainder)
|
||||
if (!CheckCanLock(bootstrapFilename))
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (!settingsRegistry)
|
||||
{
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Unable access Settings Registry. Branch Token cannot be updated");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bootstrapFile.open(QIODevice::ReadOnly))
|
||||
auto allowedListKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
|
||||
+ "/allowed_list";
|
||||
AZStd::string currentAllowedList;
|
||||
if (settingsRegistry->Get(currentAllowedList, allowedListKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Split the current allowedList into an array and compare against the new allowed list
|
||||
AZStd::vector<AZStd::string_view> allowedListArray;
|
||||
auto AppendAllowedIpTokens = [&allowedListArray](AZStd::string_view token) { allowedListArray.emplace_back(token); };
|
||||
AZ::StringFunc::TokenizeVisitor(currentAllowedList, AppendAllowedIpTokens, ',');
|
||||
|
||||
// regexp that matches either the beginning of the file, some whitespace, and allowed_list, or,
|
||||
// matches a newline, then whitespace, then allowed_list it will not match comments.
|
||||
QRegExp allowedListPattern("(^|\\n)\\s*allowed_list\\s*=\\s*(.+)", Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
|
||||
//read the file line by line and try to find the allowed_list line
|
||||
QString readAllowedList;
|
||||
QString allowedListline;
|
||||
while (!bootstrapFile.atEnd())
|
||||
{
|
||||
QString contents(bootstrapFile.readLine());
|
||||
int matchIdx = allowedListPattern.indexIn(contents);
|
||||
if (matchIdx != -1)
|
||||
auto CompareQListToAzVector = [](AZStd::string_view currentAllowedIp, const QString& newAllowedIp)
|
||||
{
|
||||
allowedListline = contents;
|
||||
readAllowedList = allowedListPattern.cap(2);
|
||||
break;
|
||||
return currentAllowedIp == newAllowedIp.toUtf8().constData();
|
||||
};
|
||||
if (AZStd::equal(allowedListArray.begin(), allowedListArray.end(), newAllowedList.begin(), newAllowedList.end(), CompareQListToAzVector))
|
||||
{
|
||||
// no need to update, remote_ip already matches
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//read the entire file into so we can do a buffer replacement
|
||||
bootstrapFile.seek(0);
|
||||
QString fileContents;
|
||||
fileContents = bootstrapFile.readAll();
|
||||
bootstrapFile.close();
|
||||
// Update Settings Registry with new token
|
||||
AZStd::string azNewAllowedList{ newAllowedList.join(', ').toUtf8().constData() };
|
||||
settingsRegistry->Set(allowedListKey, azNewAllowedList);
|
||||
|
||||
//format the new allowed list
|
||||
QString formattedNewAllowedList = newAllowedList.join(", ");
|
||||
|
||||
//if we didn't find a allowed_list entry then append one
|
||||
if (allowedListline.isEmpty())
|
||||
{
|
||||
fileContents.append("\nallowed_list = " + formattedNewAllowedList + "\n");
|
||||
}
|
||||
else if (QString::compare(formattedNewAllowedList, readAllowedList, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
// no need to update, they match
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Replace the found line with a new one
|
||||
fileContents.replace(allowedListline, "allowed_list = " + formattedNewAllowedList + "\n");
|
||||
}
|
||||
|
||||
// Make the bootstrap file writable
|
||||
if (!MakeFileWritable(bootstrapFilename))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false, "Failed to make the bootstrap file writable.")
|
||||
return false;
|
||||
}
|
||||
if (!bootstrapFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream output(&bootstrapFile);
|
||||
output << fileContents;
|
||||
bootstrapFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteRemoteIpToBootstrap(QString newRemoteIp)
|
||||
{
|
||||
QDir assetRoot;
|
||||
ComputeAssetRoot(assetRoot);
|
||||
QString bootstrapFilename = assetRoot.filePath("bootstrap.cfg");
|
||||
QFile bootstrapFile(bootstrapFilename);
|
||||
|
||||
// do not alter the branch file unless we are able to obtain an exclusive lock. Other apps (such as NPP) may actually write 0 bytes first, then slowly spool out the remainder)
|
||||
if (!CheckCanLock(bootstrapFilename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bootstrapFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// regexp that matches either the beginning of the file, and remote_ip, or,
|
||||
// matches a newline, then whitespace, then remote_ip it will not match comments.
|
||||
QRegExp remoteIpPattern("(^|\\n)\\s*remote_ip\\s*=\\s*(.+)", Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
|
||||
//read the file line by line and try to find the remote_ip line
|
||||
QString readRemoteIp;
|
||||
QString remoteIpline;
|
||||
while (!bootstrapFile.atEnd())
|
||||
{
|
||||
QString contents(bootstrapFile.readLine());
|
||||
int matchIdx = remoteIpPattern.indexIn(contents);
|
||||
if (matchIdx != -1)
|
||||
{
|
||||
remoteIpline = contents;
|
||||
readRemoteIp = remoteIpPattern.cap(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//read the entire file into so we can do a buffer replacement
|
||||
bootstrapFile.seek(0);
|
||||
QString fileContents;
|
||||
fileContents = bootstrapFile.readAll();
|
||||
bootstrapFile.close();
|
||||
|
||||
//if we didn't find a remote_ip entry then append one
|
||||
if (remoteIpline.isEmpty())
|
||||
{
|
||||
fileContents.append("\nremote_ip = " + newRemoteIp + "\n");
|
||||
}
|
||||
else if (QString::compare(newRemoteIp, readRemoteIp, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
// no need to update, they match
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Replace the found line with a new one
|
||||
fileContents.replace(remoteIpline, "remote_ip = " + newRemoteIp + "\n");
|
||||
}
|
||||
|
||||
// Make the bootstrap file writable
|
||||
if (!MakeFileWritable(bootstrapFilename))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false, "Failed to make the bootstrap file writable.")
|
||||
return false;
|
||||
}
|
||||
if (!bootstrapFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream output(&bootstrapFile);
|
||||
output << fileContents;
|
||||
bootstrapFile.close();
|
||||
return true;
|
||||
return AssetUtilsInternal::DumpAssetProcessorUserSettingsToFile(*settingsRegistry, assetProcessorUserSetregPath);
|
||||
}
|
||||
|
||||
quint16 ReadListeningPortFromSettingsRegistry(QString initialFolder /*= QString()*/)
|
||||
@@ -923,23 +820,20 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
|
||||
bool ComputeProjectCacheRoot(QDir& projectCacheRoot)
|
||||
{
|
||||
QDir assetRoot;
|
||||
if (!ComputeAssetRoot(assetRoot))
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
|
||||
{
|
||||
return false; // failed to detect engine root
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectCacheRootValue;
|
||||
if (registry->Get(projectCacheRootValue, AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder);
|
||||
!projectCacheRootValue.empty())
|
||||
{
|
||||
projectCacheRoot = QDir(QString::fromUtf8(projectCacheRootValue.c_str(), aznumeric_cast<int>(projectCacheRootValue.size())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QString gameDir = ComputeGameName(assetRoot.absolutePath());
|
||||
if (gameDir.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
projectCacheRoot = QDir(assetRoot.filePath("Cache/" + gameDir));
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ComputeFenceDirectory(QDir& fenceDir)
|
||||
{
|
||||
QDir cacheRoot;
|
||||
@@ -951,6 +845,25 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return true;
|
||||
}
|
||||
|
||||
QString StripAssetPlatform(AZStd::string_view relativeProductPath)
|
||||
{
|
||||
// Skip over the assetPlatform path segment if it is matches one of the platform defaults
|
||||
// Otherwise return the path unchanged
|
||||
AZStd::string_view strippedProductPath{ relativeProductPath };
|
||||
if (AZStd::optional pathSegment = AZ::StringFunc::TokenizeNext(strippedProductPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
|
||||
pathSegment.has_value())
|
||||
{
|
||||
AZ::IO::FixedMaxPathString assetPlatformSegmentLower{ *pathSegment };
|
||||
AZStd::to_lower(assetPlatformSegmentLower.begin(), assetPlatformSegmentLower.end());
|
||||
if (AzFramework::PlatformHelper::GetPlatformIdFromName(assetPlatformSegmentLower) != AzFramework::PlatformId::Invalid)
|
||||
{
|
||||
return QString::fromUtf8(strippedProductPath.data(), aznumeric_cast<int>(strippedProductPath.size()));
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromUtf8(relativeProductPath.data(), aznumeric_cast<int>(relativeProductPath.size()));
|
||||
}
|
||||
|
||||
QString NormalizeFilePath(const QString& filePath)
|
||||
{
|
||||
// do NOT convert to absolute paths here, we just want to manipulate the string itself.
|
||||
@@ -1035,92 +948,41 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
|
||||
bool UpdateBranchToken()
|
||||
{
|
||||
QDir assetRoot;
|
||||
ComputeAssetRoot(assetRoot);
|
||||
QString bootstrapFilename = assetRoot.filePath("bootstrap.cfg");
|
||||
QFile bootstrapFile(bootstrapFilename);
|
||||
QString fileContents;
|
||||
|
||||
// do not alter the branch file unless we are able to obtain an exclusive lock. Other apps (such as NPP) may actually write 0 bytes first, then slowly spool out the remainder)
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
bool hasLock = false;
|
||||
do
|
||||
{
|
||||
if (CheckCanLock(bootstrapFilename))
|
||||
{
|
||||
hasLock = true;
|
||||
break;
|
||||
}
|
||||
|
||||
QThread::msleep(AssetUtilsInternal::g_RetryWaitInterval);
|
||||
|
||||
} while (!timer.hasExpired(10 * AssetUtilsInternal::g_RetryWaitInterval));
|
||||
if (!hasLock)
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Unable to lock bootstrap file at: %s\n", bootstrapFilename.toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bootstrapFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Unable to open bootstrap file at: %s\n", bootstrapFilename.toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
|
||||
fileContents = bootstrapFile.readAll();
|
||||
bootstrapFile.close();
|
||||
AZ::IO::FixedMaxPath assetProcessorUserSetregPath = AZ::Utils::GetProjectPath();
|
||||
assetProcessorUserSetregPath /= AssetProcessorUserSetregRelPath;
|
||||
|
||||
AZStd::string appBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForAppRoot, appBranchToken);
|
||||
QString currentBranchToken(appBranchToken.c_str());
|
||||
QString readBranchToken;
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::CalculateBranchTokenForEngineRoot, appBranchToken);
|
||||
|
||||
// regexp that matches either the beginning of the file, some whitespace, and assetProcessor_branch_token, or,
|
||||
// matches a newline, then whitespace, then assetProcessor_branch_token
|
||||
// it will not match comments.
|
||||
QRegExp branchTokenPattern("(^|\\n)\\s*assetProcessor_branch_token\\s*=\\s*(\\S+)\\b", Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
|
||||
int matchIdx = branchTokenPattern.indexIn(fileContents);
|
||||
if (matchIdx != -1)
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (!settingsRegistry)
|
||||
{
|
||||
readBranchToken = branchTokenPattern.cap(2);
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Unable access Settings Registry. Branch Token cannot be updated");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readBranchToken.isEmpty())
|
||||
AZStd::string registryBranchToken;
|
||||
auto branchTokenKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/assetProcessor_branch_token";
|
||||
if (settingsRegistry->Get(registryBranchToken, branchTokenKey))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "adding branch token (%s) in (%s)\n", currentBranchToken.toUtf8().constData(), bootstrapFilename.toUtf8().constData());
|
||||
fileContents.append("\nassetProcessor_branch_token = " + currentBranchToken + "\n");
|
||||
}
|
||||
else if (QString::compare(currentBranchToken, readBranchToken, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
// no need to update, branch token match
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Branch token (%s) is already correct in (%s)\n", currentBranchToken.toUtf8().constData(), bootstrapFilename.toUtf8().constData());
|
||||
return true;
|
||||
if (appBranchToken == registryBranchToken)
|
||||
{
|
||||
// no need to update, branch token match
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Branch token (%s) is already correct in (%s)\n", appBranchToken.c_str(), assetProcessorUserSetregPath.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Updating branch token (%s) in (%s)\n", appBranchToken.c_str(), assetProcessorUserSetregPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Updating branch token
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Updating branch token (%s) in (%s)\n", currentBranchToken.toUtf8().constData(), bootstrapFilename.toUtf8().constData());
|
||||
fileContents.replace(branchTokenPattern.cap(0), "\nassetProcessor_branch_token = " + currentBranchToken + "\n");
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Adding branch token (%s) in (%s)\n", appBranchToken.c_str(), assetProcessorUserSetregPath.c_str());
|
||||
}
|
||||
|
||||
// Make the bootstrap file writable
|
||||
if (!MakeFileWritable(bootstrapFilename))
|
||||
{
|
||||
AZ_Warning(AssetProcessor::ConsoleChannel, false, "Failed to make the bootstrap file writable.")
|
||||
return false;
|
||||
}
|
||||
if (!bootstrapFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Unable to open bootstrap file (%s)\n", bootstrapFilename.toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
// Update Settings Registry with new token
|
||||
settingsRegistry->Set(branchTokenKey, appBranchToken);
|
||||
|
||||
QTextStream output(&bootstrapFile);
|
||||
output << fileContents;
|
||||
bootstrapFile.close();
|
||||
return true;
|
||||
return AssetUtilsInternal::DumpAssetProcessorUserSettingsToFile(*settingsRegistry, assetProcessorUserSetregPath);
|
||||
}
|
||||
|
||||
QString ComputeJobDescription(const AssetProcessor::AssetRecognizer* recognizer)
|
||||
@@ -1130,7 +992,7 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
|
||||
AZStd::string ComputeJobLogFolder()
|
||||
{
|
||||
return AZStd::string::format("@log@/logs/JobLogs");
|
||||
return AZStd::string::format("@log@/JobLogs");
|
||||
}
|
||||
|
||||
AZStd::string ComputeJobLogFileName(const AzToolsFramework::AssetSystem::JobInfo& jobInfo)
|
||||
@@ -1477,14 +1339,28 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
|
||||
bool CreateTempWorkspace(QString& result)
|
||||
{
|
||||
// Use the engine root as a temp workspace folder
|
||||
// this works better for numerous reasons
|
||||
// * Its on the same drive as the /Cache/ so we will be moving files instead of copying from drive to drive
|
||||
// Use the project user folder as a temp workspace folder
|
||||
// The benefits are
|
||||
// * It's on the same drive as the Cache/ so we will be moving files instead of copying from drive to drive
|
||||
// * It is discoverable by the user and thus deletable and we can also tell people to send us that folder without them having to go digging for it
|
||||
// * If you can't write to it you have much bigger problems
|
||||
|
||||
QDir rootDir;
|
||||
if (ComputeAssetRoot(rootDir))
|
||||
bool foundValidPath{};
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if (AZ::IO::Path userPath; settingsRegistry->Get(userPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
|
||||
{
|
||||
rootDir.setPath(QString::fromUtf8(userPath.c_str(), aznumeric_cast<int>(userPath.Native().size())));
|
||||
foundValidPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundValidPath)
|
||||
{
|
||||
foundValidPath = ComputeAssetRoot(rootDir);
|
||||
}
|
||||
|
||||
if (foundValidPath)
|
||||
{
|
||||
QString tempPath = rootDir.absolutePath();
|
||||
return CreateTempWorkspace(tempPath, result);
|
||||
@@ -1499,7 +1375,6 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
QString inputName;
|
||||
QString platformName;
|
||||
QString jobDescription;
|
||||
QString gameName = AssetUtilities::ComputeGameName();
|
||||
AZ::Uuid guid = AZ::Uuid::CreateNull();
|
||||
|
||||
using namespace AzToolsFramework::AssetDatabase;
|
||||
@@ -1513,16 +1388,16 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
platform = AzToolsFramework::AssetSystem::GetHostAssetPlatform();
|
||||
}
|
||||
|
||||
QString platformPrepend = QString("%1/%2/").arg(platform, gameName);
|
||||
QString productNameWithPlatformAndGameName = productName;
|
||||
QString platformPrepend = QString("%1/").arg(platform);
|
||||
QString productNameWithPlatform = productName;
|
||||
|
||||
if (!productName.startsWith(platformPrepend, Qt::CaseInsensitive))
|
||||
{
|
||||
productNameWithPlatformAndGameName = productName = QString("%1/%2/%3").arg(platform, gameName, productName);
|
||||
productNameWithPlatform = productName = QString("%1/%2").arg(platform, productName);
|
||||
}
|
||||
|
||||
ProductDatabaseEntryContainer products;
|
||||
if (databaseConnection->GetProductsByProductName(productNameWithPlatformAndGameName, products))
|
||||
if (databaseConnection->GetProductsByProductName(productNameWithPlatform, products))
|
||||
{
|
||||
// if we find stuff, then return immediately, productName is already a productName.
|
||||
return productName;
|
||||
@@ -1535,24 +1410,9 @@ to ensure that the address is correct. Asset Processor won't be running in serve
|
||||
return productName;
|
||||
}
|
||||
|
||||
if (!databaseConnection->GetProductsLikeProductName(productNameWithPlatformAndGameName, AssetDatabaseConnection::LikeType::StartsWith, products))
|
||||
if (!databaseConnection->GetProductsLikeProductName(productNameWithPlatform, AssetDatabaseConnection::LikeType::StartsWith, products))
|
||||
{
|
||||
//if we are here it means that the asset database does not know about this product,
|
||||
//we will now remove the gameName and try again ,so now the path will only have $PLATFORM/ in front of it
|
||||
int gameNameIndex = productName.indexOf(gameName, 0, Qt::CaseInsensitive);
|
||||
|
||||
if (gameNameIndex != -1)
|
||||
{
|
||||
//we will now remove the gameName and the separator
|
||||
productName.remove(gameNameIndex, gameName.length() + 1);// adding one for the native separator
|
||||
}
|
||||
|
||||
//Search the database for this product
|
||||
if (!databaseConnection->GetProductsLikeProductName(productName, AssetDatabaseConnection::LikeType::StartsWith, products))
|
||||
{
|
||||
//return empty string if the database still does not have any idea about the product
|
||||
productName = QString();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
return productName.toLower();
|
||||
}
|
||||
|
||||
@@ -51,8 +51,7 @@ namespace AssetProcessor
|
||||
|
||||
namespace AssetUtilities
|
||||
{
|
||||
|
||||
inline constexpr char GameFolderOverrideParameter[] = "gamefolder";
|
||||
inline constexpr char ProjectPathOverrideParameter[] = "project-path";
|
||||
|
||||
//! Set precision fingerprint timestamps will be truncated to avoid mismatches across systems/packaging with different file timestamp precisions
|
||||
//! Timestamps default to milliseconds. A value of 1 will keep the default millisecond precision. A value of 1000 will reduce the precision to seconds
|
||||
@@ -79,10 +78,10 @@ namespace AssetUtilities
|
||||
|
||||
//! makes the file writable
|
||||
//! return true if operation is successful, otherwise return false
|
||||
bool MakeFileWritable(QString filename);
|
||||
bool MakeFileWritable(const QString& filename);
|
||||
|
||||
//! Check to see if we can Lock the file
|
||||
bool CheckCanLock(QString filename);
|
||||
bool CheckCanLock(const QString& filename);
|
||||
|
||||
//! Updates the branch token in the bootstrap file
|
||||
bool UpdateBranchToken();
|
||||
@@ -98,11 +97,14 @@ namespace AssetUtilities
|
||||
|
||||
bool ShouldUseFileHashing();
|
||||
|
||||
//! Determine the name of the current game - for example, SamplesProject
|
||||
//! Can be overridden by passing in a non-empty gameNameOverride
|
||||
//! The override will persist if the GameName wasn't set previously or
|
||||
//! Determine the name of the current project - for example, SamplesProject
|
||||
//! Can be overridden by passing in a non-empty projectNameOverride
|
||||
//! The override will persist if the project name wasn't set previously or
|
||||
//! force=true is supplied
|
||||
QString ComputeGameName(QString gameNameOverride = QString(), bool force = false);
|
||||
QString ComputeProjectName(QString projectNameOverride = QString(), bool force = false);
|
||||
|
||||
//! Determine the absolute path of the current project
|
||||
QString ComputeProjectPath();
|
||||
|
||||
//! Reads the allowed list directly from the bootstrap file
|
||||
QString ReadAllowedlistFromSettingsRegistry(QString initialFolder = QString());
|
||||
@@ -111,13 +113,7 @@ namespace AssetUtilities
|
||||
QString ReadRemoteIpFromSettingsRegistry(QString initialFolder = QString());
|
||||
|
||||
//! Writes the allowed list directly to the bootstrap file
|
||||
bool WriteAllowedlistToBootstrap(QStringList allowedList);
|
||||
|
||||
//! Writes the remote ip directly to the bootstrap file
|
||||
bool WriteRemoteIpToBootstrap(QString remoteIp);
|
||||
|
||||
//! Reads the game name directly from the bootstrap file
|
||||
QString ReadGameNameFromSettingsRegistry(QString initialFolder = QString());
|
||||
bool WriteAllowedlistToSettingsRegistry(const QStringList& allowedList);
|
||||
|
||||
//! Reads the listening port from the bootstrap file
|
||||
//! By default the listening port is 45643
|
||||
@@ -143,13 +139,24 @@ namespace AssetUtilities
|
||||
QString ComputeJobDescription(const AssetProcessor::AssetRecognizer* recognizer);
|
||||
|
||||
//! Compute the root of the cache for the current project.
|
||||
//! This is generally the "cache" folder, subfolder gamedir.
|
||||
//! This is generally the "<Project>/Cache" folder
|
||||
bool ComputeProjectCacheRoot(QDir& projectCacheRoot);
|
||||
|
||||
//! Compute the folder that will be used for fence files.
|
||||
bool ComputeFenceDirectory(QDir& fenceDir);
|
||||
|
||||
//! Converts all slashes to forward slashes, removes double slashes,
|
||||
//! Strips the first "asset platform" from the first path segment of a relative product path
|
||||
//! This is meant for removing the asset platform for paths such as "pc/MyAssetFolder/MyAsset.asset"
|
||||
//! Therefore the result here becomes "MyAssetFolder/MyAsset"
|
||||
//!
|
||||
//! Similarly invoking this function on relative path that begins with the "server" platform
|
||||
//! "server/AssetFolder/Server.asset2" -> "AssetFolder/Server.asset2"
|
||||
//! This function does not strip an asset platform from anywhere, but the first path segment
|
||||
//! Therefore invoking strip Asset on "MyProject/Cache/pc/MyAsset/MyAsset.asset"
|
||||
//! would return a copy of the relative path
|
||||
QString StripAssetPlatform(AZStd::string_view relativeProductPath);
|
||||
|
||||
//! Converts all slashes to forward slashes, removes double slashes,
|
||||
//! replaces all indirections such as '.' or '..' as appropriate.
|
||||
//! On windows, the drive letter (if present) is converted to uppercase.
|
||||
//! Besides that, all case is preserved.
|
||||
|
||||
Reference in New Issue
Block a user