diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt index e4354bac32..e2b5aaf696 100644 --- a/Code/Tools/ProjectManager/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -13,6 +13,13 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +# This will set python_package_name to whatever the package 'Python' is associated with +ly_get_package_association(Python python_package_name) +if (NOT python_package_name) + set(python_package_name "python-no-package-assocation-found") + message(WARNING "Python was not found in the package assocation list. Did someone call ly_associate_package(xxxxxxx Python) ?") +endif() + ly_add_target( NAME ProjectManager APPLICATION OUTPUT_NAME o3de @@ -22,7 +29,13 @@ ly_add_target( AUTORCC FILES_CMAKE project_manager_files.cmake + Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + PLATFORM_INCLUDE_FILES Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + Platform/Common/${PAL_TRAIT_COMPILER_ID}/projectmanager_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake + COMPILE_DEFINITIONS + PRIVATE + PY_PACKAGE="${python_package_name}" INCLUDE_DIRECTORIES PUBLIC . @@ -34,6 +47,8 @@ ly_add_target( 3rdParty::Qt::Core 3rdParty::Qt::Concurrent 3rdParty::Qt::Widgets + 3rdParty::Python + 3rdParty::pybind11 AZ::AzCore AZ::AzFramework AZ::AzToolsFramework diff --git a/Code/Tools/ProjectManager/Platform/Common/Clang/projectmanager_clang.cmake b/Code/Tools/ProjectManager/Platform/Common/Clang/projectmanager_clang.cmake new file mode 100644 index 0000000000..fb85a6cf2a --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Common/Clang/projectmanager_clang.cmake @@ -0,0 +1,15 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_COMPILE_OPTIONS + PRIVATE + -fexceptions # The macro PYBIND11_EMBEDDED_MODULE uses a try catch block +) diff --git a/Code/Tools/ProjectManager/Platform/Common/MSVC/projectmanager_msvc.cmake b/Code/Tools/ProjectManager/Platform/Common/MSVC/projectmanager_msvc.cmake new file mode 100644 index 0000000000..669f14eae4 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Common/MSVC/projectmanager_msvc.cmake @@ -0,0 +1,15 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_COMPILE_OPTIONS + PRIVATE + /EHsc # The macro PYBIND11_EMBEDDED_MODULE uses a try catch block +) diff --git a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake index 4d5680a30d..f5b9ea77a2 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake +++ b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake @@ -8,3 +8,4 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + diff --git a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_files.cmake b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_files.cmake new file mode 100644 index 0000000000..a07534ee39 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Python_linux.cpp +) diff --git a/Code/Tools/ProjectManager/Platform/Linux/Python_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/Python_linux.cpp new file mode 100644 index 0000000000..64ab9c9ca7 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/Python_linux.cpp @@ -0,0 +1,42 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include +#include +#include + +namespace Platform +{ + extern bool InsertPythonLibraryPath(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot, const char* subPath); + + bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot) + { + bool succeeded = true; + + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7/lib-dynload"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7/site-packages"); + return succeeded; + } + + AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot) + { + // append lib path to Python paths + AZ::IO::FixedMaxPath libPath = engineRoot; + libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/python", pythonPackage); + libPath = libPath.LexicallyNormal(); + return libPath.String(); + } +} diff --git a/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_files.cmake b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_files.cmake new file mode 100644 index 0000000000..83124b6315 --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Python_mac.cpp +) diff --git a/Code/Tools/ProjectManager/Platform/Mac/Python_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/Python_mac.cpp new file mode 100644 index 0000000000..d3d55d6d5d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/Python_mac.cpp @@ -0,0 +1,43 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include +#include +#include + +namespace Platform +{ + extern bool InsertPythonLibraryPath(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot, const char* subPath); + + bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot) + { + bool succeeded = true; + + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7/lib-dynload"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7/site-packages"); + + return succeeded; + } + + AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot) + { + // append lib path to Python paths + AZ::IO::FixedMaxPath libPath = engineRoot; + libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/Python.framework/Versions/3.7", pythonPackage); + libPath = libPath.LexicallyNormal(); + return libPath.String(); + } +} diff --git a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake index 4d5680a30d..dfcc107f4d 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake +++ b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(LY_COMPILE_DEFINITIONS + PRIVATE + HAVE_ROUND # defined for Windows since http://p-nand-q.com/python/building-python-33-with-vs2013.html +) diff --git a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_files.cmake b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_files.cmake new file mode 100644 index 0000000000..de083bc91a --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Python_windows.cpp +) diff --git a/Code/Tools/ProjectManager/Platform/Windows/Python_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/Python_windows.cpp new file mode 100644 index 0000000000..2ea143c63d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/Python_windows.cpp @@ -0,0 +1,43 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include +#include +#include + +namespace Platform +{ + extern bool InsertPythonLibraryPath(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot, const char* subPath); + + bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot) + { + bool succeeded = true; + + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/site-packages"); + succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/DLLs"); + + return succeeded; + } + + AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot) + { + // append lib path to Python paths + AZ::IO::FixedMaxPath libPath = engineRoot; + libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/python", pythonPackage); + libPath = libPath.LexicallyNormal(); + return libPath.String(); + } +} diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index 8c5040eb84..4766187d2a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -37,6 +37,7 @@ namespace O3DE::ProjectManager GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded); + QString m_path; QString m_name; QString m_displayName; AZ::Uuid m_uuid; diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp new file mode 100644 index 0000000000..b3bdb87224 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp @@ -0,0 +1,24 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include "ProjectInfo.h" + +namespace O3DE::ProjectManager +{ + ProjectInfo::ProjectInfo(const QString& path, const QString& projectName, const QString& productName, const AZ::Uuid projectId) + : m_path(path) + , m_projectName(projectName) + , m_productName(productName) + , m_projectId(projectId) + { + } +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h new file mode 100644 index 0000000000..e5dca97d5e --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -0,0 +1,36 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#endif + +namespace O3DE::ProjectManager +{ + class ProjectInfo + { + public: + ProjectInfo() = default; + ProjectInfo(const QString& path, const QString& projectName, const QString& productName, const AZ::Uuid projectId); + + // from o3de_manifest.json and o3de_projects.json + QString m_path; + + // from project.json + QString m_projectName; + QString m_productName; + AZ::Uuid m_projectId; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp index 12980fc836..c86ebeee86 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp @@ -28,6 +28,8 @@ namespace O3DE::ProjectManager { m_ui->setupUi(this); + m_pythonBindings = AZStd::make_unique(engineRootPath); + ConnectSlotsAndSignals(); QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast(engineRootPath.Native().size())); @@ -44,6 +46,7 @@ namespace O3DE::ProjectManager ProjectManagerWindow::~ProjectManagerWindow() { + m_pythonBindings.reset(); } void ProjectManagerWindow::BuildScreens() diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h index 9e5761fbd2..6a17c4464c 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h @@ -17,7 +17,7 @@ #include #include -#include +#include #endif namespace Ui @@ -52,6 +52,7 @@ namespace O3DE::ProjectManager private: QScopedPointer m_ui; + AZStd::unique_ptr m_pythonBindings; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsHome.cpp b/Code/Tools/ProjectManager/Source/ProjectsHome.cpp index 1a451f3d10..a45b923946 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsHome.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsHome.cpp @@ -14,6 +14,8 @@ #include +#include + namespace O3DE::ProjectManager { ProjectsHome::ProjectsHome(ProjectManagerWindow* window) @@ -23,6 +25,9 @@ namespace O3DE::ProjectManager m_ui->setupUi(this); ConnectSlotsAndSignals(); + + // example of how to get the current project name + ProjectInfo currentProject = PythonBindingsInterface::Get()->GetCurrentProject(); } ProjectsHome::~ProjectsHome() diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp new file mode 100644 index 0000000000..cc14e9e4de --- /dev/null +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -0,0 +1,155 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include + +// Qt defines slots, which interferes with the use here. +#pragma push_macro("slots") +#undef slots +#include +#include +#include +#include +#include +#pragma pop_macro("slots") + +#include +#include +#include +#include + +namespace Platform +{ + bool InsertPythonLibraryPath( + AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot, const char* subPath) + { + // append lib path to Python paths + AZ::IO::FixedMaxPath libPath = engineRoot; + libPath /= AZ::IO::FixedMaxPathString::format(subPath, pythonPackage); + libPath = libPath.LexicallyNormal(); + if (AZ::IO::SystemFile::Exists(libPath.c_str())) + { + paths.insert(libPath.c_str()); + return true; + } + + AZ_Warning("python", false, "Python library path should exist. path:%s", libPath.c_str()); + return false; + } + + // Implemented in each different platform's PAL implentation files, as it differs per platform. + AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot); + +} // namespace Platform + +namespace O3DE::ProjectManager +{ + PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath) + : m_enginePath(enginePath) + { + StartPython(); + } + + PythonBindings::~PythonBindings() + { + StopPython(); + } + + bool PythonBindings::StartPython() + { + if (Py_IsInitialized()) + { + AZ_Warning("python", false, "Python is already active"); + return false; + } + + // set PYTHON_HOME + AZStd::string pyBasePath = Platform::GetPythonHomePath(PY_PACKAGE, m_enginePath.c_str()); + if (!AZ::IO::SystemFile::Exists(pyBasePath.c_str())) + { + AZ_Warning("python", false, "Python home path must exist. path:%s", pyBasePath.c_str()); + return false; + } + + AZStd::wstring pyHomePath; + AZStd::to_wstring(pyHomePath, pyBasePath); + Py_SetPythonHome(pyHomePath.c_str()); + + // display basic Python information + AZ_TracePrintf("python", "Py_GetVersion=%s \n", Py_GetVersion()); + AZ_TracePrintf("python", "Py_GetPath=%ls \n", Py_GetPath()); + AZ_TracePrintf("python", "Py_GetExecPrefix=%ls \n", Py_GetExecPrefix()); + AZ_TracePrintf("python", "Py_GetProgramFullPath=%ls \n", Py_GetProgramFullPath()); + + try + { + // ignore system location for sites site-packages + Py_IsolatedFlag = 1; // -I - Also sets Py_NoUserSiteDirectory. If removed PyNoUserSiteDirectory should be set. + Py_IgnoreEnvironmentFlag = 1; // -E + + const bool initializeSignalHandlers = true; + pybind11::initialize_interpreter(initializeSignalHandlers); + + // Acquire GIL before calling Python code + AZStd::lock_guard lock(m_lock); + pybind11::gil_scoped_acquire acquire; + + // Setup sys.path + int result = PyRun_SimpleString("import sys"); + AZ_Warning("ProjectManagerWindow", result != -1, "Import sys failed"); + result = PyRun_SimpleString(AZStd::string::format("sys.path.append('%s')", m_enginePath.c_str()).c_str()); + AZ_Warning("ProjectManagerWindow", result != -1, "Append to sys path failed"); + + return result == 0 && !PyErr_Occurred(); + } catch ([[maybe_unused]] const std::exception& e) + { + AZ_Warning("python", false, "Py_Initialize() failed with %s", e.what()); + return false; + } + } + + bool PythonBindings::StopPython() + { + if (Py_IsInitialized()) + { + pybind11::finalize_interpreter(); + } + else + { + AZ_Warning("python", false, "Did not finalize since Py_IsInitialized() was false"); + } + return !PyErr_Occurred(); + } + + void PythonBindings::ExecuteWithLock(AZStd::function executionCallback) + { + AZStd::lock_guard lock(m_lock); + pybind11::gil_scoped_release release; + pybind11::gil_scoped_acquire acquire; + executionCallback(); + } + + ProjectInfo PythonBindings::GetCurrentProject() + { + ProjectInfo project; + + ExecuteWithLock([&] { + auto currentProjectTool = pybind11::module::import("cmake.Tools.current_project"); + auto getCurrentProject = currentProjectTool.attr("get_current_project"); + auto currentProject = getCurrentProject(m_enginePath.c_str()); + + project.m_path = currentProject.cast().c_str(); + }); + + return project; + } +} diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h new file mode 100644 index 0000000000..ac55fffe80 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -0,0 +1,41 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include +#include +#include + +namespace O3DE::ProjectManager +{ + class PythonBindings + : public PythonBindingsInterface::Registrar + { + public: + PythonBindings() = default; + PythonBindings(const AZ::IO::PathView& enginePath); + ~PythonBindings() override; + + // PythonBindings overrides + ProjectInfo GetCurrentProject() override; + + private: + AZ_DISABLE_COPY_MOVE(PythonBindings); + + void ExecuteWithLock(AZStd::function executionCallback); + bool StartPython(); + bool StopPython(); + + AZ::IO::FixedMaxPath m_enginePath; + AZStd::recursive_mutex m_lock; + }; +} diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h new file mode 100644 index 0000000000..78c3625415 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -0,0 +1,39 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace O3DE::ProjectManager +{ + //! Interface used to interact with the o3de cli python functions + class IPythonBindings + { + public: + AZ_RTTI(O3DE::ProjectManager::IPythonBindings, "{C2B72CA4-56A9-4601-A584-3B40E83AA17C}"); + AZ_DISABLE_COPY_MOVE(IPythonBindings); + + IPythonBindings() = default; + virtual ~IPythonBindings() = default; + + //! Get the current project + virtual ProjectInfo GetCurrentProject() = 0; + }; + + using PythonBindingsInterface = AZ::Interface; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/main.cpp b/Code/Tools/ProjectManager/Source/main.cpp index 149da79491..3d8bb71a0c 100644 --- a/Code/Tools/ProjectManager/Source/main.cpp +++ b/Code/Tools/ProjectManager/Source/main.cpp @@ -35,21 +35,29 @@ int main(int argc, char* argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); - QApplication app(argc, argv); - // Need to use settings registry to get EngineRootFolder - AZ::IO::FixedMaxPath engineRootPath; + AZ::AllocatorInstance::Create(); + int runSuccess = 0; { - AZ::ComponentApplication componentApplication; - auto settingsRegistry = AZ::SettingsRegistry::Get(); - settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); - } + QApplication app(argc, argv); + + // Need to use settings registry to get EngineRootFolder + AZ::IO::FixedMaxPath engineRootPath; + { + AZ::ComponentApplication componentApplication; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); + } - AzQtComponents::StyleManager styleManager(&app); - styleManager.initialize(&app, engineRootPath); + AzQtComponents::StyleManager styleManager(&app); + styleManager.initialize(&app, engineRootPath); - O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath); - window.show(); + O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath); + window.show(); + + runSuccess = app.exec(); + } + AZ::AllocatorInstance::Destroy(); - return app.exec(); + return runSuccess; } diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index 073e220810..da0b7cdec7 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -19,9 +19,14 @@ set(FILES Source/FirstTimeUse.h Source/FirstTimeUse.cpp Source/FirstTimeUse.ui + Source/ProjectInfo.h + Source/ProjectInfo.cpp Source/ProjectManagerWindow.h Source/ProjectManagerWindow.cpp Source/ProjectManagerWindow.ui + Source/PythonBindings.h + Source/PythonBindings.cpp + Source/PythonBindingsInterface.h Source/NewProjectSettings.h Source/NewProjectSettings.cpp Source/NewProjectSettings.ui