134 lines
3.3 KiB
C++
134 lines
3.3 KiB
C++
/*
|
|
Copyright (c) 2014-2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "../model/ScriptValue.hpp"
|
|
|
|
extern "C" {
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
}
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
|
|
namespace RPGEdit {
|
|
|
|
namespace Control {
|
|
|
|
class ScriptContext {
|
|
private:
|
|
lua_State *L;
|
|
|
|
std::unordered_set<std::string> loadedScripts;
|
|
|
|
void setupEnv();
|
|
void cleanupEnv();
|
|
|
|
void load(const std::string &script);
|
|
|
|
size_t pushArgs() {
|
|
return 0;
|
|
}
|
|
|
|
template<typename... Args>
|
|
size_t pushArgs(std::nullptr_t __attribute__((unused)) v, Args ...args) {
|
|
lua_pushnil(L);
|
|
return pushArgs(args...) + 1;
|
|
}
|
|
|
|
template<typename... Args>
|
|
size_t pushArgs(const std::string &v, Args ...args) {
|
|
lua_pushstring(L, v.c_str());
|
|
return pushArgs(args...) + 1;
|
|
}
|
|
|
|
template<typename T, typename... Args>
|
|
size_t pushArgs(T v, Args ...args) {
|
|
lua_pushnumber(L, v);
|
|
return pushArgs(args...) + 1;
|
|
}
|
|
|
|
template<typename... Args>
|
|
size_t pushArgs(bool v, Args ...args) {
|
|
lua_pushboolean(L, v);
|
|
return pushArgs(args...) + 1;
|
|
}
|
|
|
|
template<typename... Args>
|
|
size_t pushArgs(Model::ScriptValue &v, Args ...args) {
|
|
v.push(L);
|
|
return pushArgs(args...) + 1;
|
|
}
|
|
|
|
public:
|
|
ScriptContext(const ScriptContext &other) = delete;
|
|
ScriptContext(ScriptContext &&other) = delete;
|
|
ScriptContext & operator=(const ScriptContext &other) = delete;
|
|
ScriptContext & operator=(ScriptContext &&other) = delete;
|
|
|
|
ScriptContext() {
|
|
L = luaL_newstate();
|
|
|
|
lua_newtable(L);
|
|
lua_rawsetp(L, LUA_REGISTRYINDEX, this);
|
|
}
|
|
|
|
~ScriptContext() {
|
|
lua_close(L);
|
|
}
|
|
|
|
void setGlobal(const std::string &key, Model::ScriptValue *value) {
|
|
value->push(L);
|
|
lua_setglobal(L, key.c_str());
|
|
}
|
|
|
|
template<typename... Args>
|
|
void run(const std::string &script, const std::string &name, Args ...args) {
|
|
load(script);
|
|
|
|
setupEnv();
|
|
|
|
lua_rawgetp(L, LUA_REGISTRYINDEX, this);
|
|
lua_getfield(L, -1, script.c_str());
|
|
lua_remove(L, -2);
|
|
|
|
lua_call(L, 0, 0);
|
|
|
|
lua_getglobal(L, name.c_str());
|
|
lua_call(L, pushArgs(args...), 0);
|
|
|
|
cleanupEnv();
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
}
|