Merge branch 'stabilization/2106' into LYN-4507

main
AMZN-Phil 5 years ago committed by GitHub
commit b3fd63a0f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,10 +2,14 @@
# Default LFS endpoint for this repository
url=https://d3df09qsjufr6g.cloudfront.net/api/v1
# To use the endpoint with your fork:
# 1. uncomment the url line below by removing the '#'
# 2. replace 'owner' with the username or organization that owns the fork
# 3. have git ignore your local modification of this file by running
# git update-index --skip-worktree .lfsconfig
# url=https://d3df09qsjufr6g.cloudfront.net/api/v1/fork/owner
# To use the endpoint with your fork, run the following git command
# in your local repository (without the '#'), replacing 'owner' with
# the username or organization that owns the fork.
#
# git config lfs.url "https://d3df09qsjufr6g.cloudfront.net/api/v1/fork/owner"
#
# For example, if your fork is https://github.com/octocat/o3de use
# git config lfs.url "https://d3df09qsjufr6g.cloudfront.net/api/v1/fork/octocat"
#
# IMPORTANT: authenticate with your GitHub username and personal access token
# not your GitHub password

@ -51,7 +51,7 @@ set(ENABLED_GEMS
)
# TODO remove conditional add once AWSNativeSDK libs are fixed for Android and Linux Monolithic release.
set(aws_excluded_platforms Linux Android)
set(aws_excluded_platforms Android)
if (NOT (LY_MONOLITHIC_GAME AND ${PAL_PLATFORM_NAME} IN_LIST aws_excluded_platforms))
list(APPEND ENABLED_GEMS
AWSCore

@ -22,7 +22,9 @@ AZ_PUSH_DISABLE_WARNING(4251 4355 4996, "-Wunknown-warning-option")
AZ_POP_DISABLE_WARNING
// AzCore
#include <AzCore/IO/Path/Path.h>
#include <AzCore/JSON/document.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzFramework
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
@ -195,8 +197,15 @@ CEditorImpl::CEditorImpl()
m_pAssetBrowserRequestHandler = nullptr;
m_assetEditorRequestsHandler = nullptr;
AZ::IO::SystemFile::CreateDir("SessionStatus");
QFile::setPermissions(m_crashLogFileName, QFileDevice::ReadOther | QFileDevice::WriteOther);
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
if (AZ::IO::FixedMaxPath crashLogPath; settingsRegistry->Get(crashLogPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
{
crashLogPath /= m_crashLogFileName;
AZ::IO::SystemFile::CreateDir(crashLogPath.ParentPath().FixedMaxPathString().c_str());
QFile::setPermissions(crashLogPath.c_str(), QFileDevice::ReadOther | QFileDevice::WriteOther);
}
}
}
void CEditorImpl::Initialize()

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:263e95489560dac6e5944ef3caba13e598f83ddead324b943ad7735ba015e1a9
size 70727

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1cf8339fb51f82a68d2ab475c0476960e75a79d96d239c5b7cd272fbe4990ffe
size 2770

@ -75,6 +75,21 @@ WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
{
ui->setupUi(this);
// Set the project preview image
QString projectPreviewPath = QDir(AZ::Utils::GetProjectPath().c_str()).filePath("preview.png");
QFileInfo projectPreviewPathInfo(projectPreviewPath);
if (!projectPreviewPathInfo.exists() || !projectPreviewPathInfo.isFile())
{
projectPreviewPath = ":/WelcomeScreenDialog/DefaultProjectImage.png";
}
ui->activeProjectIcon->setPixmap(
QPixmap(projectPreviewPath).scaled(
ui->activeProjectIcon->size(),
Qt::KeepAspectRatioByExpanding,
Qt::SmoothTransformation
)
);
ui->recentLevelTable->setColumnCount(3);
ui->recentLevelTable->setMouseTracking(true);
ui->recentLevelTable->setContextMenuPolicy(Qt::CustomContextMenu);

@ -1,5 +1,5 @@
<RCC>
<qresource prefix="WelcomeScreenDialog">
<file>DefaultActiveProject.png</file>
<file>DefaultProjectImage.png</file>
</qresource>
</RCC>

@ -158,11 +158,8 @@
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="WelcomeScreenDialog.qrc">:/WelcomeScreenDialog/DefaultActiveProject.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignHCenter | Qt::AlignVCenter</set>
</property>
</widget>
</item>

@ -229,7 +229,6 @@ set(FILES
res/warning16x16.ico
res/water.bmp
res/work_in_progress_icon.ico
res/LegacyLogo.bmp
res/MannFileManagerImageList.bmp
res/infobar/CameraCollision-default.svg
res/infobar/GotoLocation-default.svg

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97f4004da6ec1bf07d522d6675f814e53e36923a45084ff5d7e4113e293d4fec
size 117656

@ -41,7 +41,7 @@ ly_add_target(
)
ly_add_target(
NAME AmazonQtControlGallery APPLICATION
NAME O3DEQtControlGallery APPLICATION
NAMESPACE AZ
AUTOMOC
AUTOUIC

@ -45,6 +45,7 @@
#include <AzToolsFramework/UI/UICore/QTreeViewStateSaver.hxx>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <AzToolsFramework/UI/UICore/ProgressShield.hxx>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <AzToolsFramework/Slice/SliceUtilities.h>
#include <AzToolsFramework/ToolsComponents/EditorInspectorComponent.h>
#include <AzToolsFramework/API/ComponentEntityObjectBus.h>
@ -1589,7 +1590,13 @@ namespace AzToolsFramework
// Multiple changes to the same entity are just split between different undo nodes.
for (AZ::EntityId entityId : m_dirtyEntities)
{
prefabPublicInterface->GenerateUndoNodesForEntityChangeAndUpdateCache(entityId, m_currentBatchUndo);
auto outcome = prefabPublicInterface->GenerateUndoNodesForEntityChangeAndUpdateCache(entityId, m_currentBatchUndo);
if (!outcome.IsSuccess())
{
QMessageBox::warning(
AzToolsFramework::GetActiveWindow(), QString("Error"), QString(outcome.GetError().c_str()), QMessageBox::Ok, QMessageBox::Ok);
}
}
}
}

@ -587,21 +587,21 @@ namespace AzToolsFramework
return AZ::Success(entityId);
}
void PrefabPublicHandler::GenerateUndoNodesForEntityChangeAndUpdateCache(
PrefabOperationResult PrefabPublicHandler::GenerateUndoNodesForEntityChangeAndUpdateCache(
AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch)
{
// Create Undo node on entities if they belong to an instance
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
if (!owningInstance.has_value())
{
return;
return AZ::Success();
}
AZ::Entity* entity = GetEntityById(entityId);
if (!entity)
{
m_prefabUndoCache.PurgeCache(entityId);
return;
return AZ::Success();
}
PrefabDom beforeState;
@ -633,6 +633,41 @@ namespace AzToolsFramework
(&beforeOwningInstance->get() != &afterOwningInstance->get()))
{
isNewParentOwnedByDifferentInstance = true;
// Detect loops. Assert if an instance has been reparented in such a way to generate circular dependencies.
AZStd::vector<Instance*> instancesInvolved;
if (isInstanceContainerEntity)
{
instancesInvolved.push_back(&owningInstance->get());
}
else
{
// Retrieve all nested instances that are part of the subtree under the current entity.
EntityList entities;
RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instancesInvolved);
}
for (Instance* instance : instancesInvolved)
{
const PrefabDom& templateDom =
m_prefabSystemComponentInterface->FindTemplateDom(instance->GetTemplateId());
AZStd::unordered_set<AZ::IO::Path> templatePaths;
PrefabDomUtils::GetTemplateSourcePaths(templateDom, templatePaths);
if (IsCyclicalDependencyFound(afterOwningInstance->get(), templatePaths))
{
// Cancel the operation by restoring the previous parent
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetParent, beforeParentId);
m_prefabUndoCache.UpdateCache(entityId);
// Skip the creation of an undo node
return AZ::Failure(AZStd::string::format(
"Reparent Prefab operation aborted - Cyclical dependency detected\n(%s depends on %s).",
instance->GetTemplateSourcePath().Native().c_str(),
afterOwningInstance->get().GetTemplateSourcePath().Native().c_str()));
}
}
}
}
@ -673,6 +708,8 @@ namespace AzToolsFramework
}
m_prefabUndoCache.UpdateCache(entityId);
return AZ::Success();
}
void PrefabPublicHandler::Internal_HandleContainerOverride(

@ -46,7 +46,7 @@ namespace AzToolsFramework
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
void GenerateUndoNodesForEntityChangeAndUpdateCache(AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) override;
PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) override;
bool IsInstanceContainerEntity(AZ::EntityId entityId) const override;
bool IsLevelInstanceContainerEntity(AZ::EntityId entityId) const override;

