diff --git a/apps/twnlua/bindgen.py b/apps/twnlua/bindgen.py index 42d4096..9bc51ae 100755 --- a/apps/twnlua/bindgen.py +++ b/apps/twnlua/bindgen.py @@ -36,6 +36,8 @@ def to_table(typedesc, variable, indent = 0): for field in typedesc["fields"]: if field["type"] == "float": binding += ' ' * indent + "lua_pushnumber(L, (double)(%s));\n" % (variable + ".%s" % field["name"]) + elif field["type"] == "bool": + binding += ' ' * indent + "lua_pushboolean(L, (%s));\n" % (variable + ".%s" % field["name"]) elif field["type"] in api["types"]: binding += to_table(api["types"][field["type"]], variable + ".%s" % field["name"], indent + 4) else: @@ -52,9 +54,68 @@ print('#include ') print('#include ') print('#include \n') +bindings, used_converters = [], {} +for procedure, procedure_desc in api["procedures"].items(): + binding = "static int binding_%s(lua_State *L) {\n" % procedure + binding += " luaL_checktype(L, 1, LUA_TTABLE);\n" + + if "params" in procedure_desc: + for parameter in procedure_desc["params"]: + basetype = parameter["type"].rsplit(' *', 1)[0] + + if parameter["type"].endswith("*"): + binding += " %s %s_value;\n" % (basetype, parameter["name"]) + binding += " %s %s;\n" % (parameter["type"], parameter["name"]) + binding += " lua_getfield(L, 1, \"%s\");\n" % parameter["name"] + + if "default" in parameter: + binding += " if (lua_isnoneornil(L, -1))\n" + binding += " %s = %s;\n" % (parameter["name"], default(parameter)) + binding += " else\n " + + if parameter["type"] == "float": + binding += " %s = (float)lua_tonumber(L, -1);\n" % (parameter["name"]); + elif parameter["type"] == "bool": + binding += " %s = lua_toboolean(L, -1);\n" % (parameter["name"]); + elif parameter["type"] == "char *": + binding += " %s = lua_tostring(L, -1);\n" % (parameter["name"]); + elif basetype in api["types"]: + used_converters[basetype] = api["types"][basetype] + if parameter["type"].endswith(" *"): + binding += " { %s_value = to_%s(L, -1); %s = &%s_value; }\n" % (parameter["name"], basetype.lower(), parameter["name"], parameter["name"]); + else: + binding += " %s = to_%s(L, -1);\n" % (parameter["name"], basetype.lower()); + else: + raise BaseException("Unhandled parameter type '%s'" % (parameter["type"])) + + if "return" in procedure_desc: + if procedure_desc["return"] == "bool": + binding += " lua_pushboolean(L, (int)%s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) + elif procedure_desc["return"] == "float": + binding += " lua_pushnumber(L, (double)%s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) + elif procedure_desc["return"] == "char *": + binding += " lua_pushstring(L, %s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) + elif type(procedure_desc["return"]) is dict or procedure_desc["return"] in api["types"]: + # TODO: handle enums + type_desc = procedure_desc["return"] if type(procedure_desc["return"]) is dict else api["types"][procedure_desc["return"]] + binding += " %s result = %s(%s);\n" % (type_desc["c_type"], procedure, ", ".join(param["name"] for param in procedure_desc["params"])) + binding += to_table(type_desc, "result", 4) + else: + raise BaseException("Unhandled return type '%s'" % (procedure_desc["return"])) + binding += " return 1;\n}\n" + else: + binding += " %s(%s);\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) + binding += " return 0;\n}\n" + + bindings += [binding] + + storages, converters, initializers, deinitializers = [], [], [], [] -for typename, typedesc in api["types"].items(): +for typename, typedesc in used_converters.items(): + if "no_convert" in typedesc and typedesc["no_convert"]: + continue + converter = "static %s to_%s(lua_State *L, int idx) {\n" % (typename, typename.lower()) converter += " %s %s;\n" % (typename, typename.lower()); @@ -87,63 +148,11 @@ for typename, typedesc in api["types"].items(): converter += " return %s;\n}\n" % (typename.lower()) converters += [converter] + print('\n'.join(storages)) print("void bindgen_init(void) {\n" + '\n'.join(initializers) + "\n}\n") print('\n'.join(converters)) - -bindings = [] -for procedure, procedure_desc in api["procedures"].items(): - binding = "static int binding_%s(lua_State *L) {\n" % procedure - binding += " luaL_checktype(L, 1, LUA_TTABLE);\n" - - if "params" in procedure_desc: - for parameter in procedure_desc["params"]: - basetype = parameter["type"].rsplit(' *', 1)[0] - - if parameter["type"].endswith("*"): - binding += " %s %s_value;\n" % (basetype, parameter["name"]) - binding += " %s %s;\n" % (parameter["type"], parameter["name"]) - binding += " lua_getfield(L, 1, \"%s\");\n" % parameter["name"] - - if "default" in parameter: - binding += " if (lua_isnoneornil(L, -1))\n" - binding += " %s = %s;\n" % (parameter["name"], default(parameter)) - binding += " else\n " - - if parameter["type"] == "float": - binding += " %s = (float)lua_tonumber(L, -1);\n" % (parameter["name"]); - elif parameter["type"] == "bool": - binding += " %s = lua_toboolean(L, -1);\n" % (parameter["name"]); - elif parameter["type"] == "char *": - binding += " %s = lua_tostring(L, -1);\n" % (parameter["name"]); - elif basetype in api["types"]: - if parameter["type"].endswith(" *"): - binding += " { %s_value = to_%s(L, -1); %s = &%s_value; }\n" % (parameter["name"], basetype.lower(), parameter["name"], parameter["name"]); - else: - binding += " %s = to_%s(L, -1);\n" % (parameter["name"], basetype.lower()); - else: - raise BaseException("Unhandled parameter type '%s'" % (parameter["type"])) - - if "return" in procedure_desc: - if procedure_desc["return"] == "bool": - binding += " lua_pushboolean(L, (int)%s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) - elif procedure_desc["return"] == "float": - binding += " lua_pushnumber(L, (double)%s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) - elif procedure_desc["return"] == "char *": - binding += " lua_pushstring(L, %s(%s));\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) - elif type(procedure_desc["return"]) is dict or procedure_desc["return"] in api["types"]: - # TODO: handle enums - type_desc = procedure_desc["return"] if type(procedure_desc["return"]) is dict else api["types"][procedure_desc["return"]] - binding += " %s result = %s(%s);\n" % (type_desc["c_type"], procedure, ", ".join(param["name"] for param in procedure_desc["params"])) - binding += to_table(type_desc, "result", 4) - else: - raise BaseException("Unhandled return type '%s'" % (procedure_desc["return"])) - binding += " return 1;\n}\n" - else: - binding += " %s(%s);\n" % (procedure, ", ".join(param["name"] for param in procedure_desc["params"])) - binding += " return 0;\n}\n" - - print(binding) +print('\n'.join(bindings)) loader = "void bindgen_load_%s(lua_State *L) {\n" % api["name"] @@ -157,11 +166,20 @@ for module in modules: loader += " lua_setfield(L, -2, \"%s\");\n" % procedure_desc["symbol"] loader += " lua_setglobal(L, \"%s\");\n" % module -loader += "}" +loader += "}\n" print(loader) unloader = "void bindgen_unload_%s(lua_State *L) {\n" % api["name"] unloader += '\n'.join(deinitializers) -unloader += "}" +unloader += "}\n" print(unloader) + + +# exceptions for the base townengine api +# TODO: is there a way to generalize it? or rather, is there any need to do so? +if api["name"] == "twn": + contexter = "void bindgen_build_context(lua_State *L) {\n" + contexter += to_table(api["types"]["Context"], "ctx", 4) + contexter += "}" + print(contexter) diff --git a/apps/twnlua/game.c b/apps/twnlua/game.c index 5da7dd4..6df50a5 100644 --- a/apps/twnlua/game.c +++ b/apps/twnlua/game.c @@ -13,6 +13,7 @@ /* generated by bindgen.py */ void bindgen_load_twn(lua_State *L); void bindgen_unload_twn(lua_State *L); +void bindgen_build_context(lua_State *L); /* require will go through physicsfs exclusively so that scripts can be in the data dir */ @@ -110,6 +111,9 @@ void game_tick(void) { State *state = ctx.udata; + bindgen_build_context(state->L); + lua_setglobal(state->L, "ctx"); + lua_getglobal(state->L, "game_tick"); if (lua_pcall(state->L, 0, 0, 0) != LUA_OK) { log_critical("%s", lua_tostring(state->L, -1)); diff --git a/share/twn_api.json b/share/twn_api.json index 8cac587..6f9e044 100644 --- a/share/twn_api.json +++ b/share/twn_api.json @@ -259,6 +259,20 @@ "c_type": "Rect" }, + "Context": { + "fields": [ + { "name": "frame_number", "type": "float" }, + { "name": "frame_duration", "type": "float" }, + { "name": "resolution", "type": "Vec2" }, + { "name": "mouse_position", "type": "Vec2" }, + { "name": "mouse_movement", "type": "Vec2" }, + { "name": "random_seed", "type": "float" }, + { "name": "debug", "type": "bool" }, + { "name": "initialization_needed", "type": "bool" } + ], + "c_type": "Context" + }, + "Control": { "enums": { "A": 4,