You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1198 lines
45 KiB
C++
1198 lines
45 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 "EditorDefs.h"
|
|
|
|
#include "PythonEditorFuncs.h"
|
|
|
|
// Qt
|
|
#include <QMessageBox>
|
|
#include <QFileDialog>
|
|
|
|
#include <AzCore/Utils/Utils.h>
|
|
|
|
// AzToolsFramework
|
|
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
|
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
|
|
|
// Editor
|
|
#include "CryEdit.h"
|
|
#include "GameEngine.h"
|
|
#include "ViewManager.h"
|
|
#include "StringDlg.h"
|
|
#include "GenericSelectItemDialog.h"
|
|
#include "Objects/BaseObject.h"
|
|
#include "Commands/CommandManager.h"
|
|
|
|
|
|
namespace
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char* PyGetCVar(const char* pName)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
Warning("PyGetCVar: Attempt to access non-existent CVar '%s'", pName ? pName : "(null)");
|
|
throw std::logic_error((QString("\"") + pName + "\" is an invalid cvar.").toUtf8().data());
|
|
}
|
|
return pCVar->GetString();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char* PyGetCVarAsString(const char* pName)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
AZ_Warning("editor", false, "PyGetCVar: Attempt to access non-existent CVar '%s'", pName ? pName : "(null)");
|
|
return "(missing)";
|
|
}
|
|
return pCVar->GetString();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// forward declarations
|
|
void PySetCVarFromInt(const char* pName, int pValue);
|
|
void PySetCVarFromFloat(const char* pName, float pValue);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PySetCVarFromString(const char* pName, const char* pValue)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
AZ_Warning("editor", false, "Attempt to set non-existent string CVar '%s'", pName ? pName : "(null)");
|
|
}
|
|
else if (pCVar->GetType() == CVAR_INT)
|
|
{
|
|
PySetCVarFromInt(pName, std::stol(pValue));
|
|
}
|
|
else if (pCVar->GetType() == CVAR_FLOAT)
|
|
{
|
|
PySetCVarFromFloat(pName, std::stod(pValue));
|
|
}
|
|
else if (pCVar->GetType() != CVAR_STRING)
|
|
{
|
|
AZ_Warning("editor", false, "Type mismatch while assigning CVar '%s' as a string.", pName ? pName : "(null)");
|
|
}
|
|
else
|
|
{
|
|
pCVar->Set(pValue);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PySetCVarFromInt(const char* pName, int pValue)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
AZ_Warning("editor", false, "Attempt to set non-existent integer CVar '%s'", pName ? pName : "(null)");
|
|
}
|
|
else if (pCVar->GetType() == CVAR_FLOAT)
|
|
{
|
|
PySetCVarFromFloat(pName, float(pValue));
|
|
}
|
|
else if (pCVar->GetType() == CVAR_STRING)
|
|
{
|
|
auto stringValue = AZStd::to_string(pValue);
|
|
PySetCVarFromString(pName, stringValue.c_str());
|
|
}
|
|
else if (pCVar->GetType() != CVAR_INT)
|
|
{
|
|
AZ_Warning("editor", false, "Type mismatch while assigning CVar '%s' as an integer.", pName ? pName : "(null)");
|
|
}
|
|
else
|
|
{
|
|
pCVar->Set(pValue);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PySetCVarFromFloat(const char* pName, float pValue)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
AZ_Warning("editor", false, "Attempt to set non-existent float CVar '%s'", pName ? pName : "(null)");
|
|
}
|
|
else if (pCVar->GetType() == CVAR_INT)
|
|
{
|
|
PySetCVarFromInt(pName, static_cast<int>(pValue));
|
|
}
|
|
else if (pCVar->GetType() == CVAR_STRING)
|
|
{
|
|
auto stringValue = AZStd::to_string(pValue);
|
|
PySetCVarFromString(pName, stringValue.c_str());
|
|
}
|
|
else if (pCVar->GetType() != CVAR_FLOAT)
|
|
{
|
|
AZ_Warning("editor", false, "Type mismatch while assigning CVar '%s' as a float.", pName ? pName : "(null)");
|
|
}
|
|
else
|
|
{
|
|
pCVar->Set(pValue);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PySetCVarFromAny(const char* pName, const AZStd::any& value)
|
|
{
|
|
ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(pName);
|
|
if (!pCVar)
|
|
{
|
|
AZ_Warning("editor", false, "Attempt to set non-existent float CVar '%s'", pName ? pName : "(null)");
|
|
}
|
|
else if (pCVar->GetType() == CVAR_INT)
|
|
{
|
|
PySetCVarFromInt(pName, AZStd::any_cast<AZ::s64>(value));
|
|
}
|
|
else if (pCVar->GetType() == CVAR_FLOAT)
|
|
{
|
|
PySetCVarFromFloat(pName, AZStd::any_cast<double>(value));
|
|
}
|
|
else if (pCVar->GetType() == CVAR_STRING)
|
|
{
|
|
PySetCVarFromString(pName, AZStd::any_cast<AZStd::string_view>(value).data());
|
|
}
|
|
else
|
|
{
|
|
AZ_Warning("editor", false, "Type mismatch while assigning CVar '%s' as a float.", pName ? pName : "(null)");
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyEnterGameMode()
|
|
{
|
|
if (GetIEditor()->GetGameEngine())
|
|
{
|
|
GetIEditor()->GetGameEngine()->RequestSetGameMode(true);
|
|
}
|
|
}
|
|
|
|
void PyExitGameMode()
|
|
{
|
|
if (GetIEditor()->GetGameEngine())
|
|
{
|
|
GetIEditor()->GetGameEngine()->RequestSetGameMode(false);
|
|
}
|
|
}
|
|
|
|
bool PyIsInGameMode()
|
|
{
|
|
return GetIEditor()->IsInGameMode();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyEnterSimulationMode()
|
|
{
|
|
if (!GetIEditor()->IsInSimulationMode())
|
|
{
|
|
CCryEditApp::instance()->OnSwitchPhysics();
|
|
}
|
|
}
|
|
|
|
void PyExitSimulationMode()
|
|
{
|
|
if (GetIEditor()->IsInSimulationMode())
|
|
{
|
|
CCryEditApp::instance()->OnSwitchPhysics();
|
|
}
|
|
}
|
|
|
|
bool PyIsInSimulationMode()
|
|
{
|
|
return GetIEditor()->IsInSimulationMode();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
QString PyNewObject(const char* typeName, const char* fileName, const char* name, float x, float y, float z)
|
|
{
|
|
CBaseObject* object = GetIEditor()->NewObject(typeName, fileName, name, x, y, z);
|
|
if (object)
|
|
{
|
|
return object->GetName();
|
|
}
|
|
else
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
QString PyNewObjectAtCursor(const char* typeName, const char* fileName, const char* name)
|
|
{
|
|
CUndo undo("Create new object");
|
|
|
|
Vec3 pos(0, 0, 0);
|
|
|
|
QPoint p = QCursor::pos();
|
|
CViewport* viewport = GetIEditor()->GetViewManager()->GetViewportAtPoint(p);
|
|
if (viewport)
|
|
{
|
|
viewport->ScreenToClient(p);
|
|
if (GetIEditor()->GetAxisConstrains() != AXIS_TERRAIN)
|
|
{
|
|
pos = viewport->MapViewToCP(p);
|
|
}
|
|
else
|
|
{
|
|
// Snap to terrain.
|
|
bool hitTerrain;
|
|
pos = viewport->ViewToWorld(p, &hitTerrain);
|
|
if (hitTerrain)
|
|
{
|
|
pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y) + 1.0f;
|
|
}
|
|
pos = viewport->SnapToGrid(pos);
|
|
}
|
|
}
|
|
|
|
return PyNewObject(typeName, fileName, name, pos.x, pos.y, pos.z);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyRunConsole(const char* text)
|
|
{
|
|
GetIEditor()->GetSystem()->GetIConsole()->ExecuteString(text);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool GetPythonScriptPath(const char* pFile, QString& path)
|
|
{
|
|
bool bRelativePath = true;
|
|
char drive[_MAX_DRIVE];
|
|
char fdir[_MAX_DIR];
|
|
char fname[_MAX_FNAME];
|
|
char fext[_MAX_EXT];
|
|
drive[0] = '\0';
|
|
|
|
_splitpath_s(pFile, drive, fdir, fname, fext);
|
|
if (strlen(drive) != 0)
|
|
{
|
|
bRelativePath = false;
|
|
}
|
|
|
|
if (bRelativePath)
|
|
{
|
|
// Try to open from user folder
|
|
QString userSandboxFolder = Path::GetResolvedUserSandboxFolder();
|
|
Path::ConvertBackSlashToSlash(userSandboxFolder);
|
|
path = userSandboxFolder + pFile;
|
|
|
|
// If not found try editor folder
|
|
if (!CFileUtil::FileExists(path))
|
|
{
|
|
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
|
|
QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
|
|
|
|
QString scriptFolder = engineDir.absoluteFilePath("Assets/Editor/Scripts/");
|
|
Path::ConvertBackSlashToSlash(scriptFolder);
|
|
path = scriptFolder + pFile;
|
|
|
|
if (!CFileUtil::FileExists(path))
|
|
{
|
|
QString error = QString("Could not find '%1'\n in '%2'\n or '%3'\n").arg(pFile).arg(userSandboxFolder).arg(scriptFolder);
|
|
AZ_Warning("python", false, error.toUtf8().data());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
path = pFile;
|
|
if (!CFileUtil::FileExists(path))
|
|
{
|
|
QString error = QString("Could not find '") + pFile + "'\n";
|
|
AZ_Warning("python", false, error.toUtf8().data());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Path::ConvertBackSlashToSlash(path);
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void GetPythonArgumentsVector(const char* pArguments, QStringList& inputArguments)
|
|
{
|
|
if (pArguments == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
inputArguments = QString(pArguments).split(" ", Qt::SkipEmptyParts);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyRunFileWithParameters(const char* pFile, const char* pArguments)
|
|
{
|
|
QString path;
|
|
QStringList inputArguments;
|
|
GetPythonArgumentsVector(pArguments, inputArguments);
|
|
if (GetPythonScriptPath(pFile, path))
|
|
{
|
|
AZStd::vector<AZStd::string_view> argList;
|
|
argList.reserve(inputArguments.size() + 1);
|
|
QByteArray p = path.toUtf8();
|
|
|
|
QVector<QByteArray> argData;
|
|
argData.reserve(inputArguments.count());
|
|
for (auto iter = inputArguments.begin(); iter != inputArguments.end(); ++iter)
|
|
{
|
|
argData.push_back(iter->toLatin1());
|
|
argList.push_back(argData.last().data());
|
|
}
|
|
using namespace AzToolsFramework;
|
|
EditorPythonRunnerRequestBus::Broadcast(&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, p.data(), argList);
|
|
}
|
|
}
|
|
|
|
void PyRunFile(const char* pFile)
|
|
{
|
|
PyRunFileWithParameters(pFile, nullptr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyExecuteCommand(const char* cmdline)
|
|
{
|
|
GetIEditor()->GetCommandManager()->Execute(cmdline);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyLog(const char* pMessage)
|
|
{
|
|
if (strcmp(pMessage, "") != 0)
|
|
{
|
|
CryLogAlways(pMessage);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool PyMessageBox(const char* pMessage)
|
|
{
|
|
return QMessageBox::information(QApplication::activeWindow(), QString(), pMessage, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok;
|
|
}
|
|
|
|
bool PyMessageBoxYesNo(const char* pMessage)
|
|
{
|
|
return QMessageBox::question(QApplication::activeWindow(), QString(), pMessage) == QMessageBox::Yes;
|
|
}
|
|
|
|
bool PyMessageBoxOK(const char* pMessage)
|
|
{
|
|
return QMessageBox::information(QApplication::activeWindow(), QString(), pMessage) == QMessageBox::Ok;
|
|
}
|
|
|
|
AZStd::string PyEditBox(AZStd::string_view pTitle)
|
|
{
|
|
StringDlg stringDialog(pTitle.data());
|
|
if (stringDialog.exec() == QDialog::Accepted)
|
|
{
|
|
return stringDialog.GetString().toUtf8().constData();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
AZStd::any PyEditBoxAndCheckProperty(const char* pTitle)
|
|
{
|
|
StringDlg stringDialog(pTitle);
|
|
stringDialog.SetString(QStringLiteral(""));
|
|
if (stringDialog.exec() == QDialog::Accepted)
|
|
{
|
|
const QString stringValue = stringDialog.GetString();
|
|
|
|
// detect data type
|
|
QString tempString = stringValue;
|
|
int countComa = 0;
|
|
int countOpenRoundBraket = 0;
|
|
int countCloseRoundBraket = 0;
|
|
int countDots = 0;
|
|
|
|
int posDots = 0;
|
|
int posComa = 0;
|
|
int posOpenRoundBraket = 0;
|
|
int posCloseRoundBraket = 0;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if (tempString.indexOf(".", posDots) > -1)
|
|
{
|
|
posDots = tempString.indexOf(".", posDots) + 1;
|
|
countDots++;
|
|
}
|
|
if (tempString.indexOf(",", posComa) > -1)
|
|
{
|
|
posComa = tempString.indexOf(",", posComa) + 1;
|
|
countComa++;
|
|
}
|
|
if (tempString.indexOf("(", posOpenRoundBraket) > -1)
|
|
{
|
|
posOpenRoundBraket = tempString.indexOf("(", posOpenRoundBraket) + 1;
|
|
countOpenRoundBraket++;
|
|
}
|
|
if (tempString.indexOf(")", posCloseRoundBraket) > -1)
|
|
{
|
|
posCloseRoundBraket = tempString.indexOf(")", posCloseRoundBraket) + 1;
|
|
countCloseRoundBraket++;
|
|
}
|
|
}
|
|
|
|
if (countDots == 3 && countComa == 2 && countOpenRoundBraket == 1 && countCloseRoundBraket == 1)
|
|
{
|
|
// for example: (1.95, 2.75, 3.36)
|
|
QString valueRed = stringValue;
|
|
int iStart = valueRed.indexOf("(");
|
|
valueRed.remove(0, iStart + 1);
|
|
int iEnd = valueRed.indexOf(",");
|
|
valueRed.remove(iEnd, valueRed.length());
|
|
float fValueRed = valueRed.toFloat();
|
|
|
|
QString valueGreen = stringValue;
|
|
iStart = valueGreen.indexOf(",");
|
|
valueGreen.remove(0, iStart + 1);
|
|
iEnd = valueGreen.indexOf(",");
|
|
valueGreen.remove(iEnd, valueGreen.length());
|
|
float fValueGreen = valueGreen.toFloat();
|
|
|
|
QString valueBlue = stringValue;
|
|
valueBlue.remove(0, valueBlue.indexOf(",") + 1);
|
|
valueBlue.remove(0, valueBlue.indexOf(",") + 1);
|
|
valueBlue.remove(valueBlue.indexOf(")"), valueBlue.length());
|
|
float fValueBlue = valueBlue.toFloat();
|
|
|
|
return AZStd::make_any<AZ::Vector3>(fValueRed, fValueGreen, fValueBlue);
|
|
}
|
|
else if (countDots == 0 && countComa == 2 && countOpenRoundBraket == 1 && countCloseRoundBraket == 1)
|
|
{
|
|
// for example: (128, 32, 240)
|
|
const AZ::u8 lowColorValue { 0 };
|
|
const AZ::u8 highColorValue { 255 };
|
|
QString valueRed = stringValue;
|
|
int iStart = valueRed.indexOf("(");
|
|
valueRed.remove(0, iStart + 1);
|
|
int iEnd = valueRed.indexOf(",");
|
|
valueRed.remove(iEnd, valueRed.length());
|
|
AZ::u8 iValueRed = AZStd::clamp(aznumeric_cast<AZ::u8>(valueRed.toInt()), lowColorValue, highColorValue);
|
|
|
|
QString valueGreen = stringValue;
|
|
iStart = valueGreen.indexOf(",");
|
|
valueGreen.remove(0, iStart + 1);
|
|
iEnd = valueGreen.indexOf(",");
|
|
valueGreen.remove(iEnd, valueGreen.length());
|
|
AZ::u8 iValueGreen = AZStd::clamp(aznumeric_cast<AZ::u8>(valueGreen.toInt()), lowColorValue, highColorValue);
|
|
|
|
QString valueBlue = stringValue;
|
|
valueBlue.remove(0, valueBlue.indexOf(",") + 1);
|
|
valueBlue.remove(0, valueBlue.indexOf(",") + 1);
|
|
valueBlue.remove(valueBlue.indexOf(")"), valueBlue.length());
|
|
AZ::u8 iValueBlue = AZStd::clamp(aznumeric_cast<AZ::u8>(valueBlue.toInt()), lowColorValue, highColorValue);
|
|
|
|
return AZStd::make_any<AZ::Color>(iValueRed, iValueGreen, iValueBlue, highColorValue);
|
|
}
|
|
else if (countDots == 1 && countComa == 0 && countOpenRoundBraket == 0 && countCloseRoundBraket == 0)
|
|
{
|
|
// for example: 2.56
|
|
return AZStd::make_any<double>(stringValue.toDouble());
|
|
}
|
|
else if (countDots == 0 && countComa == 0 && countOpenRoundBraket == 0 && countCloseRoundBraket == 0)
|
|
{
|
|
if (stringValue == "False" || stringValue == "True")
|
|
{
|
|
// for example: True
|
|
return AZStd::make_any<bool>(stringValue == "True");
|
|
}
|
|
else
|
|
{
|
|
const bool anyNotDigits = AZStd::any_of(stringValue.begin(), stringValue.end(), [](const QChar& ch) { return !ch.isDigit(); });
|
|
|
|
// looks like a string value?
|
|
if (stringValue.isEmpty() || anyNotDigits)
|
|
{
|
|
// for example: Hello
|
|
return AZStd::make_any<AZStd::string>(stringValue.toUtf8().data());
|
|
}
|
|
else // then it looks like an integer
|
|
{
|
|
// for example: 456
|
|
return AZStd::make_any<AZ::s64>(stringValue.toInt());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QObject::tr("Invalid Data"), QObject::tr("Invalid data type."));
|
|
return {};
|
|
}
|
|
|
|
AZStd::string PyOpenFileBox()
|
|
{
|
|
QString path = QFileDialog::getOpenFileName();
|
|
if (!path.isEmpty())
|
|
{
|
|
Path::ConvertBackSlashToSlash(path);
|
|
}
|
|
return path.toUtf8().constData();
|
|
}
|
|
|
|
AZStd::string PyComboBox(AZStd::string title, AZStd::vector<AZStd::string> values, int selectedIdx = 0)
|
|
{
|
|
AZStd::string result;
|
|
|
|
if (title.empty())
|
|
{
|
|
throw std::runtime_error("Incorrect title argument passed in. ");
|
|
return result;
|
|
}
|
|
|
|
if (values.size() == 0)
|
|
{
|
|
throw std::runtime_error("Empty value list passed in. ");
|
|
return result;
|
|
}
|
|
|
|
QStringList list;
|
|
|
|
for (const AZStd::string& str : values)
|
|
{
|
|
list.push_back(str.c_str());
|
|
}
|
|
|
|
CGenericSelectItemDialog pyDlg;
|
|
pyDlg.setWindowTitle(title.c_str());
|
|
pyDlg.SetMode(CGenericSelectItemDialog::eMODE_LIST);
|
|
pyDlg.SetItems(list);
|
|
pyDlg.PreSelectItem(list[selectedIdx]);
|
|
|
|
if (pyDlg.exec() == QDialog::Accepted)
|
|
{
|
|
result = pyDlg.GetSelectedItem().toUtf8().constData();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void PyCrash()
|
|
{
|
|
AZ_Crash();
|
|
}
|
|
|
|
static void PyDrawLabel(int x, int y, float size, float r, float g, float b, float a, const char* pLabel)
|
|
{
|
|
if (!pLabel)
|
|
{
|
|
throw std::logic_error("No label given.");
|
|
return;
|
|
}
|
|
|
|
if (!r || !g || !b || !a)
|
|
{
|
|
throw std::logic_error("Invalid color parameters given.");
|
|
return;
|
|
}
|
|
|
|
if (!x || !y || !size)
|
|
{
|
|
throw std::logic_error("Invalid position or size parameters given.");
|
|
}
|
|
else
|
|
{
|
|
// ToDo: Remove function or update to work with Atom? LYN-3672
|
|
// float color[] = {r, g, b, a};
|
|
// ???->Draw2dLabel(x, y, size, color, false, pLabel);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Constrain
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char* PyGetAxisConstraint()
|
|
{
|
|
AxisConstrains actualConstrain = GetIEditor()->GetAxisConstrains();
|
|
switch (actualConstrain)
|
|
{
|
|
case AXIS_X:
|
|
return "X";
|
|
case AXIS_Y:
|
|
return "Y";
|
|
case AXIS_Z:
|
|
return "Z";
|
|
case AXIS_XY:
|
|
return "XY";
|
|
case AXIS_XZ:
|
|
return "XZ";
|
|
case AXIS_YZ:
|
|
return "YZ";
|
|
case AXIS_XYZ:
|
|
return "XYZ";
|
|
case AXIS_TERRAIN:
|
|
return (GetIEditor()->IsTerrainAxisIgnoreObjects()) ? "TERRAIN" : "TERRAINSNAP";
|
|
default:
|
|
throw std::logic_error("Invalid axes.");
|
|
}
|
|
}
|
|
|
|
void PySetAxisConstraint(AZStd::string_view pConstrain)
|
|
{
|
|
if (pConstrain == "X")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_X);
|
|
}
|
|
else if (pConstrain == "Y")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_Y);
|
|
}
|
|
else if (pConstrain == "Z")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_Z);
|
|
}
|
|
else if (pConstrain == "XY")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_XY);
|
|
}
|
|
else if (pConstrain == "YZ")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_YZ);
|
|
}
|
|
else if (pConstrain == "XZ")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_XZ);
|
|
}
|
|
else if (pConstrain == "XYZ")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_XYZ);
|
|
}
|
|
else if (pConstrain == "TERRAIN")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_TERRAIN);
|
|
GetIEditor()->SetTerrainAxisIgnoreObjects(true);
|
|
}
|
|
else if (pConstrain == "TERRAINSNAP")
|
|
{
|
|
GetIEditor()->SetAxisConstraints(AXIS_TERRAIN);
|
|
GetIEditor()->SetTerrainAxisIgnoreObjects(false);
|
|
}
|
|
else
|
|
{
|
|
throw std::logic_error("Invalid axes.");
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const char* PyGetPakFromFile(const char* filename)
|
|
{
|
|
auto pIPak = GetIEditor()->GetSystem()->GetIPak();
|
|
AZ::IO::HandleType fileHandle = pIPak->FOpen(filename, "rb");
|
|
if (fileHandle == AZ::IO::InvalidHandle)
|
|
{
|
|
throw std::logic_error("Invalid file name.");
|
|
}
|
|
const char* pArchPath = pIPak->GetFileArchivePath(fileHandle);
|
|
pIPak->FClose(fileHandle);
|
|
return pArchPath;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyUndo()
|
|
{
|
|
GetIEditor()->Undo();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void PyRedo()
|
|
{
|
|
GetIEditor()->Redo();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Temporal, to be removed by LY-101149
|
|
AZ::EntityId PyFindEditorEntity(const char* name)
|
|
{
|
|
AZ::EntityId foundEntityId;
|
|
|
|
auto searchFunc = [name, &foundEntityId](AZ::Entity* e)
|
|
{
|
|
if (!foundEntityId.IsValid() && e->GetName() == name)
|
|
{
|
|
bool isEditorEntity = false;
|
|
AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(isEditorEntity, &AzToolsFramework::EditorEntityContextRequests::IsEditorEntity, e->GetId());
|
|
if (isEditorEntity)
|
|
{
|
|
foundEntityId = e->GetId();
|
|
}
|
|
}
|
|
};
|
|
|
|
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::EnumerateEntities, searchFunc);
|
|
return foundEntityId;
|
|
}
|
|
|
|
AZ::EntityId PyFindGameEntity(const char* name)
|
|
{
|
|
AZ::EntityId foundEntityId;
|
|
|
|
auto searchFunc = [name, &foundEntityId](AZ::Entity* e)
|
|
{
|
|
if (!foundEntityId.IsValid() && e->GetName() == name)
|
|
{
|
|
bool isEditorEntity = true;
|
|
AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(isEditorEntity, &AzToolsFramework::EditorEntityContextRequests::IsEditorEntity, e->GetId());
|
|
if (!isEditorEntity)
|
|
{
|
|
foundEntityId = e->GetId();
|
|
}
|
|
}
|
|
};
|
|
|
|
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::EnumerateEntities, searchFunc);
|
|
return foundEntityId;
|
|
}
|
|
|
|
|
|
struct PyDumpBindings
|
|
{
|
|
static AZ_INLINE bool IsBehaviorFlaggedForEditor(const AZ::AttributeArray& attributes)
|
|
{
|
|
// defaults to Launcher
|
|
AZ::Script::Attributes::ScopeFlags scopeType = AZ::Script::Attributes::ScopeFlags::Launcher;
|
|
AZ::Attribute* scopeAttribute = AZ::FindAttribute(AZ::Script::Attributes::Scope, attributes);
|
|
if (scopeAttribute)
|
|
{
|
|
AZ::AttributeReader scopeAttributeReader(nullptr, scopeAttribute);
|
|
scopeAttributeReader.Read<AZ::Script::Attributes::ScopeFlags>(scopeType);
|
|
}
|
|
return (scopeType == AZ::Script::Attributes::ScopeFlags::Automation || scopeType == AZ::Script::Attributes::ScopeFlags::Common);
|
|
}
|
|
|
|
static AZ_INLINE AZStd::string GetModuleName(const AZ::AttributeArray& attributes)
|
|
{
|
|
AZStd::string moduleName;
|
|
AZ::Attribute* moduleAttribute = AZ::FindAttribute(AZ::Script::Attributes::Module, attributes);
|
|
if (moduleAttribute)
|
|
{
|
|
AZ::AttributeReader scopeAttributeReader(nullptr, moduleAttribute);
|
|
scopeAttributeReader.Read<AZStd::string>(moduleName);
|
|
}
|
|
if (!moduleName.empty())
|
|
{
|
|
moduleName = "azlmbr." + moduleName;
|
|
}
|
|
else
|
|
{
|
|
moduleName = "azlmbr";
|
|
}
|
|
|
|
return moduleName;
|
|
}
|
|
|
|
|
|
static AZStd::string ParameterToString(const AZ::BehaviorMethod* method, size_t index)
|
|
{
|
|
const AZStd::string* argNameStr = method->GetArgumentName(index);
|
|
const char* argName = (argNameStr && !argNameStr->empty()) ? argNameStr->c_str() : nullptr;
|
|
if (argName)
|
|
{
|
|
return AZStd::string::format("%s %s", method->GetArgument(index)->m_name, argName);
|
|
}
|
|
else
|
|
{
|
|
return method->GetArgument(index)->m_name;
|
|
}
|
|
}
|
|
|
|
static AZStd::string MethodArgumentsToString(const AZ::BehaviorMethod* method)
|
|
{
|
|
AZStd::string ret;
|
|
AZStd::string argumentStr;
|
|
for (size_t i = 0; i < method->GetNumArguments(); ++i)
|
|
{
|
|
argumentStr = ParameterToString(method, i);
|
|
ret += argumentStr;
|
|
if (i < method->GetNumArguments() - 1)
|
|
{
|
|
ret += ", ";
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static AZStd::string MethodToString(const AZStd::string& methodName, const AZ::BehaviorMethod* method)
|
|
{
|
|
AZStd::string methodNameStrip = methodName.data() + methodName.rfind(':') + 1; // remove ClassName:: part as it is redundant
|
|
return AZStd::string::format("%s %s(%s)%s", method->GetResult()->m_name, methodNameStrip.c_str(), MethodArgumentsToString(method).c_str(), method->m_isConst ? " const" : "");
|
|
}
|
|
|
|
static AZStd::string GetExposedPythonClasses()
|
|
{
|
|
AZ::BehaviorContext* behaviorContext(nullptr);
|
|
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
|
|
|
|
AZStd::string output = "";
|
|
output += "// Classes\n\n";
|
|
|
|
for (auto elem : behaviorContext->m_classes)
|
|
{
|
|
AZ::BehaviorClass* cls = elem.second;
|
|
|
|
bool exposedToPython = IsBehaviorFlaggedForEditor(cls->m_attributes);
|
|
if (!exposedToPython)
|
|
continue;
|
|
|
|
output += AZStd::string::format("// Module: %s\n", GetModuleName(cls->m_attributes).c_str());
|
|
output += AZStd::string::format("class %s\n", cls->m_name.c_str());
|
|
output += "{\n";
|
|
|
|
if (cls->m_methods.size() > 0)
|
|
{
|
|
output += " // Methods\n";
|
|
for (auto method_elem : cls->m_methods)
|
|
{
|
|
output += AZStd::string::format(" %s;\n", MethodToString(method_elem.first, method_elem.second).c_str());
|
|
}
|
|
}
|
|
if (cls->m_properties.size() > 0)
|
|
{
|
|
output += " // Properties\n";
|
|
for (auto property_elem : cls->m_properties)
|
|
{
|
|
AZ::BehaviorProperty* bproperty = property_elem.second;
|
|
output += AZStd::string::format(" %s %s;\n", bproperty->m_getter->GetResult()->m_name, bproperty->m_name.c_str());
|
|
}
|
|
}
|
|
|
|
output += "}\n";
|
|
}
|
|
output += "\n\n// Ebuses\n\n";
|
|
for (auto elem : behaviorContext->m_ebuses)
|
|
{
|
|
AZ::BehaviorEBus* ebus = elem.second;
|
|
|
|
bool exposedToPython = IsBehaviorFlaggedForEditor(ebus->m_attributes);
|
|
if (!exposedToPython)
|
|
continue;
|
|
|
|
output += AZStd::string::format("// Module: %s\n", GetModuleName(ebus->m_attributes).c_str());
|
|
output += AZStd::string::format("ebus %s\n", ebus->m_name.c_str());
|
|
output += "{\n";
|
|
for (auto event_elem : ebus->m_events)
|
|
{
|
|
auto method = event_elem.second.m_event ? event_elem.second.m_event : event_elem.second.m_broadcast;
|
|
if (method)
|
|
{
|
|
const char* comment = event_elem.second.m_event ? "/* event */" : "/* broadcast */";
|
|
output += AZStd::string::format(" %s %s\n", comment, MethodToString(event_elem.first, method).c_str());
|
|
}
|
|
else
|
|
{
|
|
output += AZStd::string::format(" %s %s\n", "/* unknown */", event_elem.first.c_str());
|
|
}
|
|
}
|
|
|
|
if (ebus->m_createHandler)
|
|
{
|
|
AZ::BehaviorEBusHandler* handler = nullptr;
|
|
ebus->m_createHandler->InvokeResult(handler);
|
|
if (handler)
|
|
{
|
|
const auto& notifications = handler->GetEvents();
|
|
for (const auto& notification : notifications)
|
|
{
|
|
AZStd::string argsStr;
|
|
const size_t paramCount = notification.m_parameters.size();
|
|
for (size_t i = 0; i < notification.m_parameters.size(); ++i)
|
|
{
|
|
AZStd::string argName = notification.m_parameters[i].m_name;
|
|
argsStr += argName;
|
|
if (i != paramCount - 1)
|
|
{
|
|
argsStr += ", ";
|
|
}
|
|
}
|
|
|
|
AZStd::string funcName = notification.m_name;
|
|
output += AZStd::string::format(" /* notification */ %s(%s);\n", funcName.c_str(), argsStr.c_str());
|
|
}
|
|
ebus->m_destroyHandler->Invoke(handler);
|
|
}
|
|
}
|
|
|
|
output += "}\n";
|
|
|
|
}
|
|
AzFramework::StringFunc::Replace(output, "AZStd::basic_string<char, AZStd::char_traits<char>, allocator>", "AZStd::string");
|
|
return output;
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace AzToolsFramework
|
|
{
|
|
void PythonEditorComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
|
{
|
|
behaviorContext->EBus<EditorLayerPythonRequestBus>("PythonEditorBus")
|
|
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
|
->Attribute(AZ::Script::Attributes::Module, "python_editor_funcs")
|
|
->Event("GetCVar", &EditorLayerPythonRequestBus::Events::GetCVar)
|
|
->Event("SetCVar", &EditorLayerPythonRequestBus::Events::SetCVar)
|
|
->Event("SetCVarFromString", &EditorLayerPythonRequestBus::Events::SetCVarFromString)
|
|
->Event("SetCVarFromInteger", &EditorLayerPythonRequestBus::Events::SetCVarFromInteger)
|
|
->Event("SetCVarFromFloat", &EditorLayerPythonRequestBus::Events::SetCVarFromFloat)
|
|
->Event("RunConsole", &EditorLayerPythonRequestBus::Events::PyRunConsole)
|
|
->Event("EnterGameMode", &EditorLayerPythonRequestBus::Events::EnterGameMode)
|
|
->Event("IsInGameMode", &EditorLayerPythonRequestBus::Events::IsInGameMode)
|
|
->Event("ExitGameMode", &EditorLayerPythonRequestBus::Events::ExitGameMode)
|
|
->Event("EnterSimulationMode", &EditorLayerPythonRequestBus::Events::EnterSimulationMode)
|
|
->Event("IsInSimulationMode", &EditorLayerPythonRequestBus::Events::IsInSimulationMode)
|
|
->Event("ExitSimulationMode", &EditorLayerPythonRequestBus::Events::ExitSimulationMode)
|
|
->Event("RunFile", &EditorLayerPythonRequestBus::Events::RunFile)
|
|
->Event("RunFileParameters", &EditorLayerPythonRequestBus::Events::RunFileParameters)
|
|
->Event("ExecuteCommand", &EditorLayerPythonRequestBus::Events::ExecuteCommand)
|
|
->Event("MessageBoxOkCancel", &EditorLayerPythonRequestBus::Events::MessageBoxOkCancel)
|
|
->Event("MessageBoxYesNo", &EditorLayerPythonRequestBus::Events::MessageBoxYesNo)
|
|
->Event("MessageBoxOk", &EditorLayerPythonRequestBus::Events::MessageBoxOk)
|
|
->Event("EditBox", &EditorLayerPythonRequestBus::Events::EditBox)
|
|
->Event("EditBoxCheckDataType", &EditorLayerPythonRequestBus::Events::EditBoxCheckDataType)
|
|
->Event("OpenFileBox", &EditorLayerPythonRequestBus::Events::OpenFileBox)
|
|
->Event("GetAxisConstraint", &EditorLayerPythonRequestBus::Events::GetAxisConstraint)
|
|
->Event("SetAxisConstraint", &EditorLayerPythonRequestBus::Events::SetAxisConstraint)
|
|
->Event("GetPakFromFile", &EditorLayerPythonRequestBus::Events::GetPakFromFile)
|
|
->Event("Log", &EditorLayerPythonRequestBus::Events::Log)
|
|
->Event("Undo", &EditorLayerPythonRequestBus::Events::Undo)
|
|
->Event("Redo", &EditorLayerPythonRequestBus::Events::Redo)
|
|
->Event("DrawLabel", &EditorLayerPythonRequestBus::Events::DrawLabel)
|
|
->Event("ComboBox", &EditorLayerPythonRequestBus::Events::ComboBox)
|
|
;
|
|
}
|
|
}
|
|
|
|
void PythonEditorComponent::Activate()
|
|
{
|
|
EditorLayerPythonRequestBus::Handler::BusConnect(GetEntityId());
|
|
}
|
|
|
|
void PythonEditorComponent::Deactivate()
|
|
{
|
|
EditorLayerPythonRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
const char* PythonEditorComponent::GetCVar(const char* pName)
|
|
{
|
|
return PyGetCVarAsString(pName);
|
|
}
|
|
|
|
void PythonEditorComponent::SetCVar(const char* pName, const AZStd::any& value)
|
|
{
|
|
return PySetCVarFromAny(pName, value);
|
|
}
|
|
|
|
void PythonEditorComponent::SetCVarFromString(const char* pName, const char* pValue)
|
|
{
|
|
return PySetCVarFromString(pName, pValue);
|
|
}
|
|
|
|
void PythonEditorComponent::SetCVarFromInteger(const char* pName, int pValue)
|
|
{
|
|
return PySetCVarFromInt(pName, pValue);
|
|
}
|
|
|
|
void PythonEditorComponent::SetCVarFromFloat(const char* pName, float pValue)
|
|
{
|
|
return PySetCVarFromFloat(pName, pValue);
|
|
}
|
|
|
|
void PythonEditorComponent::PyRunConsole(const char* text)
|
|
{
|
|
return ::PyRunConsole(text);
|
|
}
|
|
|
|
void PythonEditorComponent::EnterGameMode()
|
|
{
|
|
return PyEnterGameMode();
|
|
}
|
|
|
|
bool PythonEditorComponent::IsInGameMode()
|
|
{
|
|
return PyIsInGameMode();
|
|
}
|
|
|
|
void PythonEditorComponent::ExitGameMode()
|
|
{
|
|
return PyExitGameMode();
|
|
}
|
|
|
|
void PythonEditorComponent::EnterSimulationMode()
|
|
{
|
|
return PyEnterSimulationMode();
|
|
}
|
|
|
|
bool PythonEditorComponent::IsInSimulationMode()
|
|
{
|
|
return PyIsInSimulationMode();
|
|
}
|
|
|
|
void PythonEditorComponent::ExitSimulationMode()
|
|
{
|
|
return PyExitSimulationMode();
|
|
}
|
|
|
|
void PythonEditorComponent::RunFile(const char *pFile)
|
|
{
|
|
return PyRunFile(pFile);
|
|
}
|
|
|
|
void PythonEditorComponent::RunFileParameters(const char* pFile, const char* pArguments)
|
|
{
|
|
return PyRunFileWithParameters(pFile, pArguments);
|
|
}
|
|
|
|
void PythonEditorComponent::ExecuteCommand(const char* cmdline)
|
|
{
|
|
return PyExecuteCommand(cmdline);
|
|
}
|
|
|
|
bool PythonEditorComponent::MessageBoxOkCancel(const char* pMessage)
|
|
{
|
|
return PyMessageBox(pMessage);
|
|
}
|
|
|
|
bool PythonEditorComponent::MessageBoxYesNo(const char* pMessage)
|
|
{
|
|
return PyMessageBoxYesNo(pMessage);
|
|
}
|
|
|
|
bool PythonEditorComponent::MessageBoxOk(const char* pMessage)
|
|
{
|
|
return PyMessageBoxOK(pMessage);
|
|
}
|
|
|
|
AZStd::string PythonEditorComponent::EditBox(AZStd::string_view pTitle)
|
|
{
|
|
return PyEditBox(pTitle);
|
|
}
|
|
|
|
AZStd::any PythonEditorComponent::EditBoxCheckDataType(const char* pTitle)
|
|
{
|
|
return PyEditBoxAndCheckProperty(pTitle);
|
|
}
|
|
|
|
AZStd::string PythonEditorComponent::OpenFileBox()
|
|
{
|
|
return PyOpenFileBox();
|
|
}
|
|
|
|
const char* PythonEditorComponent::GetAxisConstraint()
|
|
{
|
|
return PyGetAxisConstraint();
|
|
}
|
|
|
|
void PythonEditorComponent::SetAxisConstraint(AZStd::string_view pConstrain)
|
|
{
|
|
return PySetAxisConstraint(pConstrain);
|
|
}
|
|
|
|
const char* PythonEditorComponent::GetPakFromFile(const char* filename)
|
|
{
|
|
return PyGetPakFromFile(filename);
|
|
}
|
|
|
|
void PythonEditorComponent::Log(const char* pMessage)
|
|
{
|
|
return PyLog(pMessage);
|
|
}
|
|
|
|
void PythonEditorComponent::Undo()
|
|
{
|
|
return PyUndo();
|
|
}
|
|
|
|
void PythonEditorComponent::Redo()
|
|
{
|
|
return PyRedo();
|
|
}
|
|
|
|
void PythonEditorComponent::DrawLabel(int x, int y, float size, float r, float g, float b, float a, const char* pLabel)
|
|
{
|
|
return PyDrawLabel(x, y, size, r, g, b, a, pLabel);
|
|
}
|
|
|
|
AZStd::string PythonEditorComponent::ComboBox(AZStd::string title, AZStd::vector<AZStd::string> values, int selectedIdx)
|
|
{
|
|
return PyComboBox(title, values, selectedIdx);
|
|
}
|
|
}
|
|
|
|
namespace AzToolsFramework
|
|
{
|
|
void PythonEditorFuncsHandler::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
|
{
|
|
// this will put these methods into the 'azlmbr.legacy.general' module
|
|
auto addLegacyGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
|
|
{
|
|
methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
|
->Attribute(AZ::Script::Attributes::Category, "Legacy/General")
|
|
->Attribute(AZ::Script::Attributes::Module, "legacy.general");
|
|
};
|
|
addLegacyGeneral(behaviorContext->Method("get_cvar", PyGetCVarAsString, nullptr, "Gets a CVar value as a string."));
|
|
addLegacyGeneral(behaviorContext->Method("set_cvar", PySetCVarFromAny, nullptr, "Sets a CVar value from any simple value."));
|
|
addLegacyGeneral(behaviorContext->Method("set_cvar_string", PySetCVarFromString, nullptr, "Sets a CVar value from a string."));
|
|
addLegacyGeneral(behaviorContext->Method("set_cvar_integer", PySetCVarFromInt, nullptr, "Sets a CVar value from an integer."));
|
|
addLegacyGeneral(behaviorContext->Method("set_cvar_float", PySetCVarFromFloat, nullptr, "Sets a CVar value from a float."));
|
|
addLegacyGeneral(behaviorContext->Method("run_console", PyRunConsole, nullptr, "Runs a console command."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("enter_game_mode", PyEnterGameMode, nullptr, "Enters the editor game mode."));
|
|
addLegacyGeneral(behaviorContext->Method("is_in_game_mode", PyIsInGameMode, nullptr, "Queries if it's in the game mode or not."));
|
|
addLegacyGeneral(behaviorContext->Method("exit_game_mode", PyExitGameMode, nullptr, "Exits the editor game mode."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("enter_simulation_mode", PyEnterSimulationMode, nullptr, "Enters the editor AI/Physics simulation mode."));
|
|
addLegacyGeneral(behaviorContext->Method("is_in_simulation_mode", PyIsInSimulationMode, nullptr, "Queries if the editor is currently in the AI/Physics simulation mode or not."));
|
|
addLegacyGeneral(behaviorContext->Method("exit_simulation_mode", PyExitSimulationMode, nullptr, "Exits the editor AI/Physics simulation mode."));
|
|
addLegacyGeneral(behaviorContext->Method("run_file", PyRunFile, nullptr, "Runs a script file. A relative path from the editor user folder or an absolute path should be given as an argument."));
|
|
addLegacyGeneral(behaviorContext->Method("run_file_parameters", PyRunFileWithParameters, nullptr, "Runs a script file with parameters. A relative path from the editor user folder or an absolute path should be given as an argument. The arguments should be separated by whitespace."));
|
|
addLegacyGeneral(behaviorContext->Method("execute_command", PyExecuteCommand, nullptr, "Executes a given string as an editor command."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("message_box", PyMessageBox, nullptr, "Shows a confirmation message box with ok|cancel and shows a custom message."));
|
|
addLegacyGeneral(behaviorContext->Method("message_box_yes_no", PyMessageBoxYesNo, nullptr, "Shows a confirmation message box with yes|no and shows a custom message."));
|
|
addLegacyGeneral(behaviorContext->Method("message_box_ok", PyMessageBoxOK, nullptr, "Shows a confirmation message box with only ok and shows a custom message."));
|
|
addLegacyGeneral(behaviorContext->Method("edit_box", PyEditBox, nullptr, "Shows an edit box and returns the value as string."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("edit_box_check_data_type", PyEditBoxAndCheckProperty, nullptr, "Shows an edit box and checks the custom value to use the return value with other functions correctly."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("open_file_box", PyOpenFileBox, nullptr, "Shows an open file box and returns the selected file path and name."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("get_axis_constraint", PyGetAxisConstraint, nullptr, "Gets axis."));
|
|
addLegacyGeneral(behaviorContext->Method("set_axis_constraint", PySetAxisConstraint, nullptr, "Sets axis."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("get_pak_from_file", PyGetPakFromFile, nullptr, "Finds a pak file name for a given file."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("log", PyLog, nullptr, "Prints the message to the editor console window."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("undo", PyUndo, nullptr, "Undoes the last operation."));
|
|
addLegacyGeneral(behaviorContext->Method("redo", PyRedo, nullptr, "Redoes the last undone operation."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("draw_label", PyDrawLabel, nullptr, "Shows a 2d label on the screen at the given position and given color."));
|
|
addLegacyGeneral(behaviorContext->Method("combo_box", PyComboBox, nullptr, "Shows a combo box listing each value passed in, returns string value selected by the user."));
|
|
|
|
addLegacyGeneral(behaviorContext->Method("crash", PyCrash, nullptr, "Crashes the application, useful for testing crash reporting and other automation tools."));
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Temporal, to be removed by LY-101149
|
|
addLegacyGeneral(behaviorContext->Method("find_editor_entity", PyFindEditorEntity, nullptr, "Retrieves a editor entity id by name"));
|
|
addLegacyGeneral(behaviorContext->Method("find_game_entity", PyFindGameEntity, nullptr, "Retrieves a game entity id by name"));
|
|
//////////////////////////////////////////////////////////////////////////
|
|
addLegacyGeneral(behaviorContext->Method("dump_exposed_classes", PyDumpBindings::GetExposedPythonClasses, nullptr, "Retrieves exposed classes"));
|
|
}
|
|
}
|
|
}
|