Merge pull request #1091 from aws-lumberyard-dev/prism/LYN-2514
[LYN-2514] Gems Page - Saving & applying changes to project
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <ScreenHeaderWidget.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
@@ -42,9 +41,10 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_stack = new QStackedWidget(this);
|
||||
m_stack->setObjectName("body");
|
||||
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding));
|
||||
m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
|
||||
m_stack->addWidget(new NewProjectSettingsScreen());
|
||||
m_stack->addWidget(new GemCatalogScreen());
|
||||
m_gemCatalog = new GemCatalogScreen();
|
||||
m_stack->addWidget(m_gemCatalog);
|
||||
vLayout->addWidget(m_stack);
|
||||
|
||||
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
|
||||
@@ -88,6 +88,7 @@ namespace O3DE::ProjectManager
|
||||
emit GotoPreviousScreenRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::HandleNextButton()
|
||||
{
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
@@ -106,6 +107,9 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_projectInfo = newProjectScreen->GetProjectInfo();
|
||||
m_projectTemplatePath = newProjectScreen->GetProjectTemplatePath();
|
||||
|
||||
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalog->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +133,9 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
QMessageBox::critical(this, tr("Project creation failed"), tr("Failed to create project."));
|
||||
}
|
||||
|
||||
// Enable/disable gems for the newly created project.
|
||||
m_gemCatalog->EnableDisableGemsForProject(m_projectInfo.m_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.h>
|
||||
#include <ProjectInfo.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QStackedWidget)
|
||||
@@ -48,6 +49,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
QString m_projectTemplatePath;
|
||||
ProjectInfo m_projectInfo;
|
||||
|
||||
GemCatalogScreen* m_gemCatalog = nullptr;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
#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 +28,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);
|
||||
GemCatalogHeaderWidget* headerWidget = new GemCatalogHeaderWidget(m_proxModel);
|
||||
vLayout->addWidget(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 +64,111 @@ 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_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_proxModel->InvalidateFilter();
|
||||
|
||||
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));
|
||||
// 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 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));
|
||||
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("Cloud Gem Core",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
true));
|
||||
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("Gestures",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
false));
|
||||
// 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("Effects System",
|
||||
"O3DE Foundation",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
|
||||
true));
|
||||
void GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath)
|
||||
{
|
||||
IPythonBindings* pythonBindings = PythonBindingsInterface::Get();
|
||||
QVector<QModelIndex> toBeAdded = m_gemModel->GatherGemsToBeAdded();
|
||||
QVector<QModelIndex> toBeRemoved = m_gemModel->GatherGemsToBeRemoved();
|
||||
|
||||
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));
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
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,11 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.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 +31,17 @@ 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;
|
||||
GemSortFilterProxyModel* m_proxModel = nullptr;
|
||||
QVBoxLayout* m_filterWidgetLayout = nullptr;
|
||||
GemFilterWidget* m_filterWidget = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -79,4 +79,9 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
return (m_platforms & platform);
|
||||
}
|
||||
|
||||
bool GemInfo::operator<(const GemInfo& gemInfo) const
|
||||
{
|
||||
return (m_displayName < gemInfo.m_displayName);
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool operator<(const GemInfo& gemInfo) const;
|
||||
|
||||
QString m_path;
|
||||
QString m_name = "Unknown Gem Name";
|
||||
QString m_displayName = "Unknown Gem Name";
|
||||
|
||||
@@ -283,6 +283,7 @@ namespace O3DE::ProjectManager
|
||||
AZ_Warning("ProjectManagerWindow", result != -1, "Append to sys path failed");
|
||||
|
||||
// import required modules
|
||||
m_cmake = pybind11::module::import("o3de.cmake");
|
||||
m_register = pybind11::module::import("o3de.register");
|
||||
m_manifest = pybind11::module::import("o3de.manifest");
|
||||
m_engineTemplate = pybind11::module::import("o3de.engine_template");
|
||||
@@ -311,7 +312,7 @@ namespace O3DE::ProjectManager
|
||||
return !PyErr_Occurred();
|
||||
}
|
||||
|
||||
bool PythonBindings::ExecuteWithLock(AZStd::function<void()> executionCallback)
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback)
|
||||
{
|
||||
AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
|
||||
pybind11::gil_scoped_release release;
|
||||
@@ -320,13 +321,19 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
executionCallback();
|
||||
return true;
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
AZ_Warning("PythonBindings", false, "Python exception %s", e.what());
|
||||
return false;
|
||||
return AZ::Failure<AZStd::string>(e.what());
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
bool PythonBindings::ExecuteWithLock(AZStd::function<void()> executionCallback)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling(executionCallback).IsSuccess();
|
||||
}
|
||||
|
||||
AZ::Outcome<EngineInfo> PythonBindings::GetEngineInfo()
|
||||
@@ -419,7 +426,7 @@ namespace O3DE::ProjectManager
|
||||
return result;
|
||||
}
|
||||
|
||||
AZ::Outcome<GemInfo> PythonBindings::GetGem(const QString& path)
|
||||
AZ::Outcome<GemInfo> PythonBindings::GetGemInfo(const QString& path)
|
||||
{
|
||||
GemInfo gemInfo = GemInfoFromPath(pybind11::str(path.toStdString()));
|
||||
if (gemInfo.IsValid())
|
||||
@@ -432,32 +439,79 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Outcome<QVector<GemInfo>> PythonBindings::GetGems()
|
||||
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetEngineGemInfos()
|
||||
{
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
bool result = ExecuteWithLock([&] {
|
||||
// external gems
|
||||
for (auto path : m_manifest.attr("get_gems")())
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
}
|
||||
|
||||
// gems from the engine
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
std::sort(gems.begin(), gems.end());
|
||||
return AZ::Success(AZStd::move(gems));
|
||||
}
|
||||
|
||||
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetAllGemInfos(const QString& projectPath)
|
||||
{
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
}
|
||||
|
||||
if (!result)
|
||||
std::sort(gems.begin(), gems.end());
|
||||
return AZ::Success(AZStd::move(gems));
|
||||
}
|
||||
|
||||
AZ::Outcome<QVector<AZStd::string>, AZStd::string> PythonBindings::GetEnabledGemNames(const QString& projectPath)
|
||||
{
|
||||
// Retrieve the path to the cmake file that lists the enabled gems.
|
||||
pybind11::str enabledGemsFilename;
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure();
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
}
|
||||
else
|
||||
|
||||
// Retrieve the actual list of names from the cmake file.
|
||||
QVector<AZStd::string> gemNames;
|
||||
result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Success(AZStd::move(gems));
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
}
|
||||
|
||||
return AZ::Success(AZStd::move(gemNames));
|
||||
}
|
||||
|
||||
bool PythonBindings::AddProject(const QString& path)
|
||||
@@ -637,38 +691,36 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
bool PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
bool result = ExecuteWithLock([&] {
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem_name
|
||||
pyGemPath,
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
|
||||
return result;
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
bool PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
bool result = ExecuteWithLock([&] {
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem_name
|
||||
pyGemPath,
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
|
||||
return result;
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)
|
||||
|
||||
@@ -39,8 +39,10 @@ namespace O3DE::ProjectManager
|
||||
bool SetEngineInfo(const EngineInfo& engineInfo) override;
|
||||
|
||||
// Gem
|
||||
AZ::Outcome<GemInfo> GetGem(const QString& path) override;
|
||||
AZ::Outcome<QVector<GemInfo>> GetGems() override;
|
||||
AZ::Outcome<GemInfo> GetGemInfo(const QString& path) override;
|
||||
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetEngineGemInfos() override;
|
||||
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) override;
|
||||
AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) override;
|
||||
|
||||
// Project
|
||||
AZ::Outcome<ProjectInfo> CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override;
|
||||
@@ -49,8 +51,8 @@ namespace O3DE::ProjectManager
|
||||
bool AddProject(const QString& path) override;
|
||||
bool RemoveProject(const QString& path) override;
|
||||
bool UpdateProject(const ProjectInfo& projectInfo) override;
|
||||
bool AddGemToProject(const QString& gemPath, const QString& projectPath) override;
|
||||
bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
|
||||
AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) override;
|
||||
AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
|
||||
|
||||
// ProjectTemplate
|
||||
AZ::Outcome<QVector<ProjectTemplateInfo>> GetProjectTemplates() override;
|
||||
@@ -58,6 +60,7 @@ namespace O3DE::ProjectManager
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(PythonBindings);
|
||||
|
||||
AZ::Outcome<void, AZStd::string> ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback);
|
||||
bool ExecuteWithLock(AZStd::function<void()> executionCallback);
|
||||
GemInfo GemInfoFromPath(pybind11::handle path);
|
||||
ProjectInfo ProjectInfoFromPath(pybind11::handle path);
|
||||
@@ -68,6 +71,7 @@ namespace O3DE::ProjectManager
|
||||
AZ::IO::FixedMaxPath m_enginePath;
|
||||
pybind11::handle m_engineTemplate;
|
||||
AZStd::recursive_mutex m_lock;
|
||||
pybind11::handle m_cmake;
|
||||
pybind11::handle m_register;
|
||||
pybind11::handle m_manifest;
|
||||
pybind11::handle m_enableGemProject;
|
||||
|
||||
@@ -57,13 +57,27 @@ namespace O3DE::ProjectManager
|
||||
* @param path the absolute path to the Gem
|
||||
* @return an outcome with GemInfo on success
|
||||
*/
|
||||
virtual AZ::Outcome<GemInfo> GetGem(const QString& path) = 0;
|
||||
virtual AZ::Outcome<GemInfo> GetGemInfo(const QString& path) = 0;
|
||||
|
||||
/**
|
||||
* Get info about all known Gems
|
||||
* @return an outcome with GemInfos on success
|
||||
* Get all available gem infos. This concatenates gems registered by the engine and the project.
|
||||
* @param path The absolute path to the project.
|
||||
* @return A list of gem infos.
|
||||
*/
|
||||
virtual AZ::Outcome<QVector<GemInfo>> GetGems() = 0;
|
||||
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) = 0;
|
||||
|
||||
/**
|
||||
* Get engine gem infos.
|
||||
* @return A list of all registered gem infos.
|
||||
*/
|
||||
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetEngineGemInfos() = 0;
|
||||
|
||||
/**
|
||||
* Get a list of all enabled gem names for a given project.
|
||||
* @param[in] projectPath Absolute file path to the project.
|
||||
* @return A list of gem names of all the enabled gems for a given project or a error message on failure.
|
||||
*/
|
||||
virtual AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) = 0;
|
||||
|
||||
|
||||
// Projects
|
||||
@@ -114,17 +128,17 @@ namespace O3DE::ProjectManager
|
||||
* Add a gem to a project
|
||||
* @param gemPath the absolute path to the gem
|
||||
* @param projectPath the absolute path to the project
|
||||
* @return true on success, false on failure
|
||||
* @return An outcome with the success flag as well as an error message in case of a failure.
|
||||
*/
|
||||
virtual bool AddGemToProject(const QString& gemPath, const QString& projectPath) = 0;
|
||||
virtual AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) = 0;
|
||||
|
||||
/**
|
||||
* Remove gem to a project
|
||||
* @param gemPath the absolute path to the gem
|
||||
* @param projectPath the absolute path to the project
|
||||
* @return true on success, false on failure
|
||||
* @return An outcome with the success flag as well as an error message in case of a failure.
|
||||
*/
|
||||
virtual bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) = 0;
|
||||
virtual AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) = 0;
|
||||
|
||||
|
||||
// Project Templates
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void UpdateProjectCtrl::HandleGemsButton()
|
||||
{
|
||||
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
|
||||
|
||||
m_stack->setCurrentWidget(m_gemCatalogScreen);
|
||||
Update();
|
||||
}
|
||||
@@ -113,6 +116,7 @@ namespace O3DE::ProjectManager
|
||||
emit GotoPreviousScreenRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::HandleNextButton()
|
||||
{
|
||||
if (m_stack->currentIndex() == ScreenOrder::Settings)
|
||||
@@ -152,6 +156,12 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stack->currentIndex() == ScreenOrder::Gems && m_gemCatalogScreen)
|
||||
{
|
||||
// Enable or disable the gems that got adjusted in the gem catalog and apply them to the given project.
|
||||
m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path);
|
||||
}
|
||||
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::Projects);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user