Merge branch 'development' into o3de_sdk/installer_configs
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -61,8 +61,12 @@ namespace AssetBundler
|
||||
{
|
||||
AZStd::string absolutePath = filePath.toUtf8().data();
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath.c_str()))
|
||||
{
|
||||
AZStd::string projectName = pathToProjectNameMap.at(absolutePath);
|
||||
{
|
||||
AZStd::string projectName;
|
||||
if (pathToProjectNameMap.contains(absolutePath))
|
||||
{
|
||||
projectName = pathToProjectNameMap.at(absolutePath);
|
||||
}
|
||||
|
||||
// If a project name is already specified, then the associated file is a default file
|
||||
LoadFile(absolutePath, projectName, !projectName.empty());
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/AZStdContainers.inl>
|
||||
#include <AzCore/std/string/regex.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/parallel/atomic.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
#include <AzFramework/Asset/AssetProcessorMessages.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
|
||||
@@ -3576,23 +3576,24 @@ namespace AssetProcessor
|
||||
// Absolute path, just check the 1 scan folder
|
||||
if (AZ::IO::PathView(encodedFileData.toUtf8().constData()).IsAbsolute())
|
||||
{
|
||||
QString scanFolderName;
|
||||
if (!m_platformConfig->ConvertToRelativePath(encodedFileData, resultDatabaseSourceName, scanFolderName))
|
||||
auto scanFolderInfo = m_platformConfig->GetScanFolderForFile(encodedFileData);
|
||||
|
||||
if (!m_platformConfig->ConvertToRelativePath(encodedFileData, scanFolderInfo, resultDatabaseSourceName))
|
||||
{
|
||||
AZ_Warning(
|
||||
AssetProcessor::ConsoleChannel, false,
|
||||
"'%s' does not appear to be in any input folder. Use relative paths instead.",
|
||||
sourceDependency.m_sourceFileDependencyPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make an absolute path that is ScanFolderPath + Part of search path before the wildcard
|
||||
QDir rooted(scanFolderInfo->ScanPath());
|
||||
QString scanFolderAndKnownSubPath = rooted.absoluteFilePath(knownPathBeforeWildcard);
|
||||
|
||||
auto scanFolderInfo = m_platformConfig->GetScanFolderByPath(scanFolderName);
|
||||
|
||||
// Make an absolute path that is ScanFolderPath + Part of search path before the wildcard
|
||||
QDir rooted(scanFolderName);
|
||||
QString scanFolderAndKnownSubPath = rooted.absoluteFilePath(knownPathBeforeWildcard);
|
||||
|
||||
resolvedDependencyList.append(m_platformConfig->FindWildcardMatches(
|
||||
scanFolderAndKnownSubPath, relativeSearch, false, scanFolderInfo->RecurseSubFolders()));
|
||||
resolvedDependencyList.append(m_platformConfig->FindWildcardMatches(
|
||||
scanFolderAndKnownSubPath, relativeSearch, false, scanFolderInfo->RecurseSubFolders()));
|
||||
}
|
||||
}
|
||||
else // Relative path, check every scan folder
|
||||
{
|
||||
|
||||
@@ -259,6 +259,11 @@ namespace AssetProcessor
|
||||
scratchBuffer.reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
||||
AZStd::fixed_vector<AZStd::string_view, AzFramework::MaxPlatformCodeNames> platformCodes;
|
||||
AzFramework::PlatformHelper::AppendPlatformCodeNames(platformCodes, request.m_platformInfo.m_identifier);
|
||||
AZ_Assert(platformCodes.size() <= 1, "A one-to-one mapping of asset type platform identifier"
|
||||
" to platform codename is required in the SettingsRegistryBuilder."
|
||||
" The bootstrap.game is now only produced per build configuration and doesn't take into account"
|
||||
" different platforms names");
|
||||
|
||||
const AZStd::string& assetPlatformIdentifier = request.m_jobDescription.GetPlatformIdentifier();
|
||||
// Determines the suffix that will be used for the launcher based on processing server vs non-server assets
|
||||
const char* launcherType = assetPlatformIdentifier != AzFramework::PlatformHelper::GetPlatformName(AzFramework::PlatformId::SERVER)
|
||||
@@ -293,9 +298,10 @@ namespace AssetProcessor
|
||||
outputBuffer.Reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
||||
SettingsExporter exporter(outputBuffer, excludes);
|
||||
|
||||
for (AZStd::string_view platform : platformCodes)
|
||||
if (!platformCodes.empty())
|
||||
{
|
||||
AZ::u32 productSubID = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(platform)); // Deliberately ignoring half the bits.
|
||||
AZStd::string_view platform = platformCodes.front();
|
||||
constexpr AZ::u32 productSubID = 0;
|
||||
for (size_t i = 0; i < AZStd::size(specializations); ++i)
|
||||
{
|
||||
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
|
||||
@@ -337,7 +343,7 @@ namespace AssetProcessor
|
||||
// The purpose of this section is to copy the Gem's SourcePaths from the Global Settings Registry
|
||||
// the local SettingsRegistry. The reason this is needed is so that the call to
|
||||
// `MergeSettingsToRegistry_GemRegistries` below is able to locate each gem's "<gem-root>/Registry" folder
|
||||
// that will be merged into the bootstrap.game.<configuration>.<platform>.setreg file
|
||||
// that will be merged into the bootstrap.game.<configuration>.setreg file
|
||||
// This is used by the GameLauncher applications to read from a single merged .setreg file
|
||||
// containing the settings needed to run a game/simulation without have access to the source code base registry
|
||||
AZStd::vector<AzFramework::GemInfo> gemInfos;
|
||||
@@ -408,8 +414,6 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
outputPath += specialization.GetSpecialization(0); // Append configuration
|
||||
outputPath += '.';
|
||||
outputPath += platform;
|
||||
outputPath += ".setreg";
|
||||
|
||||
AZ::IO::SystemFile file;
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace AssetProcessor
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/savebackup\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|.+/)savebackup/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
config.AddExcludeRecognizer(excludeRecogniser);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
friend struct DuplicateProductsTest;
|
||||
friend struct DuplicateProcessTest;
|
||||
friend struct AbsolutePathProductDependencyTest;
|
||||
friend struct WildcardSourceDependencyTest;
|
||||
|
||||
explicit AssetProcessorManager_Test(PlatformConfiguration* config, QObject* parent = nullptr);
|
||||
~AssetProcessorManager_Test() override;
|
||||
@@ -4446,7 +4447,9 @@ AssetBuilderSDK::AssetBuilderDesc MockBuilderInfoHandler::CreateBuilderDesc(cons
|
||||
|
||||
void FingerprintTest::SetUp()
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "SetUp start");
|
||||
AssetProcessorManagerTest::SetUp();
|
||||
AZ_Printf("FingerprintTest", "SetUp self");
|
||||
|
||||
// We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
|
||||
m_mockApplicationManager->BusDisconnect();
|
||||
@@ -4465,18 +4468,23 @@ void FingerprintTest::SetUp()
|
||||
});
|
||||
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(m_absolutePath, ""));
|
||||
AZ_Printf("FingerprintTest", "SetUp end");
|
||||
}
|
||||
|
||||
void FingerprintTest::TearDown()
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "TearDown start");
|
||||
m_jobResults = AZStd::vector<AssetProcessor::JobDetails>{};
|
||||
m_mockBuilderInfoHandler = {};
|
||||
|
||||
AZ_Printf("FingerprintTest", "TearDown parent");
|
||||
AssetProcessorManagerTest::TearDown();
|
||||
AZ_Printf("FingerprintTest", "TearDown end");
|
||||
}
|
||||
|
||||
void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString jobFingerprint, bool expectedResult)
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test Start");
|
||||
m_mockBuilderInfoHandler.m_builderDesc.m_analysisFingerprint = builderFingerprint.toUtf8().data();
|
||||
m_mockBuilderInfoHandler.m_jobFingerprint = jobFingerprint;
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, m_absolutePath));
|
||||
@@ -4485,6 +4493,7 @@ void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString job
|
||||
ASSERT_EQ(m_mockBuilderInfoHandler.m_createJobsCount, 1);
|
||||
ASSERT_EQ(m_jobResults.size(), 1);
|
||||
ASSERT_EQ(m_jobResults[0].m_autoFail, expectedResult);
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test End");
|
||||
}
|
||||
|
||||
TEST_F(FingerprintTest, FingerprintChecking_JobFingerprint_NoBuilderFingerprint)
|
||||
@@ -5308,3 +5317,141 @@ TEST_F(MetadataFileTest, MetadataFile_SourceFileExtensionDifferentCase)
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
ASSERT_EQ(jobDetails.m_jobEntry.m_pathRelativeToWatchFolder, relFileName);
|
||||
}
|
||||
|
||||
bool WildcardSourceDependencyTest::Test(
|
||||
const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths)
|
||||
{
|
||||
[[maybe_unused]] QString resolvedName;
|
||||
QStringList stringlistPaths;
|
||||
AssetBuilderSDK::SourceFileDependency dependency(dependencyPath, AZ::Uuid::CreateNull(), AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
||||
bool result = m_assetProcessorManager->ResolveSourceFileDependencyPath(dependency, resolvedName, stringlistPaths);
|
||||
|
||||
// Convert to a vector of AZStd::strings because GTest handles this type better when displaying errors
|
||||
for (const QString& resolvedPath : stringlistPaths)
|
||||
{
|
||||
resolvedPaths.emplace_back(resolvedPath.toUtf8().constData());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WildcardSourceDependencyTest::SetUp()
|
||||
{
|
||||
AssetProcessorManagerTest::SetUp();
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
// Add a non-recursive scan folder. Only files directly inside of this folder should be picked up, subfolders are ignored
|
||||
m_config->AddScanFolder(ScanFolderInfo(tempPath.filePath("no_recurse"), "no_recurse",
|
||||
"no_recurse", false, false, m_config->GetEnabledPlatforms(), 1));
|
||||
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/1a.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder1/1b.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/a.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/b.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/c.foo"));
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/d.foo"));
|
||||
|
||||
// Add a file that is not in a scanfolder. Should always be ignored
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("not/a/scanfolder/e.foo"));
|
||||
|
||||
// Add a file in the non-recursive scanfolder. Since its not directly in the scan folder, it should always be ignored
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("no_recurse/one/two/three/f.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_Broad)
|
||||
{
|
||||
// Expect all files except for the 2 invalid ones (e and f)
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("*.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "b.foo", "folder/one/c.foo", "folder/one/d.foo", "1a.foo", "1b.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_WithFolder)
|
||||
{
|
||||
// Make sure we can filter to files under a folder
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("folder/*.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("folder/one/c.foo", "folder/one/d.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_WildcardPath)
|
||||
{
|
||||
// Make sure the * wildcard works even if the full filename is given
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
|
||||
ASSERT_TRUE(Test("*a.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "1a.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_WithFolder)
|
||||
{
|
||||
// Make sure we can use absolute paths to filter to files under a folder
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("subfolder2/redirected/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "b.foo", "folder/one/c.foo", "folder/one/d.foo"));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_NotInScanfolder)
|
||||
{
|
||||
// Files outside a scanfolder should not be returned even with an absolute path
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("not/a/scanfolder/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_NotInScanfolder)
|
||||
{
|
||||
// Files outside a scanfolder should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test("*/e.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_InNonRecursiveScanfolder)
|
||||
{
|
||||
// Files deep inside non-recursive scanfolders should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test("*/f.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_InNonRecursiveScanfolder)
|
||||
{
|
||||
// Absolute paths to files deep inside non-recursive scanfolders should not be returned
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_TRUE(Test(tempPath.absoluteFilePath("one/two/three/*.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_NoWildcard)
|
||||
{
|
||||
// No wildcard results in a failure
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_FALSE(Test("subfolder1/1a.foo", resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Absolute_NoWildcard)
|
||||
{
|
||||
// No wildcard results in a failure
|
||||
AZStd::vector<AZStd::string> resolvedPaths;
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
ASSERT_FALSE(Test(tempPath.absoluteFilePath("subfolder1/1a.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
@@ -131,6 +131,14 @@ struct MultiplatformPathDependencyTest
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
struct WildcardSourceDependencyTest
|
||||
: AssetProcessorManagerTest
|
||||
{
|
||||
bool Test(const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths);
|
||||
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
struct MockBuilderInfoHandler
|
||||
: public AssetProcessor::AssetBuilderInfoBus::Handler
|
||||
{
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace AssetProcessor
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
// we are excluding all the files in the folder but not the folder itself
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/subfolder2\\/aaa\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|[^/]+/)aaa/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
m_platformConfig.get()->AddExcludeRecognizer(excludeRecogniser);
|
||||
m_assetScanner.get()->StartScan();
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace AssetProcessor
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
// we are excluding the complete folder here
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/subfolder2\\/aaa", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|[^/]+/)aaa", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
m_platformConfig.get()->AddExcludeRecognizer(excludeRecogniser);
|
||||
m_assetScanner.get()->StartScan();
|
||||
|
||||
|
||||
+2
@@ -405,6 +405,8 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
|
||||
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
|
||||
ASSERT_TRUE(configRoot);
|
||||
UnitTestPlatformConfiguration config;
|
||||
|
||||
config.AddScanFolder(ScanFolderInfo("blahblah", "Blah ScanFolder", "sf2", true, true), true);
|
||||
m_absorber.Clear();
|
||||
ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
|
||||
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace AssetProcessor
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
excludeRecogniser.m_name = "backup";
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher(".*\\/savebackup\\/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
excludeRecogniser.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("(^|.+/)savebackup/.*", AssetBuilderSDK::AssetBuilderPattern::Regex);
|
||||
config.AddExcludeRecognizer(excludeRecogniser);
|
||||
|
||||
AssetProcessorManager_Test apm(&config); // note, this will 'push' the scan folders in to the db.
|
||||
@@ -1791,13 +1791,8 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForPCAfterVersionChange != fingerprintForPC) || (newfingerprintForPCAfterVersionChange != newfingerprintForPC));//Fingerprints should be different
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForANDROIDAfterVersionChange != fingerprintForANDROID) || (newfingerprintForANDROIDAfterVersionChange != newfingerprintForANDROID));//Fingerprints should be different
|
||||
|
||||
//------Test for Files which are excluded
|
||||
processResults.clear();
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder3/savebackup/test.txt"));
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
UNIT_TEST_EXPECT_FALSE(BlockUntil(idling, 3000)); //Processing a file that will be excluded should not cause assetprocessor manager to emit the onBecameIdle signal because its state should not change
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 0);
|
||||
|
||||
|
||||
// ------------- Test querying asset status -------------------
|
||||
{
|
||||
absolutePath = tempPath.absoluteFilePath("subfolder2/folder/ship.tiff");
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <AzCore/UnitTest/UnitTest.h>
|
||||
|
||||
//! These macros can be used for checking your unit tests,
|
||||
//! you can check AssetScannerUnitTest.cpp for usage
|
||||
@@ -155,6 +156,7 @@ namespace UnitTestUtils
|
||||
|
||||
bool OnPreWarning([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
|
||||
{
|
||||
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
|
||||
++m_numWarningsAbsorbed;
|
||||
if (m_debugMessages)
|
||||
{
|
||||
@@ -165,6 +167,7 @@ namespace UnitTestUtils
|
||||
|
||||
bool OnPreAssert([[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
|
||||
{
|
||||
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
|
||||
++m_numAssertsAbsorbed;
|
||||
if (m_debugMessages)
|
||||
{
|
||||
@@ -175,6 +178,7 @@ namespace UnitTestUtils
|
||||
|
||||
bool OnPreError([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
|
||||
{
|
||||
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
|
||||
++m_numErrorsAbsorbed;
|
||||
if (m_debugMessages)
|
||||
{
|
||||
@@ -183,8 +187,9 @@ namespace UnitTestUtils
|
||||
return true; // I handled this, do not forward it
|
||||
}
|
||||
|
||||
bool OnPrintf(const char* /*window*/, const char* /*message*/) override
|
||||
bool OnPrintf(const char* /*window*/, const char* message) override
|
||||
{
|
||||
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
|
||||
++m_numMessagesAbsorbed;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1633,13 +1633,18 @@ namespace AssetProcessor
|
||||
|
||||
bool AssetProcessor::PlatformConfiguration::IsFileExcluded(QString fileName) const
|
||||
{
|
||||
for (const ExcludeAssetRecognizer& excludeRecognizer : m_excludeAssetRecognizers)
|
||||
QString relPath, scanFolderName;
|
||||
if (ConvertToRelativePath(fileName, relPath, scanFolderName))
|
||||
{
|
||||
if (excludeRecognizer.m_patternMatcher.MatchesPath(fileName.toUtf8().constData()))
|
||||
for (const ExcludeAssetRecognizer& excludeRecognizer : m_excludeAssetRecognizers)
|
||||
{
|
||||
return true;
|
||||
if (excludeRecognizer.m_patternMatcher.MatchesPath(relPath.toUtf8().constData()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -50,10 +50,10 @@
|
||||
"order": 6000
|
||||
},
|
||||
"Exclude HoldFiles": {
|
||||
"pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
|
||||
"pattern": "(^|.+/)Levels/.*_hold(/.*)?$"
|
||||
},
|
||||
"Exclude TempFiles": {
|
||||
"pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
|
||||
"pattern": "(^|.+/)\\\\$tmp[0-9]*_.*"
|
||||
},
|
||||
"RC i_caf": {
|
||||
"glob": "*.i_caf",
|
||||
|
||||
+2
-2
@@ -74,10 +74,10 @@
|
||||
"include": "test"
|
||||
},
|
||||
"Exclude HoldFiles": {
|
||||
"pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
|
||||
"pattern": "(^|.+/)Levels/.*_hold(/.*)?$"
|
||||
},
|
||||
"Exclude TempFiles": {
|
||||
"pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
|
||||
"pattern": "(^|.+/)\\\\$tmp[0-9]*_.*"
|
||||
},
|
||||
"RC i_caf": {
|
||||
"glob": "*.i_caf",
|
||||
|
||||
@@ -34,6 +34,7 @@ ly_add_target(
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Platform/${PAL_PLATFORM_NAME}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_linux.cpp
|
||||
ProjectUtils_linux.cpp
|
||||
ProjectManagerDefs_linux.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Linux.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Linux.h>
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_mac.cpp
|
||||
ProjectUtils_mac.cpp
|
||||
ProjectManagerDefs_mac.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Mac.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Mac.h>
|
||||
@@ -11,4 +11,6 @@ set(FILES
|
||||
ProjectBuilderWorker_windows.cpp
|
||||
ProjectUtils_windows.cpp
|
||||
ProjectManagerDefs_windows.cpp
|
||||
ProjectManager_Traits_Platform.h
|
||||
ProjectManager_Traits_Windows.h
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Traits_Windows.h>
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR true
|
||||
@@ -9,7 +9,7 @@ QMainWindow {
|
||||
|
||||
#ScreensCtrl {
|
||||
min-width:1200px;
|
||||
min-height:800px;
|
||||
min-height:700px;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
@@ -691,6 +691,12 @@ QProgressBar::chunk {
|
||||
|
||||
#gemRepoAddDialogInstructionTitleLabel {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#gemRepoAddDialogWarningLabel {
|
||||
font-size:12px;
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
#addGemRepoDialog #formFrame {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
#include <ProjectManager_Traits_Platform.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
@@ -194,8 +195,12 @@ namespace O3DE::ProjectManager
|
||||
// set stylesheet after creating the main window or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
#if AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
|
||||
#else
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionDisabled);
|
||||
#endif
|
||||
wrapper->setGuest(m_mainWindow.data());
|
||||
|
||||
// show the main window here to apply the stylesheet before restoring geometry or we
|
||||
|
||||
@@ -42,7 +42,9 @@ namespace O3DE::ProjectManager
|
||||
m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxModel, m_downloadController);
|
||||
vLayout->addWidget(m_headerWidget);
|
||||
|
||||
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
|
||||
connect(m_headerWidget, &GemCatalogHeaderWidget::OpenGemsRepo, this, &GemCatalogScreen::HandleOpenGemRepo);
|
||||
connect(m_headerWidget, &GemCatalogHeaderWidget::AddGem, this, &GemCatalogScreen::OnAddGemClicked);
|
||||
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setMargin(0);
|
||||
@@ -73,6 +75,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_notificationsView = AZStd::make_unique<AzToolsFramework::ToastNotificationsView>(this, AZ_CRC("GemCatalogNotificationsView"));
|
||||
m_notificationsView->SetOffset(QPoint(10, 70));
|
||||
m_notificationsView->SetMaxQueuedNotifications(1);
|
||||
}
|
||||
|
||||
void GemCatalogScreen::ReinitForProject(const QString& projectPath)
|
||||
@@ -94,48 +97,6 @@ namespace O3DE::ProjectManager
|
||||
m_headerWidget->ReinitForProject();
|
||||
|
||||
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
|
||||
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
|
||||
connect(
|
||||
m_headerWidget, &GemCatalogHeaderWidget::AddGem,
|
||||
[&]()
|
||||
{
|
||||
EngineInfo engineInfo;
|
||||
QString defaultPath;
|
||||
|
||||
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
if (engineInfoResult.IsSuccess())
|
||||
{
|
||||
engineInfo = engineInfoResult.GetValue();
|
||||
defaultPath = engineInfo.m_defaultGemsFolder;
|
||||
}
|
||||
|
||||
if (defaultPath.isEmpty())
|
||||
{
|
||||
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Browse"), defaultPath));
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
// register the gem to the o3de_manifest.json and to the project after the user confirms
|
||||
// project creation/update
|
||||
auto registerResult = PythonBindingsInterface::Get()->RegisterGem(directory);
|
||||
if(!registerResult)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to add gem"), registerResult.GetError().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gemsToRegisterWithProject.insert(directory);
|
||||
AZ::Outcome<GemInfo, void> gemInfoResult = PythonBindingsInterface::Get()->GetGemInfo(directory);
|
||||
if (gemInfoResult)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
|
||||
m_gemModel->UpdateGemDependencies();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Select the first entry after everything got correctly sized
|
||||
QTimer::singleShot(200, [=]{
|
||||
@@ -144,6 +105,46 @@ namespace O3DE::ProjectManager
|
||||
});
|
||||
}
|
||||
|
||||
void GemCatalogScreen::OnAddGemClicked()
|
||||
{
|
||||
EngineInfo engineInfo;
|
||||
QString defaultPath;
|
||||
|
||||
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
if (engineInfoResult.IsSuccess())
|
||||
{
|
||||
engineInfo = engineInfoResult.GetValue();
|
||||
defaultPath = engineInfo.m_defaultGemsFolder;
|
||||
}
|
||||
|
||||
if (defaultPath.isEmpty())
|
||||
{
|
||||
defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Browse"), defaultPath));
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
// register the gem to the o3de_manifest.json and to the project after the user confirms
|
||||
// project creation/update
|
||||
auto registerResult = PythonBindingsInterface::Get()->RegisterGem(directory);
|
||||
if(!registerResult)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to add gem"), registerResult.GetError().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gemsToRegisterWithProject.insert(directory);
|
||||
AZ::Outcome<GemInfo, void> gemInfoResult = PythonBindingsInterface::Get()->GetGemInfo(directory);
|
||||
if (gemInfoResult)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfoResult.GetValue<GemInfo>());
|
||||
m_gemModel->UpdateGemDependencies();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GemCatalogScreen::OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies)
|
||||
{
|
||||
if (m_notificationsEnabled)
|
||||
@@ -166,6 +167,10 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
notification += " " + tr("and") + " ";
|
||||
}
|
||||
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
|
||||
{
|
||||
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
|
||||
}
|
||||
}
|
||||
|
||||
if (numChangedDependencies == 1 )
|
||||
@@ -174,7 +179,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
else if (numChangedDependencies > 1)
|
||||
{
|
||||
notification += QString("%d Gem ").arg(numChangedDependencies) + tr("dependencies");
|
||||
notification += QString("%1 Gem ").arg(numChangedDependencies) + tr("dependencies");
|
||||
}
|
||||
notification += " " + (added ? tr("activated") : tr("deactivated"));
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
public slots:
|
||||
void OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies);
|
||||
void OnAddGemClicked();
|
||||
|
||||
protected:
|
||||
void hideEvent(QHideEvent* event) override;
|
||||
|
||||
@@ -225,21 +225,22 @@ namespace O3DE::ProjectManager
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
const int selectedGemTotal = m_gemModel->GatherGemsToBeAdded(/*includeDependencies=*/true).size();
|
||||
const int unselectedGemTotal = m_gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true).size();
|
||||
const int enabledGemTotal = m_gemModel->TotalAddedGems(/*includeDependencies=*/true);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(unselectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Active));
|
||||
elementCounts.push_back(enabledGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
@@ -262,44 +263,51 @@ namespace O3DE::ProjectManager
|
||||
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
|
||||
QAbstractButton* unselectedButton = buttons[0];
|
||||
QAbstractButton* selectedButton = buttons[1];
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
QAbstractButton* selectedButton = buttons[0];
|
||||
QAbstractButton* unselectedButton = buttons[1];
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
|
||||
auto updateGemSelection = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Selected);
|
||||
}
|
||||
else if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
if (unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Both);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
}
|
||||
}
|
||||
};
|
||||
connect(unselectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
connect(selectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
|
||||
QAbstractButton* inactiveButton = buttons[2];
|
||||
QAbstractButton* activeButton = buttons[3];
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
QAbstractButton* activeButton = buttons[2];
|
||||
QAbstractButton* inactiveButton = buttons[3];
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
|
||||
auto updateGemActive = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Active);
|
||||
}
|
||||
else if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::NoFilter);
|
||||
|
||||
@@ -50,11 +50,26 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter != GemSelected::NoFilter)
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter == GemSelected::Selected)
|
||||
{
|
||||
const GemSelected sourceGemStatus = static_cast<GemSelected>(GemModel::IsAdded(sourceIndex));
|
||||
if (m_gemSelectedFilter != sourceGemStatus)
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Unselected)
|
||||
{
|
||||
if (!GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem selected or unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Both)
|
||||
{
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true) && !GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
NoFilter = -1,
|
||||
Unselected,
|
||||
Selected
|
||||
Selected,
|
||||
Both
|
||||
};
|
||||
enum class GemActive
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace O3DE::ProjectManager
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(30, 30, 25, 10);
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
setLayout(vLayout);
|
||||
|
||||
QLabel* instructionTitleLabel = new QLabel(tr("Enter a valid path to add a new user repository"));
|
||||
@@ -41,9 +42,18 @@ namespace O3DE::ProjectManager
|
||||
vLayout->addWidget(instructionContextLabel);
|
||||
|
||||
m_repoPath = new FormFolderBrowseEditWidget(tr("Repository Path"), "", this);
|
||||
m_repoPath->setFixedWidth(600);
|
||||
m_repoPath->setFixedSize(QSize(600, 100));
|
||||
vLayout->addWidget(m_repoPath);
|
||||
|
||||
vLayout->addSpacing(10);
|
||||
|
||||
QLabel* warningLabel = new QLabel(tr("Online repositories may contain files that could potentially harm your computer,"
|
||||
" please ensure you understand the risks before downloading Gems from third-party sources."));
|
||||
warningLabel->setObjectName("gemRepoAddDialogWarningLabel");
|
||||
warningLabel->setWordWrap(true);
|
||||
warningLabel->setAlignment(Qt::AlignLeft);
|
||||
vLayout->addWidget(warningLabel);
|
||||
|
||||
vLayout->addSpacing(40);
|
||||
|
||||
QDialogButtonBox* dialogButtons = new QDialogButtonBox();
|
||||
|
||||
@@ -133,6 +133,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are already on this screen still notify we are on this screen to refresh it
|
||||
newScreen->NotifyCurrentScreen();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -187,6 +187,7 @@ namespace AZ
|
||||
|
||||
// Register utilities
|
||||
AZ::SceneAPI::SceneCore::PatternMatcher::Reflect(context);
|
||||
AZ::SceneAPI::Utilities::DebugSceneGraph::Reflect(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <AzCore/std/optional.h>
|
||||
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||
@@ -20,6 +21,36 @@
|
||||
|
||||
namespace AZ::SceneAPI::Utilities
|
||||
{
|
||||
void DebugNode::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DebugNode>()
|
||||
->Field("Name", &DebugNode::m_name)
|
||||
->Field("Path", &DebugNode::m_path)
|
||||
->Field("Type", &DebugNode::m_type)
|
||||
->Field("Data", &DebugNode::m_data);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugSceneGraph::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
DebugNode::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<DebugSceneGraph>()
|
||||
->Field("Version", &DebugSceneGraph::m_version)
|
||||
->Field("ProductName", &DebugSceneGraph::m_productName)
|
||||
->Field("SceneName", &DebugSceneGraph::m_sceneName)
|
||||
->Field("Nodes", &DebugSceneGraph::m_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, const char* data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %s\n", name, data);
|
||||
@@ -38,21 +69,29 @@ namespace AZ::SceneAPI::Utilities
|
||||
void DebugOutput::Write(const char* name, const AZStd::string& data)
|
||||
{
|
||||
Write(name, data.c_str());
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, double data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %f\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, uint64_t data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %" PRIu64 "\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, int64_t data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %" PRId64 "\n", name, data);
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, const DataTypes::MatrixType& data)
|
||||
@@ -63,6 +102,7 @@ namespace AZ::SceneAPI::Utilities
|
||||
AZ::Vector3 translation{};
|
||||
data.GetBasisAndTranslation(&basisX, &basisY, &basisZ, &translation);
|
||||
|
||||
m_pauseNodeData = true;
|
||||
m_output += AZStd::string::format("\t%s:\n", name);
|
||||
|
||||
m_output += "\t";
|
||||
@@ -76,16 +116,23 @@ namespace AZ::SceneAPI::Utilities
|
||||
|
||||
m_output += "\t";
|
||||
Write("Transl", translation);
|
||||
m_pauseNodeData = false;
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, bool data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: %s\n", name, data ? "true" : "false");
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, Vector3 data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: <% f, % f, % f>\n", name, data.GetX(), data.GetY(), data.GetZ());
|
||||
|
||||
AddToNode(name, data);
|
||||
}
|
||||
|
||||
void DebugOutput::Write(const char* name, AZStd::optional<bool> data)
|
||||
@@ -128,6 +175,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
return m_output;
|
||||
}
|
||||
|
||||
DebugNode DebugOutput::GetDebugNode() const
|
||||
{
|
||||
return m_currentNode;
|
||||
}
|
||||
|
||||
void WriteAndLog(AZ::IO::SystemFile& dbgFile, const char* strToWrite)
|
||||
{
|
||||
AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "%s", strToWrite);
|
||||
@@ -137,7 +189,6 @@ namespace AZ::SceneAPI::Utilities
|
||||
|
||||
void DebugOutput::BuildDebugSceneGraph(const char* outputFolder, AZ::SceneAPI::Events::ExportProductList& productList, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene, AZStd::string productName)
|
||||
{
|
||||
const int debugSceneGraphVersion = 1;
|
||||
AZStd::string debugSceneFile;
|
||||
|
||||
AzFramework::StringFunc::Path::ConstructFull(outputFolder, productName.c_str(), debugSceneFile);
|
||||
@@ -147,7 +198,7 @@ namespace AZ::SceneAPI::Utilities
|
||||
if (dbgFile.Open(debugSceneFile.c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY))
|
||||
{
|
||||
WriteAndLog(dbgFile, AZStd::string::format("ProductName: %s", productName.c_str()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("debugSceneGraphVersion: %d", debugSceneGraphVersion).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("debugSceneGraphVersion: %d", SceneGraphVersion).c_str());
|
||||
WriteAndLog(dbgFile, scene->GetName().c_str());
|
||||
|
||||
const AZ::SceneAPI::Containers::SceneGraph& sceneGraph = scene->GetGraph();
|
||||
@@ -158,6 +209,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
AZ::SceneAPI::Containers::Views::BreadthFirst>(
|
||||
sceneGraph, sceneGraph.GetRoot(), pairView.cbegin(), true);
|
||||
|
||||
DebugSceneGraph debugSceneGraph;
|
||||
debugSceneGraph.m_version = SceneGraphVersion;
|
||||
debugSceneGraph.m_productName = productName;
|
||||
debugSceneGraph.m_sceneName = scene->GetName().c_str();
|
||||
|
||||
for (auto&& viewIt : view)
|
||||
{
|
||||
if (viewIt.second == nullptr)
|
||||
@@ -170,20 +226,31 @@ namespace AZ::SceneAPI::Utilities
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Name: %s", viewIt.first.GetName()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Path: %s", viewIt.first.GetPath()).c_str());
|
||||
WriteAndLog(dbgFile, AZStd::string::format("Node Type: %s", graphObject->RTTI_GetTypeName()).c_str());
|
||||
|
||||
AZ::SceneAPI::Utilities::DebugOutput debugOutput;
|
||||
|
||||
AZ::SceneAPI::Utilities::DebugOutput debugOutput(
|
||||
DebugNode(viewIt.first.GetName(), viewIt.first.GetPath(), graphObject->RTTI_GetTypeName()));
|
||||
|
||||
viewIt.second->GetDebugOutput(debugOutput);
|
||||
|
||||
if (!debugOutput.GetOutput().empty())
|
||||
{
|
||||
WriteAndLog(dbgFile, debugOutput.GetOutput().c_str());
|
||||
}
|
||||
|
||||
debugSceneGraph.m_nodes.push_back(debugOutput.GetDebugNode());
|
||||
}
|
||||
dbgFile.Close();
|
||||
|
||||
Utils::SaveObjectToFile((debugSceneFile + ".xml").c_str(), DataStream::StreamType::ST_XML, &debugSceneGraph);
|
||||
|
||||
static const AZ::Data::AssetType dbgSceneGraphAssetType("{07F289D1-4DC7-4C40-94B4-0A53BBCB9F0B}");
|
||||
productList.AddProduct(productName, AZ::Uuid::CreateName(productName.c_str()), dbgSceneGraphAssetType,
|
||||
AZStd::nullopt, AZStd::nullopt);
|
||||
|
||||
static const AZ::Data::AssetType dbgSceneGraphXmlAssetType("{51F37614-0D77-4F36-9AC6-7ED70A0AC868}");
|
||||
productList.AddProduct(
|
||||
(productName + ".xml"), AZ::Uuid::CreateName((productName + ".xml").c_str()), dbgSceneGraphXmlAssetType,
|
||||
AZStd::nullopt, AZStd::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <cinttypes>
|
||||
#include <AzCore/std/any.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -34,15 +35,63 @@ namespace AZ
|
||||
|
||||
namespace AZ::SceneAPI::Utilities
|
||||
{
|
||||
constexpr int SceneGraphVersion = 1;
|
||||
|
||||
struct DebugNode
|
||||
{
|
||||
AZ_TYPE_INFO(DebugNode, "{490B9D4C-1847-46EB-BEBC-49812E104626}");
|
||||
|
||||
AZStd::string m_name;
|
||||
AZStd::string m_path;
|
||||
AZStd::string m_type;
|
||||
|
||||
DebugNode() = default;
|
||||
|
||||
DebugNode(AZStd::string name, AZStd::string path, AZStd::string type)
|
||||
: m_name(AZStd::move(name)),
|
||||
m_path(AZStd::move(path)),
|
||||
m_type(AZStd::move(type))
|
||||
{
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
using DataItem = AZStd::pair<AZStd::string, AZStd::any>;
|
||||
AZStd::vector<DataItem> m_data;
|
||||
};
|
||||
|
||||
struct DebugSceneGraph
|
||||
{
|
||||
AZ_TYPE_INFO(DebugSceneGraph, "{375F6558-5709-409F-881E-8ED575D56C92}");
|
||||
|
||||
int m_version = SceneGraphVersion;
|
||||
AZStd::string m_productName;
|
||||
AZStd::string m_sceneName;
|
||||
AZStd::vector<DebugNode> m_nodes;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
class DebugOutput
|
||||
{
|
||||
public:
|
||||
DebugOutput(DebugNode node) : m_currentNode(AZStd::move(node)){}
|
||||
|
||||
template<typename T>
|
||||
void Write(const char* name, const AZStd::vector<T>& data);
|
||||
|
||||
template<typename T>
|
||||
void Write(const char* name, const AZStd::vector<AZStd::vector<T>>& data);
|
||||
|
||||
template<typename T>
|
||||
void AddToNode(const char* name, const T& data)
|
||||
{
|
||||
if (!m_pauseNodeData)
|
||||
{
|
||||
m_currentNode.m_data.emplace_back(name, AZStd::make_any<AZStd::decay_t<T>>(data));
|
||||
}
|
||||
}
|
||||
|
||||
SCENE_CORE_API void Write(const char* name, const char* data);
|
||||
SCENE_CORE_API void WriteArray(const char* name, const unsigned int* data, int size);
|
||||
SCENE_CORE_API void Write(const char* name, const AZStd::string& data);
|
||||
@@ -57,11 +106,15 @@ namespace AZ::SceneAPI::Utilities
|
||||
SCENE_CORE_API void Write(const char* name, AZStd::optional<AZ::Vector3> data);
|
||||
|
||||
SCENE_CORE_API const AZStd::string& GetOutput() const;
|
||||
SCENE_CORE_API DebugNode GetDebugNode() const;
|
||||
|
||||
SCENE_CORE_API static void BuildDebugSceneGraph(const char* outputFolder, AZ::SceneAPI::Events::ExportProductList& productList, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene, AZStd::string productName);
|
||||
|
||||
protected:
|
||||
AZStd::string m_output;
|
||||
DebugSceneGraph m_graph;
|
||||
DebugNode m_currentNode;
|
||||
bool m_pauseNodeData = false; // If true, don't append any data to the DebugNode. Useful when a Write function calls other Write functions
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,11 @@ namespace AZ::SceneAPI::Utilities
|
||||
template <typename T>
|
||||
void DebugOutput::Write(const char* name, const AZStd::vector<T>& data)
|
||||
{
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), AZStd::hash_range(data.begin(), data.end()));
|
||||
size_t hash = AZStd::hash_range(data.begin(), data.end());
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), hash);
|
||||
|
||||
AddToNode(AZStd::string::format("%s - Count", name).c_str(), data.size());
|
||||
AddToNode(AZStd::string::format("%s - Hash", name).c_str(), hash);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -27,5 +31,9 @@ namespace AZ::SceneAPI::Utilities
|
||||
}
|
||||
|
||||
m_output += AZStd::string::format("\t%s: Count %zu. Hash: %zu\n", name, data.size(), hash);
|
||||
|
||||
AddToNode(AZStd::string::format("%s - Count", name).c_str(), data.size());
|
||||
AddToNode(AZStd::string::format("%s - Hash", name).c_str(), hash);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,8 +81,6 @@ namespace AZ
|
||||
|
||||
// Load the asset catalog so that we can find any nested assets successfully. We also need to tick the tick bus
|
||||
// so that the OnCatalogLoaded event gets processed now, instead of during application shutdown.
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(
|
||||
&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@products@/assetcatalog.xml");
|
||||
application.Tick();
|
||||
|
||||
AZStd::string logggingScratchBuffer;
|
||||
|
||||
Reference in New Issue
Block a user