Files
o3de/Code/Tools/PythonBindingsExample/source/Application.cpp
T
lumberyard-employee-dm 5fc4551ac0 [LYN-8041] Enable relocation of the Project Game Release Layout (#5380)
* Enable relocation of the Project Game Release Layout

Relocating the Project Game Release Layout to another directory on the file system failed due to the querying of the engine root failing due to the ComponentApplication::m_engineRoot not using the project path stored in the SettingsRegisry if the engine root cannot be detected

Removed the ApplicationRequestBus GetEngineRoot function.
The ComponentApplicationRequestBus has a function of the same name that returns the same path.

Removed the deprecated GetAppRoot function.
The path it returns has no defined value. It was not the engine root or the project root.
Removed unused CFileUtil and CFileUtil_impl functions that were invoking the ApplicationREquestBus GetEngineRoot function.
On the way to update the functions it was discovered that they aren't called

Added a CalculateBranchToken overload that can populate a fixed_string to avoid heap allocations

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Protect against an empty list of artifacts to remove when generating the
engine.pak

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
2021-11-09 12:03:52 -06:00

274 lines
8.7 KiB
C++

/*
* 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 <source/Application.h>
#include <source/ApplicationParameters.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/CommandLine/CommandRegistrationBus.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/Asset/AssetUtils.h>
#include <iostream>
#include <string>
namespace PythonBindingsExample
{
//////////////////////////////////////////////////////////////////////////
// Application
Application::Application(int* argc, char*** argv)
: AzToolsFramework::ToolsApplication(argc, argv)
{
}
Application::~Application()
{
TearDown();
}
void Application::SetUp()
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect();
// prepare the Python binding gem(s)
Start(Descriptor());
AZ::SerializeContext* context;
EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(context, "Application did not start; detected no serialize context");
AZ_TracePrintf("Python Bindings", "Init() \n");
}
void Application::TearDown()
{
StopPythonVM();
m_showVerboseOutput = false;
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect();
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
Stop();
}
void Application::StartPythonVM()
{
auto&& editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface)
{
// already started?
if (m_startedPython == false)
{
m_startedPython = editorPythonEventsInterface->StartPython();
AZ_Error("python_app", m_startedPython, "Python VM did not start.");
}
}
}
void Application::StopPythonVM()
{
auto&& editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface && m_startedPython)
{
editorPythonEventsInterface->StopPython();
m_startedPython = false;
}
else if (m_showVerboseOutput)
{
AZ_Warning("python_app", false, "Python interface could not be stopped.");
}
}
bool Application::Run()
{
ApplicationParameters params;
if (params.Parse(GetCommandLine()))
{
return RunWithParameters(params);
}
return false;
}
bool Application::RunWithParameters(const ApplicationParameters& params)
{
using namespace AzFramework;
using namespace AzToolsFramework;
m_showVerboseOutput = params.m_verbose;
auto&& editorPythonEventsInterface = AZ::Interface<EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface)
{
try
{
StartPythonVM();
if (!m_startedPython)
{
AZ_Error("python_app", false, "Python VM did not start.");
return false;
}
if (params.m_pythonStatement.empty() == false)
{
EditorPythonRunnerRequestBus::Broadcast(
&EditorPythonRunnerRequestBus::Events::ExecuteByString,
params.m_pythonStatement,
params.m_verbose);
}
if (params.m_pythonFilename.empty() == false)
{
if (m_pythonExceptionCount == 0)
{
RunFileWithArgs(params);
}
else
{
AZ_Warning("python_app", false, "Did not execute script file since statement threw exceptions.");
}
}
const bool errorFree = (m_pythonExceptionCount == 0) && (m_pythonErrorCount == 0);
if (errorFree && params.m_interactiveMode)
{
AZSTD_PRINTF("Interactive mode enabled \n");
std::string statement;
bool executeStatement = false;
do
{
AZSTD_PRINTF("> ");
std::getline(std::cin, statement);
executeStatement = (statement.empty() == false);
if (executeStatement)
{
EditorPythonRunnerRequestBus::Broadcast(
&EditorPythonRunnerRequestBus::Events::ExecuteByString,
statement.c_str(),
params.m_verbose);
}
}
while (executeStatement);
}
if (errorFree == false)
{
AZ_Warning("python_app", false, "Encountered %d exceptions and %d errors", m_pythonExceptionCount, m_pythonErrorCount);
}
return errorFree;
}
catch (const std::exception& e)
{
OnExceptionMessage(e.what());
}
}
else
{
AZ_Error("python_app", false, "Python interface missing. "
"This likely means that the project has not enabled the EditorPythonBindings gem.");
}
return false;
}
bool Application::RunFileWithArgs(const ApplicationParameters& params)
{
using namespace AzFramework;
using namespace AzToolsFramework;
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
if (fileIO->Exists(params.m_pythonFilename.c_str()) == false)
{
AZ_Error("python_app", false, "Python file (%s) is missing.", params.m_pythonFilename.c_str());
return false;
}
AZStd::vector<AZStd::string_view> pythonArgs;
pythonArgs.reserve(params.m_pythonArgs.size());
for(auto&& arg : params.m_pythonArgs)
{
pythonArgs.push_back(arg);
}
AZStd::transform(params.m_pythonArgs.begin(), params.m_pythonArgs.end(), pythonArgs.begin(), [](auto&& arg)
{
return arg.c_str();
});
EditorPythonRunnerRequestBus::Broadcast(
&EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs,
params.m_pythonFilename,
pythonArgs);
return m_pythonExceptionCount == 0;
}
bool Application::OnPreError(const char* window, const char* fileName, int line, [[maybe_unused]] const char* func, const char* message)
{
printf("\n");
printf("[ERROR] - %s:\n", window);
if (m_showVerboseOutput)
{
printf("(%s - Line %i)\n", fileName, line);
}
printf("%s \n", message);
return true;
}
bool Application::OnPreWarning(const char* window, const char* fileName, int line, [[maybe_unused]] const char* func, const char* message)
{
// remove the warnings about the command line options from AZ::Console
if (AZ::StringFunc::Equal(window, "Az Console"))
{
return true;
}
printf("\n");
printf("[WARN] - %s:\n", window);
if (m_showVerboseOutput)
{
printf("(%s - Line %i)\n", fileName, line);
}
printf("%s \n", message);
return true;
}
bool Application::OnPrintf([[maybe_unused]] const char* window, const char* message)
{
if (m_showVerboseOutput)
{
printf("%s\n", message);
return true;
}
return !m_showVerboseOutput;
}
void Application::OnTraceMessage(AZStd::string_view message)
{
if (m_showVerboseOutput)
{
printf("(python) %.*s \n", aznumeric_cast<int>(message.size()), message.data());
}
}
void Application::OnErrorMessage(AZStd::string_view message)
{
++m_pythonErrorCount;
printf("(python) [ERROR] %.*s \n", aznumeric_cast<int>(message.size()), message.data());
}
void Application::OnExceptionMessage(AZStd::string_view message)
{
++m_pythonExceptionCount;
printf("(python) [EXCEPTION] %.*s \n", aznumeric_cast<int>(message.size()), message.data());
}
}