@ -79,8 +79,9 @@ namespace AzToolsFramework
*
* @param entityId The entity to patch.
* @param parentUndoBatch The undo batch the undo nodes should be parented to.
* @return Returns Success if the node was generated correctly, or an error message otherwise.
*/
virtual void GenerateUndoNodesForEntityChangeAndUpdateCache(
virtual PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(
AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) = 0;
/**

@ -84,7 +84,10 @@ namespace AssetProcessor
AssetProcessorTest::TearDown();
}
void OnError([[maybe_unused]] const AZ::IO::SystemFile* file, const char* fileName, int errorCode) override
void OnError(
[[maybe_unused]] const AZ::IO::SystemFile* file,
[[maybe_unused]] const char* fileName,
[[maybe_unused]] int errorCode) override
{
AZ_Error("LegacyTestAdapter", false, "File error detected with %s with code %d", fileName, errorCode);
}

@ -7,4 +7,5 @@
set(FILES
Python_linux.cpp
ProjectBuilderWorker_linux.cpp
)

@ -0,0 +1,19 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilderWorker.h>
namespace O3DE::ProjectManager
{
AZ::Outcome<void, QString> ProjectBuilderWorker::BuildProjectForPlatform()
{
QString error = tr("Automatic building on Linux not currently supported!");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
} // namespace O3DE::ProjectManager

@ -7,4 +7,5 @@
set(FILES
Python_mac.cpp
ProjectBuilderWorker_mac.cpp
)

@ -0,0 +1,19 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilderWorker.h>
namespace O3DE::ProjectManager
{
AZ::Outcome<void, QString> ProjectBuilderWorker::BuildProjectForPlatform()
{
QString error = tr("Automatic building on MacOS not currently supported!");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
} // namespace O3DE::ProjectManager

@ -7,4 +7,5 @@
set(FILES
Python_windows.cpp
ProjectBuilderWorker_windows.cpp
)

@ -0,0 +1,175 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilderWorker.h>
#include <ProjectManagerDefs.h>
#include <PythonBindingsInterface.h>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QProcessEnvironment>
#include <QTextStream>
#include <QThread>
namespace O3DE::ProjectManager
{
AZ::Outcome<void, QString> ProjectBuilderWorker::BuildProjectForPlatform()
{
// Check if we are trying to cancel task
if (QThread::currentThread()->isInterruptionRequested())
{
QStringToAZTracePrint(BuildCancelled);
return AZ::Failure(BuildCancelled);
}
QFile logFile(GetLogFilePath());
if (!logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
{
QString error = tr("Failed to open log file.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
EngineInfo engineInfo;
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
if (engineInfoResult.IsSuccess())
{
engineInfo = engineInfoResult.GetValue();
}
else
{
QString error = tr("Failed to get engine info.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
QTextStream logStream(&logFile);
if (QThread::currentThread()->isInterruptionRequested())
{
logFile.close();
QStringToAZTracePrint(BuildCancelled);
return AZ::Failure(BuildCancelled);
}
// Show some kind of progress with very approximate estimates
UpdateProgress(++m_progressEstimate);
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
// Append cmake path to PATH incase it is missing
QDir cmakePath(engineInfo.m_path);
cmakePath.cd("cmake/runtime/bin");
QString pathValue = currentEnvironment.value("PATH");
pathValue += ";" + cmakePath.path();
currentEnvironment.insert("PATH", pathValue);
m_configProjectProcess = new QProcess(this);
m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
m_configProjectProcess->setProcessEnvironment(currentEnvironment);
m_configProjectProcess->start(
"cmake",
QStringList{ "-B", QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix), "-S", m_projectInfo.m_path, "-G",
"Visual Studio 16", "-DLY_3RDPARTY_PATH=" + engineInfo.m_thirdPartyPath });
if (!m_configProjectProcess->waitForStarted())
{
QString error = tr("Configuring project failed to start.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
bool containsGeneratingDone = false;
while (m_configProjectProcess->waitForReadyRead(MaxBuildTimeMSecs))
{
QString configOutput = m_configProjectProcess->readAllStandardOutput();
if (configOutput.contains("Generating done"))
{
containsGeneratingDone = true;
}
logStream << configOutput;
logStream.flush();
UpdateProgress(qMin(++m_progressEstimate, 19));
if (QThread::currentThread()->isInterruptionRequested())
{
logFile.close();
m_configProjectProcess->close();
QStringToAZTracePrint(BuildCancelled);
return AZ::Failure(BuildCancelled);
}
}
if (m_configProjectProcess->exitCode() != 0 || !containsGeneratingDone)
{
QString error = tr("Configuring project failed. See log for details.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
UpdateProgress(++m_progressEstimate);
m_buildProjectProcess = new QProcess(this);
m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
m_buildProjectProcess->setProcessEnvironment(currentEnvironment);
m_buildProjectProcess->start(
"cmake",
QStringList{ "--build", QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix), "--target",
m_projectInfo.m_projectName + ".GameLauncher", "Editor", "--config", "profile" });
if (!m_buildProjectProcess->waitForStarted())
{
QString error = tr("Building project failed to start.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
// There are a lot of steps when building so estimate around 800 more steps ((100 - 20) * 10) remaining
m_progressEstimate = 200;
while (m_buildProjectProcess->waitForReadyRead(MaxBuildTimeMSecs))
{
logStream << m_buildProjectProcess->readAllStandardOutput();
logStream.flush();
// Show 1% progress for every 10 steps completed
UpdateProgress(qMin(++m_progressEstimate / 10, 99));
if (QThread::currentThread()->isInterruptionRequested())
{
// QProcess is unable to kill its child processes so we need to ask the operating system to do that for us
QProcess killBuildProcess;
killBuildProcess.setProcessChannelMode(QProcess::MergedChannels);
killBuildProcess.start(
"cmd.exe", QStringList{ "/C", "taskkill", "/pid", QString::number(m_buildProjectProcess->processId()), "/f", "/t" });
killBuildProcess.waitForFinished();
logStream << "Killing Project Build.";
logStream << killBuildProcess.readAllStandardOutput();
m_buildProjectProcess->kill();
logFile.close();
QStringToAZTracePrint(BuildCancelled);
return AZ::Failure(BuildCancelled);
}
}
if (m_configProjectProcess->exitCode() != 0)
{
QString error = tr("Building project failed. See log for details.");
QStringToAZTracePrint(error);
return AZ::Failure(error);
}
return AZ::Success();
}
} // namespace O3DE::ProjectManager

@ -131,6 +131,17 @@ namespace O3DE::ProjectManager
return false;
}
if (event->type() == QEvent::KeyPress)
{
auto keyEvent = static_cast<const QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Space)
{
const bool isAdded = GemModel::IsAdded(modelIndex);
GemModel::SetIsAdded(*model, modelIndex, !isAdded);
return true;
}
}
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);

@ -1,244 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilder.h>
#include <ProjectManagerDefs.h>
#include <ProjectButtonWidget.h>
#include <PythonBindingsInterface.h>
#include <QProcess>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QDir>
#include <QProcessEnvironment>
//#define MOCK_BUILD_PROJECT true
namespace O3DE::ProjectManager
{
// QProcess::waitForFinished uses -1 to indicate that the process should not timeout
constexpr int MaxBuildTimeMSecs = -1;
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
: QObject()
, m_projectInfo(projectInfo)
{
}
void ProjectBuilderWorker::BuildProject()
{
#ifdef MOCK_BUILD_PROJECT
for (int i = 0; i < 10; ++i)
{
QThread::sleep(1);
UpdateProgress(i * 10);
}
Done(m_projectPath);
#else
EngineInfo engineInfo;
AZ::Outcome<EngineInfo> engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
if (engineInfoResult.IsSuccess())
{
engineInfo = engineInfoResult.GetValue();
}
else
{
emit Done(tr("Failed to get engine info."));
return;
}
// Show some kind of progress with very approximate estimates
UpdateProgress(1);
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
// Append cmake path to PATH incase it is missing
QDir cmakePath(engineInfo.m_path);
cmakePath.cd("cmake/runtime/bin");
QString pathValue = currentEnvironment.value("PATH");
pathValue += ";" + cmakePath.path();
currentEnvironment.insert("PATH", pathValue);
QProcess configProjectProcess;
configProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
configProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
configProjectProcess.setProcessEnvironment(currentEnvironment);
configProjectProcess.start(
"cmake",
QStringList
{
"-B",
QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix),
"-S",
m_projectInfo.m_path,
"-G",
"Visual Studio 16",
"-DLY_3RDPARTY_PATH=" + engineInfo.m_thirdPartyPath
});
if (!configProjectProcess.waitForStarted())
{
emit Done(tr("Configuring project failed to start."));
return;
}
if (!configProjectProcess.waitForFinished(MaxBuildTimeMSecs))
{
WriteErrorLog(configProjectProcess.readAllStandardOutput());
emit Done(tr("Configuring project timed out. See log for details"));
return;
}
QString configProjectOutput(configProjectProcess.readAllStandardOutput());
if (configProjectProcess.exitCode() != 0 || !configProjectOutput.contains("Generating done"))
{
WriteErrorLog(configProjectOutput);
emit Done(tr("Configuring project failed. See log for details."));
return;
}
UpdateProgress(20);
QProcess buildProjectProcess;
buildProjectProcess.setProcessChannelMode(QProcess::MergedChannels);
buildProjectProcess.setWorkingDirectory(m_projectInfo.m_path);
buildProjectProcess.setProcessEnvironment(currentEnvironment);
buildProjectProcess.start(
"cmake",
QStringList
{
"--build",
QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix),
"--target",
m_projectInfo.m_projectName + ".GameLauncher",
"Editor",
"--config",
"profile"
});
if (!buildProjectProcess.waitForStarted())
{
emit Done(tr("Building project failed to start."));
return;
}
if (!buildProjectProcess.waitForFinished(MaxBuildTimeMSecs))
{
WriteErrorLog(configProjectProcess.readAllStandardOutput());
emit Done(tr("Building project timed out. See log for details"));
return;
}
QString buildProjectOutput(buildProjectProcess.readAllStandardOutput());
if (configProjectProcess.exitCode() != 0)
{
WriteErrorLog(buildProjectOutput);
emit Done(tr("Building project failed. See log for details."));
}
else
{
emit Done("");
}
#endif
}
QString ProjectBuilderWorker::LogFilePath() const
{
QDir logFilePath(m_projectInfo.m_path);
logFilePath.cd(ProjectBuildPathPostfix);
return logFilePath.filePath(ProjectBuildErrorLogPathPostfix);
}
void ProjectBuilderWorker::WriteErrorLog(const QString& log)
{
QFile logFile(LogFilePath());
// Overwrite file with truncate
if (logFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
QTextStream output(&logFile);
output << log;
logFile.close();
}
}
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
: QObject()
, m_projectInfo(projectInfo)
, m_projectButton(projectButton)
, m_parent(parent)
{
m_worker = new ProjectBuilderWorker(m_projectInfo);
m_worker->moveToThread(&m_workerThread);
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
connect(m_worker, &ProjectBuilderWorker::UpdateProgress, this, &ProjectBuilderController::UpdateUIProgress);
}
ProjectBuilderController::~ProjectBuilderController()
{
m_workerThread.quit();
m_workerThread.wait();
}
void ProjectBuilderController::Start()
{
m_workerThread.start();
UpdateUIProgress(0);
}
void ProjectBuilderController::SetProjectButton(ProjectButton* projectButton)
{
m_projectButton = projectButton;
}
QString ProjectBuilderController::GetProjectPath() const
{
return m_projectInfo.m_path;
}
void ProjectBuilderController::UpdateUIProgress(int progress)
{
if (m_projectButton)
{
m_projectButton->SetButtonOverlayText(QString("%1 (%2%)\n\n").arg(tr("Building Project..."), QString::number(progress)));
m_projectButton->SetProgressBarValue(progress);
}
}
void ProjectBuilderController::HandleResults(const QString& result)
{
if (!result.isEmpty())
{
if (result.contains(tr("log")))
{
QMessageBox::StandardButton openLog = QMessageBox::critical(
m_parent,
tr("Project Failed to Build!"),
result + tr("\n\nWould you like to view log?"),
QMessageBox::No | QMessageBox::Yes);
if (openLog == QMessageBox::Yes)
{
// Open application assigned to this file type
QDesktopServices::openUrl(QUrl("file:///" + m_worker->LogFilePath()));
}
}
else
{
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
}
}
emit Done();
}
} // namespace O3DE::ProjectManager

@ -0,0 +1,113 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilderController.h>
#include <ProjectBuilderWorker.h>
#include <ProjectButtonWidget.h>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
namespace O3DE::ProjectManager
{
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
: QObject()
, m_projectInfo(projectInfo)
, m_projectButton(projectButton)
, m_lastProgress(0)
, m_parent(parent)
{
m_worker = new ProjectBuilderWorker(m_projectInfo);
m_worker->moveToThread(&m_workerThread);
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
connect(m_worker, &ProjectBuilderWorker::UpdateProgress, this, &ProjectBuilderController::UpdateUIProgress);
}
ProjectBuilderController::~ProjectBuilderController()
{
m_workerThread.requestInterruption();
m_workerThread.quit();
m_workerThread.wait();
}
void ProjectBuilderController::Start()
{
m_workerThread.start();
UpdateUIProgress(0);
}
void ProjectBuilderController::SetProjectButton(ProjectButton* projectButton)
{
m_projectButton = projectButton;
if (projectButton)
{
projectButton->SetProjectButtonAction(tr("Cancel Build"), [this] { HandleCancel(); });
if (m_lastProgress != 0)
{
UpdateUIProgress(m_lastProgress);
}
}
}
const ProjectInfo& ProjectBuilderController::GetProjectInfo() const
{
return m_projectInfo;
}
void ProjectBuilderController::UpdateUIProgress(int progress)
{
m_lastProgress = progress;
if (m_projectButton)
{
m_projectButton->SetButtonOverlayText(QString("%1 (%2%)\n\n").arg(tr("Building Project..."), QString::number(progress)));
m_projectButton->SetProgressBarValue(progress);
}
}
void ProjectBuilderController::HandleResults(const QString& result)
{
if (!result.isEmpty())
{
if (result.contains(tr("log")))
{
QMessageBox::StandardButton openLog = QMessageBox::critical(
m_parent,
tr("Project Failed to Build!"),
result + tr("\n\nWould you like to view log?"),
QMessageBox::No | QMessageBox::Yes);
if (openLog == QMessageBox::Yes)
{
// Open application assigned to this file type
QDesktopServices::openUrl(QUrl("file:///" + m_worker->GetLogFilePath()));
}
}
else
{
QMessageBox::critical(m_parent, tr("Project Failed to Build!"), result);
}
emit Done(false);
return;
}
emit Done(true);
}
void ProjectBuilderController::HandleCancel()
{
m_workerThread.quit();
emit Done(false);
}
} // namespace O3DE::ProjectManager

@ -12,32 +12,12 @@
#include <QThread>
#endif
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace O3DE::ProjectManager
{
QT_FORWARD_DECLARE_CLASS(ProjectButton)
class ProjectBuilderWorker : public QObject
{
Q_OBJECT
public:
explicit ProjectBuilderWorker(const ProjectInfo& projectInfo);
~ProjectBuilderWorker() = default;
QString LogFilePath() const;
public slots:
void BuildProject();
signals:
void UpdateProgress(int progress);
void Done(QString result);
private:
void WriteErrorLog(const QString& log);
ProjectInfo m_projectInfo;
};
QT_FORWARD_DECLARE_CLASS(ProjectBuilderWorker)
class ProjectBuilderController : public QObject
{
@ -48,15 +28,16 @@ namespace O3DE::ProjectManager
~ProjectBuilderController();
void SetProjectButton(ProjectButton* projectButton);
QString GetProjectPath() const;
const ProjectInfo& GetProjectInfo() const;
public slots:
void Start();
void UpdateUIProgress(int progress);
void HandleResults(const QString& result);
void HandleCancel();
signals:
void Done();
void Done(bool success = true);
private:
ProjectInfo m_projectInfo;
@ -64,5 +45,7 @@ namespace O3DE::ProjectManager
QThread m_workerThread;
ProjectButton* m_projectButton;
QWidget* m_parent;
int m_lastProgress;
};
} // namespace O3DE::ProjectManager

@ -0,0 +1,71 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <ProjectBuilderWorker.h>
#include <ProjectManagerDefs.h>
#include <QDir>
//#define MOCK_BUILD_PROJECT true
namespace O3DE::ProjectManager
{
const QString ProjectBuilderWorker::BuildCancelled = ProjectBuilderWorker::tr("Build Cancelled.");
ProjectBuilderWorker::ProjectBuilderWorker(const ProjectInfo& projectInfo)
: QObject()
, m_projectInfo(projectInfo)
, m_progressEstimate(0)
{
}
void ProjectBuilderWorker::BuildProject()
{
#ifdef MOCK_BUILD_PROJECT
for (int i = 0; i < 10; ++i)
{
QThread::sleep(1);
UpdateProgress(i * 10);
}
Done("");
#else
auto result = BuildProjectForPlatform();
if (result.IsSuccess())
{
emit Done();
}
else
{
emit Done(result.GetError());
}
#endif
}
QString ProjectBuilderWorker::GetLogFilePath() const
{
QDir logFilePath(m_projectInfo.m_path);
// Make directories if they aren't on disk
if (!logFilePath.cd(ProjectBuildPathPostfix))
{
logFilePath.mkpath(ProjectBuildPathPostfix);
logFilePath.cd(ProjectBuildPathPostfix);
}
if (!logFilePath.cd(ProjectBuildPathCmakeFiles))
{
logFilePath.mkpath(ProjectBuildPathCmakeFiles);
logFilePath.cd(ProjectBuildPathCmakeFiles);
}
return logFilePath.filePath(ProjectBuildErrorLogName);
}
void ProjectBuilderWorker::QStringToAZTracePrint([[maybe_unused]] const QString& error)
{
AZ_TracePrintf("Project Manager", error.toStdString().c_str());
}
} // namespace O3DE::ProjectManager

@ -0,0 +1,52 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <ProjectInfo.h>
#include <AzCore/Outcome/Outcome.h>
#include <QObject>
#endif
QT_FORWARD_DECLARE_CLASS(QProcess)
namespace O3DE::ProjectManager
{
class ProjectBuilderWorker : public QObject
{
// QProcess::waitForFinished uses -1 to indicate that the process should not timeout
static constexpr int MaxBuildTimeMSecs = -1;
// Build was cancelled
static const QString BuildCancelled;
Q_OBJECT
public:
explicit ProjectBuilderWorker(const ProjectInfo& projectInfo);
~ProjectBuilderWorker() = default;
QString GetLogFilePath() const;
public slots:
void BuildProject();
signals:
void UpdateProgress(int progress);
void Done(QString result = "");
private:
AZ::Outcome<void, QString> BuildProjectForPlatform();
void QStringToAZTracePrint(const QString& error);
QProcess* m_configProjectProcess = nullptr;
QProcess* m_buildProjectProcess = nullptr;
ProjectInfo m_projectInfo;
int m_progressEstimate;
};
} // namespace O3DE::ProjectManager

@ -40,8 +40,8 @@ namespace O3DE::ProjectManager
m_overlayLabel->setVisible(false);
vLayout->addWidget(m_overlayLabel);
m_buildButton = new QPushButton(tr("Build Project"), this);
m_buildButton->setVisible(false);
m_actionButton = new QPushButton(tr("Project Action"), this);
m_actionButton->setVisible(false);
m_progressBar = new QProgressBar(this);
m_progressBar->setObjectName("labelButtonProgressBar");
@ -78,9 +78,9 @@ namespace O3DE::ProjectManager
return m_progressBar;
}
QPushButton* LabelButton::GetBuildButton()
QPushButton* LabelButton::GetActionButton()
{
return m_buildButton;
return m_actionButton;
}
ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent, bool processing)
@ -135,7 +135,6 @@ namespace O3DE::ProjectManager
void ProjectButton::ProcessingSetup()
{
m_projectImageLabel->GetOverlayLabel()->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
m_projectImageLabel->SetEnabled(false);
m_projectImageLabel->SetOverlayText(tr("Processing...\n\n"));
@ -146,8 +145,6 @@ namespace O3DE::ProjectManager
void ProjectButton::ReadySetup()
{
connect(m_projectImageLabel->GetBuildButton(), &QPushButton::clicked, [this](){ emit BuildProject(m_projectInfo); });
QMenu* menu = new QMenu(this);
menu->addAction(tr("Edit Project Settings..."), this, [this]() { emit EditProject(m_projectInfo.m_path); });
menu->addAction(tr("Build"), this, [this]() { emit BuildProject(m_projectInfo); });
@ -168,18 +165,38 @@ namespace O3DE::ProjectManager
m_projectFooter->layout()->addWidget(projectMenuButton);
}
void ProjectButton::SetLaunchButtonEnabled(bool enabled)
void ProjectButton::SetProjectButtonAction(const QString& text, AZStd::function<void()> lambda)
{
m_projectImageLabel->SetEnabled(enabled);
QPushButton* projectActionButton = m_projectImageLabel->GetActionButton();
if (!m_actionButtonConnection)
{
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
m_projectImageLabel->layout()->addItem(buttonSpacer);
m_projectImageLabel->layout()->addWidget(projectActionButton);
projectActionButton->setVisible(true);
}
else
{
disconnect(m_actionButtonConnection);
}
projectActionButton->setText(text);
m_actionButtonConnection = connect(projectActionButton, &QPushButton::clicked, lambda);
}
void ProjectButton::ShowBuildButton(bool show)
void ProjectButton::SetProjectBuildButtonAction()
{
QSpacerItem* buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
SetProjectButtonAction(tr("Build Project"), [this]() { emit BuildProject(m_projectInfo); });
}
m_projectImageLabel->layout()->addItem(buttonSpacer);
m_projectImageLabel->layout()->addWidget(m_projectImageLabel->GetBuildButton());
m_projectImageLabel->GetBuildButton()->setVisible(show);
void ProjectButton::BuildThisProject()
{
emit BuildProject(m_projectInfo);
}
void ProjectButton::SetLaunchButtonEnabled(bool enabled)
{
m_projectImageLabel->SetEnabled(enabled);
}
void ProjectButton::SetButtonOverlayText(const QString& text)
@ -191,4 +208,9 @@ namespace O3DE::ProjectManager
{
m_projectImageLabel->GetProgressBar()->setValue(progress);
}
LabelButton* ProjectButton::GetLabelButton()
{
return m_projectImageLabel;
}
} // namespace O3DE::ProjectManager

@ -9,12 +9,15 @@
#if !defined(Q_MOC_RUN)
#include <ProjectInfo.h>
#include <AzCore/std/functional.h>
#include <QLabel>
#include <QPushButton>
#include <QSpacerItem>
#include <QLayout>
#endif
QT_FORWARD_DECLARE_CLASS(QPixmap)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QProgressBar)
@ -34,7 +37,7 @@ namespace O3DE::ProjectManager
QLabel* GetOverlayLabel();
QProgressBar* GetProgressBar();
QPushButton* GetBuildButton();
QPushButton* GetActionButton();
signals:
void triggered();
@ -45,7 +48,7 @@ namespace O3DE::ProjectManager
private:
QLabel* m_overlayLabel;
QProgressBar* m_progressBar;
QPushButton* m_buildButton;
QPushButton* m_actionButton;
bool m_enabled = true;
};
@ -58,10 +61,13 @@ namespace O3DE::ProjectManager
explicit ProjectButton(const ProjectInfo& m_projectInfo, QWidget* parent = nullptr, bool processing = false);
~ProjectButton() = default;
void SetProjectButtonAction(const QString& text, AZStd::function<void()> lambda);
void SetProjectBuildButtonAction();
void SetLaunchButtonEnabled(bool enabled);
void ShowBuildButton(bool show);
void SetButtonOverlayText(const QString& text);
void SetProgressBarValue(int progress);
LabelButton* GetLabelButton();
signals:
void OpenProject(const QString& projectName);
@ -75,9 +81,12 @@ namespace O3DE::ProjectManager
void BaseSetup();
void ProcessingSetup();
void ReadySetup();
void BuildThisProject();
ProjectInfo m_projectInfo;
LabelButton* m_projectImageLabel;
QFrame* m_projectFooter;
QMetaObject::Connection m_actionButtonConnection;
};
} // namespace O3DE::ProjectManager

@ -14,6 +14,7 @@ namespace O3DE::ProjectManager
inline constexpr static int ProjectPreviewImageHeight = 280;
static const QString ProjectBuildPathPostfix = "build/windows_vs2019";
static const QString ProjectBuildErrorLogPathPostfix = "CMakeFiles/CMakeProjectBuildError.log";
static const QString ProjectBuildPathCmakeFiles = "CMakeFiles";
static const QString ProjectBuildErrorLogName = "CMakeProjectBuildError.log";
static const QString ProjectPreviewImagePath = "preview.png";
} // namespace O3DE::ProjectManager

@ -11,7 +11,7 @@
#include <ProjectButtonWidget.h>
#include <PythonBindingsInterface.h>
#include <ProjectUtils.h>
#include <ProjectBuilder.h>
#include <ProjectBuilderController.h>
#include <ScreensCtrl.h>
#include <AzQtComponents/Components/FlowLayout.h>
@ -43,8 +43,6 @@
#include <QDir>
#include <QGuiApplication>
//#define DISPLAY_PROJECT_DEV_DATA true
namespace O3DE::ProjectManager
{
ProjectsScreen::ProjectsScreen(QWidget* parent)
@ -86,7 +84,7 @@ namespace O3DE::ProjectManager
layout->setAlignment(Qt::AlignTop);
frame->setLayout(layout);
QLabel* titleLabel = new QLabel(tr("Ready. Set. Create."), this);
QLabel* titleLabel = new QLabel(tr("Ready? Set. Create!"), this);
titleLabel->setObjectName("titleLabel");
layout->addWidget(titleLabel);
@ -166,43 +164,38 @@ namespace O3DE::ProjectManager
projectsScrollArea->setWidget(scrollWidget);
projectsScrollArea->setWidgetResizable(true);
#ifndef DISPLAY_PROJECT_DEV_DATA
// Iterate once to insert building project first
if (!buildProjectPath.isEmpty())
QVector<ProjectInfo> nonProcessingProjects;
buildProjectPath = QDir::fromNativeSeparators(buildProjectPath);
for (auto& project : projectsResult.GetValue())
{
buildProjectPath = QDir::fromNativeSeparators(buildProjectPath);
for (auto project : projectsResult.GetValue())
if (projectButton && !*projectButton)
{
if (QDir::fromNativeSeparators(project.m_path) == buildProjectPath)
{
ProjectButton* buildingProjectButton = CreateProjectButton(project, flowLayout, true);
if (projectButton)
{
*projectButton = buildingProjectButton;
}
break;
*projectButton = CreateProjectButton(project, flowLayout, true);
continue;
}
}
nonProcessingProjects.append(project);
}
for (auto project : projectsResult.GetValue())
#else
ProjectInfo project = projectsResult.GetValue().at(0);
for (int i = 0; i < 15; i++)
#endif
for (auto& project : nonProcessingProjects)
{
// Add all other projects skipping building project
// Safe if no building project because it is just an empty string
if (project.m_path != buildProjectPath)
{
ProjectButton* projectButtonWidget = CreateProjectButton(project, flowLayout);
ProjectButton* projectButtonWidget = CreateProjectButton(project, flowLayout);
if (RequiresBuildProjectIterator(project.m_path) != m_requiresBuild.end())
{
projectButtonWidget->ShowBuildButton(true);
}
if (BuildQueueContainsProject(project.m_path))
{
projectButtonWidget->SetProjectButtonAction(tr("Cancel Queued Build"),
[this, project]
{
UnqueueBuildProject(project);
SuggestBuildProjectMsg(project, false);
});
}
else if (RequiresBuildProjectIterator(project.m_path) != m_requiresBuild.end())
{
projectButtonWidget->SetProjectBuildButtonAction();
}
}
@ -244,9 +237,9 @@ namespace O3DE::ProjectManager
// Make sure to update builder with latest Project Button
if (m_currentBuilder)
{
ProjectButton* projectButtonPtr;
ProjectButton* projectButtonPtr = nullptr;
m_projectsContent = CreateProjectsContent(m_currentBuilder->GetProjectPath(), &projectButtonPtr);
m_projectsContent = CreateProjectsContent(m_currentBuilder->GetProjectInfo().m_path, &projectButtonPtr);
m_currentBuilder->SetProjectButton(projectButtonPtr);
}
else
@ -414,17 +407,15 @@ namespace O3DE::ProjectManager
}
}
void ProjectsScreen::SuggestBuildProject(const ProjectInfo& projectInfo)
void ProjectsScreen::SuggestBuildProjectMsg(const ProjectInfo& projectInfo, bool showMessage)
{
if (projectInfo.m_needsBuild)
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end())
{
if (RequiresBuildProjectIterator(projectInfo.m_path) == m_requiresBuild.end())
{
m_requiresBuild.append(projectInfo);
}
ResetProjectsContent();
m_requiresBuild.append(projectInfo);
}
else
ResetProjectsContent();
if (showMessage)
{
QMessageBox::information(this,
tr("Project Should be rebuilt."),
@ -432,6 +423,11 @@ namespace O3DE::ProjectManager
}
}
void ProjectsScreen::SuggestBuildProject(const ProjectInfo& projectInfo)
{
SuggestBuildProjectMsg(projectInfo, true);
}
void ProjectsScreen::QueueBuildProject(const ProjectInfo& projectInfo)
{
auto requiredIter = RequiresBuildProjectIterator(projectInfo.m_path);
@ -445,14 +441,22 @@ namespace O3DE::ProjectManager
if (m_buildQueue.empty() && !m_currentBuilder)
{
StartProjectBuild(projectInfo);
// Projects Content is already reset in fuction
}
else
{
m_buildQueue.append(projectInfo);
ResetProjectsContent();
}
}
}
void ProjectsScreen::UnqueueBuildProject(const ProjectInfo& projectInfo)
{
m_buildQueue.removeAll(projectInfo);
ResetProjectsContent();
}
void ProjectsScreen::NotifyCurrentScreen()
{
if (ShouldDisplayFirstTimeContent())
@ -488,7 +492,7 @@ namespace O3DE::ProjectManager
return PythonBindingsInterface::Get()->RemoveInvalidProjects();
}
void ProjectsScreen::StartProjectBuild(const ProjectInfo& projectInfo)
bool ProjectsScreen::StartProjectBuild(const ProjectInfo& projectInfo)
{
if (ProjectUtils::IsVS2019Installed())
{
@ -508,25 +512,42 @@ namespace O3DE::ProjectManager
}
else
{
ProjectBuildDone();
SuggestBuildProjectMsg(projectInfo, false);
return false;
}
return true;
}
return false;
}
void ProjectsScreen::ProjectBuildDone()
void ProjectsScreen::ProjectBuildDone(bool success)
{
ProjectInfo currentBuilderProject;
if (!success)
{
currentBuilderProject = m_currentBuilder->GetProjectInfo();
}
delete m_currentBuilder;
m_currentBuilder = nullptr;
if (!m_buildQueue.empty())
if (!success)
{
StartProjectBuild(m_buildQueue.front());
m_buildQueue.pop_front();
SuggestBuildProjectMsg(currentBuilderProject, false);
}
else
if (!m_buildQueue.empty())
{
ResetProjectsContent();
while (!StartProjectBuild(m_buildQueue.front()) && m_buildQueue.size() > 1)
{
m_buildQueue.pop_front();
}
m_buildQueue.pop_front();
}
ResetProjectsContent();
}
QList<ProjectInfo>::iterator ProjectsScreen::RequiresBuildProjectIterator(const QString& projectPath)

@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
protected:
void NotifyCurrentScreen() override;
void ProjectBuildDone();
void SuggestBuildProjectMsg(const ProjectInfo& projectInfo, bool showMessage);
protected slots:
void HandleNewProjectButton();
@ -50,6 +50,9 @@ namespace O3DE::ProjectManager
void SuggestBuildProject(const ProjectInfo& projectInfo);
void QueueBuildProject(const ProjectInfo& projectInfo);
void UnqueueBuildProject(const ProjectInfo& projectInfo);
void ProjectBuildDone(bool success = true);
void paintEvent(QPaintEvent* event) override;
@ -61,7 +64,7 @@ namespace O3DE::ProjectManager
bool ShouldDisplayFirstTimeContent();
bool RemoveInvalidProjects();
void StartProjectBuild(const ProjectInfo& projectInfo);
bool StartProjectBuild(const ProjectInfo& projectInfo);
QList<ProjectInfo>::iterator RequiresBuildProjectIterator(const QString& projectPath);
bool BuildQueueContainsProject(const QString& projectPath);
bool WarnIfInBuildQueue(const QString& projectPath);

@ -39,8 +39,10 @@ set(FILES
Source/ProjectInfo.cpp
Source/ProjectUtils.h
Source/ProjectUtils.cpp
Source/ProjectBuilder.h
Source/ProjectBuilder.cpp
Source/ProjectBuilderWorker.h
Source/ProjectBuilderWorker.cpp
Source/ProjectBuilderController.h
Source/ProjectBuilderController.cpp
Source/UpdateProjectSettingsScreen.h
Source/UpdateProjectSettingsScreen.cpp
Source/NewProjectSettingsScreen.h

@ -86,7 +86,7 @@ namespace AZ
// AssImp only has one bitangentStream per mesh.
bitangentStream->SetBitangentSetIndex(0);
bitangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
bitangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
bitangentStream->ReserveContainerSpace(vertexCount);
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
{

@ -88,7 +88,7 @@ namespace AZ
// AssImp only has one tangentStream per mesh.
tangentStream->SetTangentSetIndex(0);
tangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
tangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
tangentStream->ReserveContainerSpace(vertexCount);
for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
{

@ -23,9 +23,9 @@ namespace AZ
{
enum class TangentSpace
{
FromFbx = 0,
MikkT = 1,
EMotionFX = 2
FromSourceScene = 0,
MikkT = 1,
EMotionFX = 2
};
enum class BitangentMethod

@ -20,7 +20,7 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<MeshVertexBitangentData>()->Version(1);
serializeContext->Class<MeshVertexBitangentData>()->Version(2);
}
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
@ -34,7 +34,7 @@ namespace AZ
->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex)
->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace)
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromFbx>("FromFbx")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
}
}

@ -50,7 +50,7 @@ namespace AZ
SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
protected:
AZStd::vector<AZ::Vector3> m_bitangents;
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromFbx;
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene;
size_t m_setIndex = 0;
};

@ -20,7 +20,7 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<MeshVertexTangentData>()->Version(1);
serializeContext->Class<MeshVertexTangentData>()->Version(2);
}
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
@ -34,7 +34,7 @@ namespace AZ
->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex)
->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace)
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromFbx>("FromFbx")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
}
}

@ -49,7 +49,7 @@ namespace AZ
SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
protected:
AZStd::vector<AZ::Vector4> m_tangents;
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromFbx;
AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene;
size_t m_setIndex = 0;
};

@ -142,7 +142,7 @@ namespace AZ
return;
}
serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(1)
serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(2)
->Field("tangentSpace", &TangentsRule::m_tangentSpace)
->Field("bitangentMethod", &TangentsRule::m_bitangentMethod)
->Field("normalize", &TangentsRule::m_normalize)
@ -156,7 +156,7 @@ namespace AZ
->Attribute("AutoExpand", true)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_tangentSpace, "Tangent space", "Specify the tangent space used for normal map baking. Choose 'From Fbx' to extract the tangents and bitangents directly from the Fbx file. When there is no tangents rule or the Fbx has no tangents stored inside it, the 'MikkT' option will be used with orthogonal tangents of unit length, so with the normalize option enabled, using the first UV set.")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx, "From Fbx")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene, "From Source Scene")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::MikkT, "MikkT")
->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX, "EMotion FX")
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)

@ -83,7 +83,7 @@ namespace AZ
auto* bitangentData = AZStd::any_cast<AZ::SceneData::GraphData::MeshVertexBitangentData>(&data);
bitangentData->AppendBitangent(AZ::Vector3{0.12f, 0.34f, 0.56f});
bitangentData->AppendBitangent(AZ::Vector3{0.77f, 0.88f, 0.99f});
bitangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
bitangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
bitangentData->SetBitangentSetIndex(1);
return true;
}
@ -317,7 +317,7 @@ namespace AZ
ExpectExecute("TestExpectFloatEquals(bitangentData.y, 0.88)");
ExpectExecute("TestExpectFloatEquals(bitangentData.z, 0.99)");
ExpectExecute("TestExpectIntegerEquals(meshVertexBitangentData:GetBitangentSetIndex(), 1)");
ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetTangentSpace(), MeshVertexBitangentData.FromFbx)");
ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetTangentSpace(), MeshVertexBitangentData.FromSourceScene)");
}
TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_MeshVertexTangentData_AccessWorks)

@ -21,6 +21,7 @@ ly_add_target(
AZ::AzFramework
PUBLIC
Gem::AWSCore
3rdParty::AWSNativeSDK::Core
)
ly_add_target(

@ -28,7 +28,7 @@ float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lig
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight, lightingData.diffuseResponse);
}
if(o_clearCoat_feature_enabled)

@ -28,7 +28,7 @@ float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lig
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight, lightingData.diffuseResponse);
}
if(o_clearCoat_feature_enabled)

@ -20,7 +20,7 @@
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
float3 diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight, lightingData.diffuseResponse);
if(o_clearCoat_feature_enabled)
{

@ -21,10 +21,10 @@
// ------- Diffuse Lighting -------
//! Simple Lambertian BRDF.
float3 DiffuseLambertian(float3 albedo, float3 normal, float3 dirToLight)
float3 DiffuseLambertian(float3 albedo, float3 normal, float3 dirToLight, float diffuseResponse)
{
float NdotL = saturate(dot(normal, dirToLight));
return albedo * NdotL * INV_PI;
return albedo * NdotL * INV_PI * diffuseResponse;
}
// Normalized Disney diffuse function taken from Frostbite's PBR course notes (page 10):

@ -129,7 +129,7 @@ namespace EMotionFX
return;
}
serializeContext->Class<MotionSamplingRule, IRule>()->Version(3)
serializeContext->Class<MotionSamplingRule, IRule>()->Version(4)
->Field("motionDataType", &MotionSamplingRule::m_motionDataType)
->Field("sampleRateMethod", &MotionSamplingRule::m_sampleRateMethod)
->Field("customSampleRate", &MotionSamplingRule::m_customSampleRate)
@ -151,7 +151,7 @@ namespace EMotionFX
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &MotionSamplingRule::m_sampleRateMethod, "Sample rate", "Either use the Fbx sample rate or use a custom sample rate. The sample rate is automatically limited to the rate from Fbx.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
->EnumAttribute(SampleRateMethod::FromFbx, "From Fbx")
->EnumAttribute(SampleRateMethod::FromSourceScene, "From Source Scene")
->EnumAttribute(SampleRateMethod::Custom, "Custom sample rate")
->DataElement(AZ::Edit::UIHandlers::Default, &MotionSamplingRule::m_keepDuration, "Keep duration", "When enabled this keep the duration the same as the Fbx motion duration, even if no joints are animated. "
"When this option is disabled and the motion doesn't animate any joints then the resulting motion will have a duration of zero seconds.")
@ -199,7 +199,7 @@ namespace EMotionFX
AZ::Crc32 MotionSamplingRule::GetVisibilityCustomSampleRate() const
{
return m_sampleRateMethod == SampleRateMethod::FromFbx ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
return m_sampleRateMethod == SampleRateMethod::FromSourceScene ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
}
AZ::Crc32 MotionSamplingRule::GetVisibilityAllowedSizePercentage() const

@ -30,7 +30,7 @@ namespace EMotionFX
enum class SampleRateMethod : AZ::u8
{
FromFbx = 0,
FromSourceScene = 0,
Custom = 1
};
@ -71,7 +71,7 @@ namespace EMotionFX
AZ::Crc32 GetVisibilityAllowedSizePercentage() const;
float m_customSampleRate = 60.0f;
SampleRateMethod m_sampleRateMethod = SampleRateMethod::FromFbx;
SampleRateMethod m_sampleRateMethod = SampleRateMethod::FromSourceScene;
AZ::TypeId m_motionDataType = AZ::TypeId::CreateNull();
bool m_keepDuration = true;

@ -107,7 +107,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
NAME Multiplayer.Builders GEM_MODULE
NAMESPACE Gem
OUTPUT_NAME Gem.Multiplayer.Builders
FILES_CMAKE
multiplayer_tools_files.cmake
INCLUDE_DIRECTORIES

@ -123,8 +123,8 @@ namespace AZ::SceneGenerationComponents
while (uvData)
{
// Get the tangents and bitangents from the source scene.
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
if (fbxTangentData && fbxBitangentData)
{
@ -198,8 +198,8 @@ namespace AZ::SceneGenerationComponents
}
// Check if we had tangents inside the source scene file.
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
// Check what tangent spaces we need.
AZStd::vector<AZ::SceneAPI::DataTypes::TangentSpace> requiredSpaces = CollectRequiredTangentSpaces(scene);
@ -212,7 +212,7 @@ namespace AZ::SceneGenerationComponents
}
// If all we need is import from the source scene, and we have tangent data from the source scene already, then skip generating.
if ((requiredSpaces.size() == 1 && requiredSpaces[0] == AZ::SceneAPI::DataTypes::TangentSpace::FromFbx) && fbxTangentData && fbxBitangentData)
if ((requiredSpaces.size() == 1 && requiredSpaces[0] == AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene) && fbxTangentData && fbxBitangentData)
{
return true;
}
@ -232,7 +232,7 @@ namespace AZ::SceneGenerationComponents
switch (space)
{
// If we want Fbx tangents, we don't need to do anything for that.
case AZ::SceneAPI::DataTypes::TangentSpace::FromFbx:
case AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene:
{
allSuccess &= true;
}

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:61efd8df621780af995fc1250918df5e00364ff00f849bef67702cd4b0a152e1
size 65537
oid sha256:41239f8345fa91fe546442208461ad3cd17c7a7a7047af45018b97363bfea204
size 109783

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cf6d56fe4c367d39bd78500dd34332fcad57ad41241768b52781dbdb60ddd972
size 347568
oid sha256:7c8433178baebafe984ca23d9325d3c71b5a177fc3b3b869afbb01a583542fbe
size 462842

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2
size 32037
oid sha256:094620c172320b062f9a1f8cc758ef4bbee11bc0a6049f46ad6b42f9bf613c92
size 9679

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9f41a37d2347a617e93bd97adaf6d4c161c471ca3ef7e04b98c65ddda52396dc
size 27833
oid sha256:f3c651ca45a83d0f68bdaa466826a29b2ca6f674e225d90e68b7dbadc2ba582d
size 6620

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b07984494059bf827bc485cbea06d12e0283811face1a18799495f9ba7ae8af1
size 20779
oid sha256:f7d5b15add5104d91a03df7d86898f4bc415d095d11c23555b24440497371948
size 1061

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926
size 21857
oid sha256:148fdae6493d7b7e1bb6cc6aae1861e0469838f54dcb3c15cc157a548c707fec
size 1910

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:07631f41b8dea80713d2463f81a713a9a93798975b6fb50afbeeb13d26c57fa2
size 48899
oid sha256:934502e242ff7a2e34e21eed1424b5e0953e701761d158520b3297944132328e
size 18716

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2
size 32037
oid sha256:094620c172320b062f9a1f8cc758ef4bbee11bc0a6049f46ad6b42f9bf613c92
size 9679

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926
size 21857
oid sha256:148fdae6493d7b7e1bb6cc6aae1861e0469838f54dcb3c15cc157a548c707fec
size 1910

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ad83faf98b49f4e37112baedeae726f4f8d71bcdd1961d9cdad31f043f8ca666
size 24003
oid sha256:749bcd29d73e5ef2d1ef8b2d878626d0bca09c6b0d5f1c9dc6cefe7b9082c8cc
size 3758

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:68529a6c11d5ffa7ecd9d5bbb11ceea28e6852bd45946b525af09602c9a1e1bf
size 48899
oid sha256:934502e242ff7a2e34e21eed1424b5e0953e701761d158520b3297944132328e
size 18716

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8a70003840b418848b2ce6c18ed7cbbfcd6fcf76598a6601dca8b98d9b6c1a2f
size 114706
oid sha256:5719043940db268dccd2e20bd9d6aa13131890d43edf002a173714ae33890422
size 29510

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:31afa7ed44c5d9844c8d6ce08beccac482c3f43590869a3d190d06e2df377ccc
size 137472
oid sha256:a4018d9df45b4a04d4cf24a40fe01aa7e30e44a9fdd8ad9a41b0d87791786c12
size 30442

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0aac8ef9899442820bec0df8bf6434a46cc787d57c5d6d38a04727b8dc310048
size 338281
oid sha256:2eea06cb8ad05acefe9664551af5645d52d9763b82473b1fd4a2b2b6f62e96d3
size 53550

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c07495891f15b138ba09f142777b0f43217bf8be05cbb74ba938319f3425980c
size 321125
oid sha256:90991aca91ab7222fdb85c03947cff38f549a6492551e7447e0c8f55022aae48
size 52467

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d6bf6acb92421a453a36fc143ab6cefda14d631ea5e6dbf95c6e252a445fcbac
size 144797
oid sha256:6c8439a64d18dbff17dd67f6405bf49f99695e9b22fc2cc541dc72c6e3167307
size 30564

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e9ad650fda925b1c076a67d1ef70315fe4f14db888c9fd36ee4eba1d18c1e7d1
size 166749
oid sha256:f752615184160d7a78f28d9eef354c86e544f11eb1dde9f651d7acd315b3f2e6
size 35934

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:16f6e9d7bd15fc528d934c252213de8792812e708b1810191c5f1767f7165852
size 142331
oid sha256:1a43f1d893e85aa99d335a657ec0f6c13a741db976c033451ab9a2328b8a5970
size 35559

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e4901093fa6190bf37291b0fb6de23fba1be8ebbd742775a8565a4106722fbb6
size 31942
oid sha256:ebfc95bd4c0cbcc53d0ef9d314d26e09a347a22dabbf210597f405d9ed8646bf
size 7729

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e4ae97c4f44910121a61686862c8342ce598db4cdf9d46b29e96d3cb9e43bd06
size 22158
oid sha256:99cb7da9282cfcfa64598455827f27ca6791d45ca0d2c3c2dc090d82468dac03
size 4447

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:061e2d0ce8dc852dd298c80f2aed5fee8ea4b87511c00662aa2d00922c0ba3c2
size 30162
oid sha256:101568e946f1d4cea86d666187bbf71116bbf62e6eaf6d80bc3c5e2e184bdb15
size 7938

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0fb4b4b77620d99dae7473b7bd8affe14630419835bd5719167ed200e657fa4f
size 17504
oid sha256:cf930ffd4efb0b7b627e05aac6e0f56252ea206623e8b5d097d803aa315cdfb8
size 1812

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8aa9b1194f3244025578225a6a87cbc2dd12c70955ff615c8af640ea7f1334f1
size 19619
oid sha256:ba5fea53b349e254b4625035a308d5731cb06f6d0adc278874d14db2627962cb
size 3424

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0c25ffb1af8160b3202977de8c32aaa235e22c643ffd8004e4546c96868ef3b9
size 18317
oid sha256:cf087f357cd439d14651073ac079542c60f0648a30dced2a8d19912124b3f8b6
size 2310

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2db961b8f922a552d8ad374fdb56029efd4049a6cde10399b3d961242c82ce53
size 22571
oid sha256:421ad4db14c28ed18666158f9ec30747c5b8c757405c1efb32442978911b0c06
size 4437

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f39d897a57d4da0a70ede7c91339660b28e9d8c57b3e7d749807b13baa4b85f3
size 28559
oid sha256:0d0044ebf7e0a5dd23ed64a1289c705d8f6c3c41a62d65e5a1371058855b8cec
size 6546

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:263b75d58328499eef1f8fa2e64c30706f546badcc0c4464a043b231da93cd0d
size 34969
oid sha256:3b8717c5f2109dfce1bf7b017278059d4915b524a6eb7e83cfb1926e54ed6869
size 7383

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:33522ad8a8e826b22dd9ad214f56e63e24bf55c00bd8c845925d848b855dfb48
size 19619
oid sha256:ba5fea53b349e254b4625035a308d5731cb06f6d0adc278874d14db2627962cb
size 3424

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f405c9f3d908d038aea26049e533b0d10955adfac370c7b3b80209997ea706d0
size 24407
oid sha256:a32908a839a6cb0ca2a76d6aa60376ba8a14b4428f06c13149ec277514eb5676
size 4533

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d110f6e151799a2327bcdf5ef94d6fc82b114783a8cc973a8915896679ba4a80
size 28559
oid sha256:0d0044ebf7e0a5dd23ed64a1289c705d8f6c3c41a62d65e5a1371058855b8cec
size 6546

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:db8f00568fad4e49b05249aaa7a48c9fbf85c8b7a78489c83dc9b8161778bcef
size 22571
oid sha256:421ad4db14c28ed18666158f9ec30747c5b8c757405c1efb32442978911b0c06
size 4437

@ -4,8 +4,8 @@
"restricted_platform_relative_path": "Templates",
"origin": "The primary repo for DefaultProject goes here: i.e. http://www.mydomain.com",
"license": "What license DefaultProject uses goes here: i.e. https://opensource.org/licenses/MIT",
"display_name": "Default",
"summary": "A short description of DefaultProject.",
"display_name": "Standard",
"summary": "This template has everything you need to build a full online 3D game or application.",
"included_gems": ["Atom","Camera","EMotionFX","UI","Maestro","Input","ImGui"],
"canonical_tags": [],
"user_tags": [

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:61efd8df621780af995fc1250918df5e00364ff00f849bef67702cd4b0a152e1
size 65537
oid sha256:41239f8345fa91fe546442208461ad3cd17c7a7a7047af45018b97363bfea204
size 109783

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cf6d56fe4c367d39bd78500dd34332fcad57ad41241768b52781dbdb60ddd972
size 347568
oid sha256:7c8433178baebafe984ca23d9325d3c71b5a177fc3b3b869afbb01a583542fbe
size 462842

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2
size 32037
oid sha256:094620c172320b062f9a1f8cc758ef4bbee11bc0a6049f46ad6b42f9bf613c92
size 9679

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9f41a37d2347a617e93bd97adaf6d4c161c471ca3ef7e04b98c65ddda52396dc
size 27833
oid sha256:f3c651ca45a83d0f68bdaa466826a29b2ca6f674e225d90e68b7dbadc2ba582d
size 6620

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b07984494059bf827bc485cbea06d12e0283811face1a18799495f9ba7ae8af1
size 20779
oid sha256:f7d5b15add5104d91a03df7d86898f4bc415d095d11c23555b24440497371948
size 1061

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926
size 21857
oid sha256:148fdae6493d7b7e1bb6cc6aae1861e0469838f54dcb3c15cc157a548c707fec
size 1910

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:07631f41b8dea80713d2463f81a713a9a93798975b6fb50afbeeb13d26c57fa2
size 48899
oid sha256:934502e242ff7a2e34e21eed1424b5e0953e701761d158520b3297944132328e
size 18716

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2
size 32037
oid sha256:094620c172320b062f9a1f8cc758ef4bbee11bc0a6049f46ad6b42f9bf613c92
size 9679

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926
size 21857
oid sha256:148fdae6493d7b7e1bb6cc6aae1861e0469838f54dcb3c15cc157a548c707fec
size 1910

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ad83faf98b49f4e37112baedeae726f4f8d71bcdd1961d9cdad31f043f8ca666
size 24003
oid sha256:749bcd29d73e5ef2d1ef8b2d878626d0bca09c6b0d5f1c9dc6cefe7b9082c8cc
size 3758

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:68529a6c11d5ffa7ecd9d5bbb11ceea28e6852bd45946b525af09602c9a1e1bf
size 48899
oid sha256:934502e242ff7a2e34e21eed1424b5e0953e701761d158520b3297944132328e
size 18716

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8a70003840b418848b2ce6c18ed7cbbfcd6fcf76598a6601dca8b98d9b6c1a2f
size 114706
oid sha256:5719043940db268dccd2e20bd9d6aa13131890d43edf002a173714ae33890422
size 29510

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:31afa7ed44c5d9844c8d6ce08beccac482c3f43590869a3d190d06e2df377ccc
size 137472
oid sha256:a4018d9df45b4a04d4cf24a40fe01aa7e30e44a9fdd8ad9a41b0d87791786c12
size 30442

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0aac8ef9899442820bec0df8bf6434a46cc787d57c5d6d38a04727b8dc310048
size 338281
oid sha256:2eea06cb8ad05acefe9664551af5645d52d9763b82473b1fd4a2b2b6f62e96d3
size 53550

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c07495891f15b138ba09f142777b0f43217bf8be05cbb74ba938319f3425980c
size 321125
oid sha256:90991aca91ab7222fdb85c03947cff38f549a6492551e7447e0c8f55022aae48
size 52467

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d6bf6acb92421a453a36fc143ab6cefda14d631ea5e6dbf95c6e252a445fcbac
size 144797
oid sha256:6c8439a64d18dbff17dd67f6405bf49f99695e9b22fc2cc541dc72c6e3167307
size 30564

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save