Merge pull request #2235 from aws-lumberyard-dev/daimini/gitflow_210716_o3de
Gitflow 7/16/21 - O3DE
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <ProjectUtils.h>
|
||||
#include <ProjectManagerDefs.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
|
||||
#include <QFileDialog>
|
||||
@@ -18,6 +19,8 @@
|
||||
#include <QProcessEnvironment>
|
||||
#include <QGuiApplication>
|
||||
#include <QProgressDialog>
|
||||
#include <QSpacerItem>
|
||||
#include <QGridLayout>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -58,29 +61,63 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SkipFilePaths(const QString& curPath, QStringList& skippedPaths, QStringList& deeperSkippedPaths)
|
||||
{
|
||||
bool skip = false;
|
||||
for (const QString& skippedPath : skippedPaths)
|
||||
{
|
||||
QString nativeSkippedPath = QDir::toNativeSeparators(skippedPath);
|
||||
QString firstSectionSkippedPath = nativeSkippedPath.section(QDir::separator(), 0, 0);
|
||||
if (curPath == firstSectionSkippedPath)
|
||||
{
|
||||
// We are at the end of the path to skip, so skip it
|
||||
if (nativeSkippedPath == firstSectionSkippedPath)
|
||||
{
|
||||
skippedPaths.removeAll(skippedPath);
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
// Append the next section of the skipped path
|
||||
else
|
||||
{
|
||||
deeperSkippedPaths.append(nativeSkippedPath.section(QDir::separator(), 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
typedef AZStd::function<void(/*fileCount=*/int, /*totalSizeInBytes=*/int)> StatusFunction;
|
||||
static void RecursiveGetAllFiles(const QDir& directory, QStringList& outFileList, qint64& outTotalSizeInBytes, StatusFunction statusCallback)
|
||||
static void RecursiveGetAllFiles(const QDir& directory, QStringList& skippedPaths, int& outFileCount, qint64& outTotalSizeInBytes, StatusFunction statusCallback)
|
||||
{
|
||||
const QStringList entries = directory.entryList(QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
||||
for (const QString& entryPath : entries)
|
||||
{
|
||||
const QString filePath = QDir::toNativeSeparators(QString("%1/%2").arg(directory.path()).arg(entryPath));
|
||||
|
||||
QStringList deeperSkippedPaths;
|
||||
if (SkipFilePaths(entryPath, skippedPaths, deeperSkippedPaths))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo fileInfo(filePath);
|
||||
|
||||
if (fileInfo.isDir())
|
||||
{
|
||||
QDir subDirectory(filePath);
|
||||
RecursiveGetAllFiles(subDirectory, outFileList, outTotalSizeInBytes, statusCallback);
|
||||
RecursiveGetAllFiles(subDirectory, deeperSkippedPaths, outFileCount, outTotalSizeInBytes, statusCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
outFileList.push_back(filePath);
|
||||
++outFileCount;
|
||||
outTotalSizeInBytes += fileInfo.size();
|
||||
|
||||
const int updateStatusEvery = 64;
|
||||
if (outFileList.size() % updateStatusEvery == 0)
|
||||
if (outFileCount % updateStatusEvery == 0)
|
||||
{
|
||||
statusCallback(outFileList.size(), outTotalSizeInBytes);
|
||||
statusCallback(outFileCount, outTotalSizeInBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +126,8 @@ namespace O3DE::ProjectManager
|
||||
static bool CopyDirectory(QProgressDialog* progressDialog,
|
||||
const QString& origPath,
|
||||
const QString& newPath,
|
||||
QStringList& filesToCopy,
|
||||
QStringList& skippedPaths,
|
||||
int filesToCopyCount,
|
||||
int& outNumCopiedFiles,
|
||||
qint64 totalSizeToCopy,
|
||||
qint64& outCopiedFileSize,
|
||||
@@ -101,18 +139,24 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
for (QString directory : original.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
|
||||
for (const QString& directory : original.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
|
||||
{
|
||||
if (progressDialog->wasCanceled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList deeperSkippedPaths;
|
||||
if (SkipFilePaths(directory, skippedPaths, deeperSkippedPaths))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QString newDirectoryPath = newPath + QDir::separator() + directory;
|
||||
original.mkpath(newDirectoryPath);
|
||||
|
||||
if (!CopyDirectory(progressDialog, origPath + QDir::separator() + directory,
|
||||
newDirectoryPath, filesToCopy, outNumCopiedFiles, totalSizeToCopy, outCopiedFileSize, showIgnoreFileDialog))
|
||||
if (!CopyDirectory(progressDialog, origPath + QDir::separator() + directory, newDirectoryPath, deeperSkippedPaths,
|
||||
filesToCopyCount, outNumCopiedFiles, totalSizeToCopy, outCopiedFileSize, showIgnoreFileDialog))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -120,18 +164,25 @@ namespace O3DE::ProjectManager
|
||||
|
||||
QLocale locale;
|
||||
const float progressDialogRangeHalf = qFabs(progressDialog->maximum() - progressDialog->minimum()) * 0.5f;
|
||||
for (QString file : original.entryList(QDir::Files))
|
||||
for (const QString& file : original.entryList(QDir::Files))
|
||||
{
|
||||
if (progressDialog->wasCanceled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unused by this function but neccesary to pass in to SkipFilePaths
|
||||
QStringList deeperSkippedPaths;
|
||||
if (SkipFilePaths(file, skippedPaths, deeperSkippedPaths))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Progress window update
|
||||
{
|
||||
// Weight in the number of already copied files as well as the copied bytes to get a better progress indication
|
||||
// for cases combining many small files and some really large files.
|
||||
const float normalizedNumFiles = static_cast<float>(outNumCopiedFiles) / filesToCopy.count();
|
||||
const float normalizedNumFiles = static_cast<float>(outNumCopiedFiles) / filesToCopyCount;
|
||||
const float normalizedFileSize = static_cast<float>(outCopiedFileSize) / totalSizeToCopy;
|
||||
const int progress = normalizedNumFiles * progressDialogRangeHalf + normalizedFileSize * progressDialogRangeHalf;
|
||||
progressDialog->setValue(progress);
|
||||
@@ -139,7 +190,7 @@ namespace O3DE::ProjectManager
|
||||
const QString copiedFileSizeString = locale.formattedDataSize(outCopiedFileSize);
|
||||
const QString totalFileSizeString = locale.formattedDataSize(totalSizeToCopy);
|
||||
progressDialog->setLabelText(QString("Coping file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles),
|
||||
QString::number(filesToCopy.count()),
|
||||
QString::number(filesToCopyCount),
|
||||
copiedFileSizeString,
|
||||
totalFileSizeString));
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
@@ -193,6 +244,39 @@ namespace O3DE::ProjectManager
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ClearProjectBuildArtifactsAndCache(const QString& origPath, const QString& newPath, QWidget* parent)
|
||||
{
|
||||
QDir buildDirectory = QDir(newPath);
|
||||
if ((!buildDirectory.cd(ProjectBuildDirectoryName) || !DeleteProjectFiles(buildDirectory.path(), true))
|
||||
&& QDir(origPath).cd(ProjectBuildDirectoryName))
|
||||
{
|
||||
QMessageBox::warning(
|
||||
parent,
|
||||
QObject::tr("Clear Build Artifacts"),
|
||||
QObject::tr("Build artifacts failed to delete for moved project. Please manually delete build directory at \"%1\"")
|
||||
.arg(buildDirectory.path()),
|
||||
QMessageBox::Close);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir cacheDirectory = QDir(newPath);
|
||||
if ((!cacheDirectory.cd(ProjectCacheDirectoryName) || !DeleteProjectFiles(cacheDirectory.path(), true))
|
||||
&& QDir(origPath).cd(ProjectCacheDirectoryName))
|
||||
{
|
||||
QMessageBox::warning(
|
||||
parent,
|
||||
QObject::tr("Clear Asset Cache"),
|
||||
QObject::tr("Asset cache failed to delete for moved project. Please manually delete cache directory at \"%1\"")
|
||||
.arg(cacheDirectory.path()),
|
||||
QMessageBox::Close);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AddProjectDialog(QWidget* parent)
|
||||
{
|
||||
QString path = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(parent, QObject::tr("Select Project Directory")));
|
||||
@@ -214,7 +298,7 @@ namespace O3DE::ProjectManager
|
||||
return PythonBindingsInterface::Get()->RemoveProject(path);
|
||||
}
|
||||
|
||||
bool CopyProjectDialog(const QString& origPath, QWidget* parent)
|
||||
bool CopyProjectDialog(const QString& origPath, ProjectInfo& newProjectInfo, QWidget* parent)
|
||||
{
|
||||
bool copyResult = false;
|
||||
|
||||
@@ -224,6 +308,8 @@ namespace O3DE::ProjectManager
|
||||
QFileDialog::getExistingDirectory(parent, QObject::tr("Select New Project Directory"), parentOrigDir.path()));
|
||||
if (!newPath.isEmpty())
|
||||
{
|
||||
newProjectInfo.m_path = newPath;
|
||||
|
||||
if (!WarnDirectoryOverwrite(newPath, parent))
|
||||
{
|
||||
return false;
|
||||
@@ -235,7 +321,7 @@ namespace O3DE::ProjectManager
|
||||
return copyResult;
|
||||
}
|
||||
|
||||
bool CopyProject(const QString& origPath, const QString& newPath, QWidget* parent)
|
||||
bool CopyProject(const QString& origPath, const QString& newPath, QWidget* parent, bool skipRegister)
|
||||
{
|
||||
// Disallow copying from or into subdirectory
|
||||
if (IsDirectoryDescedent(origPath, newPath) || IsDirectoryDescedent(newPath, origPath))
|
||||
@@ -243,8 +329,13 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList filesToCopy;
|
||||
int filesToCopyCount = 0;
|
||||
qint64 totalSizeInBytes = 0;
|
||||
QStringList skippedPaths
|
||||
{
|
||||
ProjectBuildDirectoryName,
|
||||
ProjectCacheDirectoryName
|
||||
};
|
||||
|
||||
QProgressDialog* progressDialog = new QProgressDialog(parent);
|
||||
progressDialog->setAutoClose(true);
|
||||
@@ -255,7 +346,8 @@ namespace O3DE::ProjectManager
|
||||
progressDialog->show();
|
||||
|
||||
QLocale locale;
|
||||
RecursiveGetAllFiles(origPath, filesToCopy, totalSizeInBytes, [=](int fileCount, int sizeInBytes)
|
||||
QStringList getFilesSkippedPaths(skippedPaths);
|
||||
RecursiveGetAllFiles(origPath, getFilesSkippedPaths, filesToCopyCount, totalSizeInBytes, [=](int fileCount, int sizeInBytes)
|
||||
{
|
||||
// Create a human-readable version of the file size.
|
||||
const QString fileSizeString = locale.formattedDataSize(sizeInBytes);
|
||||
@@ -274,8 +366,10 @@ namespace O3DE::ProjectManager
|
||||
|
||||
// Phase 1: Copy files
|
||||
bool showIgnoreFileDialog = true;
|
||||
bool success = CopyDirectory(progressDialog, origPath, newPath, filesToCopy, numFilesCopied, totalSizeInBytes, copiedFileSize, showIgnoreFileDialog);
|
||||
if (success)
|
||||
QStringList copyFilesSkippedPaths(skippedPaths);
|
||||
bool success = CopyDirectory(progressDialog, origPath, newPath, copyFilesSkippedPaths, filesToCopyCount, numFilesCopied,
|
||||
totalSizeInBytes, copiedFileSize, showIgnoreFileDialog);
|
||||
if (success && !skipRegister)
|
||||
{
|
||||
// Phase 2: Register project
|
||||
success = RegisterProject(newPath);
|
||||
@@ -298,7 +392,7 @@ namespace O3DE::ProjectManager
|
||||
QDir projectDirectory(path);
|
||||
if (projectDirectory.exists())
|
||||
{
|
||||
// Check if there is an actual project hereor just force it
|
||||
// Check if there is an actual project here or just force it
|
||||
if (force || PythonBindingsInterface::Get()->GetProject(path).IsSuccess())
|
||||
{
|
||||
return projectDirectory.removeRecursively();
|
||||
@@ -308,12 +402,12 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MoveProject(QString origPath, QString newPath, QWidget* parent, bool ignoreRegister)
|
||||
bool MoveProject(QString origPath, QString newPath, QWidget* parent, bool skipRegister)
|
||||
{
|
||||
origPath = QDir::toNativeSeparators(origPath);
|
||||
newPath = QDir::toNativeSeparators(newPath);
|
||||
|
||||
if (!WarnDirectoryOverwrite(newPath, parent) || (!ignoreRegister && !UnregisterProject(origPath)))
|
||||
if (!WarnDirectoryOverwrite(newPath, parent) || (!skipRegister && !UnregisterProject(origPath)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -333,8 +427,13 @@ namespace O3DE::ProjectManager
|
||||
|
||||
DeleteProjectFiles(origPath, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If directoy rename succeeded then build and cache directories need to be deleted seperately
|
||||
ClearProjectBuildArtifactsAndCache(origPath, newPath, parent);
|
||||
}
|
||||
|
||||
if (!ignoreRegister && !RegisterProject(newPath))
|
||||
if (!skipRegister && !RegisterProject(newPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -375,46 +474,27 @@ namespace O3DE::ProjectManager
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsVS2019Installed_internal()
|
||||
bool FindSupportedCompiler(QWidget* parent)
|
||||
{
|
||||
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
|
||||
QString programFilesPath = environment.value("ProgramFiles(x86)");
|
||||
QString vsWherePath = programFilesPath + "\\Microsoft Visual Studio\\Installer\\vswhere.exe";
|
||||
auto findCompilerResult = FindSupportedCompilerForPlatform();
|
||||
|
||||
QFileInfo vsWhereFile(vsWherePath);
|
||||
if (vsWhereFile.exists() && vsWhereFile.isFile())
|
||||
if (!findCompilerResult.IsSuccess())
|
||||
{
|
||||
QProcess vsWhereProcess;
|
||||
vsWhereProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
QMessageBox vsWarningMessage(parent);
|
||||
vsWarningMessage.setIcon(QMessageBox::Warning);
|
||||
vsWarningMessage.setWindowTitle(QObject::tr("Create Project"));
|
||||
// Makes link clickable
|
||||
vsWarningMessage.setTextFormat(Qt::RichText);
|
||||
vsWarningMessage.setText(findCompilerResult.GetError());
|
||||
vsWarningMessage.setStandardButtons(QMessageBox::Close);
|
||||
|
||||
vsWhereProcess.start(
|
||||
vsWherePath,
|
||||
QStringList{ "-version", "16.0", "-latest", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"-property", "isComplete" });
|
||||
|
||||
if (!vsWhereProcess.waitForStarted())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (vsWhereProcess.waitForReadyRead())
|
||||
{
|
||||
}
|
||||
|
||||
QString vsWhereOutput(vsWhereProcess.readAllStandardOutput());
|
||||
if (vsWhereOutput.startsWith("1"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
QSpacerItem* horizontalSpacer = new QSpacerItem(600, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
QGridLayout* layout = reinterpret_cast<QGridLayout*>(vsWarningMessage.layout());
|
||||
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
|
||||
vsWarningMessage.exec();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsVS2019Installed()
|
||||
{
|
||||
static bool vs2019Installed = IsVS2019Installed_internal();
|
||||
return vs2019Installed;
|
||||
return findCompilerResult.IsSuccess();
|
||||
}
|
||||
|
||||
ProjectManagerScreen GetProjectManagerScreen(const QString& screen)
|
||||
|
||||
Reference in New Issue
Block a user