lua environmnents-related update
This commit is contained in:
parent
9ad371862c
commit
fce77bc896
@ -1,3 +1,4 @@
|
|||||||
<inventory color="#00000080">
|
<inventory color="#00000080" size="400,100">
|
||||||
<slots-grid cols="4" count="40"/>
|
<slots-grid cols="4" count="40"/>
|
||||||
|
<button coord="300,10">Test</button>
|
||||||
</inventory>
|
</inventory>
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
-- use for engine development tests
|
||||||
|
-- must be empty in release
|
||||||
|
-- must not be modified by content-packs
|
||||||
@ -66,6 +66,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
|
|||||||
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
|
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
|
||||||
|
|
||||||
for (fs::path& file : loader.getPaths()->listdir(LAYOUTS_FOLDER)) {
|
for (fs::path& file : loader.getPaths()->listdir(LAYOUTS_FOLDER)) {
|
||||||
|
if (file.extension().u8string() != ".xml")
|
||||||
|
continue;
|
||||||
std::string packName = file.parent_path().parent_path().filename();
|
std::string packName = file.parent_path().parent_path().filename();
|
||||||
if (packName == "res") {
|
if (packName == "res") {
|
||||||
packName = "core";
|
packName = "core";
|
||||||
|
|||||||
@ -10,8 +10,9 @@
|
|||||||
UiDocument::UiDocument(
|
UiDocument::UiDocument(
|
||||||
std::string namesp,
|
std::string namesp,
|
||||||
uidocscript script,
|
uidocscript script,
|
||||||
std::shared_ptr<gui::UINode> root
|
std::shared_ptr<gui::UINode> root,
|
||||||
) : namesp(namesp), script(script), root(root) {
|
int env
|
||||||
|
) : namesp(namesp), script(script), root(root), env(env) {
|
||||||
collect(map, root);
|
collect(map, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ std::unique_ptr<UiDocument> UiDocument::read(std::string namesp, fs::path file)
|
|||||||
uidocscript script {};
|
uidocscript script {};
|
||||||
auto scriptFile = fs::path(file.u8string()+".lua");
|
auto scriptFile = fs::path(file.u8string()+".lua");
|
||||||
if (fs::is_regular_file(scriptFile)) {
|
if (fs::is_regular_file(scriptFile)) {
|
||||||
scripting::load_layout_script(scriptFile, script);
|
scripting::load_layout_script(env->getId(), scriptFile, script);
|
||||||
}
|
}
|
||||||
return std::make_unique<UiDocument>(namesp, script, view);
|
return std::make_unique<UiDocument>(namesp, script, view, env.release()->getId());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,8 +25,13 @@ class UiDocument {
|
|||||||
uidocscript script;
|
uidocscript script;
|
||||||
uinodes_map map;
|
uinodes_map map;
|
||||||
std::shared_ptr<gui::UINode> root;
|
std::shared_ptr<gui::UINode> root;
|
||||||
|
int env;
|
||||||
public:
|
public:
|
||||||
UiDocument(std::string namesp, uidocscript script, std::shared_ptr<gui::UINode> root);
|
UiDocument(
|
||||||
|
std::string namesp,
|
||||||
|
uidocscript script,
|
||||||
|
std::shared_ptr<gui::UINode> root,
|
||||||
|
int env);
|
||||||
|
|
||||||
const uinodes_map& getMap() const;
|
const uinodes_map& getMap() const;
|
||||||
const std::string& getNamespace() const;
|
const std::string& getNamespace() const;
|
||||||
|
|||||||
@ -117,7 +117,11 @@ static std::shared_ptr<UINode> readButton(UiXmlReader& reader, xml::xmlelement e
|
|||||||
_readPanel(reader, element, *button);
|
_readPanel(reader, element, *button);
|
||||||
|
|
||||||
if (element->has("onclick")) {
|
if (element->has("onclick")) {
|
||||||
auto callback = scripting::create_runnable("<onclick>", element->attr("onclick").getText(), reader.getEnvironment());
|
auto callback = scripting::create_runnable(
|
||||||
|
reader.getEnvironment().getId(),
|
||||||
|
"<onclick>",
|
||||||
|
element->attr("onclick").getText()
|
||||||
|
);
|
||||||
button->listenAction([callback](GUI*) {
|
button->listenAction([callback](GUI*) {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
@ -137,6 +141,7 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
|
|
||||||
if (element->has("consumer")) {
|
if (element->has("consumer")) {
|
||||||
auto consumer = scripting::create_wstring_consumer(
|
auto consumer = scripting::create_wstring_consumer(
|
||||||
|
reader.getEnvironment().getId(),
|
||||||
element->attr("consumer").getText(),
|
element->attr("consumer").getText(),
|
||||||
reader.getFilename()
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,8 +25,12 @@ lua::LuaState::LuaState() {
|
|||||||
|
|
||||||
createFuncs();
|
createFuncs();
|
||||||
|
|
||||||
lua_getglobal(L, "_G");
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||||
lua_setglobal(L, ":G");
|
setglobal(envName(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string lua::LuaState::envName(int env) const {
|
||||||
|
return "_ENV"+util::mangleid(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua::LuaState::~LuaState() {
|
lua::LuaState::~LuaState() {
|
||||||
@ -109,10 +113,13 @@ void lua::LuaState::createFuncs() {
|
|||||||
addfunc("set_block_user_bits", l_set_block_user_bits);
|
addfunc("set_block_user_bits", l_set_block_user_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lua::LuaState::loadbuffer(const std::string& src, const std::string& file) {
|
void lua::LuaState::loadbuffer(int env, const std::string& src, const std::string& file) {
|
||||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
|
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
|
||||||
throw lua::luaerror(lua_tostring(L, -1));
|
throw lua::luaerror(lua_tostring(L, -1));
|
||||||
}
|
}
|
||||||
|
if (env && getglobal(envName(env))) {
|
||||||
|
lua_setfenv(L, -2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int lua::LuaState::call(int argc) {
|
int lua::LuaState::call(int argc) {
|
||||||
@ -130,14 +137,14 @@ int lua::LuaState::callNoThrow(int argc) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lua::LuaState::eval(const std::string& src, const std::string& file) {
|
int lua::LuaState::eval(int env, const std::string& src, const std::string& file) {
|
||||||
auto srcText = "return ("+src+")";
|
auto srcText = "return ("+src+")";
|
||||||
loadbuffer(srcText, file);
|
loadbuffer(env, srcText, file);
|
||||||
return call(0);
|
return call(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lua::LuaState::execute(const std::string& src, const std::string& file) {
|
int lua::LuaState::execute(int env, const std::string& src, const std::string& file) {
|
||||||
loadbuffer(src, file);
|
loadbuffer(env, src, file);
|
||||||
return callNoThrow(0);
|
return callNoThrow(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,49 +193,24 @@ const std::string lua::LuaState::storeAnonymous() {
|
|||||||
return funcName;
|
return funcName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lua::LuaState::initEnvironment() {
|
|
||||||
lua_getglobal(L, "_G");
|
|
||||||
lua_setfield(L, -1, ":G");
|
|
||||||
}
|
|
||||||
|
|
||||||
int lua::LuaState::createEnvironment() {
|
int lua::LuaState::createEnvironment() {
|
||||||
int id = nextEnvironment++;
|
int id = nextEnvironment++;
|
||||||
|
// globals table
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
|
||||||
if (currentEnvironment != 0) {
|
// metatable
|
||||||
setEnvironment(0);
|
lua_createtable(L, 0, 1);
|
||||||
}
|
|
||||||
|
|
||||||
lua_createtable(L, 0, 0);
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||||
initEnvironment();
|
lua_setfield(L, -2, "__index");
|
||||||
setglobal("_N"+util::mangleid(id));
|
lua_setmetatable(L, -2);
|
||||||
|
|
||||||
setEnvironment(id);
|
setglobal(envName(id));
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void lua::LuaState::removeEnvironment(int id) {
|
void lua::LuaState::removeEnvironment(int id) {
|
||||||
if (currentEnvironment == id) {
|
|
||||||
setEnvironment(0);
|
|
||||||
}
|
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
setglobal("_N"+util::mangleid(id));
|
setglobal(envName(id));
|
||||||
}
|
|
||||||
|
|
||||||
int lua::LuaState::getEnvironment() const {
|
|
||||||
return currentEnvironment;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lua::LuaState::setEnvironment(int id) {
|
|
||||||
if (id == 0) {
|
|
||||||
getglobal(":G");
|
|
||||||
lua_setfenv(L, -1);
|
|
||||||
} else {
|
|
||||||
getglobal(":G");
|
|
||||||
lua_getfield(L, -1, ("_N"+util::mangleid(id)).c_str());
|
|
||||||
if (lua_isnil(L, -1)) {
|
|
||||||
lua_pop(L, -1);
|
|
||||||
throw luaerror("environment "+std::to_string(id)+" was not found");
|
|
||||||
}
|
|
||||||
lua_setfenv(L, -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,6 @@ namespace lua {
|
|||||||
class LuaState {
|
class LuaState {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
int nextEnvironment = 1;
|
int nextEnvironment = 1;
|
||||||
int currentEnvironment = 0;
|
|
||||||
|
|
||||||
void logError(const std::string& text);
|
void logError(const std::string& text);
|
||||||
void initEnvironment();
|
void initEnvironment();
|
||||||
@ -25,7 +24,8 @@ namespace lua {
|
|||||||
LuaState();
|
LuaState();
|
||||||
~LuaState();
|
~LuaState();
|
||||||
|
|
||||||
void loadbuffer(const std::string& src, const std::string& file);
|
const std::string envName(int env) const;
|
||||||
|
void loadbuffer(int env, const std::string& src, const std::string& file);
|
||||||
int gettop() const;
|
int gettop() const;
|
||||||
int pushivec3(luaint x, luaint y, luaint z);
|
int pushivec3(luaint x, luaint y, luaint z);
|
||||||
int pushinteger(luaint x);
|
int pushinteger(luaint x);
|
||||||
@ -35,8 +35,8 @@ namespace lua {
|
|||||||
luaint tointeger(int index);
|
luaint tointeger(int index);
|
||||||
int call(int argc);
|
int call(int argc);
|
||||||
int callNoThrow(int argc);
|
int callNoThrow(int argc);
|
||||||
int execute(const std::string& src, const std::string& file="<string>");
|
int execute(int env, const std::string& src, const std::string& file="<string>");
|
||||||
int eval(const std::string& src, const std::string& file="<eval>");
|
int eval(int env, const std::string& src, const std::string& file="<eval>");
|
||||||
void openlib(const std::string& name, const luaL_Reg* libfuncs, int nup);
|
void openlib(const std::string& name, const luaL_Reg* libfuncs, int nup);
|
||||||
void addfunc(const std::string& name, lua_CFunction func);
|
void addfunc(const std::string& name, lua_CFunction func);
|
||||||
bool getglobal(const std::string& name);
|
bool getglobal(const std::string& name);
|
||||||
@ -47,9 +47,6 @@ namespace lua {
|
|||||||
void createFuncs();
|
void createFuncs();
|
||||||
int createEnvironment();
|
int createEnvironment();
|
||||||
void removeEnvironment(int id);
|
void removeEnvironment(int id);
|
||||||
int getEnvironment() const;
|
|
||||||
void setEnvironment(int id);
|
|
||||||
|
|
||||||
const std::string storeAnonymous();
|
const std::string storeAnonymous();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ void load_script(fs::path name) {
|
|||||||
fs::path file = paths->getResources()/fs::path("scripts")/name;
|
fs::path file = paths->getResources()/fs::path("scripts")/name;
|
||||||
|
|
||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
state->execute(src, file.u8string());
|
state->execute(0, src, file.u8string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::initialize(Engine* engine) {
|
void scripting::initialize(Engine* engine) {
|
||||||
@ -58,35 +58,23 @@ void scripting::initialize(Engine* engine) {
|
|||||||
load_script(fs::path("stdlib.lua"));
|
load_script(fs::path("stdlib.lua"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: luaL state check
|
|
||||||
runnable scripting::create_runnable(
|
runnable scripting::create_runnable(
|
||||||
|
int env,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& src
|
const std::string& src
|
||||||
) {
|
) {
|
||||||
return [=](){
|
return [=](){
|
||||||
state->execute(src, file);
|
state->execute(env, src, file);
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
runnable scripting::create_runnable(
|
|
||||||
const std::string& file,
|
|
||||||
const std::string& src,
|
|
||||||
const Environment& env
|
|
||||||
) {
|
|
||||||
return [=](){
|
|
||||||
int previous = state->getEnvironment();
|
|
||||||
state->setEnvironment(env.getId());
|
|
||||||
state->execute(src, file);
|
|
||||||
state->setEnvironment(previous);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
wstringconsumer scripting::create_wstring_consumer(
|
wstringconsumer scripting::create_wstring_consumer(
|
||||||
|
int env,
|
||||||
const std::string& src,
|
const std::string& src,
|
||||||
const std::string& file
|
const std::string& file
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (state->eval(src, file) == 0)
|
if (state->eval(env, src, file) == 0)
|
||||||
return [](const std::wstring& _) {};
|
return [](const std::wstring& _) {};
|
||||||
} catch (const lua::luaerror& err) {
|
} catch (const lua::luaerror& err) {
|
||||||
std::cerr << err.what() << std::endl;
|
std::cerr << err.what() << std::endl;
|
||||||
@ -220,7 +208,7 @@ bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x,
|
|||||||
void scripting::load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset) {
|
void scripting::load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset) {
|
||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
std::cout << "loading script " << file.u8string() << std::endl;
|
std::cout << "loading script " << file.u8string() << std::endl;
|
||||||
state->execute(src, file.u8string());
|
state->execute(0, src, file.u8string());
|
||||||
|
|
||||||
funcsset.init=state->rename("init", prefix+".init");
|
funcsset.init=state->rename("init", prefix+".init");
|
||||||
funcsset.update=state->rename("on_update", prefix+".update");
|
funcsset.update=state->rename("on_update", prefix+".update");
|
||||||
@ -234,7 +222,7 @@ void scripting::load_block_script(std::string prefix, fs::path file, block_funcs
|
|||||||
void scripting::load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset) {
|
void scripting::load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset) {
|
||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
std::cout << "loading script " << file.u8string() << std::endl;
|
std::cout << "loading script " << file.u8string() << std::endl;
|
||||||
state->execute(src, file.u8string());
|
state->execute(0, src, file.u8string());
|
||||||
funcsset.init=state->rename("init", prefix+".init");
|
funcsset.init=state->rename("init", prefix+".init");
|
||||||
funcsset.on_use_on_block=state->rename("on_use_on_block", prefix+".useon");
|
funcsset.on_use_on_block=state->rename("on_use_on_block", prefix+".useon");
|
||||||
funcsset.on_block_break_by=state->rename("on_block_break_by", prefix+".blockbreakby");
|
funcsset.on_block_break_by=state->rename("on_block_break_by", prefix+".blockbreakby");
|
||||||
@ -244,7 +232,7 @@ void scripting::load_world_script(std::string prefix, fs::path file) {
|
|||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
std::cout << "loading script " << file.u8string() << std::endl;
|
std::cout << "loading script " << file.u8string() << std::endl;
|
||||||
|
|
||||||
state->loadbuffer(src, file.u8string());
|
state->loadbuffer(0, src, file.u8string());
|
||||||
state->callNoThrow(0);
|
state->callNoThrow(0);
|
||||||
|
|
||||||
state->rename("init", prefix+".init");
|
state->rename("init", prefix+".init");
|
||||||
@ -253,12 +241,12 @@ void scripting::load_world_script(std::string prefix, fs::path file) {
|
|||||||
state->rename("on_world_quit", prefix+".worldquit");
|
state->rename("on_world_quit", prefix+".worldquit");
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::load_layout_script(fs::path file, uidocscript& script) {
|
void scripting::load_layout_script(int env, fs::path file, uidocscript& script) {
|
||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
std::cout << "loading script " << file.u8string() << std::endl;
|
std::cout << "loading script " << file.u8string() << std::endl;
|
||||||
|
|
||||||
script.environment = state->createEnvironment();
|
script.environment = env;
|
||||||
state->loadbuffer(src, file.u8string());
|
state->loadbuffer(env, src, file.u8string());
|
||||||
state->callNoThrow(0);
|
state->callNoThrow(0);
|
||||||
script.onopen = state->hasglobal("on_open");
|
script.onopen = state->hasglobal("on_open");
|
||||||
script.onclose = state->hasglobal("on_close");
|
script.onclose = state->hasglobal("on_close");
|
||||||
|
|||||||
@ -38,17 +38,13 @@ namespace scripting {
|
|||||||
void initialize(Engine* engine);
|
void initialize(Engine* engine);
|
||||||
|
|
||||||
runnable create_runnable(
|
runnable create_runnable(
|
||||||
|
int env,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& source
|
const std::string& source
|
||||||
);
|
);
|
||||||
|
|
||||||
runnable create_runnable(
|
|
||||||
const std::string& filename,
|
|
||||||
const std::string& source,
|
|
||||||
const Environment& env
|
|
||||||
);
|
|
||||||
|
|
||||||
wstringconsumer create_wstring_consumer(
|
wstringconsumer create_wstring_consumer(
|
||||||
|
int env,
|
||||||
const std::string& src,
|
const std::string& src,
|
||||||
const std::string& file="<string>"
|
const std::string& file="<string>"
|
||||||
);
|
);
|
||||||
@ -69,6 +65,6 @@ namespace scripting {
|
|||||||
void load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset);
|
void load_block_script(std::string prefix, fs::path file, block_funcs_set& funcsset);
|
||||||
void load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset);
|
void load_item_script(std::string prefix, fs::path file, item_funcs_set& funcsset);
|
||||||
void load_world_script(std::string prefix, fs::path file);
|
void load_world_script(std::string prefix, fs::path file);
|
||||||
void load_layout_script(fs::path file, uidocscript& script);
|
void load_layout_script(int env, fs::path file, uidocscript& script);
|
||||||
void close();
|
void close();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user