Merge branch 'aws-lumberyard:development' into SerializeContextToolsConvertHandleAnyValidation
@@ -15,14 +15,14 @@ android {
|
||||
${SIGNING_CONFIGS}
|
||||
compileSdkVersion sdkVer
|
||||
buildToolsVersion buildToolsVer
|
||||
|
||||
ndkVersion ndkPlatformVer
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
checkReleaseBuilds false
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion ndkPlatformVer
|
||||
minSdkVersion minSdkVer
|
||||
targetSdkVersion sdkVer
|
||||
${NATIVE_CMAKE_SECTION_DEFAULT_CONFIG}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,5 @@
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
# ${GENERATION_TIMESTAMP}
|
||||
ndk.dir=${ANDROID_NDK_PATH}
|
||||
sdk.dir=${ANDROID_SDK_PATH}
|
||||
${CMAKE_DIR_LINE}
|
||||
|
||||
@@ -12,10 +12,9 @@ buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.4'
|
||||
classpath 'com.android.tools.build:gradle:${ANDROID_GRADLE_PLUGIN_VERSION}'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@@ -26,14 +25,14 @@ allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
ext {
|
||||
minSdkVer = ${MIN_SDK_VER}
|
||||
sdkVer = ${SDK_VER}
|
||||
ndkPlatformVer = ${NDK_PLATFORM_VER}
|
||||
ndkPlatformVer = '${NDK_VERSION}'
|
||||
buildToolsVer = '${SDK_BUILD_TOOL_VER}'
|
||||
lyEngineRoot = '${LY_ENGINE_ROOT}'
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"AssetProcessor": {
|
||||
"Settings": {
|
||||
"Platforms": {
|
||||
"es3": "enabled"
|
||||
"android": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace AssetBundler
|
||||
|
||||
AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot.c_str(), m_data->m_testEngineRoot.c_str(), DummyProjectName);
|
||||
AzFramework::PlatformFlags hostPlatformFlag = AzFramework::PlatformHelper::GetPlatformFlag(AzToolsFramework::AssetSystem::GetHostAssetPlatform());
|
||||
AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ES3 | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag;
|
||||
AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ANDROID | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag;
|
||||
ASSERT_EQ(platformFlags, expectedFlags);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,14 +40,14 @@ namespace AssetBundler
|
||||
|
||||
TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_MacFile_OutputBaseNameAndPlatform)
|
||||
{
|
||||
AZStd::string filePath = "assetInfoFile_osx_gl.xml";
|
||||
AZStd::string filePath = "assetInfoFile_mac.xml";
|
||||
AZStd::string baseFilename;
|
||||
AZStd::string platformIdentifier;
|
||||
|
||||
AzToolsFramework::SplitFilename(filePath, baseFilename, platformIdentifier);
|
||||
|
||||
ASSERT_EQ(baseFilename, "assetInfoFile");
|
||||
ASSERT_EQ(platformIdentifier, "osx_gl");
|
||||
ASSERT_EQ(platformIdentifier, "mac");
|
||||
}
|
||||
|
||||
TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_PcFile_OutputBaseNameAndPlatform)
|
||||
@@ -64,14 +64,14 @@ namespace AssetBundler
|
||||
|
||||
TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_MacFileWithUnderScoreInFileName_OutputBaseNameAndPlatform)
|
||||
{
|
||||
AZStd::string filePath = "assetInfoFile_test_osx_gl.xml";
|
||||
AZStd::string filePath = "assetInfoFile_test_mac.xml";
|
||||
AZStd::string baseFilename;
|
||||
AZStd::string platformIdentifier;
|
||||
|
||||
AzToolsFramework::SplitFilename(filePath, baseFilename, platformIdentifier);
|
||||
|
||||
ASSERT_EQ(baseFilename, "assetInfoFile_test");
|
||||
ASSERT_EQ(platformIdentifier, "osx_gl");
|
||||
ASSERT_EQ(platformIdentifier, "mac");
|
||||
}
|
||||
|
||||
TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_PcFileWithUnderScoreInFileName_OutputBaseNameAndPlatform)
|
||||
|
||||
@@ -28,6 +28,10 @@ ly_add_target(
|
||||
AZ::AzToolsFramework
|
||||
)
|
||||
|
||||
if(LY_DEFAULT_PROJECT_PATH)
|
||||
set_property(TARGET AssetBuilder APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${LY_DEFAULT_PROJECT_PATH}\"")
|
||||
endif()
|
||||
|
||||
# Aggregates all combined AssetBuilders into a single LY_ASSET_BUILDERS #define
|
||||
get_property(asset_builders GLOBAL PROPERTY LY_ASSET_BUILDERS)
|
||||
string (REPLACE ";" "," asset_builders "${asset_builders}")
|
||||
|
||||
@@ -78,17 +78,17 @@ namespace AssetBuilderSDK
|
||||
{
|
||||
return AssetBuilderSDK::Platform_PC;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "es3") == 0)
|
||||
if (azstricmp(newPlatformName, "android") == 0)
|
||||
{
|
||||
return AssetBuilderSDK::Platform_ES3;
|
||||
return AssetBuilderSDK::Platform_ANDROID;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "ios") == 0)
|
||||
{
|
||||
return AssetBuilderSDK::Platform_IOS;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "osx_gl") == 0)
|
||||
if (azstricmp(newPlatformName, "mac") == 0)
|
||||
{
|
||||
return AssetBuilderSDK::Platform_OSX;
|
||||
return AssetBuilderSDK::Platform_MAC;
|
||||
}
|
||||
if (azstricmp(newPlatformName, "provo") == 0)
|
||||
{
|
||||
@@ -115,12 +115,12 @@ namespace AssetBuilderSDK
|
||||
{
|
||||
case AssetBuilderSDK::Platform_PC:
|
||||
return "pc";
|
||||
case AssetBuilderSDK::Platform_ES3:
|
||||
return "es3";
|
||||
case AssetBuilderSDK::Platform_ANDROID:
|
||||
return "android";
|
||||
case AssetBuilderSDK::Platform_IOS:
|
||||
return "ios";
|
||||
case AssetBuilderSDK::Platform_OSX:
|
||||
return "osx_gl";
|
||||
case AssetBuilderSDK::Platform_MAC:
|
||||
return "mac";
|
||||
case AssetBuilderSDK::Platform_PROVO:
|
||||
return "provo";
|
||||
case AssetBuilderSDK::Platform_SALEM:
|
||||
|
||||
@@ -148,15 +148,15 @@ namespace AssetBuilderSDK
|
||||
{
|
||||
Platform_NONE = 0x00,
|
||||
Platform_PC = 0x01,
|
||||
Platform_ES3 = 0x02,
|
||||
Platform_ANDROID = 0x02,
|
||||
Platform_IOS = 0x04,
|
||||
Platform_OSX = 0x08,
|
||||
Platform_MAC = 0x08,
|
||||
Platform_PROVO = 0x20,
|
||||
Platform_SALEM = 0x40,
|
||||
Platform_JASPER = 0x80,
|
||||
|
||||
//! if you add a new platform entry to this enum, you must add it to allplatforms as well otherwise that platform would not be considered valid.
|
||||
AllPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER
|
||||
AllPlatforms = Platform_PC | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER
|
||||
};
|
||||
#endif // defined(ENABLE_LEGACY_PLATFORMFLAGS_SUPPORT)
|
||||
//! Map data structure to holder parameters that are passed into a job for ProcessJob requests.
|
||||
@@ -503,7 +503,7 @@ namespace AssetBuilderSDK
|
||||
AZ_CLASS_ALLOCATOR(PlatformInfo, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(PlatformInfo, "{F7DA39A5-C319-4552-954B-3479E2454D3F}");
|
||||
|
||||
AZStd::string m_identifier; ///< like "pc" or "es3" or "ios"...
|
||||
AZStd::string m_identifier; ///< like "pc" or "android" or "ios"...
|
||||
AZStd::unordered_set<AZStd::string> m_tags; ///< The tags like "console" or "tools" on that platform
|
||||
|
||||
PlatformInfo() = default;
|
||||
|
||||
@@ -125,6 +125,10 @@ ly_add_target(
|
||||
AZ::AssetProcessorBatch.Static
|
||||
)
|
||||
|
||||
if(LY_DEFAULT_PROJECT_PATH)
|
||||
set_property(TARGET AssetProcessor AssetProcessorBatch APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${LY_DEFAULT_PROJECT_PATH}\"")
|
||||
endif()
|
||||
|
||||
# Adds the AssetProcessorBatch target as a C preprocessor define so that it can be used as a Settings Registry
|
||||
# specialization in order to look up the generated .setreg which contains the dependencies
|
||||
# specified for the target.
|
||||
@@ -255,8 +259,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::AssetProcessor.Tests
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::AssetProcessor.Tests> --unittest
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::AssetProcessor.Tests> --unittest --gtest_filter=-*.SUITE_sandbox*
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
@@ -11,9 +11,127 @@
|
||||
*/
|
||||
#include <native/FileWatcher/FileWatcher.h>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
|
||||
static constexpr int s_handleToFolderMapLockTimeout = 1000; // 1 sec timeout for obtaining the handle to folder map lock
|
||||
static constexpr size_t s_iNotifyMaxEntries = 1024 * 16; // Control the maximum number of entries (from inotify) that can be read at one time
|
||||
static constexpr size_t s_iNotifyEventSize = sizeof(struct inotify_event);
|
||||
static constexpr size_t s_iNotifyReadBufferSize = s_iNotifyMaxEntries * s_iNotifyEventSize;
|
||||
|
||||
struct FolderRootWatch::PlatformImplementation
|
||||
{
|
||||
PlatformImplementation() { }
|
||||
PlatformImplementation() = default;
|
||||
|
||||
int m_iNotifyHandle = -1;
|
||||
QMutex m_handleToFolderMapLock;
|
||||
QHash<int, QString> m_handleToFolderMap;
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
if (m_iNotifyHandle < 0)
|
||||
{
|
||||
m_iNotifyHandle = inotify_init();
|
||||
}
|
||||
return (m_iNotifyHandle >= 0);
|
||||
}
|
||||
|
||||
void Finalize()
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
|
||||
QHashIterator<int, QString> iter(m_handleToFolderMap);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
iter.next();
|
||||
int watchHandle = iter.key();
|
||||
inotify_rm_watch(m_iNotifyHandle, watchHandle);
|
||||
}
|
||||
m_handleToFolderMap.clear();
|
||||
m_handleToFolderMapLock.unlock();
|
||||
|
||||
::close(m_iNotifyHandle);
|
||||
m_iNotifyHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void AddWatchFolder(QString folder)
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
// Clean up the path before accepting it as a watch folder
|
||||
QString cleanPath = QDir::cleanPath(folder);
|
||||
|
||||
// Add the folder to watch and track it
|
||||
int watchHandle = inotify_add_watch(m_iNotifyHandle,
|
||||
cleanPath.toUtf8().constData(),
|
||||
IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY);
|
||||
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
m_handleToFolderMap[watchHandle] = cleanPath;
|
||||
m_handleToFolderMapLock.unlock();
|
||||
|
||||
// Add all the subfolders to watch and track them
|
||||
QDirIterator dirIter(folder, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
|
||||
while (dirIter.hasNext())
|
||||
{
|
||||
QString dirName = dirIter.next();
|
||||
if (dirName.endsWith("/.") || dirName.endsWith("/.."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int watchHandle = inotify_add_watch(m_iNotifyHandle,
|
||||
dirName.toUtf8().constData(),
|
||||
IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY);
|
||||
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
m_handleToFolderMap[watchHandle] = dirName;
|
||||
m_handleToFolderMapLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveWatchFolder(int watchHandle)
|
||||
{
|
||||
if (m_iNotifyHandle >= 0)
|
||||
{
|
||||
if (!m_handleToFolderMapLock.tryLock(s_handleToFolderMapLockTimeout))
|
||||
{
|
||||
AZ_Error("FileWatcher", false, "Unable to obtain inotify handle lock on thread");
|
||||
return;
|
||||
}
|
||||
|
||||
QHash<int, QString>::iterator handleToRemove = m_handleToFolderMap.find(watchHandle);
|
||||
if (handleToRemove != m_handleToFolderMap.end())
|
||||
{
|
||||
inotify_rm_watch(m_iNotifyHandle, watchHandle);
|
||||
m_handleToFolderMap.erase(handleToRemove);
|
||||
}
|
||||
|
||||
m_handleToFolderMapLock.unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -36,17 +154,86 @@ FolderRootWatch::~FolderRootWatch()
|
||||
|
||||
bool FolderRootWatch::Start()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
return false;
|
||||
// inotify will be used by linux to monitor file changes within directories under the root folder
|
||||
if (!m_platformImpl->Initialize())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_platformImpl->AddWatchFolder(m_root);
|
||||
|
||||
m_shutdownThreadSignal = false;
|
||||
m_thread = std::thread([this]() { WatchFolderLoop(); });
|
||||
return true;
|
||||
}
|
||||
|
||||
void FolderRootWatch::Stop()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
m_shutdownThreadSignal = true;
|
||||
|
||||
m_platformImpl->Finalize();
|
||||
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_thread.join(); // wait for the thread to finish
|
||||
m_thread = std::thread(); //destroy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FolderRootWatch::WatchFolderLoop()
|
||||
{
|
||||
// TODO: Implement for Linux
|
||||
char eventBuffer[s_iNotifyReadBufferSize];
|
||||
while (!m_shutdownThreadSignal)
|
||||
{
|
||||
ssize_t bytesRead = ::read(m_platformImpl->m_iNotifyHandle, eventBuffer, s_iNotifyReadBufferSize);
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
// Break out of the loop when the notify handle was closed (outside of this thread)
|
||||
break;
|
||||
}
|
||||
else if (bytesRead > 0)
|
||||
{
|
||||
for (size_t index=0; index<bytesRead;)
|
||||
{
|
||||
struct inotify_event *event = ( struct inotify_event * ) &eventBuffer[ index ];
|
||||
const char* eventName = event->name;
|
||||
|
||||
if (event->mask & (IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE ))
|
||||
{
|
||||
QString pathStr = QString("%1%2%3").arg(m_platformImpl->m_handleToFolderMap[event->wd], QDir::separator(), event->name);
|
||||
|
||||
if (event->mask & (IN_CREATE | IN_MOVED_TO))
|
||||
{
|
||||
if ( event->mask & IN_ISDIR )
|
||||
{
|
||||
// New Directory, add it to the watch
|
||||
m_platformImpl->AddWatchFolder(pathStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessNewFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
else if (event->mask & (IN_DELETE | IN_MOVED_FROM))
|
||||
{
|
||||
if (event->mask & IN_ISDIR)
|
||||
{
|
||||
// Directory Deleted, remove it from the watch
|
||||
m_platformImpl->RemoveWatchFolder(event->wd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessDeleteFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
else if ((event->mask & IN_MODIFY) && ((event->mask & IN_ISDIR) != IN_ISDIR))
|
||||
{
|
||||
ProcessModifyFileEvent(pathStr);
|
||||
}
|
||||
}
|
||||
index += s_iNotifyEventSize + event->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,134 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <native/FileWatcher/FileWatcher.h>
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
struct FolderRootWatch::PlatformImplementation
|
||||
{
|
||||
PlatformImplementation() : m_directoryHandle(nullptr), m_ioHandle(nullptr) { }
|
||||
HANDLE m_directoryHandle;
|
||||
HANDLE m_ioHandle;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// FolderWatchRoot
|
||||
FolderRootWatch::FolderRootWatch(const QString rootFolder)
|
||||
: m_root(rootFolder)
|
||||
, m_shutdownThreadSignal(false)
|
||||
, m_fileWatcher(nullptr)
|
||||
, m_platformImpl(new PlatformImplementation())
|
||||
{
|
||||
}
|
||||
|
||||
FolderRootWatch::~FolderRootWatch()
|
||||
{
|
||||
// Destructor is required in here since this file contains the definition of struct PlatformImplementation
|
||||
Stop();
|
||||
|
||||
delete m_platformImpl;
|
||||
}
|
||||
|
||||
bool FolderRootWatch::Start()
|
||||
{
|
||||
m_platformImpl->m_directoryHandle = ::CreateFileW(m_root.toStdWString().data(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr);
|
||||
|
||||
if (m_platformImpl->m_directoryHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_platformImpl->m_ioHandle = ::CreateIoCompletionPort(m_platformImpl->m_directoryHandle, nullptr, 1, 0);
|
||||
if (m_platformImpl->m_ioHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_shutdownThreadSignal = false;
|
||||
m_thread = std::thread(std::bind(&FolderRootWatch::WatchFolderLoop, this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FolderRootWatch::Stop()
|
||||
{
|
||||
m_shutdownThreadSignal = true;
|
||||
CloseHandle(m_platformImpl->m_ioHandle);
|
||||
m_platformImpl->m_ioHandle = nullptr;
|
||||
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_thread.join(); // wait for the thread to finish
|
||||
m_thread = std::thread(); //destroy
|
||||
}
|
||||
CloseHandle(m_platformImpl->m_directoryHandle);
|
||||
m_platformImpl->m_directoryHandle = nullptr;
|
||||
}
|
||||
|
||||
void FolderRootWatch::WatchFolderLoop()
|
||||
{
|
||||
FILE_NOTIFY_INFORMATION aFileNotifyInformationList[50000];
|
||||
QString path;
|
||||
OVERLAPPED aOverlapped;
|
||||
LPOVERLAPPED pOverlapped;
|
||||
DWORD dwByteCount;
|
||||
ULONG_PTR ulKey;
|
||||
|
||||
while (!m_shutdownThreadSignal)
|
||||
{
|
||||
::memset(aFileNotifyInformationList, 0, sizeof(aFileNotifyInformationList));
|
||||
::memset(&aOverlapped, 0, sizeof(aOverlapped));
|
||||
|
||||
if (::ReadDirectoryChangesW(m_platformImpl->m_directoryHandle, aFileNotifyInformationList, sizeof(aFileNotifyInformationList), true, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_FILE_NAME, nullptr, &aOverlapped, nullptr))
|
||||
{
|
||||
//wait for up to a second for I/O to signal
|
||||
dwByteCount = 0;
|
||||
if (::GetQueuedCompletionStatus(m_platformImpl->m_ioHandle, &dwByteCount, &ulKey, &pOverlapped, INFINITE))
|
||||
{
|
||||
//if we are signaled to shutdown bypass
|
||||
if (!m_shutdownThreadSignal && ulKey)
|
||||
{
|
||||
if (dwByteCount)
|
||||
{
|
||||
int offset = 0;
|
||||
FILE_NOTIFY_INFORMATION* pFileNotifyInformation = aFileNotifyInformationList;
|
||||
do
|
||||
{
|
||||
pFileNotifyInformation = (FILE_NOTIFY_INFORMATION*)((char*)pFileNotifyInformation + offset);
|
||||
|
||||
path.clear();
|
||||
path.append(m_root);
|
||||
path.append(QString::fromWCharArray(pFileNotifyInformation->FileName, pFileNotifyInformation->FileNameLength / 2));
|
||||
|
||||
QString file = QDir::toNativeSeparators(QDir::cleanPath(path));
|
||||
|
||||
switch (pFileNotifyInformation->Action)
|
||||
{
|
||||
case FILE_ACTION_ADDED:
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
ProcessNewFileEvent(file);
|
||||
break;
|
||||
case FILE_ACTION_REMOVED:
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
ProcessDeleteFileEvent(file);
|
||||
break;
|
||||
case FILE_ACTION_MODIFIED:
|
||||
ProcessModifyFileEvent(file);
|
||||
break;
|
||||
}
|
||||
|
||||
offset = pFileNotifyInformation->NextEntryOffset;
|
||||
} while (offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ set(FILES
|
||||
native/AssetManager/AssetRequestHandler.cpp
|
||||
native/AssetManager/AssetRequestHandler.h
|
||||
native/AssetManager/assetScanFolderInfo.h
|
||||
native/AssetManager/assetScanFolderInfo.cpp
|
||||
native/AssetManager/assetScanner.cpp
|
||||
native/AssetManager/assetScanner.h
|
||||
native/AssetManager/assetScannerWorker.cpp
|
||||
|
||||
@@ -655,6 +655,80 @@ namespace AssetProcessor
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssetCatalog::GenerateRelativeSourcePath(
|
||||
const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& rootFolder)
|
||||
{
|
||||
QString normalizedSourcePath = AssetUtilities::NormalizeFilePath(sourcePath.c_str());
|
||||
QDir inputPath(normalizedSourcePath);
|
||||
QString scanFolder;
|
||||
QString relativeName;
|
||||
|
||||
bool validResult = false;
|
||||
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "ProcessGenerateRelativeSourcePathRequest: %s...\n", sourcePath.c_str());
|
||||
|
||||
if (sourcePath.empty())
|
||||
{
|
||||
// For an empty input path, do nothing, we'll return an empty, invalid result.
|
||||
// (We check fullPath instead of inputPath, because an empty fullPath actually produces "." for inputPath)
|
||||
}
|
||||
else if (inputPath.isAbsolute())
|
||||
{
|
||||
// For an absolute path, try to convert it to a relative path, based on the existing scan folders.
|
||||
// To get the inputPath, we use absolutePath() instead of path() so that any . or .. entries get collapsed.
|
||||
validResult = m_platformConfig->ConvertToRelativePath(inputPath.absolutePath(), relativeName, scanFolder);
|
||||
}
|
||||
else if (inputPath.isRelative())
|
||||
{
|
||||
// For a relative path, concatenate it with each scan folder, and see if a valid relative path emerges.
|
||||
int scanFolders = m_platformConfig->GetScanFolderCount();
|
||||
for (int scanIdx = 0; scanIdx < scanFolders; scanIdx++)
|
||||
{
|
||||
auto& scanInfo = m_platformConfig->GetScanFolderAt(scanIdx);
|
||||
QDir possibleRoot(scanInfo.ScanPath());
|
||||
QDir possibleAbsolutePath = possibleRoot.filePath(normalizedSourcePath);
|
||||
// To get the inputPath, we use absolutePath() instead of path() so that any . or .. entries get collapsed.
|
||||
if (m_platformConfig->ConvertToRelativePath(possibleAbsolutePath.absolutePath(), relativeName, scanFolder))
|
||||
{
|
||||
validResult = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The input has produced a valid relative path. However, the path might match multiple nested scan folders,
|
||||
// so look to see if a higher-priority folder has a better match.
|
||||
if (validResult)
|
||||
{
|
||||
QString overridingFile = m_platformConfig->GetOverridingFile(relativeName, scanFolder);
|
||||
|
||||
if (!overridingFile.isEmpty())
|
||||
{
|
||||
overridingFile = AssetUtilities::NormalizeFilePath(overridingFile);
|
||||
validResult = m_platformConfig->ConvertToRelativePath(overridingFile, relativeName, scanFolder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!validResult)
|
||||
{
|
||||
// if we are here it means we have failed to determine the relativePath, so we will send back the original path
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel,
|
||||
"GenerateRelativeSourcePath found no valid result, returning original path: %s...\n", sourcePath.c_str());
|
||||
|
||||
rootFolder.clear();
|
||||
relativePath.clear();
|
||||
relativePath = sourcePath;
|
||||
return false;
|
||||
}
|
||||
|
||||
relativePath = relativeName.toUtf8().data();
|
||||
rootFolder = scanFolder.toUtf8().data();
|
||||
|
||||
AZ_Assert(!relativePath.empty(), "ConvertToRelativePath returned true, but relativePath is empty");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssetCatalog::GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullSourcePath)
|
||||
{
|
||||
ProcessGetFullSourcePathFromRelativeProductPathRequest(relPath, fullSourcePath);
|
||||
|
||||
@@ -95,6 +95,12 @@ namespace AssetProcessor
|
||||
const char* GetAbsoluteDevGameFolderPath() override;
|
||||
const char* GetAbsoluteDevRootFolderPath() override;
|
||||
bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& relativeProductPath) override;
|
||||
|
||||
//! Given a partial or full source file path, respond with its relative path and the watch folder it is relative to.
|
||||
//! The input source path does not need to exist, so this can be used for new files that haven't been saved yet.
|
||||
bool GenerateRelativeSourcePath(
|
||||
const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder) override;
|
||||
|
||||
bool GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullSourcePath) override;
|
||||
bool GetAssetInfoById(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const AZStd::string& platformName, AZ::Data::AssetInfo& assetInfo, AZStd::string& rootFilePath) override;
|
||||
bool GetSourceInfoBySourcePath(const char* sourcePath, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder) override;
|
||||
|
||||
@@ -104,6 +104,27 @@ namespace
|
||||
return GetRelativeProductPathFromFullSourceOrProductPathResponse(relPathFound, relProductPath);
|
||||
}
|
||||
|
||||
GenerateRelativeSourcePathResponse HandleGenerateRelativeSourcePathRequest(
|
||||
MessageData<GenerateRelativeSourcePathRequest> messageData)
|
||||
{
|
||||
bool relPathFound = false;
|
||||
AZStd::string relPath;
|
||||
AZStd::string watchFolder;
|
||||
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
relPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath,
|
||||
messageData.m_message->m_sourcePath, relPath, watchFolder);
|
||||
|
||||
if (!relPathFound)
|
||||
{
|
||||
AZ_TracePrintf(
|
||||
AssetProcessor::ConsoleChannel, "Could not find relative source path for the source file (%s).",
|
||||
messageData.m_message->m_sourcePath.c_str());
|
||||
}
|
||||
|
||||
return GenerateRelativeSourcePathResponse(relPathFound, relPath, watchFolder);
|
||||
}
|
||||
|
||||
SourceAssetInfoResponse HandleSourceAssetInfoRequest(MessageData<SourceAssetInfoRequest> messageData)
|
||||
{
|
||||
SourceAssetInfoResponse response;
|
||||
@@ -407,6 +428,7 @@ AssetRequestHandler::AssetRequestHandler()
|
||||
|
||||
m_requestRouter.RegisterMessageHandler(&HandleGetFullSourcePathFromRelativeProductPathRequest);
|
||||
m_requestRouter.RegisterMessageHandler(&HandleGetRelativeProductPathFromFullSourceOrProductPathRequest);
|
||||
m_requestRouter.RegisterMessageHandler(&HandleGenerateRelativeSourcePathRequest);
|
||||
m_requestRouter.RegisterMessageHandler(&HandleSourceAssetInfoRequest);
|
||||
m_requestRouter.RegisterMessageHandler(&HandleSourceAssetProductsInfoRequest);
|
||||
m_requestRouter.RegisterMessageHandler(&HandleGetScanFoldersRequest);
|
||||
|
||||
@@ -445,10 +445,10 @@ namespace AssetProcessor
|
||||
bool isExcludedDependency = dependencyPathSearch.starts_with(ExcludedDependenciesSymbol);
|
||||
dependencyPathSearch = isExcludedDependency ? dependencyPathSearch.substr(1) : dependencyPathSearch;
|
||||
bool isExactDependency = !AzFramework::StringFunc::Replace(dependencyPathSearch, '*', '%');
|
||||
SanitizeForDatabase(dependencyPathSearch);
|
||||
|
||||
if (cleanedupDependency.m_dependencyType == AssetBuilderSDK::ProductPathDependencyType::ProductFile)
|
||||
{
|
||||
SanitizeForDatabase(dependencyPathSearch);
|
||||
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer productInfoContainer;
|
||||
QString productNameWithPlatform = QString("%1%2%3").arg(platform.c_str(), AZ_CORRECT_DATABASE_SEPARATOR_STRING, dependencyPathSearch.c_str());
|
||||
|
||||
@@ -508,6 +508,10 @@ namespace AssetProcessor
|
||||
}
|
||||
else
|
||||
{
|
||||
// For source assets, the casing of the input path must be maintained. Just fix up the path separators.
|
||||
AZStd::replace(dependencyPathSearch.begin(), dependencyPathSearch.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR);
|
||||
AzFramework::StringFunc::Replace(dependencyPathSearch, AZ_DOUBLE_CORRECT_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR_STRING);
|
||||
|
||||
// See if path matches any source files
|
||||
AzToolsFramework::AssetDatabase::SourceDatabaseEntryContainer sourceInfoContainer;
|
||||
|
||||
|
||||
@@ -190,44 +190,55 @@ Please note that only those seed files will get updated that are active for your
|
||||
void SourceFileRelocator::HandleMetaDataFiles(QStringList pathMatches, QHash<QString, int>& sourceIndexMap, const ScanFolderInfo* scanFolderInfo, SourceFileRelocationContainer& metadataFiles, bool excludeMetaDataFiles) const
|
||||
{
|
||||
QSet<QString> metaDataFileEntries;
|
||||
for (QString file : pathMatches)
|
||||
|
||||
// Remove all the metadata files
|
||||
if (excludeMetaDataFiles)
|
||||
{
|
||||
pathMatches.erase(AZStd::remove_if(pathMatches.begin(), pathMatches.end(), [this](const QString& file)
|
||||
{
|
||||
for (int idx = 0; idx < m_platformConfig->MetaDataFileTypesCount(); idx++)
|
||||
{
|
||||
const auto& [metadataType, extension] = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metadataType, Qt::CaseInsensitive))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Metadata file %s will be ignored because --excludeMetadataFiles was specified in the command line.\n",
|
||||
file.toUtf8().constData());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
pathMatches.end());
|
||||
}
|
||||
|
||||
for (const QString& file : pathMatches)
|
||||
{
|
||||
for (int idx = 0; idx < m_platformConfig->MetaDataFileTypesCount(); idx++)
|
||||
{
|
||||
QPair<QString, QString> metaInfo = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metaInfo.first, Qt::CaseInsensitive))
|
||||
const auto& [metadataType, extension] = m_platformConfig->GetMetaDataFileTypeAt(idx);
|
||||
if (file.endsWith("." + metadataType, Qt::CaseInsensitive))
|
||||
{
|
||||
//it is a metadata file
|
||||
if (excludeMetaDataFiles)
|
||||
const QString normalizedFilePath = AssetUtilities::NormalizeFilePath(file);
|
||||
if (!metaDataFileEntries.contains(normalizedFilePath))
|
||||
{
|
||||
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Metadata file %s will be ignored because --excludeMetadataFiles was specified in the command line.\n",
|
||||
file.toUtf8().constData());
|
||||
break; // don't check it against other metafile entries, we've already ascertained its a metafile.
|
||||
}
|
||||
else
|
||||
{
|
||||
QString normalizedFilePath = AssetUtilities::NormalizeFilePath(file);
|
||||
if (metaDataFileEntries.find(normalizedFilePath) == metaDataFileEntries.end())
|
||||
{
|
||||
SourceFileRelocationInfo metaDataFile(file.toUtf8().data(), scanFolderInfo);
|
||||
metaDataFile.m_isMetaDataFile = true;
|
||||
metadataFiles.emplace_back(metaDataFile);
|
||||
metaDataFileEntries.insert(normalizedFilePath);
|
||||
}
|
||||
SourceFileRelocationInfo metaDataFile(file.toUtf8().data(), scanFolderInfo);
|
||||
metaDataFile.m_isMetaDataFile = true;
|
||||
metadataFiles.emplace_back(metaDataFile);
|
||||
metaDataFileEntries.insert(normalizedFilePath);
|
||||
}
|
||||
}
|
||||
else if (!excludeMetaDataFiles && (file.endsWith("." + metaInfo.second, Qt::CaseInsensitive) || metaInfo.second.isEmpty()))
|
||||
else if (!excludeMetaDataFiles && (file.endsWith("." + extension, Qt::CaseInsensitive) || extension.isEmpty()))
|
||||
{
|
||||
// if we are here it implies that a metadata file might exists for this source file,
|
||||
// add metadata file only if it exists and is not added already
|
||||
AZStd::string metadataFilePath(file.toUtf8().data());
|
||||
if (metaInfo.second.isEmpty())
|
||||
if (extension.isEmpty())
|
||||
{
|
||||
metadataFilePath.append(AZStd::string::format(".%s", metaInfo.first.toUtf8().data()));
|
||||
metadataFilePath.append(AZStd::string::format(".%s", metadataType.toUtf8().data()));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::StringFunc::Path::ReplaceExtension(metadataFilePath, metaInfo.first.toUtf8().data());
|
||||
AZ::StringFunc::Path::ReplaceExtension(metadataFilePath, metadataType.toUtf8().data());
|
||||
};
|
||||
|
||||
// The metadata file can have a different case than the source file,
|
||||
|
||||
@@ -1697,7 +1697,10 @@ namespace AssetProcessor
|
||||
|
||||
if(productFileInfo.absoluteDir().entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).empty())
|
||||
{
|
||||
productFileInfo.absoluteDir().rmdir(".");
|
||||
const QDir productDir = productFileInfo.absoluteDir();
|
||||
QDir parentDir = productDir;
|
||||
parentDir.cdUp();
|
||||
successfullyRemoved &= parentDir.rmdir(productDir.dirName());
|
||||
}
|
||||
|
||||
if (successfullyRemoved)
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace AzFramework
|
||||
class GetRelativeProductPathFromFullSourceOrProductPathRequest;
|
||||
class GetRelativeProductPathFromFullSourceOrProductPathResponse;
|
||||
|
||||
class GenerateRelativeSourcePathRequest;
|
||||
class GenerateRelativeSourcePathResponse;
|
||||
|
||||
class GetFullSourcePathFromRelativeProductPathRequest;
|
||||
class GetFullSourcePathFromRelativeProductPathResponse;
|
||||
class AssetNotificationMessage;
|
||||
@@ -104,6 +107,8 @@ namespace AssetProcessor
|
||||
using GetAbsoluteAssetDatabaseLocationResponse = AzToolsFramework::AssetSystem::GetAbsoluteAssetDatabaseLocationResponse;
|
||||
using GetRelativeProductPathFromFullSourceOrProductPathRequest = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathRequest;
|
||||
using GetRelativeProductPathFromFullSourceOrProductPathResponse = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathResponse;
|
||||
using GenerateRelativeSourcePathRequest = AzFramework::AssetSystem::GenerateRelativeSourcePathRequest;
|
||||
using GenerateRelativeSourcePathResponse = AzFramework::AssetSystem::GenerateRelativeSourcePathResponse;
|
||||
using GetFullSourcePathFromRelativeProductPathRequest = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathRequest;
|
||||
using GetFullSourcePathFromRelativeProductPathResponse = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathResponse;
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <native/AssetManager/assetScanFolderInfo.h>
|
||||
#include <native/utilities/assetUtils.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
ScanFolderInfo::ScanFolderInfo(
|
||||
QString path,
|
||||
QString displayName,
|
||||
QString portableKey,
|
||||
bool isRoot,
|
||||
bool recurseSubFolders,
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms,
|
||||
int order,
|
||||
AZ::s64 scanFolderID,
|
||||
bool canSaveNewAssets)
|
||||
: m_scanPath(path)
|
||||
, m_displayName(displayName)
|
||||
, m_portableKey (portableKey)
|
||||
, m_isRoot(isRoot)
|
||||
, m_recurseSubFolders(recurseSubFolders)
|
||||
, m_order(order)
|
||||
, m_scanFolderID(scanFolderID)
|
||||
, m_platforms(platforms)
|
||||
, m_canSaveNewAssets(canSaveNewAssets)
|
||||
{
|
||||
m_scanPath = AssetUtilities::NormalizeFilePath(m_scanPath);
|
||||
// note that m_scanFolderID is 0 unless its filled in from the DB.
|
||||
}
|
||||
|
||||
} // end namespace AssetProcessor
|
||||
@@ -33,19 +33,7 @@ namespace AssetProcessor
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms = AZStd::vector<AssetBuilderSDK::PlatformInfo>{},
|
||||
int order = 0,
|
||||
AZ::s64 scanFolderID = 0,
|
||||
bool canSaveNewAssets = false)
|
||||
: m_scanPath(path)
|
||||
, m_displayName(displayName)
|
||||
, m_portableKey (portableKey)
|
||||
, m_isRoot(isRoot)
|
||||
, m_recurseSubFolders(recurseSubFolders)
|
||||
, m_order(order)
|
||||
, m_scanFolderID(scanFolderID)
|
||||
, m_platforms(platforms)
|
||||
, m_canSaveNewAssets(canSaveNewAssets)
|
||||
{
|
||||
// note that m_scanFolderID is 0 unless its filled in from the DB.
|
||||
}
|
||||
bool canSaveNewAssets = false);
|
||||
|
||||
ScanFolderInfo() = default;
|
||||
ScanFolderInfo(const ScanFolderInfo& other) = default;
|
||||
|
||||
@@ -224,20 +224,28 @@ namespace AssetProcessor
|
||||
dbConn->SetScanFolder(newScanFolder);
|
||||
}
|
||||
|
||||
// build some default configs.
|
||||
void BuildConfig(const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config)
|
||||
virtual void AddScanFolders(
|
||||
const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config,
|
||||
const AZStd::vector<AssetBuilderSDK::PlatformInfo>& platforms)
|
||||
{
|
||||
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 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", false, true, platforms, -1), config, dbConn); // subfolder1 overrides root
|
||||
AddScanFolder(ScanFolderInfo(tempPath.absolutePath(), "temp", "tempfolder", true, false, platforms, 0), config, dbConn); // add the root
|
||||
}
|
||||
|
||||
// build some default configs.
|
||||
void BuildConfig(const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config)
|
||||
{
|
||||
config.EnablePlatform({ "pc" ,{ "desktop", "renderer" } }, true);
|
||||
config.EnablePlatform({ "android" ,{ "mobile", "renderer" } }, true);
|
||||
config.EnablePlatform({ "fandango" ,{ "console", "renderer" } }, false);
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms;
|
||||
config.PopulatePlatformsForScanFolder(platforms);
|
||||
|
||||
AddScanFolders(tempPath, dbConn, config, platforms);
|
||||
|
||||
config.AddMetaDataType("exportsettings", QString());
|
||||
|
||||
@@ -246,22 +254,22 @@ namespace AssetProcessor
|
||||
|
||||
AssetRecognizer rec;
|
||||
AssetPlatformSpec specpc;
|
||||
AssetPlatformSpec speces3;
|
||||
AssetPlatformSpec specandroid;
|
||||
|
||||
speces3.m_extraRCParams = "somerandomparam";
|
||||
specandroid.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";
|
||||
specandroid.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);
|
||||
rec.m_platformSpecs.insert("android", specandroid);
|
||||
|
||||
config.AddRecognizer(rec);
|
||||
|
||||
@@ -272,7 +280,7 @@ namespace AssetProcessor
|
||||
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);
|
||||
ignore_rec.m_platformSpecs.insert("android", ignore_spec);
|
||||
config.AddRecognizer(ignore_rec);
|
||||
|
||||
ExcludeAssetRecognizer excludeRecogniser;
|
||||
@@ -359,7 +367,8 @@ namespace AssetProcessor
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calls the GetFullSourcePathFromRelativeProductPath function and checks the return results, returning true if it matches both of the expected results
|
||||
// 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;
|
||||
@@ -531,6 +540,177 @@ namespace AssetProcessor
|
||||
ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" }));
|
||||
}
|
||||
|
||||
class AssetCatalogTestRelativeSourcePath : public AssetCatalogTest
|
||||
{
|
||||
public:
|
||||
QDir GetRoot()
|
||||
{
|
||||
// Return an OS-friendly absolute root directory for our tests ("C:/sourceRoot" or "/sourceRoot"). It doesn't
|
||||
// need to exist, it just needs to be an absolute path.
|
||||
return QDir::root().filePath("sourceRoot");
|
||||
}
|
||||
|
||||
// Set up custom scan folders for the "relative source path" tests, so that we can try out specific combinations of watch folders
|
||||
void AddScanFolders(
|
||||
[[maybe_unused]] const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config,
|
||||
const AZStd::vector<AssetBuilderSDK::PlatformInfo>& platforms) override
|
||||
{
|
||||
QDir root = GetRoot();
|
||||
|
||||
// This will set up the following watch folders, in highest to lowest priority:
|
||||
|
||||
// /sourceRoot/recurseNested/nested (recurse)
|
||||
// /sourceRoot/noRecurse (no recurse)
|
||||
// /sourceRoot/recurseNotNested (recurse)
|
||||
// /sourceRoot/recurseNested (recurse)
|
||||
|
||||
AddScanFolder(
|
||||
ScanFolderInfo(root.filePath("recurseNested/nested"), "nested", "nested", false, true, platforms, -4), config, dbConn);
|
||||
AddScanFolder(
|
||||
ScanFolderInfo(root.filePath("noRecurse"), "noRecurse", "noRecurse", false, false, platforms, -3), config, dbConn);
|
||||
AddScanFolder(
|
||||
ScanFolderInfo(root.filePath("recurseNotNested"), "recurseNotNested", "recurseNotNested", false, true, platforms, -2),
|
||||
config, dbConn);
|
||||
AddScanFolder(
|
||||
ScanFolderInfo(root.filePath("recurseNested"), "recurseNested", "recurseNested", false, true, platforms, -1),
|
||||
config, dbConn);
|
||||
}
|
||||
|
||||
// Calls the GenerateRelativeSourcePath function and validates that the results match the expected inputs.
|
||||
void TestGetRelativeSourcePath(
|
||||
const AZStd::string& sourcePath, bool expectedToFind, const AZStd::string& expectedPath, const AZStd::string& expectedRoot)
|
||||
{
|
||||
bool relPathFound = false;
|
||||
AZStd::string relPath;
|
||||
AZStd::string rootFolder;
|
||||
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
relPathFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GenerateRelativeSourcePath, sourcePath,
|
||||
relPath, rootFolder);
|
||||
|
||||
EXPECT_EQ(relPathFound, expectedToFind);
|
||||
EXPECT_EQ(relPath, expectedPath);
|
||||
EXPECT_EQ(rootFolder, expectedRoot);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_EmptySourcePath_ReturnsNoMatch)
|
||||
{
|
||||
// Test passes in an empty source path, which shouldn't produce a valid result.
|
||||
// Input: empty source path
|
||||
// Output: empty, not found result
|
||||
TestGetRelativeSourcePath("", false, "", "");
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathOutsideWatchFolders_ReturnsNoMatch)
|
||||
{
|
||||
// Test passes in an invalid absolute source path, which shouldn't produce a valid result.
|
||||
// Input: "/sourceRoot/noWatchFolder/test.txt"
|
||||
// Output: not found result, which also returns the input as the relative file name
|
||||
QDir watchFolder = GetRoot().filePath("noWatchFolder/");
|
||||
QString fileToCheck = watchFolder.filePath("test.txt");
|
||||
|
||||
TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), false, fileToCheck.toUtf8().constData(), "");
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathUnderWatchFolder_ReturnsRelativePath)
|
||||
{
|
||||
// Test passes in a valid absolute source path, which should produce a valid relative path
|
||||
// Input: "/sourceRoot/noRecurse/test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/noRecurse/"
|
||||
QDir watchFolder = GetRoot().filePath("noRecurse/");
|
||||
QString fileToCheck = watchFolder.filePath("test.txt");
|
||||
|
||||
TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), true, "test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathUnderNestedWatchFolders_ReturnsRelativePath)
|
||||
{
|
||||
// Test passes in a valid absolute source path that matches a watch folder and a nested watch folder.
|
||||
// The output relative path should match the nested folder, because the nested folder has a higher priority registered with the AP.
|
||||
// Input: "/sourceRoot/recurseNested/nested/test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/recurseNested/nested/"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNested/nested/");
|
||||
QString fileToCheck = watchFolder.filePath("test.txt");
|
||||
|
||||
TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), true, "test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_BareFileNameValidInWatchFolder_ReturnsHighestPriorityWatchFolder)
|
||||
{
|
||||
// Test passes in a simple file name. The output should be relative to the highest-priority watch folder.
|
||||
// Input: "test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/recurseNested/nested/"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNested/nested/");
|
||||
|
||||
TestGetRelativeSourcePath("test.txt", true, "test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathValidInWatchFolder_ReturnsHighestPriorityWatchFolder)
|
||||
{
|
||||
// Test passes in a relative path. The output should preserve the relative path, but list it as relative to the highest-priority
|
||||
// watch folder.
|
||||
// Input: "a/b/c/test.txt"
|
||||
// Output: "a/b/c/test.txt" in folder "/sourceRoot/recurseNested/nested/"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNested/nested/");
|
||||
|
||||
TestGetRelativeSourcePath("a/b/c/test.txt", true, "a/b/c/test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathNotInWatchFolder_ReturnsNoMatch)
|
||||
{
|
||||
// Test passes in a relative path that "backs up" two directories. This will be invalid, because no matter which watch directory
|
||||
// we start at, the result will be outside of any watch directory.
|
||||
// Input: "../../test.txt"
|
||||
// Output: not found result, which also returns the input as the relative file name
|
||||
TestGetRelativeSourcePath("../../test.txt", false, "../../test.txt", "");
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathValidFromNestedWatchFolder_ReturnsOuterFolder)
|
||||
{
|
||||
// Test passes in a relative path that "backs up" one directory. This will produce a valid result, because we can back up from
|
||||
// the "recurseNested/nested/" watch folder to "recurseNested", which is also a valid watch folder.
|
||||
// Input: "../test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/recurseNested"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNested/");
|
||||
TestGetRelativeSourcePath("../test.txt", true, "test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathMovesToParentWatchFolder_ReturnsOuterFolder)
|
||||
{
|
||||
// Test passes in a relative path that backs up one directory and then forward into a directory. This will produce a valid
|
||||
// result, because it can validly start in the highest-priority watch folder (recurseNested/nested), move back one into the
|
||||
// outer watch folder (recurseNested), and then have a subdirectory within it.
|
||||
// Note that it would also be valid to move from recurseNested to recurseNotNested, but that won't be the result of this test
|
||||
// because that's a lower-priority match.
|
||||
// Input: "../recurseNotNested/test.txt"
|
||||
// Output: "recurseNotNested/test.txt" in folder "/sourceRoot/recurseNested/"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNested/");
|
||||
|
||||
TestGetRelativeSourcePath("../recurseNotNested/test.txt", true, "recurseNotNested/test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathMovesToSiblingWatchFolder_ReturnsSiblingFolder)
|
||||
{
|
||||
// Test passes in a relative path that backs up two directories and then forward into a directory. This will produce a valid
|
||||
// result, because it can validly start in the recurseNested/nested folder, move back two folders, then forward into the sibling
|
||||
// recurseNotNested folder. The result will be a relative path to the sibling folder.
|
||||
// Input: "../../recurseNotNested/test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/recurseNotNested/"
|
||||
QDir watchFolder = GetRoot().filePath("recurseNotNested/");
|
||||
|
||||
TestGetRelativeSourcePath("../../recurseNotNested/test.txt", true, "test.txt", watchFolder.path().toUtf8().constData());
|
||||
}
|
||||
|
||||
TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathBacksOutOfWatchFolder_ReturnsNoMatch)
|
||||
{
|
||||
// Test passes in a relative path that adds a directory, then "backs up" three directories. This will be invalid, because no
|
||||
// matter which watch directory we start at, the result will be outside of any watch directory.
|
||||
// Input: "../test.txt"
|
||||
// Output: "test.txt" in folder "/sourceRoot/recurseNested"
|
||||
TestGetRelativeSourcePath("a/../../../test.txt", false, "a/../../../test.txt", "");
|
||||
}
|
||||
|
||||
class AssetCatalogTest_GetFullSourcePath
|
||||
: public AssetCatalogTest
|
||||
{
|
||||
@@ -912,7 +1092,7 @@ namespace AssetProcessor
|
||||
{
|
||||
AssetCatalogTest::SetUp();
|
||||
m_platforms.push_back("pc");
|
||||
m_platforms.push_back("es3");
|
||||
m_platforms.push_back("android");
|
||||
|
||||
// 4 products for one platform, 1 product for the other.
|
||||
m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefilez.arc2");
|
||||
@@ -920,7 +1100,7 @@ namespace AssetProcessor
|
||||
m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefile.arc2");
|
||||
m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefile.azm2");
|
||||
|
||||
m_platformToProductsForSourceWithDifferentProducts["es3"].push_back("subfolder3/es3exclusivefile.azm2");
|
||||
m_platformToProductsForSourceWithDifferentProducts["android"].push_back("subfolder3/androidexclusivefile.azm2");
|
||||
|
||||
m_sourceFileWithDifferentProductsPerPlatform = AZ::Uuid::CreateString("{38032FC9-2838-4D6A-9DA0-79E5E4F20C1B}");
|
||||
m_sourceFileWithDependency = AZ::Uuid::CreateString("{807C4174-1D19-42AD-B8BC-A59291D9388C}");
|
||||
@@ -933,7 +1113,7 @@ namespace AssetProcessor
|
||||
// resulting in image processing jobs having different products per platform. Because of this, the material jobs will then have different
|
||||
// dependencies per platform, because each material will depend on a referenced texture and all of that texture's mipmaps.
|
||||
|
||||
// Add a source file with 4 products on pc, but 1 on es3
|
||||
// Add a source file with 4 products on pc, but 1 on android
|
||||
bool result = AddSourceAndJobForMultiplePlatforms(
|
||||
"subfolder3",
|
||||
"MultiplatformFile.txt",
|
||||
@@ -948,7 +1128,7 @@ namespace AssetProcessor
|
||||
result = AddSourceAndJobForMultiplePlatforms("subfolder3", "FileWithDependency.txt", &(m_data->m_dbConn), sourceFileWithSameProductsJobsPerPlatform, m_platforms, m_sourceFileWithDependency);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
const AZStd::string fileWithDependencyProductPath = "subfolder3/es3exclusivefile.azm2";
|
||||
const AZStd::string fileWithDependencyProductPath = "subfolder3/androidexclusivefile.azm2";
|
||||
|
||||
for (const AZStd::string& platform : m_platforms)
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AssetProcessorMessagesTests
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
|
||||
static constexpr unsigned short AssetProcessorPort = static_cast<unsigned short>(888u);
|
||||
static constexpr unsigned short AssetProcessorPort{65535u};
|
||||
|
||||
class AssetProcessorMessages;
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace AssetProcessorMessagesTests
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
AssetUtilities::ResetGameName();
|
||||
|
||||
m_temporarySourceDir = QDir(m_temporaryDir.path());
|
||||
@@ -166,12 +165,10 @@ namespace AssetProcessorMessagesTests
|
||||
});
|
||||
|
||||
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
QEventLoop eventLoop;
|
||||
|
||||
QObject::connect(m_batchApplicationManager->m_connectionManager, &ConnectionManager::ReadyToQuit, &eventLoop, &QEventLoop::quit);
|
||||
@@ -182,7 +179,6 @@ namespace AssetProcessorMessagesTests
|
||||
|
||||
m_assetSystemComponent->Deactivate();
|
||||
m_batchApplicationManager->Destroy();
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
}
|
||||
|
||||
void RunNetworkRequest(AZStd::function<void()> func) const
|
||||
@@ -207,6 +203,7 @@ namespace AssetProcessorMessagesTests
|
||||
|
||||
thread.join();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
MockAssetRequestHandler* m_assetRequestHandler{}; // Not owned, AP will delete this pointer
|
||||
@@ -226,11 +223,7 @@ namespace AssetProcessorMessagesTests
|
||||
AZStd::unique_ptr<AzFramework::AssetSystem::BaseAssetProcessorMessage> m_response;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorMessages, DISABLED_All)
|
||||
#else
|
||||
TEST_F(AssetProcessorMessages, All)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
// Test that we can successfully send network messages and have them arrive for processing
|
||||
// For messages that have a response, it also verifies the response comes back
|
||||
@@ -265,6 +258,9 @@ namespace AssetProcessorMessagesTests
|
||||
|
||||
addPairFunc(new GetFullSourcePathFromRelativeProductPathRequest(), new GetFullSourcePathFromRelativeProductPathResponse());
|
||||
addPairFunc(new GetRelativeProductPathFromFullSourceOrProductPathRequest(), new GetRelativeProductPathFromFullSourceOrProductPathResponse());
|
||||
addPairFunc(
|
||||
new GenerateRelativeSourcePathRequest(),
|
||||
new GenerateRelativeSourcePathResponse());
|
||||
addPairFunc(new SourceAssetInfoRequest(), new SourceAssetInfoResponse());
|
||||
addPairFunc(new SourceAssetProductsInfoRequest(), new SourceAssetProductsInfoResponse());
|
||||
addPairFunc(new GetScanFoldersRequest(), new GetScanFoldersResponse());
|
||||
@@ -308,11 +304,7 @@ namespace AssetProcessorMessagesTests
|
||||
});
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorMessages, DISABLED_GetUnresolvedProductReferences_Succeeds)
|
||||
#else
|
||||
TEST_F(AssetProcessorMessages, GetUnresolvedProductReferences_Succeeds)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetDatabase;
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ namespace UnitTests
|
||||
SourceDatabaseEntry sourceFile8 = { m_data->m_scanFolder1.m_scanFolderID, "test.txt", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile9 = { m_data->m_scanFolder1.m_scanFolderID, "duplicate/folder/file1.tif", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile10 = { m_data->m_scanFolder1.m_scanFolderID, "folder/file.foo", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
SourceDatabaseEntry sourceFile11 = { m_data->m_scanFolder1.m_scanFolderID, "testfolder/file.foo", AZ::Uuid::CreateRandom(), "AnalysisFingerprint" };
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile1));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile2));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile3));
|
||||
@@ -123,7 +122,6 @@ namespace UnitTests
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile8));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile9));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile10));
|
||||
ASSERT_TRUE(m_data->m_connection->SetSource(sourceFile11));
|
||||
|
||||
SourceFileDependencyEntry dependency1 = { AZ::Uuid::CreateRandom(), "subfolder1/somefile.tif", "subfolder1/otherfile.tif", SourceFileDependencyEntry::TypeOfDependency::DEP_SourceToSource, false };
|
||||
SourceFileDependencyEntry dependency2 = { AZ::Uuid::CreateRandom(), "subfolder1/otherfile.tif", "otherfile.tif", SourceFileDependencyEntry::TypeOfDependency::DEP_JobToJob, false };
|
||||
@@ -176,8 +174,6 @@ namespace UnitTests
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/dummy/foo.metadataextension")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/folder/file.foo")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/folder/file.bar")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/file.foo")));
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("dev/testfolder/File.bar")));
|
||||
|
||||
if (AZ::IO::FileIOBase::GetInstance() == nullptr)
|
||||
{
|
||||
@@ -487,20 +483,12 @@ namespace UnitTests
|
||||
TestGetSourcesByPath("dev/", { }, false);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_MultipleScanFolders_Fails)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_MultipleScanFolders_Fails)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
TestGetSourcesByPath("*", { }, false);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_PartialPath_FailsWithNoResults)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_PartialPath_FailsWithNoResults)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
TestGetSourcesByPath("older/*", { }, false);
|
||||
}
|
||||
@@ -547,18 +535,6 @@ namespace UnitTests
|
||||
TestGetSourcesByPath(filePath.toUtf8().constData(), { "folder/file.foo" }, true, true);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_GetSources_HaveMetadataDifferentFileCase_AbsolutePath_Succeeds)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, GetSources_HaveMetadataDifferentFileCase_AbsolutePath_Succeeds)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto filePath = QDir(tempPath.absoluteFilePath(m_data->m_scanFolder1.m_scanFolder.c_str())).absoluteFilePath("testfolder/file.foo");
|
||||
TestGetSourcesByPath(filePath.toUtf8().constData(), { "testfolder/file.foo", "testfolder/File.bar" }, true, false);
|
||||
}
|
||||
|
||||
TEST_F(SourceFileRelocatorTest, GetMetaDataFile_SingleFileWildcard_Succeeds)
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
@@ -921,32 +897,46 @@ namespace UnitTests
|
||||
ASSERT_FALSE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(SourceFileRelocatorTest, DISABLED_Delete_Real_Readonly_Fails)
|
||||
#else
|
||||
TEST_F(SourceFileRelocatorTest, Delete_Real_Readonly_Fails)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
struct AutoResetDirectoryReadOnlyState
|
||||
{
|
||||
AutoResetDirectoryReadOnlyState(QString dirName)
|
||||
: m_dirName(AZStd::move(dirName))
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(m_dirName.toUtf8().constData(), false);
|
||||
}
|
||||
~AutoResetDirectoryReadOnlyState()
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(m_dirName.toUtf8().constData(), true);
|
||||
}
|
||||
AZ_DISABLE_COPY_MOVE(AutoResetDirectoryReadOnlyState)
|
||||
private:
|
||||
QString m_dirName;
|
||||
};
|
||||
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto filePath = QDir(tempPath.absoluteFilePath(m_data->m_scanFolder1.m_scanFolder.c_str())).absoluteFilePath("duplicate/file1.tif");
|
||||
|
||||
ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
|
||||
AutoResetDirectoryReadOnlyState readOnlyResetter(QFileInfo(filePath).absoluteDir().absolutePath());
|
||||
|
||||
AZ::IO::SystemFile::SetWritable(filePath.toUtf8().constData(), false);
|
||||
|
||||
auto result = m_data->m_reporter->Delete(filePath.toUtf8().constData(), false);
|
||||
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
|
||||
RelocationSuccess successResult = result.TakeValue();
|
||||
|
||||
ASSERT_EQ(successResult.m_moveSuccessCount, 0);
|
||||
ASSERT_EQ(successResult.m_moveFailureCount, 1);
|
||||
ASSERT_EQ(successResult.m_moveTotalCount, 1);
|
||||
ASSERT_EQ(successResult.m_updateTotalCount, 0);
|
||||
EXPECT_EQ(successResult.m_moveSuccessCount, 0);
|
||||
EXPECT_EQ(successResult.m_moveFailureCount, 1);
|
||||
EXPECT_EQ(successResult.m_moveTotalCount, 1);
|
||||
EXPECT_EQ(successResult.m_updateTotalCount, 0);
|
||||
|
||||
ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
EXPECT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
|
||||
}
|
||||
|
||||
TEST_F(SourceFileRelocatorTest, Delete_Real_WithDependencies_Fails)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AssetProcessor
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformsCount(), 2);
|
||||
@@ -48,19 +48,19 @@ namespace AssetProcessor
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_NONE);
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "es3", {}
|
||||
{ "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_ES3);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_ANDROID);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_NONE);
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_NONE);
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
@@ -72,24 +72,24 @@ namespace AssetProcessor
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}, { "ios", {}
|
||||
}, { "osx_gl", {}
|
||||
}, { "mac", {}
|
||||
}
|
||||
};
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_IOS);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(3), AssetBuilderSDK::Platform_OSX);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(3), AssetBuilderSDK::Platform_MAC);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(4), AssetBuilderSDK::Platform_NONE);
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID);
|
||||
ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_NONE);
|
||||
// using a deprecated API should have generated warnings.
|
||||
// but we can't test for it because these warnings are WarningOnce and some other unit test might have already triggered it
|
||||
@@ -106,23 +106,23 @@ namespace AssetProcessor
|
||||
}
|
||||
};
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC));
|
||||
ASSERT_FALSE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3));
|
||||
ASSERT_FALSE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID));
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID));
|
||||
|
||||
createJobsRequest.m_enabledPlatforms = {
|
||||
{ "pc", {}
|
||||
}, { "es3", {}
|
||||
}, { "android", {}
|
||||
}
|
||||
};
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID));
|
||||
// using a deprecated API should have generated warnings.
|
||||
// but we can't test for it because these warnings are WarningOnce and some other unit test might have already triggered it
|
||||
}
|
||||
@@ -133,9 +133,9 @@ namespace AssetProcessor
|
||||
UnitTestUtils::AssertAbsorber absorb;
|
||||
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_PC));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_ES3));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_ANDROID));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_IOS));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_OSX));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_MAC));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_PROVO));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_SALEM));
|
||||
ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_JASPER));
|
||||
|
||||
@@ -30,11 +30,7 @@ public:
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies);
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_DeferredResolution);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, DISABLED_AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, DeleteFolder_SignalsDeleteOfContainedFiles);
|
||||
|
||||
@@ -70,19 +66,11 @@ public:
|
||||
friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_ValidatePathDependenciesMap);
|
||||
friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedSourceFileTypeProductPathDependency_DependencyHasNoProductOutput_ValidatePathDependenciesMap);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, DISABLED_ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged);
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, DISABLED_ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform);
|
||||
#else
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform);
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile);
|
||||
friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAgain);
|
||||
@@ -2362,11 +2350,7 @@ TEST_F(PathDependencyTest, ChangeDependencies_Existing_ResolveCorrectly)
|
||||
);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(PathDependencyTest, DISABLED_MixedPathDependencies_Existing_ResolveCorrectly)
|
||||
#else
|
||||
TEST_F(PathDependencyTest, MixedPathDependencies_Existing_ResolveCorrectly)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
@@ -2661,11 +2645,7 @@ TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDepende
|
||||
ASSERT_NE(SearchDependencies(dependencyContainer, asset1.m_products[0]), SearchDependencies(dependencyContainer, asset1.m_products[1]));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(MultiplatformPathDependencyTest, DISABLED_AssetProcessed_Impl_MultiplatformDependencies_SourcePath)
|
||||
#else
|
||||
TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
// One product will be pc, one will be console (order is non-deterministic)
|
||||
TestAsset asset1("testAsset1");
|
||||
@@ -3894,7 +3874,7 @@ void ModtimeScanningTest::ProcessAssetJobs()
|
||||
|
||||
for (const auto& processResult : m_data->m_processResults)
|
||||
{
|
||||
auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName + ".arc1");
|
||||
auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName.toLower() + ".arc1");
|
||||
m_data->m_productPaths.emplace(
|
||||
QDir(processResult.m_jobEntry.m_watchFolderPath)
|
||||
.absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName)
|
||||
@@ -3943,11 +3923,11 @@ void ModtimeScanningTest::ExpectWork(int createJobs, int processJobs)
|
||||
{
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
|
||||
ASSERT_EQ(m_data->m_processResults.size(), processJobs);
|
||||
ASSERT_FALSE(m_data->m_processResults[0].m_autoFail);
|
||||
ASSERT_FALSE(m_data->m_processResults[1].m_autoFail);
|
||||
ASSERT_EQ(m_data->m_deletedSources.size(), 0);
|
||||
EXPECT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
|
||||
EXPECT_EQ(m_data->m_processResults.size(), processJobs);
|
||||
EXPECT_FALSE(m_data->m_processResults[0].m_autoFail);
|
||||
EXPECT_FALSE(m_data->m_processResults[1].m_autoFail);
|
||||
EXPECT_EQ(m_data->m_deletedSources.size(), 0);
|
||||
|
||||
m_isIdling = false;
|
||||
}
|
||||
@@ -3975,11 +3955,7 @@ void ModtimeScanningTest::SetFileContents(QString filePath, QString contents)
|
||||
file.close();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(ModtimeScanningTest, DISABLED_ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
|
||||
#else
|
||||
TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
|
||||
@@ -4008,11 +3984,7 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged)
|
||||
ExpectNoWork();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(ModtimeScanningTest, DISABLED_ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
|
||||
#else
|
||||
TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
|
||||
@@ -4020,15 +3992,15 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesFor
|
||||
m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
|
||||
AssetUtilities::SetUseFileHashOverride(true, true);
|
||||
|
||||
// Enable es3 platform after the initial SetUp has already processed the files for pc
|
||||
// Enable android 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);
|
||||
AssetBuilderSDK::PlatformInfo androidPlatform("android", { "host", "renderer" });
|
||||
m_config->EnablePlatform(androidPlatform, 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());
|
||||
platforms.push_back(es3Platform);
|
||||
platforms.push_back(androidPlatform);
|
||||
|
||||
// We need the builder fingerprints to be updated to reflect the newly enabled platform
|
||||
m_assetProcessorManager->ComputeBuilderDirty();
|
||||
@@ -4036,10 +4008,10 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesFor
|
||||
QSet<AssetFileInfo> filePaths = BuildFileSet();
|
||||
SimulateAssetScanner(filePaths);
|
||||
|
||||
ExpectWork(4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the es3 platform jobs (pc is already processed)
|
||||
ExpectWork(4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the android platform jobs (pc is already processed)
|
||||
|
||||
ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("es3"));
|
||||
ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("es3"));
|
||||
ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("android"));
|
||||
ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("android"));
|
||||
}
|
||||
|
||||
TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestamp)
|
||||
@@ -4633,11 +4605,7 @@ TEST_F(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_WildcardM
|
||||
dependList.clear();
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(AssetProcessorManagerTest, DISABLED_RemoveSource_RemoveCacheFolderIfEmpty_Ok)
|
||||
#else
|
||||
TEST_F(AssetProcessorManagerTest, RemoveSource_RemoveCacheFolderIfEmpty_Ok)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AssetProcessor;
|
||||
using namespace AssetBuilderSDK;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "native/tests/platformconfiguration/platformconfigurationtests.h"
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
const char TestAppRoot[] = "@exefolder@/testdata";
|
||||
const char EmptyDummyProjectName[] = "EmptyDummyProject";
|
||||
@@ -120,14 +121,14 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms)
|
||||
|
||||
// verify the data.
|
||||
ASSERT_NE(config.GetPlatformByIdentifier(AzToolsFramework::AssetSystem::GetHostAssetPlatform()), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("es3"), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("android"), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("server"), nullptr);
|
||||
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("mobile"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("renderer"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("android"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("mobile"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("renderer"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("android"));
|
||||
ASSERT_TRUE(config.GetPlatformByIdentifier("server")->HasTag("server"));
|
||||
ASSERT_FALSE(config.GetPlatformByIdentifier("es3")->HasTag("server"));
|
||||
ASSERT_FALSE(config.GetPlatformByIdentifier("android")->HasTag("server"));
|
||||
ASSERT_FALSE(config.GetPlatformByIdentifier("server")->HasTag("renderer"));
|
||||
}
|
||||
|
||||
@@ -238,33 +239,6 @@ TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetScanFolderForFile_Sub
|
||||
EXPECT_STREQ(info->GetDisplayName().toUtf8().constData(), "Editor ScanFolder");
|
||||
}
|
||||
|
||||
// note that in the case of GetOverridingFile, this SHOULD return the correct case if an override is found
|
||||
// because its possible to override a file with another file with different case in a different scan folder
|
||||
// such a situation is supposed to be very rare, so the cost of correcting the case is mitigated.
|
||||
TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_Exists_ReturnsCorrectCase)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
|
||||
// create two scan folders, since its order dependent, the ScanFolder1 is the "winner" in tie breakers (when they both contain same file relpath)
|
||||
QString scanfolder1Path = m_tempPath.filePath("scanfolder1");
|
||||
QString scanfolder2Path = m_tempPath.filePath("scanfolder2");
|
||||
QString caseSensitiveDummyFileName = m_tempPath.absoluteFilePath("scanfolder1/TestCase.tXt");
|
||||
QString differentCaseDummyFileName = m_tempPath.absoluteFilePath("scanfolder2/testcase.txt");
|
||||
UnitTestUtils::CreateDummyFile(caseSensitiveDummyFileName, QString("testcase1\n"));
|
||||
UnitTestUtils::CreateDummyFile(differentCaseDummyFileName, QString("testcase2\n"));
|
||||
m_config->AddScanFolder(ScanFolderInfo(scanfolder1Path, "ScanFolder1", "sf1", false, true, m_platforms), true);
|
||||
m_config->AddScanFolder(ScanFolderInfo(scanfolder2Path, "ScanFolder2", "sf2", false, true, m_platforms), true);
|
||||
|
||||
// Perform the test by asking it whether anyone overrides "testcase" (lowercase) in scanfolder 2.
|
||||
QString overrider = m_config->GetOverridingFile("testcase.txt", scanfolder2Path);
|
||||
|
||||
ASSERT_FALSE(overrider.isEmpty());
|
||||
// the result should be the real actual case of the file in scanfolder 1:
|
||||
EXPECT_STREQ(overrider.toUtf8().constData(), caseSensitiveDummyFileName.toUtf8().constData());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(PlatformConfigurationUnitTests_OnePCHostFixture, GetOverridingFile_ExistsButNotOverridden_ReturnsEmpty)
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
@@ -360,7 +334,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
|
||||
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::ComputeProjectPath() + " Scan Folder";
|
||||
QString scanName = AssetUtilities::ComputeProjectPath(true) + " Scan Folder";
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetDisplayName(), scanName);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).RecurseSubFolders(), true);
|
||||
ASSERT_EQ(config.GetScanFolderAt(0).GetOrder(), 0);
|
||||
@@ -397,7 +371,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms = config.GetScanFolderAt(0).GetPlatforms();
|
||||
ASSERT_EQ(platforms.size(), 4);
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("ios", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("server", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
|
||||
@@ -405,12 +379,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP
|
||||
platforms = config.GetScanFolderAt(1).GetPlatforms();
|
||||
ASSERT_EQ(platforms.size(), 2);
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderAt(2).GetDisplayName(), QString("folder1output"));
|
||||
platforms = config.GetScanFolderAt(2).GetPlatforms();
|
||||
ASSERT_EQ(platforms.size(), 1);
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set<AZStd::string>{})) != platforms.end());
|
||||
|
||||
ASSERT_EQ(config.GetScanFolderAt(3).GetDisplayName(), QString("folder2output"));
|
||||
platforms = config.GetScanFolderAt(3).GetPlatforms();
|
||||
@@ -445,16 +419,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
|
||||
ASSERT_FALSE(config.IsFileExcluded("blahblah/Levels/blahblahhold/whatever.test"));
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
TEST_F(PlatformConfigurationUnitTests, DISABLED_TestFailReadConfigFile_Recognizers)
|
||||
#else
|
||||
TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
{
|
||||
using namespace AzToolsFramework::AssetSystem;
|
||||
using namespace AssetProcessor;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const char* platformWhichIsNotCurrentPlatform = "osx_gl";
|
||||
#if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_LINUX)
|
||||
const char* platformWhichIsNotCurrentPlatform = "mac";
|
||||
#else
|
||||
const char* platformWhichIsNotCurrentPlatform = "pc";
|
||||
#endif
|
||||
@@ -475,58 +445,74 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
|
||||
ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_pattern, "*.i_caf");
|
||||
ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_type, AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs.size(), 2);
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_FALSE(recogs["i_caf"].m_platformSpecs.contains("server")); // server has been set to skip.
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs["es3"].m_extraRCParams, "mobile");
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs["android"].m_extraRCParams, "mobile");
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "defaultparams");
|
||||
|
||||
ASSERT_TRUE(recogs.contains("caf"));
|
||||
ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("server"));
|
||||
ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_EQ(recogs["caf"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["caf"].m_platformSpecs["es3"].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["caf"].m_platformSpecs["android"].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["caf"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
|
||||
ASSERT_TRUE(recogs.contains("mov"));
|
||||
ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("server"));
|
||||
ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_EQ(recogs["mov"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["mov"].m_platformSpecs["es3"].m_extraRCParams, "platformspecificoverride");
|
||||
ASSERT_EQ(recogs["mov"].m_platformSpecs["android"].m_extraRCParams, "platformspecificoverride");
|
||||
ASSERT_EQ(recogs["mov"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["mov"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
|
||||
// the "rend" test makes sure that even if you dont specify 'params' its still there by default for all enabled platforms.
|
||||
// (but platforms can override it)
|
||||
ASSERT_TRUE(recogs.contains("rend"));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("server"));
|
||||
ASSERT_FALSE(recogs["rend"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there.
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs["es3"].m_extraRCParams, "rendererparams");
|
||||
ASSERT_EQ(recogs["rend"].m_platformSpecs["server"].m_extraRCParams, ""); // default if not specified is empty string
|
||||
EXPECT_THAT(
|
||||
recogs["rend"].m_platformSpecs.keys(),
|
||||
testing::AllOf(
|
||||
testing::UnorderedElementsAre(
|
||||
QString(AzToolsFramework::AssetSystem::GetHostAssetPlatform()),
|
||||
QString("android"),
|
||||
QString("server")
|
||||
),
|
||||
testing::Not(testing::Contains(platformWhichIsNotCurrentPlatform)) // this is not an enabled platform and should not be there.
|
||||
)
|
||||
);
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams");
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs["android"].m_extraRCParams, "rendererparams");
|
||||
EXPECT_EQ(recogs["rend"].m_platformSpecs["server"].m_extraRCParams, ""); // default if not specified is empty string
|
||||
|
||||
ASSERT_TRUE(recogs.contains("alldefault"));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("server"));
|
||||
ASSERT_FALSE(recogs["alldefault"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there.
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs.size(), 3);
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "");
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs["es3"].m_extraRCParams, "");
|
||||
ASSERT_EQ(recogs["alldefault"].m_platformSpecs["server"].m_extraRCParams, "");
|
||||
EXPECT_THAT(
|
||||
recogs["alldefault"].m_platformSpecs.keys(),
|
||||
testing::AllOf(
|
||||
testing::UnorderedElementsAre(
|
||||
QString(AzToolsFramework::AssetSystem::GetHostAssetPlatform()),
|
||||
QString("android"),
|
||||
QString("server")
|
||||
),
|
||||
testing::Not(testing::Contains(platformWhichIsNotCurrentPlatform)) // this is not an enabled platform and should not be there.
|
||||
)
|
||||
);
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "");
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs["android"].m_extraRCParams, "");
|
||||
EXPECT_EQ(recogs["alldefault"].m_platformSpecs["server"].m_extraRCParams, "");
|
||||
|
||||
ASSERT_TRUE(recogs.contains("skipallbutone"));
|
||||
ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["skipallbutone"].m_platformSpecs.contains("server")); // server is only one enabled (set to copy)
|
||||
ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs.size(), 1);
|
||||
ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
EXPECT_THAT(
|
||||
recogs["skipallbutone"].m_platformSpecs.keys(),
|
||||
testing::UnorderedElementsAre(
|
||||
QString("server") // server is only one enabled (set to copy)
|
||||
)
|
||||
);
|
||||
EXPECT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
EXPECT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("android"));
|
||||
EXPECT_EQ(recogs["skipallbutone"].m_platformSpecs["server"].m_extraRCParams, "copy");
|
||||
}
|
||||
|
||||
|
||||
@@ -549,7 +535,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides)
|
||||
|
||||
// verify the data.
|
||||
ASSERT_NE(config.GetPlatformByIdentifier(AzToolsFramework::AssetSystem::GetHostAssetPlatform()), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("es3"), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("android"), nullptr);
|
||||
ASSERT_NE(config.GetPlatformByIdentifier("provo"), nullptr);
|
||||
// this override swaps server with provo in that it turns ON provo, turns off server
|
||||
ASSERT_EQ(config.GetPlatformByIdentifier("server"), nullptr); // this should be off due to overrides
|
||||
@@ -566,11 +552,11 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides)
|
||||
ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_pattern, "*.i_caf");
|
||||
ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_type, AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs.size(), 3);
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("es3"));
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("android"));
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("provo"));
|
||||
ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform()));
|
||||
ASSERT_FALSE(recogs["i_caf"].m_platformSpecs.contains("server")); // server has been set to skip.
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs["es3"].m_extraRCParams, "mobile");
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs["android"].m_extraRCParams, "mobile");
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "defaultparams");
|
||||
ASSERT_EQ(recogs["i_caf"].m_platformSpecs["provo"].m_extraRCParams, "copy");
|
||||
|
||||
|
||||
@@ -137,10 +137,13 @@ TEST_F(AssetUtilitiesTest, UpdateToCorrectCase_ExistingFile_ReturnsTrue_Corrects
|
||||
thingsToTry << "SomeFile.TxT";
|
||||
thingsToTry << "otherfile.txt";
|
||||
thingsToTry << "subfolder1/otherfile.txt";
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
thingsToTry << "subfolder2\\otherfile.txt";
|
||||
thingsToTry << "subFolder3\\somefile.txt";
|
||||
thingsToTry << "subFolder4\\subfolder6\\somefile.txt";
|
||||
thingsToTry << "subFolder5\\subfolder7/someFile.txt";
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
thingsToTry << "specialFileName[.txt";
|
||||
thingsToTry << "specialFileName].txt";
|
||||
thingsToTry << "specialFileName!.txt";
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "ProductAssetTreeItemData.h"
|
||||
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
@@ -159,31 +160,33 @@ namespace AssetProcessor
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::IO::Path productNamePath(product.m_productName, AZ::IO::PosixPathSeparator);
|
||||
|
||||
AZStd::vector<AZStd::string> tokens;
|
||||
AzFramework::StringFunc::Tokenize(product.m_productName.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true);
|
||||
|
||||
if (tokens.empty())
|
||||
if (productNamePath.empty())
|
||||
{
|
||||
AZ_Warning("AssetProcessor", false, "Product id %d has an invalid name: %s", product.m_productID, product.m_productName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
AssetTreeItem* parentItem = m_root.get();
|
||||
AZStd::string fullFolderName;
|
||||
for (int i = 0; i < tokens.size() - 1; ++i)
|
||||
AZ::IO::Path currentFullFolderPath;
|
||||
const AZ::IO::PathView filename = productNamePath.Filename();
|
||||
const AZ::IO::PathView fullPathWithoutFilename = productNamePath.RemoveFilename();
|
||||
AZStd::fixed_string<AZ::IO::MaxPathLength> currentPath;
|
||||
for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt)
|
||||
{
|
||||
AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName);
|
||||
AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str());
|
||||
currentPath = pathIt->FixedMaxPathString();
|
||||
currentFullFolderPath /= currentPath;
|
||||
AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str());
|
||||
if (!nextParent)
|
||||
{
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
|
||||
}
|
||||
nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, fullFolderName, tokens[i].c_str(), true, AZ::Uuid::CreateNull()));
|
||||
m_productToTreeItem[fullFolderName] = nextParent;
|
||||
nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true, AZ::Uuid::CreateNull()));
|
||||
m_productToTreeItem[currentFullFolderPath.Native()] = nextParent;
|
||||
// m_productIdToTreeItem is not used for folders, folders don't have product IDs.
|
||||
|
||||
if (!modelIsResetting)
|
||||
@@ -205,12 +208,12 @@ namespace AssetProcessor
|
||||
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<ProductAssetTreeItemData> productItemData =
|
||||
ProductAssetTreeItemData::MakeShared(&product, product.m_productName, tokens[tokens.size() - 1].c_str(), false, sourceId);
|
||||
ProductAssetTreeItemData::MakeShared(&product, product.m_productName, AZStd::fixed_string<AZ::IO::MaxPathLength>(filename.Native()).c_str(), false, sourceId);
|
||||
m_productToTreeItem[product.m_productName] =
|
||||
parentItem->CreateChild(productItemData);
|
||||
m_productIdToTreeItem[product.m_productID] = m_productToTreeItem[product.m_productName];
|
||||
|
||||
@@ -63,8 +63,7 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
|
||||
auto fullPath = AZ::IO::Path(scanFolder.m_scanFolder) / source.m_sourceName;
|
||||
|
||||
AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder, AZ::IO::PosixPathSeparator) / source.m_sourceName;
|
||||
|
||||
// It's common for Open 3D Engine game projects and scan folders to be in a subfolder
|
||||
// of the engine install. To improve readability of the source files, strip out
|
||||
@@ -78,34 +77,35 @@ namespace AssetProcessor
|
||||
AzFramework::StringFunc::Replace(fullPath.Native(), m_assetRoot.absolutePath().toUtf8(), "");
|
||||
}
|
||||
|
||||
|
||||
AZStd::vector<AZStd::string> tokens;
|
||||
AzFramework::StringFunc::Tokenize(fullPath.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true);
|
||||
|
||||
if (tokens.empty())
|
||||
if (fullPath.empty())
|
||||
{
|
||||
AZ_Warning("AssetProcessor", false, "Source id %s has an invalid name: %s",
|
||||
source.m_sourceGuid.ToString<AZStd::string>().c_str(), source.m_sourceName.c_str());
|
||||
AZ_Warning(
|
||||
"AssetProcessor", false, "Source id %s has an invalid name: %s", source.m_sourceGuid.ToString<AZStd::string>().c_str(),
|
||||
source.m_sourceName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex newIndicesStart;
|
||||
|
||||
AssetTreeItem* parentItem = m_root.get();
|
||||
AZStd::string fullFolderName;
|
||||
for (int i = 0; i < tokens.size() - 1; ++i)
|
||||
AZ::IO::Path currentFullFolderPath;
|
||||
const AZ::IO::PathView filename = fullPath.Filename();
|
||||
const AZ::IO::PathView fullPathWithoutFilename = fullPath.RemoveFilename();
|
||||
AZStd::fixed_string<AZ::IO::MaxPathLength> currentPath;
|
||||
for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt)
|
||||
{
|
||||
AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName);
|
||||
AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str());
|
||||
currentPath = pathIt->FixedMaxPathString();
|
||||
currentFullFolderPath /= currentPath;
|
||||
AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str());
|
||||
if (!nextParent)
|
||||
{
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
|
||||
}
|
||||
nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, fullFolderName, tokens[i].c_str(), true));
|
||||
m_sourceToTreeItem[fullFolderName] = nextParent;
|
||||
nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true));
|
||||
m_sourceToTreeItem[currentFullFolderPath.Native()] = nextParent;
|
||||
// Folders don't have source IDs, don't add to m_sourceIdToTreeItem
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
@@ -117,12 +117,12 @@ namespace AssetProcessor
|
||||
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
|
||||
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
|
||||
}
|
||||
|
||||
m_sourceToTreeItem[source.m_sourceName] =
|
||||
parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, tokens[tokens.size() - 1].c_str(), false));
|
||||
parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, AZStd::fixed_string<AZ::IO::MaxPathLength>(filename.Native()).c_str(), false));
|
||||
m_sourceIdToTreeItem[source.m_sourceID] = m_sourceToTreeItem[source.m_sourceName];
|
||||
if (!modelIsResetting)
|
||||
{
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace AssetProcessor
|
||||
public:
|
||||
using GetRelativeProductPathFromFullSourceOrProductPathRequest = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathRequest;
|
||||
using GetRelativeProductPathFromFullSourceOrProductPathResponse = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathResponse;
|
||||
using GenerateRelativeSourcePathRequest = AzFramework::AssetSystem::GenerateRelativeSourcePathRequest;
|
||||
using GenerateRelativeSourcePathResponse = AzFramework::AssetSystem::GenerateRelativeSourcePathResponse;
|
||||
using GetFullSourcePathFromRelativeProductPathRequest = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathRequest;
|
||||
using GetFullSourcePathFromRelativeProductPathResponse = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathResponse;
|
||||
};
|
||||
@@ -88,34 +90,34 @@ namespace AssetProcessor
|
||||
//AZ_TracePrintf("test", "-------------------------\n");
|
||||
}
|
||||
|
||||
void ComputeFingerprints(unsigned int& fingerprintForPC, unsigned int& fingerprintForES3, PlatformConfiguration& config, QString scanFolderPath, QString relPath)
|
||||
void ComputeFingerprints(unsigned int& fingerprintForPC, unsigned int& fingerprintForANDROID, PlatformConfiguration& config, QString scanFolderPath, QString relPath)
|
||||
{
|
||||
QString extraInfoForPC;
|
||||
QString extraInfoForES3;
|
||||
QString extraInfoForANDROID;
|
||||
RecognizerPointerContainer output;
|
||||
QString filePath = scanFolderPath + "/" + relPath;
|
||||
config.GetMatchingRecognizers(filePath, output);
|
||||
for (const AssetRecognizer* assetRecogniser : output)
|
||||
{
|
||||
extraInfoForPC.append(assetRecogniser->m_platformSpecs["pc"].m_extraRCParams);
|
||||
extraInfoForES3.append(assetRecogniser->m_platformSpecs["es3"].m_extraRCParams);
|
||||
extraInfoForANDROID.append(assetRecogniser->m_platformSpecs["android"].m_extraRCParams);
|
||||
extraInfoForPC.append(assetRecogniser->m_version);
|
||||
extraInfoForES3.append(assetRecogniser->m_version);
|
||||
extraInfoForANDROID.append(assetRecogniser->m_version);
|
||||
}
|
||||
|
||||
//Calculating fingerprints for the file for pc and es3 platforms
|
||||
//Calculating fingerprints for the file for pc and android platforms
|
||||
AZ::Uuid sourceId = AZ::Uuid("{2206A6E0-FDBC-45DE-B6FE-C2FC63020BD5}");
|
||||
JobEntry jobEntryPC(scanFolderPath, relPath, relPath, 0, { "pc", {"desktop", "renderer"} }, "", 0, 1, sourceId);
|
||||
JobEntry jobEntryES3(scanFolderPath, relPath, relPath, 0, { "es3", {"mobile", "renderer"} }, "", 0, 2, sourceId);
|
||||
JobEntry jobEntryANDROID(scanFolderPath, relPath, relPath, 0, { "android", {"mobile", "renderer"} }, "", 0, 2, sourceId);
|
||||
|
||||
JobDetails jobDetailsPC;
|
||||
jobDetailsPC.m_extraInformationForFingerprinting = extraInfoForPC.toUtf8().constData();
|
||||
jobDetailsPC.m_jobEntry = jobEntryPC;
|
||||
JobDetails jobDetailsES3;
|
||||
jobDetailsES3.m_extraInformationForFingerprinting = extraInfoForES3.toUtf8().constData();
|
||||
jobDetailsES3.m_jobEntry = jobEntryES3;
|
||||
JobDetails jobDetailsANDROID;
|
||||
jobDetailsANDROID.m_extraInformationForFingerprinting = extraInfoForANDROID.toUtf8().constData();
|
||||
jobDetailsANDROID.m_jobEntry = jobEntryANDROID;
|
||||
fingerprintForPC = AssetUtilities::GenerateFingerprint(jobDetailsPC);
|
||||
fingerprintForES3 = AssetUtilities::GenerateFingerprint(jobDetailsES3);
|
||||
fingerprintForANDROID = AssetUtilities::GenerateFingerprint(jobDetailsANDROID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +175,16 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_FALSE(gameName.isEmpty());
|
||||
// should create cache folder in the root, and read everything from there.
|
||||
|
||||
// There is a sub-case of handling mixed cases, but is only supported on case-insensitive filesystems.
|
||||
#if defined(AZ_PLATFORM_LINUX)
|
||||
// Linux is case-sensitive, so 'basefile.txt' will stay the same case as the other subfolder versions
|
||||
constexpr const char* subfolder3BaseFilePath = "subfolder3/basefile.txt";
|
||||
constexpr int expectedLegacyAssetIdCount = 1;
|
||||
#else
|
||||
constexpr const char* subfolder3BaseFilePath = "subfolder3/BaseFile.txt";
|
||||
constexpr int expectedLegacyAssetIdCount = 2;
|
||||
#endif
|
||||
|
||||
QSet<QString> expectedFiles;
|
||||
// set up some interesting files:
|
||||
expectedFiles << tempPath.absoluteFilePath("rootfile2.txt");
|
||||
@@ -183,7 +195,9 @@ namespace AssetProcessor
|
||||
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(subfolder3BaseFilePath);
|
||||
|
||||
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
|
||||
@@ -240,7 +254,7 @@ namespace AssetProcessor
|
||||
|
||||
PlatformConfiguration config;
|
||||
config.EnablePlatform({ "pc",{ "desktop", "renderer" } }, true);
|
||||
config.EnablePlatform({ "es3",{ "mobile", "renderer" } }, true);
|
||||
config.EnablePlatform({ "android",{ "mobile", "renderer" } }, true);
|
||||
config.EnablePlatform({ "fandago",{ "console", "renderer" } }, false);
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms;
|
||||
config.PopulatePlatformsForScanFolder(platforms);
|
||||
@@ -259,9 +273,9 @@ namespace AssetProcessor
|
||||
|
||||
AssetRecognizer rec;
|
||||
AssetPlatformSpec specpc;
|
||||
AssetPlatformSpec speces3;
|
||||
AssetPlatformSpec specandroid;
|
||||
|
||||
speces3.m_extraRCParams = "somerandomparam";
|
||||
specandroid.m_extraRCParams = "somerandomparam";
|
||||
rec.m_name = "random files";
|
||||
rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.random", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
@@ -269,13 +283,13 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(mockAppManager.RegisterAssetRecognizerAsBuilder(rec));
|
||||
|
||||
specpc.m_extraRCParams = ""; // blank must work
|
||||
speces3.m_extraRCParams = "testextraparams";
|
||||
specandroid.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);
|
||||
rec.m_platformSpecs.insert("android", specandroid);
|
||||
|
||||
config.AddRecognizer(rec);
|
||||
|
||||
@@ -305,21 +319,21 @@ namespace AssetProcessor
|
||||
rec.m_testLockSource = false;
|
||||
|
||||
specpc.m_extraRCParams = "pcparams";
|
||||
speces3.m_extraRCParams = "es3params";
|
||||
specandroid.m_extraRCParams = "androidparams";
|
||||
|
||||
rec.m_name = "xxx files";
|
||||
rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.xxx", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
rec.m_platformSpecs.insert("es3", speces3);
|
||||
rec.m_platformSpecs.insert("android", specandroid);
|
||||
config.AddRecognizer(rec);
|
||||
mockAppManager.RegisterAssetRecognizerAsBuilder(rec);
|
||||
|
||||
// two recognizers for the same pattern.
|
||||
rec.m_name = "xxx files 2 (builder2)";
|
||||
specpc.m_extraRCParams = "pcparams2";
|
||||
speces3.m_extraRCParams = "es3params2";
|
||||
specandroid.m_extraRCParams = "androidparams2";
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
rec.m_platformSpecs.insert("es3", speces3);
|
||||
rec.m_platformSpecs.insert("android", specandroid);
|
||||
config.AddRecognizer(rec);
|
||||
mockAppManager.RegisterAssetRecognizerAsBuilder(rec);
|
||||
|
||||
@@ -330,7 +344,7 @@ namespace AssetProcessor
|
||||
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);
|
||||
ignore_rec.m_platformSpecs.insert("android", ignore_spec);
|
||||
config.AddRecognizer(ignore_rec);
|
||||
mockAppManager.RegisterAssetRecognizerAsBuilder(ignore_rec);
|
||||
|
||||
@@ -432,7 +446,7 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 1); // 1, since we have one recognizer for .ignore, but the 'es3' platform is marked as skip
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 1); // 1, since we have one recognizer for .ignore, but the 'android' platform is marked as skip
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
|
||||
|
||||
@@ -455,16 +469,16 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
|
||||
|
||||
QList<int> es3JobsIndex;
|
||||
QList<int> androidJobsIndex;
|
||||
QList<int> pcJobsIndex;
|
||||
for (int checkIdx = 0; checkIdx < 4; ++checkIdx)
|
||||
{
|
||||
@@ -662,19 +676,19 @@ namespace AssetProcessor
|
||||
// ---------- test successes ----------
|
||||
|
||||
|
||||
QStringList es3outs;
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc1")));
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc2")));
|
||||
QStringList androidouts;
|
||||
androidouts.push_back(cacheRoot.filePath(QString("android/basefile.arc1")));
|
||||
androidouts.push_back(cacheRoot.filePath(QString("android/basefile.arc2")));
|
||||
|
||||
// feed it the messages its waiting for (create the files)
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[1], "products."))
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "products."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[1], "products."))
|
||||
|
||||
//Invoke Asset Processed for es3 platform , txt files job description
|
||||
//Invoke Asset Processed for android platform , txt files job description
|
||||
AssetBuilderSDK::ProcessJobResponse response;
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[1].toUtf8().constData(), AZ::Uuid::CreateNull(), 2));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[1].toUtf8().constData(), AZ::Uuid::CreateNull(), 2));
|
||||
|
||||
// make sure legacy SubIds get stored in the DB and in asset response messages.
|
||||
// also make sure they don't get filed for the wrong asset.
|
||||
@@ -693,8 +707,8 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 1);
|
||||
|
||||
// always RELATIVE, always with the product name.
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefile.arc1");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_data == "basefile.arc2");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetChanged);
|
||||
@@ -793,14 +807,14 @@ namespace AssetProcessor
|
||||
changedInputResults.clear();
|
||||
assetMessages.clear();
|
||||
|
||||
es3outs.clear();
|
||||
es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.azm")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products."));
|
||||
androidouts.clear();
|
||||
androidouts.push_back(cacheRoot.filePath(QString("android/basefile.azm")));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "products."));
|
||||
|
||||
//Invoke Asset Processed for es3 platform , txt files2 job description
|
||||
//Invoke Asset Processed for android platform , txt files2 job description
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData()));
|
||||
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
@@ -812,7 +826,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 1);
|
||||
|
||||
// always RELATIVE, always with the product name.
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefile.azm");
|
||||
|
||||
changedInputResults.clear();
|
||||
@@ -1002,11 +1016,11 @@ namespace AssetProcessor
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
@@ -1025,25 +1039,25 @@ namespace AssetProcessor
|
||||
|
||||
// this time make different products:
|
||||
|
||||
QStringList oldes3outs;
|
||||
QStringList oldandroidouts;
|
||||
QStringList oldpcouts;
|
||||
oldes3outs = es3outs;
|
||||
oldandroidouts = androidouts;
|
||||
oldpcouts.append(pcouts);
|
||||
QStringList es3outs2;
|
||||
QStringList androidouts2;
|
||||
QStringList pcouts2;
|
||||
es3outs.clear();
|
||||
androidouts.clear();
|
||||
pcouts.clear();
|
||||
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
|
||||
androidouts.push_back(cacheRoot.filePath(QString("android/basefilea.arc1")));
|
||||
androidouts2.push_back(cacheRoot.filePath(QString("android/basefilea.azm")));
|
||||
// note that the android outs have changed
|
||||
// but the pc outs are still the same.
|
||||
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."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile."));
|
||||
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 50);
|
||||
@@ -1055,12 +1069,12 @@ namespace AssetProcessor
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -1083,12 +1097,12 @@ namespace AssetProcessor
|
||||
// The files removed should be the ones we did not emit this time
|
||||
// note that order isn't guarantee but an example output it this
|
||||
|
||||
// [0] Removed: ES3, basefile.arc1
|
||||
// [1] Removed: ES3, basefile.arc2
|
||||
// [2] Changed: ES3, basefilea.arc1 (added)
|
||||
// [0] Removed: ANDROID, basefile.arc1
|
||||
// [1] Removed: ANDROID, basefile.arc2
|
||||
// [2] Changed: ANDROID, basefilea.arc1 (added)
|
||||
|
||||
// [3] Removed: ES3, basefile.azm
|
||||
// [4] Changed: ES3, basefilea.azm (added)
|
||||
// [3] Removed: ANDROID, basefile.azm
|
||||
// [4] Changed: ANDROID, basefilea.azm (added)
|
||||
|
||||
// [5] changed: PC, basefile.arc1 (changed)
|
||||
// [6] changed: PC, basefile.azm (changed)
|
||||
@@ -1110,18 +1124,18 @@ namespace AssetProcessor
|
||||
if (element.m_data == "basefilea.arc1")
|
||||
{
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetChanged);
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_platform == "android");
|
||||
}
|
||||
|
||||
if (element.m_data == "basefile.arc2")
|
||||
{
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetRemoved);
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_platform == "android");
|
||||
}
|
||||
}
|
||||
|
||||
// original products must no longer exist since it should have found and deleted them!
|
||||
for (QString outFile: oldes3outs)
|
||||
for (QString outFile: oldandroidouts)
|
||||
{
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(outFile));
|
||||
}
|
||||
@@ -1145,11 +1159,11 @@ namespace AssetProcessor
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // pc and es3
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // pc and android
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
@@ -1169,12 +1183,12 @@ namespace AssetProcessor
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -1205,11 +1219,11 @@ namespace AssetProcessor
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
@@ -1220,12 +1234,12 @@ namespace AssetProcessor
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -1243,9 +1257,9 @@ namespace AssetProcessor
|
||||
|
||||
// deleting the fingerprint file should not have erased the products
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(pcouts[0]));
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(es3outs[0]));
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(androidouts[0]));
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(pcouts2[0]));
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(es3outs2[0]));
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::exists(androidouts2[0]));
|
||||
|
||||
changedInputResults.clear();
|
||||
assetMessages.clear();
|
||||
@@ -1304,9 +1318,9 @@ namespace AssetProcessor
|
||||
}
|
||||
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(pcouts[0]));
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(es3outs[0]));
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(androidouts[0]));
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(pcouts2[0]));
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(es3outs2[0]));
|
||||
UNIT_TEST_EXPECT_FALSE(QFile::exists(androidouts2[0]));
|
||||
|
||||
changedInputResults.clear();
|
||||
assetMessages.clear();
|
||||
@@ -1321,28 +1335,28 @@ namespace AssetProcessor
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile."));
|
||||
|
||||
// send both done messages simultaneously!
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData()));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData()));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
// send one failure only for PC :
|
||||
@@ -1420,12 +1434,12 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 3);
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 3);
|
||||
|
||||
// which should be for the ES3:
|
||||
// which should be for the ANDROID:
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::NormalizeFilePath(changedInputResults[0].first) == absolutePath);
|
||||
|
||||
// always RELATIVE, always with the product name.
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefilea.arc1" || assetMessages[0].m_data == "basefilea.azm");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android");
|
||||
|
||||
for (auto& payload : payloadList)
|
||||
{
|
||||
@@ -1519,35 +1533,36 @@ namespace AssetProcessor
|
||||
|
||||
// -------------- override test -----------------
|
||||
// set up by letting it compile basefile.txt from 3:
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder3/BaseFile.txt"));
|
||||
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath(subfolder3BaseFilePath));
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
|
||||
es3outs.clear();
|
||||
es3outs2.clear();
|
||||
androidouts.clear();
|
||||
androidouts2.clear();
|
||||
pcouts.clear();
|
||||
pcouts2.clear();
|
||||
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
|
||||
androidouts.push_back(cacheRoot.filePath(QString("android/basefilez.arc2")));
|
||||
androidouts2.push_back(cacheRoot.filePath(QString("android/basefileaz.azm2")));
|
||||
// note that the android outs have changed
|
||||
// but the pc outs are still the same.
|
||||
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(androidouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile."));
|
||||
UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile."));
|
||||
changedInputResults.clear();
|
||||
assetMessages.clear();
|
||||
@@ -1555,12 +1570,12 @@ namespace AssetProcessor
|
||||
// send all the done messages simultaneously:
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 2));
|
||||
response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 2));
|
||||
QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
|
||||
|
||||
response.m_outputProducts.clear();
|
||||
@@ -1581,8 +1596,7 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 4);
|
||||
for (auto element : assetMessages)
|
||||
{
|
||||
// because the source asset had UPPER CASE in it, we should have multiple legacy IDs
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_legacyAssetIds.size() == 2);
|
||||
UNIT_TEST_EXPECT_TRUE(element.m_legacyAssetIds.size() == expectedLegacyAssetIdCount);
|
||||
}
|
||||
|
||||
// ------------- setup complete, now do the test...
|
||||
@@ -1605,7 +1619,7 @@ namespace AssetProcessor
|
||||
|
||||
// delete the highest priority override file and ensure that it generates tasks
|
||||
// for the next highest priority! Basically, deleting this file should "reveal" the file underneath it in the other subfolder
|
||||
QString deletedFile = tempPath.absoluteFilePath("subfolder3/BaseFile.txt");
|
||||
QString deletedFile = tempPath.absoluteFilePath(subfolder3BaseFilePath);
|
||||
QString expectedReplacementInputFile = AssetUtilities::NormalizeFilePath(tempPath.absoluteFilePath("subfolder2/basefile.txt"));
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QFile::remove(deletedFile));
|
||||
@@ -1619,12 +1633,17 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
#if defined(AZ_PLATFORM_LINUX)
|
||||
// On Linux, because of we cannot change the case of the source file, the job fingerprint is not updated due the case-switch so
|
||||
// there will be actually nothing to process
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 0);
|
||||
#else
|
||||
// --------- same result as above ----------
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0);
|
||||
@@ -1639,15 +1658,15 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(processFile1.startsWith(platformFolder));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[checkIdx].m_jobEntry.m_computedFingerprint != 0);
|
||||
}
|
||||
|
||||
#endif // defined(AZ_PLATFORM_LINUX)
|
||||
relativePathFromWatchFolder = "somefile.xxx";
|
||||
watchFolderPath = tempPath.absoluteFilePath("subfolder3");
|
||||
absolutePath = watchFolderPath + "/" + relativePathFromWatchFolder;
|
||||
|
||||
unsigned int fingerprintForPC = 0;
|
||||
unsigned int fingerprintForES3 = 0;
|
||||
unsigned int fingerprintForANDROID = 0;
|
||||
|
||||
ComputeFingerprints(fingerprintForPC, fingerprintForES3, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
ComputeFingerprints(fingerprintForPC, fingerprintForANDROID, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
|
||||
processResults.clear();
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
@@ -1655,11 +1674,11 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and es3,since we have two recognizer for .xxx file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and android,since we have two recognizer for .xxx file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
|
||||
@@ -1681,11 +1700,11 @@ namespace AssetProcessor
|
||||
// we never actually submitted any fingerprints or indicated success, so the same number of jobs should occur as before
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and es3,since we have two recognizer for .xxx file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and android,since we have two recognizer for .xxx file
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc"));
|
||||
|
||||
@@ -1705,7 +1724,7 @@ namespace AssetProcessor
|
||||
// now re-perform the same test, this time only the pc ones should re-appear.
|
||||
// this should happen because we're changing the extra params, which should be part of the fingerprint
|
||||
// if this unit test fails, check to make sure that the extra params are being ingested into the fingerprint computation functions
|
||||
// and also make sure that the jobs that are for the remaining es3 platform don't change.
|
||||
// and also make sure that the jobs that are for the remaining android platform don't change.
|
||||
|
||||
// store the UUID so that we can insert the new one with the same UUID
|
||||
AZStd::shared_ptr<InternalMockBuilder> builderTxt2Builder;
|
||||
@@ -1743,12 +1762,12 @@ namespace AssetProcessor
|
||||
// ---------------------
|
||||
|
||||
unsigned int newfingerprintForPC = 0;
|
||||
unsigned int newfingerprintForES3 = 0;
|
||||
unsigned int newfingerprintForANDROID = 0;
|
||||
|
||||
ComputeFingerprints(newfingerprintForPC, newfingerprintForES3, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
ComputeFingerprints(newfingerprintForPC, newfingerprintForANDROID, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(newfingerprintForPC != fingerprintForPC);//Fingerprints should be different
|
||||
UNIT_TEST_EXPECT_TRUE(newfingerprintForES3 == fingerprintForES3);//Fingerprints are same
|
||||
UNIT_TEST_EXPECT_TRUE(newfingerprintForANDROID == fingerprintForANDROID);//Fingerprints are same
|
||||
|
||||
config.RemoveRecognizer("xxx files 2 (builder2)");
|
||||
mockAppManager.UnRegisterAssetRecognizerAsBuilder("xxx files 2 (builder2)");
|
||||
@@ -1763,18 +1782,18 @@ namespace AssetProcessor
|
||||
absolutePath = AssetUtilities::NormalizeFilePath(absolutePath);
|
||||
QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath));
|
||||
UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000));
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // pc and es3
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // pc and android
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier != processResults[1].m_jobEntry.m_platformInfo.m_identifier);
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android"));
|
||||
|
||||
unsigned int newfingerprintForPCAfterVersionChange = 0;
|
||||
unsigned int newfingerprintForES3AfterVersionChange = 0;
|
||||
unsigned int newfingerprintForANDROIDAfterVersionChange = 0;
|
||||
|
||||
ComputeFingerprints(newfingerprintForPCAfterVersionChange, newfingerprintForES3AfterVersionChange, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
ComputeFingerprints(newfingerprintForPCAfterVersionChange, newfingerprintForANDROIDAfterVersionChange, config, watchFolderPath, relativePathFromWatchFolder);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForPCAfterVersionChange != fingerprintForPC) || (newfingerprintForPCAfterVersionChange != newfingerprintForPC));//Fingerprints should be different
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForES3AfterVersionChange != fingerprintForES3) || (newfingerprintForES3AfterVersionChange != newfingerprintForES3));//Fingerprints should be different
|
||||
UNIT_TEST_EXPECT_TRUE((newfingerprintForANDROIDAfterVersionChange != fingerprintForANDROID) || (newfingerprintForANDROIDAfterVersionChange != newfingerprintForANDROID));//Fingerprints should be different
|
||||
|
||||
//------Test for Files which are excluded
|
||||
processResults.clear();
|
||||
@@ -1919,7 +1938,7 @@ namespace AssetProcessor
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 0); // nothing to process
|
||||
|
||||
// we are aware that 4 products went missing (es3 and pc versions of the 2 files since we renamed the SOURCE folder)
|
||||
// we are aware that 4 products went missing (android and pc versions of the 2 files since we renamed the SOURCE folder)
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 4);
|
||||
for (auto element : assetMessages)
|
||||
{
|
||||
@@ -2178,8 +2197,8 @@ namespace AssetProcessor
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[2].m_assetId != AZ::Data::AssetId());
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[3].m_assetId != AZ::Data::AssetId());
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[2].m_platform == "pc");
|
||||
UNIT_TEST_EXPECT_TRUE(assetMessages[3].m_platform == "pc");
|
||||
|
||||
@@ -2212,12 +2231,12 @@ namespace AssetProcessor
|
||||
mockAppManager.UnRegisterAllBuilders();
|
||||
|
||||
AssetRecognizer abt_rec1;
|
||||
AssetPlatformSpec abt_speces3;
|
||||
AssetPlatformSpec abt_specandroid;
|
||||
abt_rec1.m_name = "UnitTestTextBuilder1";
|
||||
abt_rec1.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
//abt_rec1.m_regexp.setPatternSyntax(QRegExp::Wildcard);
|
||||
//abt_rec1.m_regexp.setPattern("*.txt");
|
||||
abt_rec1.m_platformSpecs.insert("es3", speces3);
|
||||
abt_rec1.m_platformSpecs.insert("android", specandroid);
|
||||
mockAppManager.RegisterAssetRecognizerAsBuilder(abt_rec1);
|
||||
|
||||
AssetRecognizer abt_rec2;
|
||||
@@ -2266,8 +2285,8 @@ namespace AssetProcessor
|
||||
|
||||
sortAssetToProcessResultList(processResults);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // 1 for pc and es3
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // 1 for pc and android
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android");
|
||||
UNIT_TEST_EXPECT_TRUE(processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc");
|
||||
UNIT_TEST_EXPECT_TRUE(QString::compare(processResults[0].m_jobEntry.GetAbsoluteSourcePath(), absolutePath, Qt::CaseInsensitive) == 0);
|
||||
UNIT_TEST_EXPECT_TRUE(QString::compare(processResults[1].m_jobEntry.GetAbsoluteSourcePath(), absolutePath, Qt::CaseInsensitive) == 0);
|
||||
@@ -2719,7 +2738,12 @@ namespace AssetProcessor
|
||||
{
|
||||
AssetBuilderSDK::JobDescriptor secondDescriptor = descriptor;
|
||||
secondDescriptor.m_jobKey = "yyy";
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
sourceFileDependency.m_sourceFileDependencyPath = "some\\random/Folders/FILEa.TxT";
|
||||
#else
|
||||
sourceFileDependency.m_sourceFileDependencyPath = "some/random/folders/FileA.txt";
|
||||
#endif // defined(AZ_PLATFORM_WINDOWS)
|
||||
|
||||
// ... declare a job dependency on job A ('FileA.txt', 'xxx', platform)
|
||||
AssetBuilderSDK::JobDependency jobDependency("xxx", platformInfo.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Fingerprint, sourceFileDependency);
|
||||
secondDescriptor.m_jobDependencyList.push_back(jobDependency);
|
||||
@@ -2803,11 +2827,11 @@ namespace AssetProcessor
|
||||
QDir cacheRoot;
|
||||
UNIT_TEST_EXPECT_TRUE(AssetUtilities::ComputeProjectCacheRoot(cacheRoot));
|
||||
|
||||
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"));
|
||||
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, ""));
|
||||
|
||||
@@ -17,16 +17,16 @@ void ConnectionUnitTest::StartTest()
|
||||
m_testConnection.SetAssetPlatformsString("pc");
|
||||
AzFramework::AssetSystem::AssetNotificationMessage testMessage;
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0);
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "osx_gl");
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "mac");
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1);
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "pc");
|
||||
m_testConnection.SetAssetPlatformsString("pc,es3");
|
||||
m_testConnection.SetAssetPlatformsString("pc,android");
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1);
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "pc");
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0);
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "osx_gl");
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "mac");
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1);
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "es3");
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "android");
|
||||
EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0);
|
||||
// Intended partial string match test - shouldn't send
|
||||
m_testConnection.SendPerPlatform(0, testMessage, "es");
|
||||
|
||||
@@ -106,7 +106,7 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Waiting for remaining notifications: %d \n", outstandingFiles.count());
|
||||
}
|
||||
|
||||
if (outstandingFiles.count() > 0)
|
||||
if (outstandingFiles.count() > 0)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
AZ_TracePrintf(AssetProcessor::DebugChannel, "Timed out waiting for file changes: %d / %d missed\n", outstandingFiles.count(), maxFiles);
|
||||
@@ -226,7 +226,9 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(originalName).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName1).toLower());
|
||||
@@ -249,7 +251,10 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
// the new1 was "removed" and the new2 was "added"
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(newName1).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName2).toLower());
|
||||
|
||||
@@ -270,11 +275,15 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
// the new1 was "removed" and the new2 was "added"
|
||||
UNIT_TEST_EXPECT_TRUE(fileAddCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileRemoveCalled);
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_TRUE(fileModifiedCalled); // modified should be called on the folder that the file lives in (Only on Windows)
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(newName2).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName3).toLower());
|
||||
|
||||
// final test... make sure that renaming a DIRECTORY works too
|
||||
#if !defined(AZ_PLATFORM_LINUX)
|
||||
// final test... make sure that renaming a DIRECTORY works too.
|
||||
// Note that linux does not get any callbacks if just the directory is renamed (from inotify)
|
||||
QDir renamer;
|
||||
fileAddCalled = false;
|
||||
fileRemoveCalled = false;
|
||||
@@ -297,7 +306,7 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileRemoveName).toLower() == QDir::toNativeSeparators(tempDirPath.absoluteFilePath("dir3")).toLower());
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(tempDirPath.absoluteFilePath("dir4")).toLower());
|
||||
|
||||
#endif // AZ_PLATFORM_LINUX
|
||||
|
||||
QObject::disconnect(connectionRemove);
|
||||
QObject::disconnect(connectionAdd);
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace AssetProcessor
|
||||
|
||||
size_t SendPerPlatform(unsigned int serial, const AzFramework::AssetSystem::BaseAssetProcessorMessage& message, const QString& platform) override
|
||||
{
|
||||
if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "es3", Qt::CaseInsensitive) == 0)
|
||||
if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "android", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return Send(serial, message);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace AssetProcessor
|
||||
|
||||
size_t SendRawPerPlatform(unsigned int type, unsigned int serial, const QByteArray& data, const QString& platform) override
|
||||
{
|
||||
if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "es3", Qt::CaseInsensitive) == 0)
|
||||
if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "android", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return SendRaw(type, serial, data);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ void PlatformConfigurationTests::StartTest()
|
||||
|
||||
PlatformConfiguration config;
|
||||
config.EnablePlatform({ "pc",{ "desktop", "host" } }, true);
|
||||
config.EnablePlatform({ "es3",{ "mobile", "android" } }, true);
|
||||
config.EnablePlatform({ "android",{ "mobile", "android" } }, true);
|
||||
config.EnablePlatform({ "fandago",{ "console" } }, false);
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms;
|
||||
config.PopulatePlatformsForScanFolder(platforms);
|
||||
@@ -88,15 +88,15 @@ void PlatformConfigurationTests::StartTest()
|
||||
|
||||
AssetRecognizer rec;
|
||||
AssetPlatformSpec specpc;
|
||||
AssetPlatformSpec speces3;
|
||||
AssetPlatformSpec specandroid;
|
||||
AssetPlatformSpec specfandago;
|
||||
specpc.m_extraRCParams = ""; // blank must work
|
||||
speces3.m_extraRCParams = "testextraparams";
|
||||
specandroid.m_extraRCParams = "testextraparams";
|
||||
|
||||
rec.m_name = "txt files";
|
||||
rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard);
|
||||
rec.m_platformSpecs.insert("pc", specpc);
|
||||
rec.m_platformSpecs.insert("es3", speces3);
|
||||
rec.m_platformSpecs.insert("android", specandroid);
|
||||
rec.m_platformSpecs.insert("fandago", specfandago);
|
||||
config.AddRecognizer(rec);
|
||||
|
||||
@@ -111,7 +111,7 @@ void PlatformConfigurationTests::StartTest()
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms().size() == 2);
|
||||
UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[0].m_identifier == "pc");
|
||||
UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[1].m_identifier == "es3");
|
||||
UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[1].m_identifier == "android");
|
||||
|
||||
UNIT_TEST_EXPECT_TRUE(config.GetScanFolderCount() == 11);
|
||||
UNIT_TEST_EXPECT_FALSE(config.GetScanFolderAt(0).IsRoot());
|
||||
|
||||
@@ -239,14 +239,14 @@ void RCcontrollerUnitTests::RunRCControllerTests()
|
||||
createdJobs.push_back(job);
|
||||
}
|
||||
|
||||
// double them up for "es3" to make sure that platform is respected
|
||||
// double them up for "android" to make sure that platform is respected
|
||||
for (QString name : tempJobNames)
|
||||
{
|
||||
AZ::Uuid uuidOfSource = AZ::Uuid::CreateName(name.toUtf8().constData());
|
||||
RCJob* job0 = new RCJob(rcJobListModel);
|
||||
AssetProcessor::JobDetails jobDetails;
|
||||
jobDetails.m_jobEntry.m_databaseSourceName = jobDetails.m_jobEntry.m_pathRelativeToWatchFolder = name;
|
||||
jobDetails.m_jobEntry.m_platformInfo = { "es3" ,{ "mobile", "renderer" } };
|
||||
jobDetails.m_jobEntry.m_platformInfo = { "android" ,{ "mobile", "renderer" } };
|
||||
jobDetails.m_jobEntry.m_jobKey = "Compile Other Stuff";
|
||||
jobDetails.m_jobEntry.m_sourceFileUUID = uuidOfSource;
|
||||
job0->Init(jobDetails);
|
||||
@@ -490,7 +490,7 @@ void RCcontrollerUnitTests::RunRCControllerTests()
|
||||
UNIT_TEST_EXPECT_FALSE(gotJobsInQueueCall);
|
||||
|
||||
// submit same job but different platform:
|
||||
details.m_jobEntry = JobEntry("d:/test", "test1.txt", "test1.txt", AZ::Uuid("{7954065D-CFD1-4666-9E4C-3F36F417C7AC}"), { "es3" ,{ "mobile", "renderer" } }, "Test Job", 1234, 3, sourceId);
|
||||
details.m_jobEntry = JobEntry("d:/test", "test1.txt", "test1.txt", AZ::Uuid("{7954065D-CFD1-4666-9E4C-3F36F417C7AC}"), { "android" ,{ "mobile", "renderer" } }, "Test Job", 1234, 3, sourceId);
|
||||
m_rcController.JobSubmitted(details);
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents);
|
||||
|
||||
@@ -545,10 +545,13 @@ void RCcontrollerUnitTests::RunRCControllerTests()
|
||||
rcJob.SetCheckExclusiveLock(true);
|
||||
rcJob.Start();
|
||||
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// on windows, opening a file for reading locks it
|
||||
// but on other platforms, this is not the case.
|
||||
// we only expect work to begin when we can gain an exclusive lock on this file.
|
||||
UNIT_TEST_EXPECT_FALSE(UnitTestUtils::BlockUntil(beginWork, 5000));
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Once we release the file, it should process normally
|
||||
lockFileTest.close();
|
||||
#else
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace UnitTestUtils
|
||||
{
|
||||
void SleepForMinimumFileSystemTime()
|
||||
{
|
||||
// note that on OSX, the file system has a resolution of 1 second, and since we're using modtime for a bunch of things,
|
||||
// note that on Mac, the file system has a resolution of 1 second, and since we're using modtime for a bunch of things,
|
||||
// not the actual hash files, we have to wait different amount depending on the OS.
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
int milliseconds = 1;
|
||||
|
||||
@@ -227,8 +227,9 @@ void UtilitiesUnitTests::StartTest()
|
||||
#else
|
||||
int handle = open(lockTestFileName.toUtf8().constData(), O_RDONLY | O_EXLOCK | O_NONBLOCK);
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
UNIT_TEST_EXPECT_FALSE(AssetUtilities::CheckCanLock(lockTestFileName));
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
UNIT_TEST_EXPECT_FALSE(AssetUtilities::CheckCanLock(lockTestFileName));
|
||||
lockTestFile.close();
|
||||
#else
|
||||
if (handle != -1)
|
||||
|
||||
@@ -622,13 +622,14 @@ bool ApplicationManager::Activate()
|
||||
{
|
||||
if (!AssetUtilities::ComputeAssetRoot(m_systemRoot))
|
||||
{
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Unable to compute the asset root for the project, this application cannot launch until this is fixed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
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?");
|
||||
AZ_Error(AssetProcessor::ConsoleChannel, false, "Unable to detect name of current game project. Configure your game project name to launch this application.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1191,6 +1191,7 @@ bool ApplicationManagerBase::Activate()
|
||||
QDir projectCache;
|
||||
if (!AssetUtilities::ComputeProjectCacheRoot(projectCache))
|
||||
{
|
||||
AZ_Error("AssetProcessor", false, "Could not compute project cache root, please configure your project correctly to launch Asset Processor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1200,22 +1201,27 @@ bool ApplicationManagerBase::Activate()
|
||||
// Shutdown if the disk has less than 128MB of free space
|
||||
if (!CheckSufficientDiskSpace(projectCache.absolutePath(), 128 * 1024 * 1024, true))
|
||||
{
|
||||
// CheckSufficientDiskSpace reports an error if disk space is low.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool appInited = InitApplicationServer();
|
||||
if (!appInited)
|
||||
{
|
||||
AZ_Error(
|
||||
"AssetProcessor", false, "InitApplicationServer failed, something internal to Asset Processor has failed, please report this to support if you encounter this error.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitAssetDatabase())
|
||||
{
|
||||
// AssetDatabaseConnection::OpenDatabase reports any errors it encounters.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ApplicationManager::Activate())
|
||||
{
|
||||
// ApplicationManager::Activate() reports any errors it encounters.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1230,6 +1236,7 @@ bool ApplicationManagerBase::Activate()
|
||||
m_isCurrentlyLoadingGems = true;
|
||||
if (!ActivateModules())
|
||||
{
|
||||
// ActivateModules reports any errors it encounters.
|
||||
m_isCurrentlyLoadingGems = false;
|
||||
return false;
|
||||
}
|
||||
@@ -1299,6 +1306,7 @@ bool ApplicationManagerBase::Activate()
|
||||
{
|
||||
if (!m_applicationServer->startListening())
|
||||
{
|
||||
// startListening reports any errors it encounters.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,8 +507,13 @@ namespace AssetUtilities
|
||||
return QString::fromUtf8(s_projectName.c_str(), aznumeric_cast<int>(s_projectName.size()));
|
||||
}
|
||||
|
||||
QString ComputeProjectPath()
|
||||
QString ComputeProjectPath(bool resetCachedProjectPath/*=false*/)
|
||||
{
|
||||
if (resetCachedProjectPath)
|
||||
{
|
||||
// Clear any cached value if reset was requested
|
||||
s_projectPath.clear();
|
||||
}
|
||||
if (s_projectPath.empty())
|
||||
{
|
||||
// Check command-line args first
|
||||
|
||||
@@ -104,7 +104,8 @@ namespace AssetUtilities
|
||||
QString ComputeProjectName(QString projectNameOverride = QString(), bool force = false);
|
||||
|
||||
//! Determine the absolute path of the current project
|
||||
QString ComputeProjectPath();
|
||||
//! The path computed path will be cached on subsequent calls unless resetCachedProjectPath=true
|
||||
QString ComputeProjectPath(bool resetCachedProjectPath = false);
|
||||
|
||||
//! Reads the allowed list directly from the bootstrap file
|
||||
QString ReadAllowedlistFromSettingsRegistry(QString initialFolder = QString());
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
"Platform pc": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform osx_gl": {
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platforms": {
|
||||
"es3": "enabled"
|
||||
"android": "enabled"
|
||||
},
|
||||
"ScanFolder Game": {
|
||||
"watch": "@PROJECTROOT@",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"Platform pc": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform osx_gl": {
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"RC i_caf": {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"Platform pc": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform osx_gl": {
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"ScanFolder Game": {
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
"Platform pc": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform es3": {
|
||||
"Platform android": {
|
||||
"tags": "android,mobile,renderer"
|
||||
},
|
||||
"Platform osx_gl": {
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform server": {
|
||||
"tags": "server"
|
||||
},
|
||||
"Platforms": {
|
||||
"es3": "enabled",
|
||||
"android": "enabled",
|
||||
"server": "enabled"
|
||||
},
|
||||
"Jobs": {
|
||||
@@ -56,7 +56,7 @@
|
||||
"glob": "*.i_caf",
|
||||
"params": "defaultparams",
|
||||
"server": "skip",
|
||||
"es3": "mobile",
|
||||
"android": "mobile",
|
||||
"priority": 5,
|
||||
"checkServer": true
|
||||
},
|
||||
@@ -68,7 +68,7 @@
|
||||
"RC mov": {
|
||||
"glob": "*.mov",
|
||||
"params": "copy",
|
||||
"es3": "platformspecificoverride",
|
||||
"android": "platformspecificoverride",
|
||||
"renderer": "rendererparams"
|
||||
},
|
||||
"RC rend": {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
"Platform pc": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform es3": {
|
||||
"Platform android": {
|
||||
"tags": "android,mobile,renderer"
|
||||
},
|
||||
"Platform ios": {
|
||||
"tags": "mobile,renderer"
|
||||
},
|
||||
"Platform osx_gl": {
|
||||
"Platform mac": {
|
||||
"tags": "tools,renderer"
|
||||
},
|
||||
"Platform server": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"tags": "console,renderer"
|
||||
},
|
||||
"Platforms": {
|
||||
"es3": "enabled",
|
||||
"android": "enabled",
|
||||
"ios": "enabled",
|
||||
"server": "enabled"
|
||||
},
|
||||
@@ -54,14 +54,14 @@
|
||||
"display": "folder1output",
|
||||
"recursive": 1,
|
||||
"order": 50000,
|
||||
"include": "es3"
|
||||
"include": "android"
|
||||
},
|
||||
"ScanFolder Folder2": {
|
||||
"watch": "@ENGINEROOT@/Folder2",
|
||||
"display": "folder2output",
|
||||
"recursive": 1,
|
||||
"order": 60000,
|
||||
"exclude": "es3"
|
||||
"exclude": "android"
|
||||
},
|
||||
"ScanFolder Folder3": {
|
||||
"watch": "@ENGINEROOT@/Folder3",
|
||||
@@ -80,7 +80,7 @@
|
||||
"glob": "*.i_caf",
|
||||
"params": "defaultparams",
|
||||
"server": "skip",
|
||||
"es3": "mobile",
|
||||
"android": "mobile",
|
||||
"test": "copy",
|
||||
"priority": 5
|
||||
},
|
||||
@@ -92,7 +92,7 @@
|
||||
"RC mov": {
|
||||
"glob": "*.mov",
|
||||
"params": "copy",
|
||||
"es3": "platformspecificoverride",
|
||||
"android": "platformspecificoverride",
|
||||
"renderer": "rendererparams"
|
||||
},
|
||||
"RC rend": {
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
include(${pal_dir}/platform_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
include(${pal_dir}/platform_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
|
||||
if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED AND NOT LY_MONOLITHIC_GAME)
|
||||
|
||||
ly_add_target(
|
||||
NAME AzTestRunner ${PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE}
|
||||
NAMESPACE AZ
|
||||
@@ -32,19 +32,23 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
AZ::AzTest
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
ly_add_target(
|
||||
NAME AzTestRunner.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE AZ
|
||||
FILES_CMAKE
|
||||
aztestrunner_test_files.cmake
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzTest
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME AzTestRunner.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE AZ
|
||||
FILES_CMAKE
|
||||
aztestrunner_test_files.cmake
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzTest
|
||||
)
|
||||
ly_add_googletest(
|
||||
NAME AZ::AzTestRunner.Tests
|
||||
)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::AzTestRunner.Tests
|
||||
)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_AZTESTRUNNER_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE MODULE)
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_AZTESTRUNNER_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE EXECUTABLE)
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_AZTESTRUNNER_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE EXECUTABLE)
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_AZTESTRUNNER_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE EXECUTABLE)
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_AZTESTRUNNER_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_AZTESTRUNNER_LAUNCHER_TYPE EXECUTABLE)
|
||||
|
||||
|
||||
@@ -552,7 +552,7 @@ GridHubComponent::OnMemberJoined([[maybe_unused]] GridMate::GridSession* session
|
||||
switch( member->GetPlatformId() )
|
||||
{
|
||||
case AZ::PlatformID::PLATFORM_WINDOWS_64:
|
||||
case AZ::PlatformID::PLATFORM_APPLE_OSX:
|
||||
case AZ::PlatformID::PLATFORM_APPLE_MAC:
|
||||
{
|
||||
GridMate::string localMachineName = GridMate::Utils::GetMachineAddress();
|
||||
if( member->GetMachineName() == localMachineName )
|
||||
|
||||
@@ -20,13 +20,11 @@ if (NOT python_package_name)
|
||||
message(WARNING "Python was not found in the package assocation list. Did someone call ly_associate_package(xxxxxxx Python) ?")
|
||||
endif()
|
||||
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAME ProjectManager.Static STATIC
|
||||
NAMESPACE AZ
|
||||
AUTOMOC
|
||||
AUTOUIC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
@@ -37,11 +35,8 @@ ly_add_target(
|
||||
PRIVATE
|
||||
PY_PACKAGE="${python_package_name}"
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
PRIVATE
|
||||
Source
|
||||
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
@@ -51,6 +46,60 @@ ly_add_target(
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzToolsFramework
|
||||
AZ::AzQtComponents
|
||||
)
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_app_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzQtComponents
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_add_target(
|
||||
NAME ProjectManager.Tests EXECUTABLE
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_tests_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Platform/${PAL_PLATFORM_NAME}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzTest
|
||||
AZ::AzFramework
|
||||
AZ::AzFrameworkTestShared
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::ProjectManager.Tests
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::ProjectManager.Tests> --unittest
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Linux.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Linux.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Mac.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Mac.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Windows.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Windows.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="64" viewBox="0 0 24 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0,40)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13 3H11V11H3V13H11V21H13V13H21V11H13V3Z" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 246 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="64" viewBox="0 0 24 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0,40)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13 3H11V11H3V13H11V21H13V13H21V11H13V3Z" fill="#1e70eb"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 248 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.02554 10L9 15.0362V18L0 9L9 0V2.98885L4 8H18V10H4.02554Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.02554 10L9 15.0362V18L0 9L9 0V2.98885L4 8H18V10H4.02554Z" fill="#1e70eb"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 230 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 17L15 14H9L12 17Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 190 B |
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f82f22df64b93d4bec91e56b60efa3d5ce2915ce388a2dc627f1ab720678e3d5
|
||||
size 334987
|
||||
oid sha256:4a5881b8d6cfbc4ceefb14ab96844484fe19407ee030824768f9fcce2f729d35
|
||||
size 2949
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8358f4dad9878c662b9819b2b346622af691eb45f8eddc28fff79a50650ae6cf
|
||||
size 2503
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="64" viewBox="0 0 24 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0,40)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.98407 4H2V6V7V19.8145H2.07539L6.02059 7.99123H19V6H11.328L9.98407 4ZM19 19.7473L22.0766 10H7.05436L3.68763 19.8329H18.973L18.9788 19.8145H19V19.7473Z" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 358 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="64" viewBox="0 0 24 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0,40)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.98407 4H2V6V7V19.8145H2.07539L6.02059 7.99123H19V6H11.328L9.98407 4ZM19 19.7473L22.0766 10H7.05436L3.68763 19.8329H18.973L18.9788 19.8145H19V19.7473Z" fill="#1e70eb"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 360 B |
@@ -4,6 +4,13 @@
|
||||
</qresource>
|
||||
<qresource prefix="/">
|
||||
<file>Add.svg</file>
|
||||
<file>AddOffset.svg</file>
|
||||
<file>AddOffset_Hover.svg</file>
|
||||
<file>ArrowBack.svg</file>
|
||||
<file>ArrowBack_Hover.svg</file>
|
||||
<file>build.svg</file>
|
||||
<file>FolderOffset.svg</file>
|
||||
<file>FolderOffset_Hover.svg</file>
|
||||
<file>Select_Folder.svg</file>
|
||||
<file>o3de_editor.ico</file>
|
||||
<file>Windows.svg</file>
|
||||
@@ -12,10 +19,17 @@
|
||||
<file>Linux.svg</file>
|
||||
<file>macOS.svg</file>
|
||||
<file>DefaultProjectImage.png</file>
|
||||
<file>DefaultTemplate.png</file>
|
||||
<file>ArrowDownLine.svg</file>
|
||||
<file>ArrowUpLine.svg</file>
|
||||
<file>o3de.svg</file>
|
||||
<file>menu.svg</file>
|
||||
<file>menu_hover.svg</file>
|
||||
<file>Backgrounds/FirstTimeBackgroundImage.jpg</file>
|
||||
<file>ArrowDownLine.svg</file>
|
||||
<file>ArrowUpLine.svg</file>
|
||||
<file>CarrotArrowDown.svg</file>
|
||||
<file>Summary.svg</file>
|
||||
<file>WindowClose.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,29 +1,74 @@
|
||||
/************** General (MainWindow) **************/
|
||||
QMainWindow {
|
||||
background-color: #333333;
|
||||
background:#131313 url(:/o3de.svg) no-repeat top left;
|
||||
/* position the logo using padding and background-origin, Qt does not support background-position pixels */
|
||||
background-origin:content;
|
||||
padding:25px 16px;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#ScreensCtrl {
|
||||
min-width:1200px;
|
||||
min-height:800px;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
outline: none;
|
||||
border:1px solid #1e70eb;
|
||||
}
|
||||
|
||||
QTabBar {
|
||||
background-color: transparent;
|
||||
}
|
||||
QTabWidget::tab-bar
|
||||
{
|
||||
left: 78px; /* make room for the logo */
|
||||
}
|
||||
QTabBar::tab {
|
||||
height:82px;
|
||||
background-color: transparent;
|
||||
font-size:24px;
|
||||
min-width:100px;
|
||||
margin-right:40px;
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
QTabBar::tab:text
|
||||
{
|
||||
text-align:left;
|
||||
}
|
||||
QTabWidget::pane {
|
||||
background-color: #333333;
|
||||
border:0 none;
|
||||
}
|
||||
QTabBar::tab:selected
|
||||
{
|
||||
border-bottom: 3px solid #1e70eb;
|
||||
color: #1e70eb;
|
||||
}
|
||||
QTabBar::tab:hover
|
||||
{
|
||||
color: #1e70eb;
|
||||
}
|
||||
QTabBar::tab:pressed
|
||||
{
|
||||
color: #0e60eb;
|
||||
}
|
||||
|
||||
/************** General (Forms) **************/
|
||||
|
||||
#formLineEditWidget,
|
||||
#formBrowseEditWidget {
|
||||
max-width: 780px;
|
||||
max-width: 890px;
|
||||
}
|
||||
|
||||
#formFrame {
|
||||
max-width: 720px;
|
||||
max-width: 840px;
|
||||
background-color: #444444;
|
||||
border:1px solid #dddddd;
|
||||
border-radius: 4px;
|
||||
padding: 0px 10px 2px 6px;
|
||||
margin-top:10px;
|
||||
margin-left:30px;
|
||||
margin-left:50px;
|
||||
}
|
||||
|
||||
#formFrame[Focus="true"] {
|
||||
@@ -59,15 +104,382 @@ QPushButton:focus {
|
||||
padding-top: -4px;
|
||||
}
|
||||
|
||||
|
||||
#formErrorLabel {
|
||||
color: #ec3030;
|
||||
font-size: 14px;
|
||||
margin-left: 40px;
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
#formTitleLabel {
|
||||
font-size:21px;
|
||||
color:#ffffff;
|
||||
margin: 10px 0 10px 30px;
|
||||
margin: 24px 0 10px 50px;
|
||||
}
|
||||
|
||||
/************** General (Modal windows) **************/
|
||||
|
||||
#header {
|
||||
background-color:#111111;
|
||||
min-height:80px;
|
||||
max-height:80px;
|
||||
}
|
||||
|
||||
#header QPushButton {
|
||||
/* settings min/max lets us use a fixed size */
|
||||
min-width: 24px;
|
||||
max-width: 24px;
|
||||
min-height: 24px;
|
||||
max-height: 24px;
|
||||
margin: 20px 10px 0px 10px;
|
||||
background:transparent url(:/ArrowBack.svg) no-repeat center;
|
||||
background-origin:content;
|
||||
qproperty-flat: true;
|
||||
qproperty-iconSize: 50px;
|
||||
}
|
||||
|
||||
#header QPushButton:focus {
|
||||
border:none;
|
||||
}
|
||||
#header QPushButton:hover,
|
||||
#header QPushButton:pressed {
|
||||
background:transparent url(:/ArrowBack_Hover.svg) no-repeat center;
|
||||
}
|
||||
|
||||
#headerTitle {
|
||||
font-size:14px;
|
||||
text-align:left;
|
||||
margin:0;
|
||||
padding-top:10px;
|
||||
padding-bottom:-5px;
|
||||
min-height:15px;
|
||||
max-height:15px;
|
||||
}
|
||||
#headerSubTitle {
|
||||
font-size:24px;
|
||||
text-align:left;
|
||||
margin:0;
|
||||
min-height:42px;
|
||||
max-height:42px;
|
||||
}
|
||||
|
||||
#body {
|
||||
background-color:#333333;
|
||||
}
|
||||
#footer {
|
||||
/* settings min/max lets us use a fixed size */
|
||||
min-width: 50px;
|
||||
min-height:54px;
|
||||
max-height:54px;
|
||||
}
|
||||
|
||||
#footer > QPushButton {
|
||||
qproperty-flat: true;
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #0095f2, stop: 1.0 #1e70eb);
|
||||
border-radius: 3px;
|
||||
min-height: 28px;
|
||||
max-height: 28px;
|
||||
min-width: 150px;
|
||||
margin-right:30px;
|
||||
}
|
||||
#footer > QPushButton:hover {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #10A5f2, stop: 1.0 #2e80eb);
|
||||
}
|
||||
#footer > QPushButton:pressed {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #0085e2, stop: 1.0 #0e60db);
|
||||
}
|
||||
|
||||
#footer > QPushButton[secondary="true"] {
|
||||
margin-right: 10px;
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #888888, stop: 1.0 #555555);
|
||||
}
|
||||
#footer > QPushButton[secondary="true"]:hover {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #999999, stop: 1.0 #666666);
|
||||
}
|
||||
#footer > QPushButton[secondary="true"]:pressed {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #555555, stop: 1.0 #777777);
|
||||
}
|
||||
|
||||
/************** Project Settings **************/
|
||||
#projectSettings {
|
||||
margin-top:42px;
|
||||
}
|
||||
|
||||
#projectTemplate {
|
||||
margin: 55px 0 0 50px;
|
||||
}
|
||||
#projectTemplateLabel {
|
||||
font-size:16px;
|
||||
font-weight:100;
|
||||
}
|
||||
|
||||
#projectTemplateDetailsLabel {
|
||||
font-size:14px;
|
||||
min-height:40px;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#projectTemplateDetails {
|
||||
background-color:#444444;
|
||||
max-width:20%;
|
||||
min-width:240px;
|
||||
margin-left:30px;
|
||||
}
|
||||
|
||||
#projectTemplateDetails #displayName,
|
||||
#projectTemplateDetails #includedGemsTitle {
|
||||
font-size:18px;
|
||||
}
|
||||
|
||||
#projectTemplateDetails #moreGems {
|
||||
font-size:14px;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
#projectTemplateDetails #includedGemsTitle {
|
||||
margin-top:5px;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
#projectTemplateDetails #summary {
|
||||
padding-bottom:0px;
|
||||
border-bottom:2px solid #555555;
|
||||
min-height:80px;
|
||||
qproperty-alignment: AlignTop;
|
||||
}
|
||||
|
||||
#projectTemplateDetails #browseCatalog {
|
||||
margin:5px 0px 15px 0px;
|
||||
}
|
||||
|
||||
#projectTemplate QPushButton {
|
||||
qproperty-flat: true;
|
||||
min-width: 96px;
|
||||
max-width: 96px;
|
||||
min-height: 160px;
|
||||
max-height: 160px;
|
||||
}
|
||||
#projectTemplate #templateLabel {
|
||||
qproperty-alignment: AlignCenter;
|
||||
}
|
||||
#projectTemplate QPushButton #templateImage {
|
||||
border:3px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#projectTemplate QPushButton[Checked="true"] #templateImage {
|
||||
border:3px solid #1e70eb;
|
||||
}
|
||||
#projectTemplate QPushButton[Checked="true"] #templateLabel {
|
||||
font-weight:bold;
|
||||
}
|
||||
#projectTemplate QPushButton:hover {
|
||||
background-color: #444444;
|
||||
}
|
||||
#projectTemplate QPushButton:focus {
|
||||
outline: none;
|
||||
border:none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#projectSettingsTab::tab-bar {
|
||||
left: 60px;
|
||||
}
|
||||
|
||||
#projectSettingsTabBar::tab {
|
||||
height:50px;
|
||||
}
|
||||
|
||||
#projectSettingsTab::tab-bar > QPushButton {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #888888, stop: 1.0 #555555);
|
||||
qproperty-flat: true;
|
||||
margin-right:30px;
|
||||
margin-bottom:12px;
|
||||
margin-top:0px;
|
||||
min-width:170px;
|
||||
max-width:170px;
|
||||
min-height:26px;
|
||||
max-height:26px;
|
||||
border-radius: 3px;
|
||||
text-align:center;
|
||||
font-size:13px;
|
||||
}
|
||||
#projectSettingsTab::tab-bar > QPushButton:hover {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #999999, stop: 1.0 #666666);
|
||||
}
|
||||
#projectSettingsTab::tab-bar > QPushButton:pressed {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 #555555, stop: 1.0 #777777);
|
||||
}
|
||||
|
||||
#projectSettingsTopFrame {
|
||||
background-color:#1E252F;
|
||||
}
|
||||
|
||||
/************** Projects **************/
|
||||
#firstTimeContent > #titleLabel {
|
||||
font-size:60px;
|
||||
margin:73px 0px 0px 0px;
|
||||
qproperty-indent: 0;
|
||||
}
|
||||
|
||||
#firstTimeContent > #introLabel {
|
||||
font-size:14px;
|
||||
margin:10px 0 60px 0;
|
||||
qproperty-indent: 0;
|
||||
}
|
||||
|
||||
#firstTimeContent > QPushButton {
|
||||
min-width: 210px;
|
||||
max-width: 210px;
|
||||
min-height: 276px;
|
||||
max-height: 276px;
|
||||
qproperty-flat: true;
|
||||
background-origin:content;
|
||||
font-size:14px;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
#firstTimeContent > QPushButton:hover {
|
||||
border: 1px solid #1e70eb;
|
||||
color: #1e70eb;
|
||||
}
|
||||
|
||||
#firstTimeContent > QPushButton:pressed {
|
||||
border: 1px solid #0e60eb;
|
||||
color: #0e60eb;
|
||||
}
|
||||
|
||||
#createProjectButton {
|
||||
background:rgba(0,0,0,180) url(:/AddOffset.svg) no-repeat center center;
|
||||
}
|
||||
#createProjectButton:hover,
|
||||
#createProjectButton:pressed {
|
||||
background:rgba(0,0,0,180) url(:/AddOffset_Hover.svg) no-repeat center center;
|
||||
}
|
||||
|
||||
#addProjectButton {
|
||||
background:rgba(0,0,0,180) url(:/FolderOffset.svg) no-repeat center center;
|
||||
}
|
||||
#addProjectButton:hover,
|
||||
#addProjectButton:pressed {
|
||||
background:rgba(0,0,0,180) url(:/FolderOffset_Hover.svg) no-repeat center center;
|
||||
}
|
||||
|
||||
#projectsContent > QFrame {
|
||||
margin-top:60px;
|
||||
}
|
||||
|
||||
#projectsContent > QFrame > #titleLabel {
|
||||
font-size:24px;
|
||||
qproperty-indent: 0;
|
||||
}
|
||||
|
||||
#projectsContent > QScrollArea {
|
||||
margin-top:40px;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
#projectButton > #labelButton {
|
||||
border:1px solid white;
|
||||
}
|
||||
|
||||
#projectButton > #labelButton:hover,
|
||||
#projectButton > #labelButton:pressed {
|
||||
border:1px solid #1e70eb;
|
||||
}
|
||||
|
||||
#projectButton > QFrame {
|
||||
margin-top:6px;
|
||||
}
|
||||
|
||||
#projectButton > QFrame > QLabel {
|
||||
font-weight:bold;
|
||||
font-size:14px;
|
||||
qproperty-indent: 0;
|
||||
}
|
||||
|
||||
#projectMenuButton {
|
||||
qproperty-flat: true;
|
||||
background:transparent url(:/menu.svg) no-repeat center center;
|
||||
max-width:30px;
|
||||
min-width:30px;
|
||||
max-height:14px;
|
||||
min-height:14px;
|
||||
}
|
||||
|
||||
#projectsContent > QFrame > #newProjectButton {
|
||||
min-width:150px;
|
||||
max-width:150px;
|
||||
min-height:26px;
|
||||
max-height:26px;
|
||||
}
|
||||
|
||||
#labelButtonOverlay {
|
||||
background-color: rgba(50,50,50,200);
|
||||
min-width:210px;
|
||||
max-width:210px;;
|
||||
min-height:278px;
|
||||
max-height:278px;
|
||||
}
|
||||
|
||||
QProgressBar {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
padding: 0px;
|
||||
min-height: 14px;
|
||||
font-size: 2px;
|
||||
}
|
||||
|
||||
QProgressBar::chunk {
|
||||
background-color: #1E70EB;
|
||||
}
|
||||
|
||||
/************** Gem Catalog **************/
|
||||
|
||||
#GemCatalogTitle {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#GemCatalogCart {
|
||||
background-color: #555555;
|
||||
}
|
||||
|
||||
#GemCatalogCartCountLabel {
|
||||
font-size: 12px;
|
||||
background-color: #4285F4;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#GemCatalogCartOverlaySectionLabel {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/************** Gem Catalog (Inspector) **************/
|
||||
|
||||
#GemCatalogInspector {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
/************** Gem Catalog (Filter/left pane) **************/
|
||||
|
||||
#GemCatalogFilterWidget {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
#GemCatalogHeaderWidget {
|
||||
background-color: #1E252F;
|
||||
}
|
||||
|
||||
#GemCatalogFilterCategoryTitle {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "o3de_editor.ico"
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.5714 6.7619H16.7619C16.7619 4.13333 14.6286 2 12 2C9.37145 2 7.23811 4.13333 7.23811 6.7619H3.42859V22H20.5714V6.7619ZM12 3.90476C13.581 3.90476 14.8572 5.18095 14.8572 6.7619H9.14287C9.14287 5.18095 10.4191 3.90476 12 3.90476ZM13.7997 11.7424L12.0288 9.24095H11.9712L10.2003 11.7424H13.7997ZM5.00002 12.4335L10.9158 19.4063L9.03253 12.4335H5.00002ZM10.14 12.4335L11.9356 19.5147C11.9548 19.5189 11.974 19.521 11.9959 19.521C12.0178 19.521 12.0398 19.5189 12.0617 19.5147L13.86 12.4335H10.14ZM14.9675 12.4335H18.8547H19L13.0842 19.398L14.9675 12.4335ZM8.26457 9.24095H11.075L9.52787 11.4253L8.26457 9.24095ZM8.83789 11.7424L7.5193 9.46191L5.01921 11.7424H5.14804H8.83789ZM18.9808 11.7424H18.8547H15.1512L16.4286 9.41397L18.9808 11.7424ZM15.6558 9.24095H12.9252L14.4647 11.4146L15.6558 9.24095Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 966 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5507 19.5506L19.5213 2.58008L21.289 4.34785L4.31846 21.3184L2.5507 19.5506Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.28706 2.65015L21.2576 19.6207L19.4899 21.3885L2.51929 4.41791L4.28706 2.65015Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,11 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="3" y="16" width="5" height="5" fill="white"/>
|
||||
<rect x="9.5" y="16" width="5" height="5" fill="white"/>
|
||||
<rect x="16" y="16" width="5" height="5" fill="white"/>
|
||||
<rect x="3" y="9.5" width="5" height="5" fill="white"/>
|
||||
<rect x="9.5" y="9.5" width="5" height="5" fill="white"/>
|
||||
<rect x="19.415" y="8.58496" width="5" height="5" transform="rotate(60 19.415 8.58496)" fill="white"/>
|
||||
<rect x="3" y="3" width="5" height="5" fill="white"/>
|
||||
<rect x="8.58496" y="6.41504" width="5" height="5" transform="rotate(-60 8.58496 6.41504)" fill="white"/>
|
||||
<rect x="19.5" y="0.964844" width="5" height="5" transform="rotate(45 19.5 0.964844)" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 749 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="1.3335" y="2.66675" width="13.3333" height="1.33333" fill="white"/>
|
||||
<rect x="1.3335" y="7.33325" width="13.3333" height="1.33333" fill="white"/>
|
||||
<rect x="1.3335" y="12" width="13.3333" height="1.33333" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 329 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="1.3335" y="2.66675" width="13.3333" height="1.33333" fill="#1e70eb"/>
|
||||
<rect x="1.3335" y="7.33325" width="13.3333" height="1.33333" fill="#1e70eb"/>
|
||||
<rect x="1.3335" y="12" width="13.3333" height="1.33333" fill="#1e70eb"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 335 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="38" height="32" viewBox="0 0 38 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.0335 27.6364C30.2006 30.4503 26.4498 32 22.4729 32H22.4719L22.4007 31.9999C18.3948 31.9813 14.6226 30.396 11.7792 27.5358C7.98134 23.7148 6.67845 18.3374 7.86239 13.445H13.291C12.8522 14.5772 12.6238 15.7937 12.6313 17.0465C12.6466 19.6692 13.682 22.1248 15.5465 23.9605C17.4134 25.7987 19.8692 26.811 22.462 26.811L22.4897 26.8108C25.0998 26.8025 27.555 25.7736 29.4067 23.9136C31.2794 22.0326 32.3023 19.5505 32.2872 16.9246C32.2718 14.2963 31.2187 11.8234 29.3215 9.96131C27.4791 8.153 25.0581 7.16098 22.4942 7.16098C22.4558 7.16098 22.4177 7.16127 22.379 7.16171C20.9514 7.17701 19.5695 7.49947 18.3061 8.09355V2.5551C19.6438 2.16896 21.0401 1.96569 22.4658 1.96569L22.5394 1.96598C26.5556 1.98507 30.3331 3.58486 33.1758 6.47058C35.976 9.31332 37.5035 13.0777 37.4771 17.0703C37.4508 21.0641 35.8727 24.8164 33.0335 27.6364ZM1.73437 2.98423H4.71974V0H1.73437V2.98423ZM0 11.9513H4.68388V7.26925H0V11.9513ZM7.65831 10.0451H14.8796V2.82656H7.65831V10.0451Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c042fce57915fc749abc7b37de765fd697c3c4d7de045a3d44805aa0ce29901a
|
||||
size 107016
|
||||
oid sha256:d717f77fe01f45df934a61bbc215e5322447d21e16f3cebcf2a02f148178f266
|
||||
size 106449
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Application.h>
|
||||
#include <ProjectUtils.h>
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzFramework/Logging/LoggingComponent.h>
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
Application::~Application()
|
||||
{
|
||||
TearDown();
|
||||
}
|
||||
|
||||
bool Application::Init(bool interactive)
|
||||
{
|
||||
constexpr const char* applicationName { "O3DE" };
|
||||
|
||||
QApplication::setOrganizationName(applicationName);
|
||||
QApplication::setOrganizationDomain("o3de.org");
|
||||
|
||||
QCoreApplication::setApplicationName(applicationName);
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
|
||||
// Use the LogComponent for non-dev logging log
|
||||
RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor());
|
||||
|
||||
// set the log alias to .o3de/Logs instead of the default user/logs
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
|
||||
// DevWriteStorage is where the event log is written during development
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage, path.LexicallyNormal().Native());
|
||||
|
||||
// Save event logs to .o3de/Logs/eventlogger/EventLogO3DE.azsl
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::BuildTargetNameKey, applicationName);
|
||||
|
||||
Start(AzFramework::Application::Descriptor());
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
// Create the actual Qt Application - this needs to happen before using QMessageBox
|
||||
m_app.reset(new QApplication(*GetArgC(), *GetArgV()));
|
||||
|
||||
if(!InitLog(applicationName))
|
||||
{
|
||||
AZ_Warning("ProjectManager", false, "Failed to init logging");
|
||||
}
|
||||
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
|
||||
if (!m_pythonBindings || !m_pythonBindings->PythonStarted())
|
||||
{
|
||||
if (interactive)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QObject::tr("Failed to start Python"),
|
||||
QObject::tr("This tool requires an O3DE engine with a Python runtime, "
|
||||
"but either Python is missing or mis-configured. Please rename "
|
||||
"your python/runtime folder to python/runtime_bak, then run "
|
||||
"python/get_python.bat to restore the Python runtime folder."));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::CommandLine* commandLine = GetCommandLine();
|
||||
AZ_Assert(commandLine, "Failed to get command line");
|
||||
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects;
|
||||
if (size_t screenSwitchCount = commandLine->GetNumSwitchValues("screen"); screenSwitchCount > 0)
|
||||
{
|
||||
QString screenOption = commandLine->GetSwitchValue("screen", screenSwitchCount - 1).c_str();
|
||||
ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption);
|
||||
if (screen != ProjectManagerScreen::Invalid)
|
||||
{
|
||||
startScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath;
|
||||
if (size_t projectSwitchCount = commandLine->GetNumSwitchValues("project-path"); projectSwitchCount > 0)
|
||||
{
|
||||
projectPath = commandLine->GetSwitchValue("project-path", projectSwitchCount - 1).c_str();
|
||||
}
|
||||
|
||||
m_mainWindow.reset(new ProjectManagerWindow(nullptr, projectPath, startScreen));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::InitLog(const char* logName)
|
||||
{
|
||||
if (!m_entity)
|
||||
{
|
||||
// override the log alias to the O3de Logs directory instead of the default project user/Logs folder
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(fileIO, "Failed to get FileIOBase instance");
|
||||
|
||||
fileIO->SetAlias("@log@", path.LexicallyNormal().Native().c_str());
|
||||
|
||||
// this entity exists because we need a home for LogComponent
|
||||
// and cannot use the system entity because we need to be able to call SetLogFileBaseName
|
||||
// so the log will be named O3DE.log
|
||||
m_entity = aznew AZ::Entity("Application Entity");
|
||||
if (m_entity)
|
||||
{
|
||||
AzFramework::LogComponent* logger = aznew AzFramework::LogComponent();
|
||||
AZ_Assert(logger, "Failed to create LogComponent");
|
||||
logger->SetLogFileBaseName(logName);
|
||||
m_entity->AddComponent(logger);
|
||||
m_entity->Init();
|
||||
m_entity->Activate();
|
||||
}
|
||||
}
|
||||
|
||||
return m_entity != nullptr;
|
||||
}
|
||||
|
||||
void Application::TearDown()
|
||||
{
|
||||
if (m_entity)
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
delete m_entity;
|
||||
m_entity = nullptr;
|
||||
}
|
||||
|
||||
m_pythonBindings.reset();
|
||||
m_mainWindow.reset();
|
||||
m_app.reset();
|
||||
}
|
||||
|
||||
bool Application::Run()
|
||||
{
|
||||
// Set up the Style Manager
|
||||
AzQtComponents::StyleManager styleManager(qApp);
|
||||
styleManager.initialize(qApp, GetEngineRoot());
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
AZ::IO::FixedMaxPath engineRoot(GetEngineRoot());
|
||||
QDir rootDir(engineRoot.c_str());
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRoot);
|
||||
|
||||
// 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
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
|
||||
wrapper->setGuest(m_mainWindow.data());
|
||||
wrapper->show();
|
||||
m_mainWindow->show();
|
||||
|
||||
qApp->setQuitOnLastWindowClosed(true);
|
||||
|
||||
// Run the application
|
||||
return qApp->exec();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <QCoreApplication>
|
||||
#include <PythonBindings.h>
|
||||
#include <ProjectManagerWindow.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
}
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class Application
|
||||
: public AzFramework::Application
|
||||
{
|
||||
public:
|
||||
using AzFramework::Application::Application;
|
||||
virtual ~Application();
|
||||
|
||||
bool Init(bool interactive = true);
|
||||
bool Run();
|
||||
void TearDown();
|
||||
|
||||
private:
|
||||
bool InitLog(const char* logName);
|
||||
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
QSharedPointer<QCoreApplication> m_app;
|
||||
QSharedPointer<ProjectManagerWindow> m_mainWindow;
|
||||
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -14,11 +14,17 @@
|
||||
#include <ScreensCtrl.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <ScreenHeaderWidget.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QStackedWidget>
|
||||
#include <QLabel>
|
||||
#include <QSizePolicy>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -26,29 +32,44 @@ namespace O3DE::ProjectManager
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
m_header = new ScreenHeader(this);
|
||||
m_header->setTitle(tr("Create a New Project"));
|
||||
m_header->setSubTitle(tr("Enter Project Details"));
|
||||
connect(m_header->backButton(), &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton);
|
||||
vLayout->addWidget(m_header);
|
||||
|
||||
m_stack = new QStackedWidget(this);
|
||||
m_stack->setObjectName("body");
|
||||
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding));
|
||||
|
||||
m_newProjectSettingsScreen = new NewProjectSettingsScreen(this);
|
||||
m_stack->addWidget(m_newProjectSettingsScreen);
|
||||
|
||||
m_gemCatalogScreen = new GemCatalogScreen(this);
|
||||
m_stack->addWidget(m_gemCatalogScreen);
|
||||
vLayout->addWidget(m_stack);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox();
|
||||
buttons->setObjectName("footer");
|
||||
vLayout->addWidget(buttons);
|
||||
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
connect(m_newProjectSettingsScreen, &ScreenWidget::ChangeScreenRequest, this, &CreateProjectCtrl::OnChangeScreenRequest);
|
||||
|
||||
m_secondaryButton = buttons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
|
||||
m_secondaryButton->setProperty("secondary", true);
|
||||
m_secondaryButton->setVisible(false);
|
||||
connect(m_secondaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleSecondaryButton);
|
||||
|
||||
Update();
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
m_primaryButton = buttons->addButton(tr("Create Project"), QDialogButtonBox::ApplyRole);
|
||||
connect(m_primaryButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandlePrimaryButton);
|
||||
|
||||
setLayout(vLayout);
|
||||
|
||||
m_screensCtrl = new ScreensCtrl();
|
||||
vLayout->addWidget(m_screensCtrl);
|
||||
|
||||
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
|
||||
vLayout->addWidget(backNextButtons);
|
||||
|
||||
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
|
||||
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
|
||||
|
||||
connect(m_backButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleNextButton);
|
||||
|
||||
m_screensOrder =
|
||||
{
|
||||
ProjectManagerScreen::NewProjectSettings,
|
||||
ProjectManagerScreen::GemCatalog
|
||||
};
|
||||
m_screensCtrl->BuildScreens(m_screensOrder);
|
||||
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::NewProjectSettings, false);
|
||||
|
||||
UpdateNextButtonText();
|
||||
}
|
||||
|
||||
ProjectManagerScreen CreateProjectCtrl::GetScreenEnum()
|
||||
@@ -56,75 +77,148 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::CreateProject;
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::NotifyCurrentScreen()
|
||||
{
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
if (currentScreen)
|
||||
{
|
||||
currentScreen->NotifyCurrentScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::HandleBackButton()
|
||||
{
|
||||
if (!m_screensCtrl->GotoPreviousScreen())
|
||||
if (m_stack->currentIndex() > 0)
|
||||
{
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
PreviousScreen();
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
emit GotoPreviousScreenRequest();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
void CreateProjectCtrl::HandleSecondaryButton()
|
||||
{
|
||||
if (m_stack->currentIndex() > 0)
|
||||
{
|
||||
// return to Project Settings page
|
||||
PreviousScreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateNextButtonText();
|
||||
// Configure Gems
|
||||
NextScreen();
|
||||
}
|
||||
}
|
||||
void CreateProjectCtrl::HandleNextButton()
|
||||
|
||||
void CreateProjectCtrl::Update()
|
||||
{
|
||||
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
|
||||
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
|
||||
auto screenOrderIter = m_screensOrder.begin();
|
||||
for (; screenOrderIter != m_screensOrder.end(); ++screenOrderIter)
|
||||
if (m_stack->currentWidget() == m_gemCatalogScreen)
|
||||
{
|
||||
if (*screenOrderIter == screenEnum)
|
||||
{
|
||||
++screenOrderIter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (screenEnum == ProjectManagerScreen::NewProjectSettings)
|
||||
{
|
||||
auto newProjectScreen = reinterpret_cast<NewProjectSettingsScreen*>(currentScreen);
|
||||
if (newProjectScreen)
|
||||
{
|
||||
if (!newProjectScreen->Validate())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid project settings"), tr("Invalid project settings"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_projectInfo = newProjectScreen->GetProjectInfo();
|
||||
m_projectTemplatePath = newProjectScreen->GetProjectTemplatePath();
|
||||
}
|
||||
}
|
||||
|
||||
if (screenOrderIter != m_screensOrder.end())
|
||||
{
|
||||
m_screensCtrl->ChangeToScreen(*screenOrderIter);
|
||||
UpdateNextButtonText();
|
||||
m_header->setSubTitle(tr("Configure project with Gems"));
|
||||
m_secondaryButton->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = PythonBindingsInterface::Get()->CreateProject(m_projectTemplatePath, m_projectInfo);
|
||||
m_header->setSubTitle(tr("Enter Project Details"));
|
||||
m_secondaryButton->setVisible(true);
|
||||
m_secondaryButton->setText(tr("Configure Gems"));
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::OnChangeScreenRequest(ProjectManagerScreen screen)
|
||||
{
|
||||
if (screen == ProjectManagerScreen::GemCatalog)
|
||||
{
|
||||
HandleSecondaryButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit ChangeScreenRequest(screen);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::NextScreen()
|
||||
{
|
||||
if (m_stack->currentIndex() < m_stack->count())
|
||||
{
|
||||
if(CurrentScreenIsValid())
|
||||
{
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
|
||||
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
|
||||
|
||||
Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid project settings"), tr("Please correct the indicated project settings and try again."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::PreviousScreen()
|
||||
{
|
||||
// we don't require the current screen to be valid when moving back
|
||||
if (m_stack->currentIndex() > 0)
|
||||
{
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() - 1);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
void CreateProjectCtrl::HandlePrimaryButton()
|
||||
{
|
||||
CreateProject();
|
||||
}
|
||||
|
||||
bool CreateProjectCtrl::CurrentScreenIsValid()
|
||||
{
|
||||
if (m_stack->currentWidget() == m_newProjectSettingsScreen)
|
||||
{
|
||||
return m_newProjectSettingsScreen->Validate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::CreateProject()
|
||||
{
|
||||
if (m_newProjectSettingsScreen->Validate())
|
||||
{
|
||||
ProjectInfo projectInfo = m_newProjectSettingsScreen->GetProjectInfo();
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
|
||||
auto result = PythonBindingsInterface::Get()->CreateProject(projectTemplatePath, projectInfo);
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
// adding gems is not implemented yet because we don't know what targets to add or how to add them
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
// automatically register the project
|
||||
PythonBindingsInterface::Get()->AddProject(projectInfo.m_path);
|
||||
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
m_gemCatalogScreen->EnableDisableGemsForProject(projectInfo.m_path);
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
projectInfo.m_needsBuild = true;
|
||||
emit NotifyBuildProject(projectInfo);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::Projects);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Project creation failed"), tr("Failed to create project."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::UpdateNextButtonText()
|
||||
{
|
||||
QString nextButtonText = tr("Next");
|
||||
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
|
||||
else
|
||||
{
|
||||
nextButtonText = tr("Create Project");
|
||||
QMessageBox::warning(this, tr("Invalid project settings"), tr("Please correct the indicated project settings and try again."));
|
||||
}
|
||||
m_nextButton->setText(nextButtonText);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -12,15 +12,23 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ProjectInfo.h"
|
||||
#include <ScreenWidget.h>
|
||||
#include <ScreensCtrl.h>
|
||||
#include <QPushButton>
|
||||
#include <ProjectInfo.h>
|
||||
#endif
|
||||
|
||||
// due to current limitations, customizing template Gems is disabled
|
||||
#define TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
QT_FORWARD_DECLARE_CLASS(ScreenHeader)
|
||||
QT_FORWARD_DECLARE_CLASS(NewProjectSettingsScreen)
|
||||
QT_FORWARD_DECLARE_CLASS(GemCatalogScreen)
|
||||
|
||||
class CreateProjectCtrl
|
||||
: public ScreenWidget
|
||||
{
|
||||
@@ -28,21 +36,41 @@ namespace O3DE::ProjectManager
|
||||
explicit CreateProjectCtrl(QWidget* parent = nullptr);
|
||||
~CreateProjectCtrl() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
void NotifyCurrentScreen() override;
|
||||
|
||||
protected slots:
|
||||
void HandleBackButton();
|
||||
void HandleNextButton();
|
||||
void HandlePrimaryButton();
|
||||
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
void OnChangeScreenRequest(ProjectManagerScreen screen);
|
||||
void HandleSecondaryButton();
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
private:
|
||||
void UpdateNextButtonText();
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
void Update();
|
||||
void NextScreen();
|
||||
void PreviousScreen();
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
ScreensCtrl* m_screensCtrl;
|
||||
QPushButton* m_backButton;
|
||||
QPushButton* m_nextButton;
|
||||
QVector<ProjectManagerScreen> m_screensOrder;
|
||||
bool CurrentScreenIsValid();
|
||||
void CreateProject();
|
||||
|
||||
QStackedWidget* m_stack = nullptr;
|
||||
ScreenHeader* m_header = nullptr;
|
||||
|
||||
QPushButton* m_primaryButton = nullptr;
|
||||
|
||||
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
QPushButton* m_secondaryButton = nullptr;
|
||||
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
|
||||
|
||||
QString m_projectTemplatePath;
|
||||
ProjectInfo m_projectInfo;
|
||||
|
||||
NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr;
|
||||
GemCatalogScreen* m_gemCatalogScreen = nullptr;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace O3DE::ProjectManager
|
||||
EngineSettingsScreen::EngineSettingsScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
auto* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
|
||||
setObjectName("engineSettingsScreen");
|
||||
@@ -82,6 +82,16 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::EngineSettings;
|
||||
}
|
||||
|
||||
QString EngineSettingsScreen::GetTabText()
|
||||
{
|
||||
return tr("Engine");
|
||||
}
|
||||
|
||||
bool EngineSettingsScreen::IsTab()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void EngineSettingsScreen::OnTextChanged()
|
||||
{
|
||||
// save engine settings
|
||||
|
||||
@@ -26,7 +26,10 @@ namespace O3DE::ProjectManager
|
||||
public:
|
||||
explicit EngineSettingsScreen(QWidget* parent = nullptr);
|
||||
~EngineSettingsScreen() = default;
|
||||
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
QString GetTabText() override;
|
||||
bool IsTab() override;
|
||||
|
||||
protected slots:
|
||||
void OnTextChanged();
|
||||
|
||||
@@ -1,95 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <FirstTimeUseScreen.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QIcon>
|
||||
#include <QSpacerItem>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
FirstTimeUseScreen::FirstTimeUseScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins);
|
||||
|
||||
QLabel* titleLabel = new QLabel(this);
|
||||
titleLabel->setText(tr("Ready. Set. Create!"));
|
||||
titleLabel->setStyleSheet("font-size: 60px");
|
||||
vLayout->addWidget(titleLabel);
|
||||
|
||||
QLabel* introLabel = new QLabel(this);
|
||||
introLabel->setTextFormat(Qt::AutoText);
|
||||
introLabel->setText(tr("<html><head/><body><p>Welcome to O3DE! Start something new by creating a project. Not sure what to create? </p><p>Explore what\342\200\231s available by downloading our sample project.</p></body></html>"));
|
||||
introLabel->setStyleSheet("font-size: 14px");
|
||||
vLayout->addWidget(introLabel);
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->setSpacing(s_buttonSpacing);
|
||||
|
||||
m_createProjectButton = CreateLargeBoxButton(QIcon(":/Add.svg"), tr("Create Project"), this);
|
||||
m_createProjectButton->setIconSize(QSize(s_iconSize, s_iconSize));
|
||||
buttonLayout->addWidget(m_createProjectButton);
|
||||
|
||||
m_addProjectButton = CreateLargeBoxButton(QIcon(":/Select_Folder.svg"), tr("Add a Project"), this);
|
||||
m_addProjectButton->setIconSize(QSize(s_iconSize, s_iconSize));
|
||||
buttonLayout->addWidget(m_addProjectButton);
|
||||
|
||||
QSpacerItem* buttonSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
buttonLayout->addItem(buttonSpacer);
|
||||
|
||||
vLayout->addItem(buttonLayout);
|
||||
|
||||
QSpacerItem* verticalSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
vLayout->addItem(verticalSpacer);
|
||||
|
||||
// Using border-image allows for scaling options background-image does not support
|
||||
setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }");
|
||||
|
||||
connect(m_createProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleNewProjectButton);
|
||||
connect(m_addProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleAddProjectButton);
|
||||
}
|
||||
|
||||
ProjectManagerScreen FirstTimeUseScreen::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::FirstTimeUse;
|
||||
}
|
||||
|
||||
void FirstTimeUseScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void FirstTimeUseScreen::HandleAddProjectButton()
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
}
|
||||
|
||||
QPushButton* FirstTimeUseScreen::CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent)
|
||||
{
|
||||
QPushButton* largeBoxButton = new QPushButton(icon, text, parent);
|
||||
|
||||
largeBoxButton->setFixedSize(s_boxButtonWidth, s_boxButtonHeight);
|
||||
largeBoxButton->setFlat(true);
|
||||
largeBoxButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
largeBoxButton->setStyleSheet("QPushButton { font-size: 14px; background-color: rgba(0, 0, 0, 191); }");
|
||||
|
||||
return largeBoxButton;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -1,49 +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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QIcon)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class FirstTimeUseScreen
|
||||
: public ScreenWidget
|
||||
{
|
||||
public:
|
||||
explicit FirstTimeUseScreen(QWidget* parent = nullptr);
|
||||
~FirstTimeUseScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
protected slots:
|
||||
void HandleNewProjectButton();
|
||||
void HandleAddProjectButton();
|
||||
|
||||
private:
|
||||
QPushButton* CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent = nullptr);
|
||||
|
||||
QPushButton* m_createProjectButton;
|
||||
QPushButton* m_addProjectButton;
|
||||
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_buttonSpacing = 30;
|
||||
inline constexpr static int s_iconSize = 24;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_boxButtonWidth = 210;
|
||||
inline constexpr static int s_boxButtonHeight = 280;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -78,6 +78,14 @@ namespace O3DE::ProjectManager
|
||||
m_errorLabel->setText(labelText);
|
||||
}
|
||||
|
||||
void FormLineEditWidget::setErrorLabelVisible(bool visible)
|
||||
{
|
||||
m_errorLabel->setVisible(visible);
|
||||
m_frame->setProperty("Valid", !visible);
|
||||
|
||||
refreshStyle();
|
||||
}
|
||||
|
||||
QLineEdit* FormLineEditWidget::lineEdit() const
|
||||
{
|
||||
return m_lineEdit;
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
//! Set the error message for to display when invalid.
|
||||
void setErrorLabelText(const QString& labelText);
|
||||
void setErrorLabelVisible(bool visible);
|
||||
|
||||
//! Returns a pointer to the underlying LineEdit.
|
||||
QLineEdit* lineEdit() const;
|
||||
|
||||
@@ -10,40 +10,253 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzQtComponents/Components/SearchLineEdit.h>
|
||||
#include <GemCatalog/GemCatalogHeaderWidget.h>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <TagWidget.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
GemCatalogHeaderWidget::GemCatalogHeaderWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
|
||||
CartOverlayWidget::CartOverlayWidget(GemModel* gemModel, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_gemModel(gemModel)
|
||||
{
|
||||
setObjectName("GemCatalogCart");
|
||||
|
||||
m_layout = new QVBoxLayout();
|
||||
m_layout->setSpacing(0);
|
||||
m_layout->setMargin(0);
|
||||
m_layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(m_layout);
|
||||
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
|
||||
QPushButton* closeButton = new QPushButton();
|
||||
closeButton->setFlat(true);
|
||||
closeButton->setFocusPolicy(Qt::NoFocus);
|
||||
closeButton->setIcon(QIcon(":/WindowClose.svg"));
|
||||
connect(closeButton, &QPushButton::clicked, this, [=]
|
||||
{
|
||||
deleteLater();
|
||||
});
|
||||
hLayout->addSpacerItem(new QSpacerItem(10, 0, QSizePolicy::Expanding));
|
||||
hLayout->addWidget(closeButton);
|
||||
m_layout->addLayout(hLayout);
|
||||
|
||||
// enabled
|
||||
{
|
||||
m_enabledWidget = new QWidget();
|
||||
m_enabledWidget->setFixedWidth(s_width);
|
||||
m_layout->addWidget(m_enabledWidget);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
m_enabledWidget->setLayout(layout);
|
||||
|
||||
m_enabledLabel = new QLabel();
|
||||
m_enabledLabel->setObjectName("GemCatalogCartOverlaySectionLabel");
|
||||
layout->addWidget(m_enabledLabel);
|
||||
m_enabledTagContainer = new TagContainerWidget();
|
||||
layout->addWidget(m_enabledTagContainer);
|
||||
}
|
||||
|
||||
// disabled
|
||||
{
|
||||
m_disabledWidget = new QWidget();
|
||||
m_disabledWidget->setFixedWidth(s_width);
|
||||
m_layout->addWidget(m_disabledWidget);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
m_disabledWidget->setLayout(layout);
|
||||
|
||||
m_disabledLabel = new QLabel();
|
||||
m_disabledLabel->setObjectName("GemCatalogCartOverlaySectionLabel");
|
||||
layout->addWidget(m_disabledLabel);
|
||||
m_disabledTagContainer = new TagContainerWidget();
|
||||
layout->addWidget(m_disabledTagContainer);
|
||||
}
|
||||
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
|
||||
|
||||
Update();
|
||||
connect(gemModel, &GemModel::dataChanged, this, [=]
|
||||
{
|
||||
Update();
|
||||
});
|
||||
}
|
||||
|
||||
void CartOverlayWidget::Update()
|
||||
{
|
||||
const QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
|
||||
if (toBeAdded.isEmpty())
|
||||
{
|
||||
m_enabledWidget->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_enabledTagContainer->Update(ConvertFromModelIndices(toBeAdded));
|
||||
m_enabledLabel->setText(QString("%1 %2").arg(QString::number(toBeAdded.size()), tr("Gems to be enabled")));
|
||||
m_enabledWidget->show();
|
||||
}
|
||||
|
||||
const QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
|
||||
if (toBeRemoved.isEmpty())
|
||||
{
|
||||
m_disabledWidget->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_disabledTagContainer->Update(ConvertFromModelIndices(toBeRemoved));
|
||||
m_disabledLabel->setText(QString("%1 %2").arg(QString::number(toBeRemoved.size()), tr("Gems to be disabled")));
|
||||
m_disabledWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList CartOverlayWidget::ConvertFromModelIndices(const QVector<QModelIndex>& gems) const
|
||||
{
|
||||
QStringList gemNames;
|
||||
gemNames.reserve(gems.size());
|
||||
for (const QModelIndex& modelIndex : gems)
|
||||
{
|
||||
gemNames.push_back(GemModel::GetName(modelIndex));
|
||||
}
|
||||
return gemNames;
|
||||
}
|
||||
|
||||
CartButton::CartButton(GemModel* gemModel, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_gemModel(gemModel)
|
||||
{
|
||||
m_layout = new QHBoxLayout();
|
||||
m_layout->setMargin(0);
|
||||
setLayout(m_layout);
|
||||
|
||||
QPushButton* iconButton = new QPushButton();
|
||||
iconButton->setFlat(true);
|
||||
iconButton->setFocusPolicy(Qt::NoFocus);
|
||||
iconButton->setIcon(QIcon(":/Summary.svg"));
|
||||
iconButton->setFixedSize(s_iconSize, s_iconSize);
|
||||
connect(iconButton, &QPushButton::clicked, this, &CartButton::ShowOverlay);
|
||||
m_layout->addWidget(iconButton);
|
||||
|
||||
m_countLabel = new QLabel();
|
||||
m_countLabel->setObjectName("GemCatalogCartCountLabel");
|
||||
m_countLabel->setFixedHeight(s_iconSize - 1); // Compensate for the empty icon space by using a slightly smaller label height.
|
||||
m_layout->addWidget(m_countLabel);
|
||||
|
||||
m_dropDownButton = new QPushButton();
|
||||
m_dropDownButton->setFlat(true);
|
||||
m_dropDownButton->setFocusPolicy(Qt::NoFocus);
|
||||
m_dropDownButton->setIcon(QIcon(":/CarrotArrowDown.svg"));
|
||||
m_dropDownButton->setFixedSize(s_arrowDownIconSize, s_arrowDownIconSize);
|
||||
connect(m_dropDownButton, &QPushButton::clicked, this, &CartButton::ShowOverlay);
|
||||
m_layout->addWidget(m_dropDownButton);
|
||||
|
||||
// Adjust the label text whenever the model gets updated.
|
||||
connect(gemModel, &GemModel::dataChanged, [=]
|
||||
{
|
||||
const QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
|
||||
const QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
|
||||
|
||||
const int count = toBeAdded.size() + toBeRemoved.size();
|
||||
m_countLabel->setText(QString::number(count));
|
||||
|
||||
m_dropDownButton->setVisible(!toBeAdded.isEmpty() || !toBeRemoved.isEmpty());
|
||||
|
||||
// Automatically close the overlay window in case there are no gems to be enabled or disabled anymore.
|
||||
if (m_cartOverlay && toBeAdded.isEmpty() && toBeRemoved.isEmpty())
|
||||
{
|
||||
m_cartOverlay->deleteLater();
|
||||
m_cartOverlay = nullptr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CartButton::mousePressEvent([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
ShowOverlay();
|
||||
}
|
||||
|
||||
void CartButton::ShowOverlay()
|
||||
{
|
||||
const QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
|
||||
const QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
|
||||
if (toBeAdded.isEmpty() && toBeRemoved.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_cartOverlay)
|
||||
{
|
||||
// Directly delete the former overlay before creating the new one.
|
||||
// Don't use deleteLater() here. This might overwrite the new overlay pointer
|
||||
// depending on the event queue.
|
||||
delete m_cartOverlay;
|
||||
}
|
||||
|
||||
m_cartOverlay = new CartOverlayWidget(m_gemModel, this);
|
||||
connect(m_cartOverlay, &QWidget::destroyed, this, [=]
|
||||
{
|
||||
// Reset the overlay pointer on destruction to prevent dangling pointers.
|
||||
m_cartOverlay = nullptr;
|
||||
});
|
||||
m_cartOverlay->show();
|
||||
|
||||
const QPoint parentPos = m_dropDownButton->mapToParent(m_dropDownButton->pos());
|
||||
const QPoint globalPos = m_dropDownButton->mapToGlobal(m_dropDownButton->pos());
|
||||
const QPoint offset(-4, 10);
|
||||
m_cartOverlay->setGeometry(globalPos.x() - parentPos.x() - m_cartOverlay->width() + width() + offset.x(),
|
||||
globalPos.y() + offset.y(),
|
||||
m_cartOverlay->width(),
|
||||
m_cartOverlay->height());
|
||||
}
|
||||
|
||||
CartButton::~CartButton()
|
||||
{
|
||||
// Make sure the overlay window is automatically closed in case the gem catalog is destroyed.
|
||||
if (m_cartOverlay)
|
||||
{
|
||||
m_cartOverlay->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
GemCatalogHeaderWidget::GemCatalogHeaderWidget(GemModel* gemModel, GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setAlignment(Qt::AlignLeft);
|
||||
hLayout->setMargin(0);
|
||||
hLayout->setContentsMargins(10, 7, 10, 7);
|
||||
setLayout(hLayout);
|
||||
|
||||
setStyleSheet("background-color: #1E252F;");
|
||||
setObjectName("GemCatalogHeaderWidget");
|
||||
setFixedHeight(s_height);
|
||||
|
||||
QLabel* titleLabel = new QLabel(tr("Gem Catalog"));
|
||||
titleLabel->setStyleSheet("font-size: 21px;");
|
||||
titleLabel->setObjectName("GemCatalogTitle");
|
||||
hLayout->addWidget(titleLabel);
|
||||
|
||||
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
|
||||
|
||||
AzQtComponents::SearchLineEdit* filterLineEdit = new AzQtComponents::SearchLineEdit();
|
||||
filterLineEdit->setStyleSheet("background-color: #DDDDDD;");
|
||||
connect(filterLineEdit, &QLineEdit::textChanged, this, [=](const QString& text)
|
||||
m_filterLineEdit = new AzQtComponents::SearchLineEdit();
|
||||
m_filterLineEdit->setStyleSheet("background-color: #DDDDDD;");
|
||||
connect(m_filterLineEdit, &QLineEdit::textChanged, this, [=](const QString& text)
|
||||
{
|
||||
filterProxyModel->SetSearchString(text);
|
||||
});
|
||||
hLayout->addWidget(filterLineEdit);
|
||||
hLayout->addWidget(m_filterLineEdit);
|
||||
|
||||
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
|
||||
hLayout->addSpacerItem(new QSpacerItem(220, 0, QSizePolicy::Fixed));
|
||||
|
||||
setFixedHeight(60);
|
||||
hLayout->addSpacerItem(new QSpacerItem(75, 0, QSizePolicy::Fixed));
|
||||
|
||||
CartButton* cartButton = new CartButton(gemModel);
|
||||
hLayout->addWidget(cartButton);
|
||||
}
|
||||
|
||||
void GemCatalogHeaderWidget::ReinitForProject()
|
||||
{
|
||||
m_filterLineEdit->setText({});
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -13,19 +13,81 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzQtComponents/Components/SearchLineEdit.h>
|
||||
#include <GemCatalog/GemModel.h>
|
||||
#include <GemCatalog/GemSortFilterProxyModel.h>
|
||||
#include <TagWidget.h>
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QDialog>
|
||||
#include <QMoveEvent>
|
||||
#include <QVBoxLayout>
|
||||
#endif
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class CartOverlayWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
CartOverlayWidget(GemModel* gemModel, QWidget* parent = nullptr);
|
||||
void Update();
|
||||
|
||||
private:
|
||||
QStringList ConvertFromModelIndices(const QVector<QModelIndex>& gems) const;
|
||||
|
||||
QVBoxLayout* m_layout = nullptr;
|
||||
GemModel* m_gemModel = nullptr;
|
||||
|
||||
QWidget* m_enabledWidget = nullptr;
|
||||
QLabel* m_enabledLabel = nullptr;
|
||||
TagContainerWidget* m_enabledTagContainer = nullptr;
|
||||
|
||||
QWidget* m_disabledWidget = nullptr;
|
||||
QLabel* m_disabledLabel = nullptr;
|
||||
TagContainerWidget* m_disabledTagContainer = nullptr;
|
||||
|
||||
inline constexpr static int s_width = 240;
|
||||
};
|
||||
|
||||
class CartButton
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
CartButton(GemModel* gemModel, QWidget* parent = nullptr);
|
||||
~CartButton();
|
||||
void ShowOverlay();
|
||||
|
||||
private:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
GemModel* m_gemModel = nullptr;
|
||||
QHBoxLayout* m_layout = nullptr;
|
||||
QLabel* m_countLabel = nullptr;
|
||||
QPushButton* m_dropDownButton = nullptr;
|
||||
CartOverlayWidget* m_cartOverlay = nullptr;
|
||||
|
||||
inline constexpr static int s_iconSize = 24;
|
||||
inline constexpr static int s_arrowDownIconSize = 8;
|
||||
};
|
||||
|
||||
class GemCatalogHeaderWidget
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit GemCatalogHeaderWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
|
||||
explicit GemCatalogHeaderWidget(GemModel* gemModel, GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
|
||||
~GemCatalogHeaderWidget() = default;
|
||||
|
||||
void ReinitForProject();
|
||||
|
||||
private:
|
||||
AzQtComponents::SearchLineEdit* m_filterLineEdit = nullptr;
|
||||
inline constexpr static int s_height = 60;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -12,16 +12,14 @@
|
||||
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <GemCatalog/GemCatalogHeaderWidget.h>
|
||||
#include <GemCatalog/GemListHeaderWidget.h>
|
||||
#include <GemCatalog/GemSortFilterProxyModel.h>
|
||||
#include <GemCatalog/GemFilterWidget.h>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
|
||||
//#define USE_TESTGEMDATA
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -29,47 +27,32 @@ namespace O3DE::ProjectManager
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
m_gemModel = new GemModel(this);
|
||||
GemSortFilterProxyModel* proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
|
||||
m_proxModel = new GemSortFilterProxyModel(m_gemModel, this);
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setMargin(0);
|
||||
vLayout->setSpacing(0);
|
||||
setLayout(vLayout);
|
||||
|
||||
GemCatalogHeaderWidget* headerWidget = new GemCatalogHeaderWidget(proxyModel);
|
||||
vLayout->addWidget(headerWidget);
|
||||
m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxModel);
|
||||
vLayout->addWidget(m_headerWidget);
|
||||
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
hLayout->setMargin(0);
|
||||
vLayout->addLayout(hLayout);
|
||||
|
||||
m_gemListView = new GemListView(proxyModel, proxyModel->GetSelectionModel(), this);
|
||||
m_gemListView = new GemListView(m_proxModel, m_proxModel->GetSelectionModel(), this);
|
||||
m_gemInspector = new GemInspector(m_gemModel, this);
|
||||
m_gemInspector->setFixedWidth(320);
|
||||
m_gemInspector->setFixedWidth(240);
|
||||
|
||||
// Start: Temporary gem test data
|
||||
#ifdef USE_TESTGEMDATA
|
||||
QVector<GemInfo> testGemData = GenerateTestData();
|
||||
for (const GemInfo& gemInfo : testGemData)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfo);
|
||||
}
|
||||
#else
|
||||
// End: Temporary gem test data
|
||||
auto result = PythonBindingsInterface::Get()->GetGems();
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
for (auto gemInfo : result.GetValue())
|
||||
{
|
||||
m_gemModel->AddGem(gemInfo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
QWidget* filterWidget = new QWidget(this);
|
||||
filterWidget->setFixedWidth(240);
|
||||
m_filterWidgetLayout = new QVBoxLayout();
|
||||
m_filterWidgetLayout->setMargin(0);
|
||||
m_filterWidgetLayout->setSpacing(0);
|
||||
filterWidget->setLayout(m_filterWidgetLayout);
|
||||
|
||||
GemFilterWidget* filterWidget = new GemFilterWidget(proxyModel);
|
||||
filterWidget->setFixedWidth(250);
|
||||
|
||||
GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(proxyModel);
|
||||
GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxModel);
|
||||
|
||||
QVBoxLayout* middleVLayout = new QVBoxLayout();
|
||||
middleVLayout->setMargin(0);
|
||||
@@ -80,98 +63,114 @@ namespace O3DE::ProjectManager
|
||||
hLayout->addWidget(filterWidget);
|
||||
hLayout->addLayout(middleVLayout);
|
||||
hLayout->addWidget(m_gemInspector);
|
||||
|
||||
proxyModel->InvalidateFilter();
|
||||
}
|
||||
|
||||
QVector<GemInfo> GemCatalogScreen::GenerateTestData()
|
||||
void GemCatalogScreen::ReinitForProject(const QString& projectPath, bool isNewProject)
|
||||
{
|
||||
QVector<GemInfo> result;
|
||||
m_gemModel->clear();
|
||||
FillModel(projectPath, isNewProject);
|
||||
|
||||
GemInfo gem("EMotion FX",
|
||||
"O3DE Foundation",
|
||||
"EMFX is a real-time character animation system. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
(GemInfo::Android | GemInfo::iOS | GemInfo::macOS | GemInfo::Windows | GemInfo::Linux),
|
||||
true);
|
||||
gem.m_directoryLink = "C:/";
|
||||
gem.m_documentationLink = "http://www.amazon.com";
|
||||
gem.m_dependingGemUuids = QStringList({"EMotionFX", "Atom"});
|
||||
gem.m_conflictingGemUuids = QStringList({"Vegetation", "Camera", "ScriptCanvas", "CloudCanvas", "Networking"});
|
||||
gem.m_types = (GemInfo::Code | GemInfo::Asset);
|
||||
gem.m_version = "v1.01";
|
||||
gem.m_lastUpdatedDate = "24th April 2021";
|
||||
gem.m_binarySizeInKB = 40;
|
||||
gem.m_features = QStringList({"Animation", "Assets", "Physics"});
|
||||
gem.m_gemOrigin = GemInfo::O3DEFoundation;
|
||||
result.push_back(gem);
|
||||
if (m_filterWidget)
|
||||
{
|
||||
m_filterWidget->hide();
|
||||
m_filterWidget->deleteLater();
|
||||
}
|
||||
|
||||
gem.m_name = "Atom";
|
||||
gem.m_creator = "O3DE Seattle";
|
||||
gem.m_summary = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
||||
gem.m_platforms = (GemInfo::Android | GemInfo::Windows | GemInfo::Linux | GemInfo::macOS);
|
||||
gem.m_isAdded = true;
|
||||
gem.m_directoryLink = "C:/";
|
||||
gem.m_documentationLink = "https://aws.amazon.com/gametech/";
|
||||
gem.m_dependingGemUuids = QStringList({"EMotionFX", "Core", "AudioSystem", "Camera", "Particles"});
|
||||
gem.m_conflictingGemUuids = QStringList({"CloudCanvas", "NovaNet"});
|
||||
gem.m_version = "v2.31";
|
||||
gem.m_lastUpdatedDate = "24th November 2020";
|
||||
gem.m_features = QStringList({"Assets", "Rendering", "UI", "VR", "Debug", "Environment"});
|
||||
gem.m_binarySizeInKB = 2087;
|
||||
result.push_back(gem);
|
||||
m_proxModel->ResetFilters();
|
||||
m_filterWidget = new GemFilterWidget(m_proxModel);
|
||||
m_filterWidgetLayout->addWidget(m_filterWidget);
|
||||
|
||||
gem.m_name = "Physics";
|
||||
gem.m_creator = "O3DE London";
|
||||
gem.m_summary = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
gem.m_platforms = (GemInfo::Android | GemInfo::Linux | GemInfo::macOS);
|
||||
gem.m_isAdded = true;
|
||||
gem.m_directoryLink = "C:/";
|
||||
gem.m_documentationLink = "https://aws.amazon.com/gametech/";
|
||||
gem.m_dependingGemUuids = QStringList({"GraphCanvas", "ExpressionEvaluation", "UI Lib", "Multiplayer", "GameStateSamples"});
|
||||
gem.m_conflictingGemUuids = QStringList({"Cloud Canvas", "EMotion FX", "Streaming", "MessagePopup", "Cloth", "Graph Canvas", "Twitch Integration"});
|
||||
gem.m_version = "v1.5.102145";
|
||||
gem.m_lastUpdatedDate = "1st January 2021";
|
||||
gem.m_binarySizeInKB = 2000000;
|
||||
gem.m_features = QStringList({"Physics", "Gameplay", "Debug", "Assets"});
|
||||
result.push_back(gem);
|
||||
m_headerWidget->ReinitForProject();
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Certificate Manager",
|
||||
"O3DE Irvine",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
GemInfo::Windows,
|
||||
false));
|
||||
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Cloud Gem Framework",
|
||||
"O3DE Seattle",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
GemInfo::iOS | GemInfo::Linux,
|
||||
false));
|
||||
// Select the first entry after everything got correctly sized
|
||||
QTimer::singleShot(200, [=]{
|
||||
QModelIndex firstModelIndex = m_gemListView->model()->index(0,0);
|
||||
m_gemListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect);
|
||||
});
|
||||
}
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Cloud Gem Core",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
true));
|
||||
void GemCatalogScreen::FillModel(const QString& projectPath, bool isNewProject)
|
||||
{
|
||||
AZ::Outcome<QVector<GemInfo>, AZStd::string> allGemInfosResult;
|
||||
if (isNewProject)
|
||||
{
|
||||
allGemInfosResult = PythonBindingsInterface::Get()->GetEngineGemInfos();
|
||||
}
|
||||
else
|
||||
{
|
||||
allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(projectPath);
|
||||
}
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Gestures",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
false));
|
||||
if (allGemInfosResult.IsSuccess())
|
||||
{
|
||||
// Add all available gems to the model.
|
||||
const QVector<GemInfo> allGemInfos = allGemInfosResult.GetValue();
|
||||
for (const GemInfo& gemInfo : allGemInfos)
|
||||
{
|
||||
m_gemModel->AddGem(gemInfo);
|
||||
}
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Effects System",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
true));
|
||||
// Gather enabled gems for the given project.
|
||||
auto enabledGemNamesResult = PythonBindingsInterface::Get()->GetEnabledGemNames(projectPath);
|
||||
if (enabledGemNamesResult.IsSuccess())
|
||||
{
|
||||
const QVector<AZStd::string> enabledGemNames = enabledGemNamesResult.GetValue();
|
||||
for (const AZStd::string& enabledGemName : enabledGemNames)
|
||||
{
|
||||
const QModelIndex modelIndex = m_gemModel->FindIndexByNameString(enabledGemName.c_str());
|
||||
if (modelIndex.isValid())
|
||||
{
|
||||
GemModel::SetWasPreviouslyAdded(*m_gemModel, modelIndex, true);
|
||||
GemModel::SetIsAdded(*m_gemModel, modelIndex, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("ProjectManager::GemCatalog", false,
|
||||
"Cannot find entry for gem with name '%s'. The CMake target name probably does not match the specified name in the gem.json.",
|
||||
enabledGemName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve enabled gems for project %1.\n\nError:\n%2").arg(projectPath, enabledGemNamesResult.GetError().c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(nullptr, tr("Operation failed"), QString("Cannot retrieve gems for %1.\n\nError:\n%2").arg(projectPath, allGemInfosResult.GetError().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back(O3DE::ProjectManager::GemInfo("Microphone",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus euismod ligula vitae dui dictum, a sodales dolor luctus. Sed id elit dapibus, finibus neque sed, efficitur mi. Nam facilisis ligula at eleifend pellentesque. Praesent non ex consectetur, blandit tellus in, venenatis lacus. Duis nec neque in urna ullamcorper euismod id eu leo. Nam efficitur dolor sed odio vehicula venenatis. Suspendisse nec est non velit commodo cursus in sit amet dui. Ut bibendum nisl et libero hendrerit dapibus. Vestibulum ultrices ullamcorper urna, placerat porttitor est lobortis in. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer a magna ac tellus sollicitudin porttitor. Phasellus lobortis viverra justo id bibendum. Etiam ac pharetra risus. Nulla vitae justo nibh. Nulla viverra leo et molestie interdum. Duis sit amet bibendum nulla, sit amet vehicula augue.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
false));
|
||||
void GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath)
|
||||
{
|
||||
IPythonBindings* pythonBindings = PythonBindingsInterface::Get();
|
||||
QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
|
||||
QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
|
||||
|
||||
return result;
|
||||
for (const QModelIndex& modelIndex : toBeAdded)
|
||||
{
|
||||
const QString gemPath = GemModel::GetPath(modelIndex);
|
||||
const AZ::Outcome<void, AZStd::string> result = pythonBindings->AddGemToProject(gemPath, projectPath);
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Operation failed",
|
||||
QString("Cannot add gem %1 to project.\n\nError:\n%2").arg(GemModel::GetName(modelIndex), result.GetError().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
for (const QModelIndex& modelIndex : toBeRemoved)
|
||||
{
|
||||
const QString gemPath = GemModel::GetPath(modelIndex);
|
||||
const AZ::Outcome<void, AZStd::string> result = pythonBindings->RemoveGemFromProject(gemPath, projectPath);
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Operation failed",
|
||||
QString("Cannot remove gem %1 from project.\n\nError:\n%2").arg(GemModel::GetName(modelIndex), result.GetError().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProjectManagerScreen GemCatalogScreen::GetScreenEnum()
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.h>
|
||||
#include <GemCatalog/GemCatalogHeaderWidget.h>
|
||||
#include <GemCatalog/GemFilterWidget.h>
|
||||
#include <GemCatalog/GemListView.h>
|
||||
#include <GemCatalog/GemInspector.h>
|
||||
#include <GemCatalog/GemModel.h>
|
||||
#include <GemCatalog/GemSortFilterProxyModel.h>
|
||||
#endif
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
@@ -29,11 +32,18 @@ namespace O3DE::ProjectManager
|
||||
~GemCatalogScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
void ReinitForProject(const QString& projectPath, bool isNewProject);
|
||||
void EnableDisableGemsForProject(const QString& projectPath);
|
||||
|
||||
private:
|
||||
QVector<GemInfo> GenerateTestData();
|
||||
void FillModel(const QString& projectPath, bool isNewProject);
|
||||
|
||||
GemListView* m_gemListView = nullptr;
|
||||
GemInspector* m_gemInspector = nullptr;
|
||||
GemModel* m_gemModel = nullptr;
|
||||
GemCatalogHeaderWidget* m_headerWidget = nullptr;
|
||||
GemSortFilterProxyModel* m_proxModel = nullptr;
|
||||
QVBoxLayout* m_filterWidgetLayout = nullptr;
|
||||
GemFilterWidget* m_filterWidget = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton,
|
||||
bool collapsed,
|
||||
int defaultShowCount,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@@ -40,10 +41,10 @@ namespace O3DE::ProjectManager
|
||||
QHBoxLayout* collapseLayout = new QHBoxLayout();
|
||||
m_collapseButton = new QPushButton();
|
||||
m_collapseButton->setCheckable(true);
|
||||
m_collapseButton->setChecked(collapsed);
|
||||
m_collapseButton->setFlat(true);
|
||||
m_collapseButton->setFocusPolicy(Qt::NoFocus);
|
||||
m_collapseButton->setFixedWidth(s_collapseButtonSize);
|
||||
m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;");
|
||||
connect(m_collapseButton, &QPushButton::clicked, this, [=]()
|
||||
{
|
||||
UpdateCollapseState();
|
||||
@@ -52,7 +53,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
// Category title
|
||||
QLabel* headerLabel = new QLabel(header);
|
||||
headerLabel->setStyleSheet("font-size: 11pt;");
|
||||
headerLabel->setObjectName("GemCatalogFilterCategoryTitle");
|
||||
collapseLayout->addWidget(headerLabel);
|
||||
vLayout->addLayout(collapseLayout);
|
||||
|
||||
@@ -79,14 +80,14 @@ namespace O3DE::ProjectManager
|
||||
elementWidget->setLayout(elementLayout);
|
||||
|
||||
QCheckBox* checkbox = new QCheckBox(elementNames[i]);
|
||||
checkbox->setStyleSheet("font-size: 11pt;");
|
||||
checkbox->setStyleSheet("font-size: 12px;");
|
||||
m_buttonGroup->addButton(checkbox);
|
||||
elementLayout->addWidget(checkbox);
|
||||
|
||||
elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
|
||||
|
||||
QLabel* countLabel = new QLabel(QString::number(elementCounts[i]));
|
||||
countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;");
|
||||
countLabel->setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px; color: #94D2FF;");
|
||||
elementLayout->addWidget(countLabel);
|
||||
|
||||
m_elementWidgets.push_back(elementWidget);
|
||||
@@ -110,6 +111,8 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
vLayout->addSpacing(5);
|
||||
|
||||
// Separating line
|
||||
QFrame* hLine = new QFrame();
|
||||
hLine->setFrameShape(QFrame::HLine);
|
||||
@@ -177,10 +180,17 @@ namespace O3DE::ProjectManager
|
||||
return m_buttonGroup;
|
||||
}
|
||||
|
||||
bool FilterCategoryWidget::IsCollapsed()
|
||||
{
|
||||
return m_collapseButton->isChecked();
|
||||
}
|
||||
|
||||
GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
|
||||
: QScrollArea(parent)
|
||||
, m_filterProxyModel(filterProxyModel)
|
||||
{
|
||||
setObjectName("GemCatalogFilterWidget");
|
||||
|
||||
m_gemModel = m_filterProxyModel->GetSourceModel();
|
||||
|
||||
setWidgetResizable(true);
|
||||
@@ -190,20 +200,106 @@ namespace O3DE::ProjectManager
|
||||
QWidget* mainWidget = new QWidget();
|
||||
setWidget(mainWidget);
|
||||
|
||||
m_mainLayout = new QVBoxLayout();
|
||||
m_mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(m_mainLayout);
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout();
|
||||
mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(mainLayout);
|
||||
|
||||
QLabel* filterByLabel = new QLabel("Filter by");
|
||||
filterByLabel->setStyleSheet("font-size: 15pt;");
|
||||
m_mainLayout->addWidget(filterByLabel);
|
||||
filterByLabel->setStyleSheet("font-size: 16px;");
|
||||
mainLayout->addWidget(filterByLabel);
|
||||
|
||||
QWidget* filterSection = new QWidget(this);
|
||||
mainLayout->addWidget(filterSection);
|
||||
|
||||
m_filterLayout = new QVBoxLayout();
|
||||
m_filterLayout->setAlignment(Qt::AlignTop);
|
||||
m_filterLayout->setContentsMargins(0, 0, 0, 0);
|
||||
filterSection->setLayout(m_filterLayout);
|
||||
|
||||
ResetGemStatusFilter();
|
||||
AddGemOriginFilter();
|
||||
AddTypeFilter();
|
||||
AddPlatformFilter();
|
||||
AddFeatureFilter();
|
||||
}
|
||||
|
||||
void GemFilterWidget::ResetGemStatusFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
wasCollapsed = m_statusFilter->IsCollapsed();
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget =
|
||||
new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed);
|
||||
if (m_statusFilter)
|
||||
{
|
||||
m_filterLayout->replaceWidget(m_statusFilter, filterWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
}
|
||||
|
||||
m_statusFilter->deleteLater();
|
||||
m_statusFilter = filterWidget;
|
||||
|
||||
const GemSortFilterProxyModel::GemStatus currentFilterState = m_filterProxyModel->GetGemStatus();
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
for (int statusFilterIndex = 0; statusFilterIndex < buttons.size(); ++statusFilterIndex)
|
||||
{
|
||||
const GemSortFilterProxyModel::GemStatus gemStatus = static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex);
|
||||
QAbstractButton* button = buttons[statusFilterIndex];
|
||||
|
||||
if (static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex) == currentFilterState)
|
||||
{
|
||||
button->setChecked(true);
|
||||
}
|
||||
|
||||
connect(
|
||||
button, &QAbstractButton::toggled, this,
|
||||
[=](bool checked)
|
||||
{
|
||||
GemSortFilterProxyModel::GemStatus filterStatus = m_filterProxyModel->GetGemStatus();
|
||||
if (checked)
|
||||
{
|
||||
if (filterStatus == GemSortFilterProxyModel::GemStatus::NoFilter)
|
||||
{
|
||||
filterStatus = gemStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterStatus != gemStatus)
|
||||
{
|
||||
filterStatus = static_cast<GemSortFilterProxyModel::GemStatus>(!gemStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
m_filterProxyModel->SetGemStatus(filterStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void GemFilterWidget::AddGemOriginFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
@@ -230,7 +326,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -280,7 +376,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -330,7 +426,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -385,8 +481,8 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts,
|
||||
/*showAllLessButton=*/true, /*defaultShowCount=*/5);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
/*showAllLessButton=*/true, false, /*defaultShowCount=*/5);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
|
||||
@@ -37,11 +37,14 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton = true,
|
||||
bool collapsed = false,
|
||||
int defaultShowCount = 4,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
QButtonGroup* GetButtonGroup();
|
||||
|
||||
bool IsCollapsed();
|
||||
|
||||
private:
|
||||
void UpdateCollapseState();
|
||||
void UpdateSeeMoreLess();
|
||||
@@ -66,14 +69,18 @@ namespace O3DE::ProjectManager
|
||||
explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
|
||||
~GemFilterWidget() = default;
|
||||
|
||||
public slots:
|
||||
void ResetGemStatusFilter();
|
||||
|
||||
private:
|
||||
void AddGemOriginFilter();
|
||||
void AddTypeFilter();
|
||||
void AddPlatformFilter();
|
||||
void AddFeatureFilter();
|
||||
|
||||
QVBoxLayout* m_mainLayout = nullptr;
|
||||
QVBoxLayout* m_filterLayout = nullptr;
|
||||
GemModel* m_gemModel = nullptr;
|
||||
GemSortFilterProxyModel* m_filterProxyModel = nullptr;
|
||||
FilterCategoryWidget* m_statusFilter = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||