Tesseract-Engine/src/Engine/LuaAPI.cpp

233 lines
5.9 KiB
C++
Raw Normal View History

2024-12-27 21:27:05 +00:00
// LuaManager.cpp
#include "LuaAPI.h"
#include "LuaMacros.h"
#include "imgui.h"
#include <iostream>
#include "gcml.h"
#include "Windows/LoggerWindow.h"
extern LoggerWindow *g_LoggerWindow;
int lua_log_message(lua_State *L);
LuaManager::LuaManager() : L(nullptr) {}
LuaManager::~LuaManager()
{
if (L)
{
lua_close(L);
}
}
bool LuaManager::init(const std::string &scriptPath)
{
// Create a new Lua state
L = luaL_newstate();
if (L == nullptr)
{
std::cerr << "Failed to create Lua state.\n";
return false;
}
// Open Lua standard libraries
luaL_openlibs(L);
// Create the Engine table
CREATE_LUA_TABLE(L, Engine);
// Bind the Log function to the Engine table
BIND_LUA_FUNCTION(L, Engine, "Log", lua_log_message);
// Load and execute the Lua script
if (luaL_dofile(L, scriptPath.c_str()) != LUA_OK)
{
std::cerr << "Error running " << scriptPath << ": " << lua_tostring(L, -1) << "\n";
lua_close(L);
L = nullptr;
return false;
}
return true;
}
bool LuaManager::callLuaFunction(const std::string &funcName)
{
lua_getglobal(L, funcName.c_str());
if (!lua_isfunction(L, -1))
{
std::cerr << "'" << funcName << "' is not a function.\n";
lua_pop(L, 1); // Remove non-function value
return false;
}
// Call the function with 0 arguments and 0 return values
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
{
std::cerr << "Error calling '" << funcName << "': " << lua_tostring(L, -1) << "\n";
lua_pop(L, 1); // Remove error message
return false;
}
return true;
}
bool LuaManager::onUpdate(float deltaTime)
{
// Push the 'OnUpdate' function onto the stack
lua_getglobal(L, "OnUpdate"); // Ensure correct case
if (!lua_isfunction(L, -1))
{
std::cerr << "'OnUpdate' is not a function.\n";
lua_pop(L, 1); // Remove non-function value
return false;
}
// Push the deltaTime argument
lua_pushnumber(L, deltaTime);
// Call the function with 1 argument and 0 return values
if (lua_pcall(L, 1, 0, 0) != LUA_OK)
{
// Retrieve the error message from Lua
const char* luaError = lua_tostring(L, -1);
if (luaError)
{
std::string errorMsg(luaError);
// Check if this error message has already been logged
if (errorMsg != m_LastErrorMessage)
{
// Log the error to the in-game terminal in red
if (g_LoggerWindow)
{
g_LoggerWindow->AddLog(errorMsg.c_str(), ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
}
else
{
std::cerr << "LoggerWindow is not initialized.\n";
}
// Update the last error message
m_LastErrorMessage = errorMsg;
}
// Optionally, print to std::cerr once if LoggerWindow is unavailable
if (!g_LoggerWindow)
{
std::cerr << "Error calling 'OnUpdate': " << luaError << "\n";
}
}
else
{
std::cerr << "Unknown error calling 'OnUpdate'.\n";
}
lua_pop(L, 1); // Remove error message
return false;
}
else
{
// Reset the last error message if the call was successful
m_LastErrorMessage.clear();
}
return true;
}
bool LuaManager::onDrawGui()
{
return callLuaFunction("onDrawGui");
}
bool LuaManager::callFunction(const std::string &funcName, int args, int returns)
{
lua_getglobal(L, funcName.c_str());
if (!lua_isfunction(L, -1))
{
std::cerr << "'" << funcName << "' is not a function.\n";
lua_pop(L, 1); // Remove non-function value
return false;
}
// For simplicity, this example doesn't handle arguments and return values.
// You can extend this method to push arguments and retrieve returns as needed.
if (lua_pcall(L, args, returns, 0) != LUA_OK)
{
std::cerr << "Error calling '" << funcName << "': " << lua_tostring(L, -1) << "\n";
lua_pop(L, 1); // Remove error message
return false;
}
return true;
}
// Binding function to log messages from Lua
int lua_log_message(lua_State *L)
{
// Check and retrieve the message string
if (!lua_isstring(L, 1))
{
lua_pushstring(L, "Incorrect argument to 'log_message'. Expected string as first argument.");
lua_error(L);
return 0; // Never reached, lua_error long jumps
}
const char *message = lua_tostring(L, 1);
// Initialize default color
ImVec4 color(1.0f, 1.0f, 1.0f, 1.0f); // Default white color
// Check if a second argument (color) is provided
if (lua_gettop(L) >= 2)
{
if (lua_istable(L, 2))
{
// Retrieve color components from the table
lua_pushnumber(L, 1); // Push key 1 (r)
lua_gettable(L, 2);
float r = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 1.0f;
lua_pop(L, 1);
lua_pushnumber(L, 2); // Push key 2 (g)
lua_gettable(L, 2);
float g = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 1.0f;
lua_pop(L, 1);
lua_pushnumber(L, 3); // Push key 3 (b)
lua_gettable(L, 2);
float b = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 1.0f;
lua_pop(L, 1);
lua_pushnumber(L, 4); // Push key 4 (a)
lua_gettable(L, 2);
float a = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 1.0f;
lua_pop(L, 1);
color = ImVec4(r, g, b, a);
}
else
{
lua_pushstring(L, "Incorrect argument to 'log_message'. Expected table for color.");
lua_error(L);
return 0;
}
}
// Ensure LoggerWindow is valid
g_LoggerWindow->AddLog(message, color);
return 0; // Number of return values
}