Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,278 @@
/*
* 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 <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)
CalculateExecutablePath();
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());
}
}
@@ -0,0 +1,60 @@
/*
* 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 <AzCore/Debug/TraceMessageBus.h>
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/API/EditorPythonConsoleBus.h>
namespace PythonBindingsExample
{
struct ApplicationParameters;
class Application
: public AzToolsFramework::ToolsApplication
, protected AZ::Debug::TraceMessageBus::Handler
, protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
{
public:
Application(int* argc, char*** argv);
~Application();
void SetUp();
bool Run();
void TearDown();
bool RunWithParameters(const ApplicationParameters& params);
protected:
////////////////////////////////////////////////////////////////////////////////////////////
// TraceMessageBus
bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override;
bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override;
bool OnPrintf(const char* window, const char* message) override;
////////////////////////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorPythonConsoleNotifications
void OnTraceMessage(AZStd::string_view message) override;
void OnErrorMessage(AZStd::string_view message) override;
void OnExceptionMessage(AZStd::string_view message) override;
bool RunFileWithArgs(const ApplicationParameters& params);
void StartPythonVM();
void StopPythonVM();
protected:
bool m_showVerboseOutput = false;
bool m_startedPython = false;
int m_pythonExceptionCount = 0;
int m_pythonErrorCount = 0;
};
}
@@ -0,0 +1,76 @@
/*
* 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 <source/ApplicationParameters.h>
#include <AzCore/Settings/CommandLine.h>
#include <AzToolsFramework/Application/ToolsApplication.h>
namespace PythonBindingsExample
{
void ApplicationParameters::ShowHelp()
{
constexpr const char* helpText =
R"(PythonBindingsExample - An example of how to bind the Behavior Context in a simple Tools Application
PythonBindingsExample.exe --file path/to/file.py --arg one --arg two
--help Prints the help text
--verbose (v) Uses verbose output
--file (f) Execute this Python script file
--arg (a) Any number of args sent to the Python script
--interactive (i) Run in interactive mode after file and/or statement (note: enable --verbose to get Python output)
--statement (s) Run Python string statement)";
puts(helpText);
}
bool ApplicationParameters::Parse(const AzFramework::CommandLine* commandLine)
{
if (commandLine->GetSwitchList().empty())
{
ShowHelp();
return false;
}
auto&& switchList = commandLine->GetSwitchList();
for (auto&& switchItem : switchList)
{
if (switchItem.first == "help")
{
ShowHelp();
return false;
}
else if (switchItem.first.starts_with('v'))
{
m_verbose = true;
}
else if (switchItem.first.starts_with('f'))
{
m_pythonFilename = switchItem.second[0];
}
else if (switchItem.first.starts_with('a'))
{
m_pythonArgs.push_back(switchItem.second[0]);
}
else if (switchItem.first.starts_with('s'))
{
m_pythonStatement = switchItem.second[0];
}
else if (switchItem.first.starts_with('i'))
{
m_interactiveMode = true;
}
else
{
AZ_Warning("python_app", false, "Unknown switch %s \n", switchItem.first.c_str());
}
}
return true;
}
}
@@ -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 <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
namespace AZ
{
class CommandLine;
}
namespace PythonBindingsExample
{
struct ApplicationParameters final
{
bool Parse(const AZ::CommandLine* commandLine);
// the arguments
using StringList = AZStd::vector<AZStd::string>;
bool m_verbose = false;
AZStd::string m_pythonFilename;
StringList m_pythonArgs;
AZStd::string m_pythonStatement;
bool m_interactiveMode = false;
protected:
void ShowHelp();
};
}
@@ -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
)
@@ -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
PUBLIC
/EHsc
)
@@ -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 <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <source/Application.h>
namespace PythonBindingsExample
{
//! This function returns the build system target name
AZStd::string_view GetBuildTargetName()
{
#if !defined (LY_CMAKE_TARGET)
#error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
#endif
return AZStd::string_view{ LY_CMAKE_TARGET };
}
}
int main(int argc, char* argv[])
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
int runSuccess = 0;
{
PythonBindingsExample::Application application(&argc, &argv);
// The AZ::ComponentApplication constructor creates the settings registry
// so the CMake target name can be added at this point
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(
*AZ::SettingsRegistry::Get(), PythonBindingsExample::GetBuildTargetName());
application.SetUp();
runSuccess = application.Run() ? 0 : 1;
}
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
return runSuccess;
}