370 lines
8.7 KiB
C++
370 lines
8.7 KiB
C++
// celx_misc.cpp
|
|
//
|
|
// Copyright (C) 2019, the Celestia Development Team
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
#include <celutil/debug.h>
|
|
#include "celx_misc.h"
|
|
#include "celx_internal.h"
|
|
#include <celscript/legacy/cmdparser.h>
|
|
#include <celscript/legacy/execution.h>
|
|
#include <celestia/celestiacore.h>
|
|
#if NO_TTF
|
|
#include <celtxf/texturefont.h>
|
|
#else
|
|
#include <celttf/truetypefont.h>
|
|
#endif
|
|
|
|
using namespace celestia::scripts;
|
|
|
|
LuaState *getLuaStateObject(lua_State*);
|
|
|
|
// Wrapper for a CEL-script, including the needed Execution Environment
|
|
class CelScriptWrapper : public ExecutionEnvironment
|
|
{
|
|
public:
|
|
CelScriptWrapper(CelestiaCore& appCore, istream& scriptfile):
|
|
core(appCore)
|
|
{
|
|
CommandParser parser(scriptfile, appCore.scriptMaps());
|
|
cmdSequence = parser.parse();
|
|
if (cmdSequence != nullptr)
|
|
{
|
|
script = new Execution(*cmdSequence, *this);
|
|
}
|
|
else
|
|
{
|
|
const vector<string>* errors = parser.getErrors();
|
|
if (errors->size() > 0)
|
|
errorMessage = "Error while parsing CEL-script: " + (*errors)[0];
|
|
else
|
|
errorMessage = "Error while parsing CEL-script.";
|
|
}
|
|
}
|
|
|
|
virtual ~CelScriptWrapper()
|
|
{
|
|
delete script;
|
|
delete cmdSequence;
|
|
}
|
|
|
|
string getErrorMessage() const
|
|
{
|
|
return errorMessage;
|
|
}
|
|
|
|
// tick the CEL-script. t is in seconds and doesn't have to start with zero
|
|
bool tick(double t)
|
|
{
|
|
// use first tick to set the time
|
|
if (tickTime == 0.0)
|
|
{
|
|
tickTime = t;
|
|
return false;
|
|
}
|
|
double dt = t - tickTime;
|
|
tickTime = t;
|
|
return script->tick(dt);
|
|
}
|
|
|
|
Simulation* getSimulation() const
|
|
{
|
|
return core.getSimulation();
|
|
}
|
|
|
|
Renderer* getRenderer() const
|
|
{
|
|
return core.getRenderer();
|
|
}
|
|
|
|
CelestiaCore* getCelestiaCore() const
|
|
{
|
|
return &core;
|
|
}
|
|
|
|
void showText(string s, int horig, int vorig, int hoff, int voff,
|
|
double duration)
|
|
{
|
|
core.showText(std::move(s), horig, vorig, hoff, voff, duration);
|
|
}
|
|
|
|
private:
|
|
Execution* script{ nullptr };
|
|
CelestiaCore& core;
|
|
CommandSequence* cmdSequence{ nullptr };
|
|
double tickTime { 0.0 };
|
|
string errorMessage;
|
|
};
|
|
|
|
// ==================== Celscript-object ====================
|
|
|
|
|
|
int celxClassId(CelScriptWrapper*)
|
|
{
|
|
return Celx_CelScript;
|
|
}
|
|
|
|
// create a CelScriptWrapper from a string:
|
|
int celscript_from_string(lua_State* l, string& script_text)
|
|
{
|
|
CelxLua celx(l);
|
|
istringstream scriptfile(script_text);
|
|
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
CelScriptWrapper* celscript = new CelScriptWrapper(*appCore, scriptfile);
|
|
if (celscript->getErrorMessage() != "")
|
|
{
|
|
string error = celscript->getErrorMessage();
|
|
delete celscript;
|
|
celx.doError(error.c_str());
|
|
}
|
|
else
|
|
{
|
|
celx.pushClass(celscript);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int celscript_tostring(lua_State* l)
|
|
{
|
|
lua_pushstring(l, "[Celscript]");
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int celscript_tick(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
auto script = *celx.getThis<CelScriptWrapper*>();
|
|
LuaState* stateObject = celx.getLuaStateObject();
|
|
double t = stateObject->getTime();
|
|
return celx.push(!(script->tick(t)));
|
|
}
|
|
|
|
static int celscript_gc(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
auto script = *celx.getThis<CelScriptWrapper*>();
|
|
delete script;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CreateCelscriptMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.createClassMetatable(Celx_CelScript);
|
|
|
|
celx.registerMethod("__tostring", celscript_tostring);
|
|
celx.registerMethod("tick", celscript_tick);
|
|
celx.registerMethod("__gc", celscript_gc);
|
|
|
|
celx.pop(1); // remove metatable from stack
|
|
}
|
|
|
|
// ==================== Font Object ====================
|
|
|
|
static int font_bind(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for font:bind()");
|
|
|
|
auto font = *celx.getThis<TextureFont*>();
|
|
font->bind();
|
|
return 0;
|
|
}
|
|
|
|
static int font_unbind(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for font:unbind()");
|
|
|
|
auto font = *celx.getThis<TextureFont*>();
|
|
font->unbind();
|
|
return 0;
|
|
}
|
|
|
|
static int font_render(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(2, 2, "One argument required for font:render");
|
|
|
|
const char* s = celx.safeGetString(2, AllErrors, "First argument to font:render must be a string");
|
|
auto font = *celx.getThis<TextureFont*>();
|
|
#ifndef GL_ES
|
|
Eigen::Matrix4f p, m;
|
|
glGetFloatv(GL_PROJECTION_MATRIX, p.data());
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, m.data());
|
|
font->setMVPMatrix(p * m);
|
|
#endif
|
|
return celx.push(font->render(s));
|
|
}
|
|
|
|
static int font_getwidth(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(2, 2, "One argument expected for font:getwidth");
|
|
const char* s = celx.safeGetString(2, AllErrors, "Argument to font:getwidth must be a string");
|
|
auto font = *celx.getThis<TextureFont*>();
|
|
return celx.push(font->getWidth(s));
|
|
}
|
|
|
|
static int font_getheight(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for font:getheight()");
|
|
|
|
auto font = *celx.getThis<TextureFont*>();
|
|
lua_pushnumber(l, font->getHeight());
|
|
return 1;
|
|
}
|
|
|
|
static int font_tostring(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
return celx.push("[Font]");
|
|
}
|
|
|
|
void CreateFontMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.createClassMetatable(Celx_Font);
|
|
|
|
celx.registerMethod("__tostring", font_tostring);
|
|
celx.registerMethod("bind", font_bind);
|
|
celx.registerMethod("render", font_render);
|
|
celx.registerMethod("unbind", font_unbind);
|
|
celx.registerMethod("getwidth", font_getwidth);
|
|
celx.registerMethod("getheight", font_getheight);
|
|
|
|
celx.pop(1); // remove metatable from stack
|
|
}
|
|
|
|
// ==================== Image =============================================
|
|
#if 0
|
|
static int image_new(lua_State* l, Image* i)
|
|
{
|
|
Image** ud = static_cast<Image**>(lua_newuserdata(l, sizeof(Image*)));
|
|
*ud = i;
|
|
|
|
Celx_SetClass(l, Celx_Image);
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
int celxClassId(Image*)
|
|
{
|
|
return Celx_Image;
|
|
}
|
|
|
|
static int image_getheight(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for image:getheight()");
|
|
|
|
auto image = *celx.getThis<Image*>();
|
|
return celx.push(image->getHeight());
|
|
}
|
|
|
|
static int image_getwidth(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for image:getwidth()");
|
|
|
|
auto* image = *celx.getThis<Image*>();
|
|
return celx.push(image->getWidth());
|
|
}
|
|
|
|
static int image_tostring(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
auto image = *celx.getThis<Image*>();
|
|
std::string s = fmt::sprintf("[Image:%dx%d]", image->getWidth(), image->getHeight());
|
|
return celx.push(s.c_str());
|
|
}
|
|
|
|
void CreateImageMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.createClassMetatable(Celx_Image);
|
|
|
|
celx.registerMethod("__tostring", image_tostring);
|
|
celx.registerMethod("getheight", image_getheight);
|
|
celx.registerMethod("getwidth", image_getwidth);
|
|
|
|
celx.pop(1); // remove metatable from stack
|
|
}
|
|
|
|
// ==================== Texture ============================================
|
|
|
|
static int texture_bind(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for texture:bind()");
|
|
|
|
auto texture = *celx.getThis<Texture*>();
|
|
texture->bind();
|
|
return 0;
|
|
}
|
|
|
|
static int texture_getheight(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for texture:getheight()");
|
|
|
|
auto texture = *celx.getThis<Texture*>();
|
|
return celx.push(texture->getHeight());
|
|
}
|
|
|
|
static int texture_getwidth(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(1, 1, "No arguments expected for texture:getwidth()");
|
|
|
|
auto texture = *celx.getThis<Texture*>();
|
|
return celx.push(texture->getWidth());
|
|
}
|
|
|
|
static int texture_tostring(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
auto tex = *celx.getThis<Texture*>();
|
|
std::string s = fmt::sprintf("[Texture:%dx%d]", tex->getWidth(), tex->getHeight());
|
|
return celx.push(s.c_str());
|
|
}
|
|
|
|
void CreateTextureMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.createClassMetatable(Celx_Texture);
|
|
|
|
celx.registerMethod("__tostring", texture_tostring);
|
|
celx.registerMethod("getheight", texture_getheight);
|
|
celx.registerMethod("getwidth", texture_getwidth);
|
|
celx.registerMethod("bind", texture_bind);
|
|
|
|
celx.pop(1); // remove metatable from stack
|
|
}
|
|
|
|
|