diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2012-11-17 19:44:09 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2012-11-17 19:44:09 (GMT) |
| commit | 058a2edd75debbd0297f92572316daa704bd379f (patch) | |
| tree | ad303f091f9a08b209b91eb34a9fcad996a3de69 /src/cat | |
| parent | e3594aba9e05c6865d396418c028049cda92c2f3 (diff) | |
| parent | 7a21ae192fe19868539956f3fe28e62b2c7c4429 (diff) | |
| download | powder-058a2edd75debbd0297f92572316daa704bd379f.zip powder-058a2edd75debbd0297f92572316daa704bd379f.tar.gz | |
Merge branch 'master' of github.com:FacialTurd/PowderToypp
Diffstat (limited to 'src/cat')
29 files changed, 6644 insertions, 0 deletions
diff --git a/src/cat/CommandInterface.cpp b/src/cat/CommandInterface.cpp new file mode 100644 index 0000000..3ebc795 --- /dev/null +++ b/src/cat/CommandInterface.cpp @@ -0,0 +1,118 @@ +/* + * Kitty.cpp + * + * Created on: Feb 2, 2012 + * Author: Simon + */ + +#include <iostream> +#include <string> +#include <string.h> +#if !defined(WIN) || defined(__GNUC__) +#include <strings.h> +#endif +#include "CommandInterface.h" +#include "game/GameModel.h" +#include "game/GameController.h" + +CommandInterface::CommandInterface(GameController * c, GameModel * m) { + this->m = m; + this->c = c; +} + +/*void CommandInterface::AttachGameModel(GameModel * m) +{ + this->m = m; +}*/ + +int CommandInterface::Command(std::string command) +{ + lastError = "No interpreter"; + return -1; +} + +std::string CommandInterface::FormatCommand(std::string command) +{ + return command; +} + +void CommandInterface::Log(LogType type, std::string message) +{ + m->Log(message); +} + +int CommandInterface::GetPropertyOffset(std::string key_, FormatType & format) +{ + char * key = (char *)key_.c_str(); + int offset; + if (strcmp(key, "type")==0){ + offset = offsetof(Particle, type); + format = FormatInt; + } else if (strcmp(key, "life")==0){ + offset = offsetof(Particle, life); + format = FormatInt; + } else if (strcmp(key, "ctype")==0){ + offset = offsetof(Particle, ctype); + format = FormatInt; + } else if (strcmp(key, "temp")==0){ + offset = offsetof(Particle, temp); + format = FormatFloat; + } else if (strcmp(key, "tmp2")==0){ + offset = offsetof(Particle, tmp2); + format = FormatInt; + } else if (strcmp(key, "tmp")==0){ + offset = offsetof(Particle, tmp); + format = FormatInt; + } else if (strcmp(key, "vy")==0){ + offset = offsetof(Particle, vy); + format = FormatFloat; + } else if (strcmp(key, "vx")==0){ + offset = offsetof(Particle, vx); + format = FormatFloat; + } else if (strcmp(key, "x")==0){ + offset = offsetof(Particle, x); + format = FormatFloat; + } else if (strcmp(key, "y")==0){ + offset = offsetof(Particle, y); + format = FormatFloat; + } else if (strcmp(key, "dcolour")==0){ + offset = offsetof(Particle, dcolour); + format = FormatInt; + } else if (strcmp(key, "dcolor")==0){ + offset = offsetof(Particle, dcolour); + format = FormatInt; + } else { + offset = -1; + } + return offset; +} + +int CommandInterface::GetParticleType(std::string type) +{ + int i = -1; + char * txt = (char*)type.c_str(); + + //Scope + Element * elements = m->GetSimulation()->elements; + + // alternative names for some elements + if (strcasecmp(txt,"C4")==0) return PT_PLEX; + else if (strcasecmp(txt,"C5")==0) return PT_C5; + else if (strcasecmp(txt,"NONE")==0) return PT_NONE; + for (i=1; i<PT_NUM; i++) { + if (strcasecmp(txt, elements[i].Name)==0 && elements[i].Enabled) + { + return i; + } + } + return -1; +} + +std::string CommandInterface::GetLastError() +{ + return lastError; +} + +CommandInterface::~CommandInterface() { +} + diff --git a/src/cat/CommandInterface.h b/src/cat/CommandInterface.h new file mode 100644 index 0000000..e6119d3 --- /dev/null +++ b/src/cat/CommandInterface.h @@ -0,0 +1,44 @@ +/* + * Kitty.h + * + * Created on: Feb 2, 2012 + * Author: Simon + */ + +#ifndef KITTY_H_ +#define KITTY_H_ + +#include <string> +#include "interface/Engine.h" +//#include "game/GameModel.h" + +class GameModel; +class GameController; +class CommandInterface { +protected: + std::string lastError; + GameModel * m; + GameController * c; +public: + enum LogType { LogError, LogWarning, LogNotice }; + enum FormatType { FormatInt, FormatString, FormatChar, FormatFloat }; + CommandInterface(GameController * c, GameModel * m); + int GetPropertyOffset(std::string key_, FormatType & format); + int GetParticleType(std::string type); + void Log(LogType type, std::string message); + //void AttachGameModel(GameModel * m); + virtual bool OnBrushChanged(int brushType, int rx, int ry) {return true;} + virtual bool OnMouseMove(int x, int y, int dx, int dy) {return true;} + virtual bool OnMouseDown(int x, int y, unsigned button) {return true;} + virtual bool OnMouseUp(int x, int y, unsigned button) {return true;} + virtual bool OnMouseWheel(int x, int y, int d) {return true;} + virtual bool OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) {return true;} + virtual bool OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) {return true;} + virtual void OnTick() {} + virtual int Command(std::string command); + virtual std::string FormatCommand(std::string command); + std::string GetLastError(); + virtual ~CommandInterface(); +}; + +#endif /* KITTY_H_ */ diff --git a/src/cat/LegacyLuaAPI.cpp b/src/cat/LegacyLuaAPI.cpp new file mode 100644 index 0000000..9a478e7 --- /dev/null +++ b/src/cat/LegacyLuaAPI.cpp @@ -0,0 +1,1828 @@ +#include <string> +#include <iomanip> +#include <vector> +#include <algorithm> +#include <locale> + +#include "client/HTTP.h" +#include "Format.h" +#include "LuaScriptInterface.h" +#include "LuaScriptHelper.h" + +#include "dialogues/ErrorMessage.h" +#include "dialogues/InformationMessage.h" +#include "dialogues/TextPrompt.h" +#include "dialogues/ConfirmPrompt.h" +#include "simulation/Simulation.h" +#include "game/GameModel.h" + +#include <time.h> + +#ifndef FFI +int luacon_partread(lua_State* l){ + int format, offset, tempinteger; + float tempfloat; + int i; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_particle_getproperty(key, &format); + + i = cIndex; + + if(i < 0 || i >= NPART || offset==-1) + { + if(i < 0 || i >= NPART) { + free(key); + return luaL_error(l, "Out of range"); + } else if(strcmp(key, "id")==0) { + free(key); + lua_pushnumber(l, i); + return 1; + } else { + free(key); + return luaL_error(l, "Invalid property"); + } + } + free(key); + switch(format) + { + case 0: + tempinteger = *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)); + lua_pushnumber(l, tempinteger); + break; + case 1: + tempfloat = *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)); + lua_pushnumber(l, tempfloat); + break; + } + return 1; +} +int luacon_partwrite(lua_State* l){ + int format, offset; + int i; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_particle_getproperty(key, &format); + + i = cIndex; + + if(i < 0 || i >= NPART || offset==-1) + { + if(i < 0 || i >= NPART) { + free(key); + return luaL_error(l, "array index out of bounds"); + } else { + free(key); + return luaL_error(l, "Invalid property"); + } + } + free(key); + switch(format) + { + case 0: + *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optinteger(l, 3, 0); + break; + case 1: + *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optnumber(l, 3, 0); + break; + } + return 1; +} +int luacon_partsread(lua_State* l){ + int format, offset; + char * tempstring; + int tempinteger; + float tempfloat; + int i, currentPart, currentPartMeta; + + i = luaL_optinteger(l, 2, 0); + + if(i<0 || i>=NPART) + { + return luaL_error(l, "array index out of bounds"); + } + + lua_rawgeti(l, LUA_REGISTRYINDEX, tptPart); + cIndex = i; + return 1; +} +int luacon_partswrite(lua_State* l){ + return luaL_error(l, "table readonly"); +} +#endif +int luacon_particle_getproperty(char * key, int * format) +{ + int offset; + if (strcmp(key, "type")==0){ + offset = offsetof(Particle, type); + *format = 0; + } else if (strcmp(key, "life")==0){ + offset = offsetof(Particle, life); + *format = 0; + } else if (strcmp(key, "ctype")==0){ + offset = offsetof(Particle, ctype); + *format = 0; + } else if (strcmp(key, "temp")==0){ + offset = offsetof(Particle, temp); + *format = 1; + } else if (strcmp(key, "tmp")==0){ + offset = offsetof(Particle, tmp); + *format = 0; + } else if (strcmp(key, "tmp2")==0){ + offset = offsetof(Particle, tmp2); + *format = 0; + } else if (strcmp(key, "vy")==0){ + offset = offsetof(Particle, vy); + *format = 1; + } else if (strcmp(key, "vx")==0){ + offset = offsetof(Particle, vx); + *format = 1; + } else if (strcmp(key, "x")==0){ + offset = offsetof(Particle, x); + *format = 1; + } else if (strcmp(key, "y")==0){ + offset = offsetof(Particle, y); + *format = 1; + } else if (strcmp(key, "dcolour")==0){ + offset = offsetof(Particle, dcolour); + *format = 0; + } else if (strcmp(key, "dcolor")==0){ + offset = offsetof(Particle, dcolour); + *format = 0; + } else { + offset = -1; + } + return offset; +} +int luacon_transition_getproperty(char * key, int * format) +{ + int offset; + if (strcmp(key, "presHighValue")==0){ + offset = offsetof(Element, HighPressure); + *format = 1; + } else if (strcmp(key, "presHighType")==0){ + offset = offsetof(Element, HighPressureTransition); + *format = 0; + } else if (strcmp(key, "presLowValue")==0){ + offset = offsetof(Element, LowPressure); + *format = 1; + } else if (strcmp(key, "presLowType")==0){ + offset = offsetof(Element, LowPressureTransition); + *format = 0; + } else if (strcmp(key, "tempHighValue")==0){ + offset = offsetof(Element, HighTemperature); + *format = 1; + } else if (strcmp(key, "tempHighType")==0){ + offset = offsetof(Element, HighTemperatureTransition); + *format = 0; + } else if (strcmp(key, "tempLowValue")==0){ + offset = offsetof(Element, LowTemperature); + *format = 1; + } else if (strcmp(key, "tempLowType")==0){ + offset = offsetof(Element, LowTemperatureTransition); + *format = 0; + } else { + offset = -1; + } + return offset; +} +int luacon_transitionread(lua_State* l){ + int format, offset; + int tempinteger; + float tempfloat; + int i; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_transition_getproperty(key, &format); + free(key); + + //Get Raw Index value for element + lua_pushstring(l, "value"); + lua_rawget(l, 1); + + i = lua_tointeger(l, lua_gettop(l)); + + lua_pop(l, 1); + + if(i < 0 || i >= PT_NUM || offset==-1) + { + return luaL_error(l, "Invalid property"); + } + switch(format) + { + case 0: + tempinteger = *((int*)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushnumber(l, tempinteger); + break; + case 1: + tempfloat = *((float*)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushnumber(l, tempfloat); + break; + } + return 1; +} +int luacon_transitionwrite(lua_State* l){ + int format, offset; + int tempinteger; + float tempfloat; + int i; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_transition_getproperty(key, &format); + free(key); + + //Get Raw Index value for element + lua_pushstring(l, "value"); + lua_rawget(l, 1); + + i = lua_tointeger (l, lua_gettop(l)); + + lua_pop(l, 1); + + if(i < 0 || i >= PT_NUM || offset==-1) + { + return luaL_error(l, "Invalid property"); + } + switch(format) + { + case 0: + *((int*)(((unsigned char*)&luacon_sim->elements[i])+offset)) = luaL_optinteger(l, 3, 0); + break; + case 1: + *((float*)(((unsigned char*)&luacon_sim->elements[i])+offset)) = luaL_optnumber(l, 3, 0); + break; + } + return 0; +} +int luacon_element_getproperty(char * key, int * format, unsigned int * modified_stuff) +{ + int offset; + if (strcmp(key, "name")==0){ + offset = offsetof(Element, Name); + *format = 2; + if(modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_MENUS; + } + else if (strcmp(key, "color")==0){ + offset = offsetof(Element, Colour); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_GRAPHICS; + } + else if (strcmp(key, "colour")==0){ + offset = offsetof(Element, Colour); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_GRAPHICS; + } + else if (strcmp(key, "advection")==0){ + offset = offsetof(Element, Advection); + *format = 1; + } + else if (strcmp(key, "airdrag")==0){ + offset = offsetof(Element, AirDrag); + *format = 1; + } + else if (strcmp(key, "airloss")==0){ + offset = offsetof(Element, AirLoss); + *format = 1; + } + else if (strcmp(key, "loss")==0){ + offset = offsetof(Element, Loss); + *format = 1; + } + else if (strcmp(key, "collision")==0){ + offset = offsetof(Element, Collision); + *format = 1; + } + else if (strcmp(key, "gravity")==0){ + offset = offsetof(Element, Gravity); + *format = 1; + } + else if (strcmp(key, "diffusion")==0){ + offset = offsetof(Element, Diffusion); + *format = 1; + } + else if (strcmp(key, "hotair")==0){ + offset = offsetof(Element, HotAir); + *format = 1; + } + else if (strcmp(key, "falldown")==0){ + offset = offsetof(Element, Falldown); + *format = 0; + } + else if (strcmp(key, "flammable")==0){ + offset = offsetof(Element, Flammable); + *format = 0; + } + else if (strcmp(key, "explosive")==0){ + offset = offsetof(Element, Explosive); + *format = 0; + } + else if (strcmp(key, "meltable")==0){ + offset = offsetof(Element, Meltable); + *format = 0; + } + else if (strcmp(key, "hardness")==0){ + offset = offsetof(Element, Hardness); + *format = 0; + } + else if (strcmp(key, "menu")==0){ + offset = offsetof(Element, MenuVisible); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_MENUS; + } + else if (strcmp(key, "enabled")==0){ + offset = offsetof(Element, Enabled); + *format = 0; + } + else if (strcmp(key, "weight")==0){ + offset = offsetof(Element, Weight); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_CANMOVE; + } + else if (strcmp(key, "menusection")==0){ + offset = offsetof(Element, MenuSection); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_MENUS; + } + else if (strcmp(key, "heat")==0){ + offset = offsetof(Element, Temperature); + *format = 1; + } + else if (strcmp(key, "hconduct")==0){ + offset = offsetof(Element, HeatConduct); + *format = 3; + } + else if (strcmp(key, "state")==0){ + offset = offsetof(Element, State); + *format = 3; + } + else if (strcmp(key, "properties")==0){ + offset = offsetof(Element, Properties); + *format = 0; + if (modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_GRAPHICS | LUACON_EL_MODIFIED_CANMOVE; + } + else if (strcmp(key, "description")==0){ + offset = offsetof(Element, Description); + *format = 2; + if(modified_stuff) + *modified_stuff |= LUACON_EL_MODIFIED_MENUS; + } + else { + return -1; + } + return offset; +} +int luacon_elementread(lua_State* l){ + int format, offset; + char * tempstring; + int tempinteger; + float tempfloat; + int i; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_element_getproperty(key, &format, NULL); + free(key); + + //Get Raw Index value for element + lua_pushstring(l, "id"); + lua_rawget(l, 1); + + i = lua_tointeger (l, lua_gettop(l)); + + lua_pop(l, 1); + + if(i < 0 || i >= PT_NUM || offset==-1) + { + return luaL_error(l, "Invalid property"); + } + switch(format) + { + case 0: + tempinteger = *((int*)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushnumber(l, tempinteger); + break; + case 1: + tempfloat = *((float*)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushnumber(l, tempfloat); + break; + case 2: + tempstring = *((char**)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushstring(l, tempstring); + break; + case 3: + tempinteger = *((unsigned char*)(((unsigned char*)&luacon_sim->elements[i])+offset)); + lua_pushnumber(l, tempinteger); + break; + } + return 1; +} +int luacon_elementwrite(lua_State* l){ + int format, offset; + char * tempstring; + int tempinteger; + float tempfloat; + int i; + unsigned int modified_stuff = 0; + char * key = mystrdup((char*)luaL_optstring(l, 2, "")); + offset = luacon_element_getproperty(key, &format, &modified_stuff); + + //Get Raw Index value for element + lua_pushstring(l, "id"); + lua_rawget(l, 1); + + i = lua_tointeger (l, lua_gettop(l)); + + lua_pop(l, 1); + + if(i < 0 || i >= PT_NUM || offset==-1) + { + free(key); + return luaL_error(l, "Invalid property"); + } + switch(format) + { + case 0: + *((int*)(((unsigned char*)&luacon_sim->elements[i])+offset)) = luaL_optinteger(l, 3, 0); + break; + case 1: + *((float*)(((unsigned char*)&luacon_sim->elements[i])+offset)) = luaL_optnumber(l, 3, 0); + break; + case 2: + tempstring = mystrdup((char*)luaL_optstring(l, 3, "")); + if(strcmp(key, "name")==0) + { + int j = 0; + //Convert to upper case + for(j = 0; j < strlen(tempstring); j++) + tempstring[j] = toupper(tempstring[j]); + if(strlen(tempstring)>4) + { + free(tempstring); + free(key); + return luaL_error(l, "Name too long"); + } + if(luacon_ci->GetParticleType(tempstring) != -1) + { + free(tempstring); + free(key); + return luaL_error(l, "Name in use"); + } + } + *((char**)(((unsigned char*)&luacon_sim->elements[i])+offset)) = tempstring; + //Need some way of cleaning up previous values + break; + case 3: + *((unsigned char*)(((unsigned char*)&luacon_sim->elements[i])+offset)) = luaL_optinteger(l, 3, 0); + break; + } + if (modified_stuff) + { + if (modified_stuff & LUACON_EL_MODIFIED_MENUS) + luacon_model->BuildMenus(); + if (modified_stuff & LUACON_EL_MODIFIED_CANMOVE) + luacon_sim->init_can_move(); + if (modified_stuff & LUACON_EL_MODIFIED_GRAPHICS) + memset(luacon_ren->graphicscache, 0, sizeof(gcache_item)*PT_NUM); + } + free(key); + return 0; +} +int luacon_keyevent(int key, int modifier, int event){ + int i = 0, kpcontinue = 1, callret; + char tempkey[] = {key, 0}; + if(keypress_function_count){ + for(i = 0; i < keypress_function_count && kpcontinue; i++){ + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, keypress_functions[i]); + lua_pushstring(luacon_ci->l, tempkey); + lua_pushinteger(luacon_ci->l, key); + lua_pushinteger(luacon_ci->l, modifier); + lua_pushinteger(luacon_ci->l, event); + callret = lua_pcall(luacon_ci->l, 4, 1, 0); + if (callret) + { + luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); + } + if(lua_isboolean(luacon_ci->l, -1)){ + kpcontinue = lua_toboolean(luacon_ci->l, -1); + } + lua_pop(luacon_ci->l, 1); + } + } + return kpcontinue; +} +int luacon_mouseevent(int mx, int my, int mb, int event, int mouse_wheel){ + int i = 0, mpcontinue = 1, callret; + if(mouseclick_function_count){ + for(i = 0; i < mouseclick_function_count && mpcontinue; i++){ + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, mouseclick_functions[i]); + lua_pushinteger(luacon_ci->l, mx); + lua_pushinteger(luacon_ci->l, my); + lua_pushinteger(luacon_ci->l, mb); + lua_pushinteger(luacon_ci->l, event); + lua_pushinteger(luacon_ci->l, mouse_wheel); + callret = lua_pcall(luacon_ci->l, 5, 1, 0); + if (callret) + { + luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); + } + if(lua_isboolean(luacon_ci->l, -1)){ + mpcontinue = lua_toboolean(luacon_ci->l, -1); + } + lua_pop(luacon_ci->l, 1); + } + } + return mpcontinue; +} + +int luacon_step(int mx, int my, int selectl, int selectr, int bsx, int bsy){ + int tempret = 0, tempb, i, callret; + lua_pushinteger(luacon_ci->l, bsy); + lua_pushinteger(luacon_ci->l, bsx); + lua_pushinteger(luacon_ci->l, selectr); + lua_pushinteger(luacon_ci->l, selectl); + lua_pushinteger(luacon_ci->l, my); + lua_pushinteger(luacon_ci->l, mx); + lua_setfield(luacon_ci->l, tptProperties, "mousex"); + lua_setfield(luacon_ci->l, tptProperties, "mousey"); + lua_setfield(luacon_ci->l, tptProperties, "selectedl"); + lua_setfield(luacon_ci->l, tptProperties, "selectedr"); + lua_setfield(luacon_ci->l, tptProperties, "brushx"); + lua_setfield(luacon_ci->l, tptProperties, "brushy"); + for(i = 0; i<6; i++){ + if(step_functions[i]){ + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, step_functions[i]); + callret = lua_pcall(luacon_ci->l, 0, 0, 0); + if (callret) + { + if (!strcmp(luacon_geterror(),"Error: Script not responding")) + { + ui::Engine::Ref().LastTick(clock()); + lua_pushcfunction(luacon_ci->l, &luatpt_unregister_step); + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, step_functions[i]); + lua_pcall(luacon_ci->l, 1, 0, 0); + } + luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); + } + } + } + return 0; +} + + +int luacon_eval(char *command){ + ui::Engine::Ref().LastTick(clock()); + return luaL_dostring (luacon_ci->l, command); +} + +void luacon_hook(lua_State * l, lua_Debug * ar) +{ + if(ar->event == LUA_HOOKCOUNT && clock()-ui::Engine::Ref().LastTick() > CLOCKS_PER_SEC*3) + { + if(ConfirmPrompt::Blocking("Script not responding", "The Lua script may have stopped responding. There might be an infinite loop. Press \"Stop\" to stop it", "Stop")) + luaL_error(l, "Error: Script not responding"); + ui::Engine::Ref().LastTick(clock()); + } +} + +char *luacon_geterror(){ + char *error = (char*)lua_tostring(luacon_ci->l, -1); + if(error==NULL || !error[0]){ + error = "failed to execute"; + } + return error; +} +/*void luacon_close(){ + lua_close(l); +}*/ + +//TPT Interface methods +int luatpt_test(lua_State* l) +{ + int testint = 0; + testint = luaL_optint(l, 1, 0); + printf("Test successful, got %d\n", testint); + return 0; +} +int luatpt_getelement(lua_State *l) +{ + int t; + if(lua_isnumber(l, 1)) + { + t = luaL_optint(l, 1, 1); + if (t<0 || t>=PT_NUM) + return luaL_error(l, "Unrecognised element number '%d'", t); + lua_pushstring(l, luacon_sim->elements[t].Name); + } + else + { + char* name = (char*)luaL_optstring(l, 1, "dust"); + if ((t = luacon_ci->GetParticleType(name))==-1) + return luaL_error(l, "Unrecognised element '%s'", name); + lua_pushinteger(l, t); + } + return 1; +} + +int luacon_elementReplacement(UPDATE_FUNC_ARGS) +{ + int retval = 0; + if(lua_el_func[parts[i].type]){ + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_el_func[parts[i].type]); + lua_pushinteger(luacon_ci->l, i); + lua_pushinteger(luacon_ci->l, x); + lua_pushinteger(luacon_ci->l, y); + lua_pushinteger(luacon_ci->l, surround_space); + lua_pushinteger(luacon_ci->l, nt); + lua_pcall(luacon_ci->l, 5, 1, 0); + if(lua_isboolean(luacon_ci->l, -1)){ + retval = lua_toboolean(luacon_ci->l, -1); + } + lua_pop(luacon_ci->l, 1); + } + return retval; +} + +int luatpt_element_func(lua_State *l) +{ + if(lua_isfunction(l, 1)) + { + int element = luaL_optint(l, 2, 0); + int function; + lua_pushvalue(l, 1); + function = luaL_ref(l, LUA_REGISTRYINDEX); + if(element > 0 && element < PT_NUM) + { + lua_el_func[element] = function; + luacon_sim->elements[element].Update = &luacon_elementReplacement; + return 0; + } + else + { + return luaL_error(l, "Invalid element"); + } + } + else + return luaL_error(l, "Not a function"); + return 0; +} + +int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS) +{ + int cache = 0; + lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_gr_func[cpart->type]); + lua_pushinteger(luacon_ci->l, 0); + lua_pushinteger(luacon_ci->l, *colr); + lua_pushinteger(luacon_ci->l, *colg); + lua_pushinteger(luacon_ci->l, *colb); + lua_pcall(luacon_ci->l, 4, 10, 0); + + cache = luaL_optint(luacon_ci->l, -10, 0); + *pixel_mode = luaL_optint(luacon_ci->l, -9, *pixel_mode); + *cola = luaL_optint(luacon_ci->l, -8, *cola); + *colr = luaL_optint(luacon_ci->l, -7, *colr); + *colg = luaL_optint(luacon_ci->l, -6, *colg); + *colb = luaL_optint(luacon_ci->l, -5, *colb); + *firea = luaL_optint(luacon_ci->l, -4, *firea); + *firer = luaL_optint(luacon_ci->l, -3, *firer); + *fireg = luaL_optint(luacon_ci->l, -2, *fireg); + *fireb = luaL_optint(luacon_ci->l, -1, *fireb); + lua_pop(luacon_ci->l, 10); + return cache; +} + +int luatpt_graphics_func(lua_State *l) +{ + if(lua_isfunction(l, 1)) + { + int element = luaL_optint(l, 2, 0); + int function; + lua_pushvalue(l, 1); + function = luaL_ref(l, LUA_REGISTRYINDEX); + if(element > 0 && element < PT_NUM) + { + lua_gr_func[element] = function; + luacon_ren->graphicscache[element].isready = 0; + luacon_sim->elements[element].Graphics = &luacon_graphicsReplacement; + return 0; + } + else + { + return luaL_error(l, "Invalid element"); + } + } + else + return luaL_error(l, "Not a function"); + return 0; +} + +int luatpt_error(lua_State* l) +{ + std::string errorMessage = std::string(luaL_optstring(l, 1, "Error text")); + ErrorMessage::Blocking("Error", errorMessage); + return 0; +} +int luatpt_drawtext(lua_State* l) +{ + char *string; + int textx, texty, textred, textgreen, textblue, textalpha; + textx = luaL_optint(l, 1, 0); + texty = luaL_optint(l, 2, 0); + string = (char*)luaL_optstring(l, 3, ""); + textred = luaL_optint(l, 4, 255); + textgreen = luaL_optint(l, 5, 255); + textblue = luaL_optint(l, 6, 255); + textalpha = luaL_optint(l, 7, 255); + if (textx<0 || texty<0 || textx>=XRES+BARSIZE || texty>=YRES+MENUSIZE) + return luaL_error(l, "Screen coordinates out of range (%d,%d)", textx, texty); + if (textred<0) textred = 0; + if (textred>255) textred = 255; + if (textgreen<0) textgreen = 0; + if (textgreen>255) textgreen = 255; + if (textblue<0) textblue = 0; + if (textblue>255) textblue = 255; + if (textalpha<0) textalpha = 0; + if (textalpha>255) textalpha = 255; + if(luacon_g!=NULL){ + luacon_g->drawtext(textx, texty, string, textred, textgreen, textblue, textalpha); + return 0; + } + return luaL_error(l, "Screen buffer does not exist"); +} + +int luatpt_create(lua_State* l) +{ + int x, y, retid, t = -1; + char * name; + x = abs(luaL_optint(l, 1, 0)); + y = abs(luaL_optint(l, 2, 0)); + if(x < XRES && y < YRES){ + if(lua_isnumber(l, 3)){ + t = luaL_optint(l, 3, 0); + if (t<0 || t >= PT_NUM || !luacon_sim->elements[t].Enabled) + return luaL_error(l, "Unrecognised element number '%d'", t); + } else { + name = (char*)luaL_optstring(l, 3, "dust"); + if ((t = luacon_ci->GetParticleType(std::string(name))) == -1) + return luaL_error(l,"Unrecognised element '%s'", name); + } + retid = luacon_sim->create_part(-1, x, y, t); + // failing to create a particle often happens (e.g. if space is already occupied) and isn't usually important, so don't raise an error + lua_pushinteger(l, retid); + return 1; + } + return luaL_error(l, "Coordinates out of range (%d,%d)", x, y); +} + +int luatpt_setpause(lua_State* l) +{ + int pausestate; + pausestate = luaL_optint(l, 1, 0); + luacon_model->SetPaused(pausestate==0?0:1); + return 0; +} + +int luatpt_togglepause(lua_State* l) +{ + luacon_model->SetPaused(!luacon_model->GetPaused()); + //sys_pause=!sys_pause; + return 0; +} + +int luatpt_togglewater(lua_State* l) +{ + luacon_sim->water_equal_test=!luacon_sim->water_equal_test; + return 0; +} + +int luatpt_setconsole(lua_State* l) +{ + /*int consolestate; + consolestate = luaL_optint(l, 1, 0); + console_mode = (consolestate==0?0:1); + return 0;*/ + //TODO IMPLEMENT + return 0; +} + +int luatpt_log(lua_State* l) +{ + int args = lua_gettop(l); + for(int i = 1; i <= args; i++) + { + if((*luacon_currentCommand)) + { + if(!(*luacon_lastError).length()) + (*luacon_lastError) = luaL_optstring(l, i, ""); + else + (*luacon_lastError) += ", " + std::string(luaL_optstring(l, i, "")); + } + else + luacon_ci->Log(CommandInterface::LogNotice, luaL_optstring(l, i, "")); + } + return 0; +} + +int luatpt_set_pressure(lua_State* l) +{ + int nx, ny; + int x1, y1, width, height; + float value; + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + value = (float)luaL_optint(l, 5, 0.0f); + if(value > 256.0f) + value = 256.0f; + else if(value < -256.0f) + value = -256.0f; + + if(x1 > (XRES/CELL)-1) + x1 = (XRES/CELL)-1; + if(y1 > (YRES/CELL)-1) + y1 = (YRES/CELL)-1; + if(x1+width > (XRES/CELL)-1) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)-1) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->pv[ny][nx] = value; + } + return 0; +} + +int luatpt_set_gravity(lua_State* l) +{ + int nx, ny; + int x1, y1, width, height; + float value; + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + value = (float)luaL_optint(l, 5, 0.0f); + if(value > 256.0f) + value = 256.0f; + else if(value < -256.0f) + value = -256.0f; + + if(x1 > (XRES/CELL)-1) + x1 = (XRES/CELL)-1; + if(y1 > (YRES/CELL)-1) + y1 = (YRES/CELL)-1; + if(x1+width > (XRES/CELL)-1) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)-1) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->gravmap[ny*(XRES/CELL)+nx] = value; + } + return 0; +} + +int luatpt_reset_gravity_field(lua_State* l) +{ + int nx, ny; + int x1, y1, width, height; + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + if(x1 > (XRES/CELL)-1) + x1 = (XRES/CELL)-1; + if(y1 > (YRES/CELL)-1) + y1 = (YRES/CELL)-1; + if(x1+width > (XRES/CELL)-1) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)-1) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->gravx[ny*(XRES/CELL)+nx] = 0; + luacon_sim->gravy[ny*(XRES/CELL)+nx] = 0; + luacon_sim->gravp[ny*(XRES/CELL)+nx] = 0; + } + return 0; +} + +int luatpt_reset_velocity(lua_State* l) +{ + int nx, ny; + int x1, y1, width, height; + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + if(x1 > (XRES/CELL)-1) + x1 = (XRES/CELL)-1; + if(y1 > (YRES/CELL)-1) + y1 = (YRES/CELL)-1; + if(x1+width > (XRES/CELL)-1) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)-1) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->vx[ny][nx] = 0; + luacon_sim->vy[ny][nx] = 0; + } + return 0; +} + +int luatpt_reset_spark(lua_State* l) +{ + int i; + for (i=0; i<NPART; i++) + { + if (luacon_sim->parts[i].type==PT_SPRK) + { + if (luacon_sim->parts[i].ctype >= 0 && luacon_sim->parts[i].ctype < PT_NUM) + { + luacon_sim->parts[i].type = luacon_sim->parts[i].ctype; + luacon_sim->parts[i].life = 0; + } + else + luacon_sim->kill_part(i); + } + } + return 0; +} + +int luatpt_set_property(lua_State* l) +{ + char *prop, *name; + int r, i, x, y, w, h, t, nx, ny, partsel = 0, acount; + float f; + size_t offset; + acount = lua_gettop(l); + prop = (char*)luaL_optstring(l, 1, ""); + if(lua_isnumber(l, 3)) + i = abs(luaL_optint(l, 3, -1)); + else + i = -1; + if(lua_isnumber(l, 4)) + y = abs(luaL_optint(l, 4, -1)); + else + y = -1; + if(lua_isnumber(l, 5)) + w = abs(luaL_optint(l, 5, -1)); + else + w = -1; + if(lua_isnumber(l, 6)) + h = abs(luaL_optint(l, 6, -1)); + else + h = -1; + + CommandInterface::FormatType format; + offset = luacon_ci->GetPropertyOffset(prop, format); + if(offset == -1) + return luaL_error(l, "Invalid property '%s'", prop); + if(acount>2){ + if(!lua_isnumber(l, acount) && lua_isstring(l, acount)){ + name = (char*)luaL_optstring(l, acount, "none"); + if((partsel = luacon_ci->GetParticleType(std::string(name)))==-1) + return luaL_error(l, "Unrecognised element '%s'", name); + } + } + if(lua_isnumber(l, 2)){ + if(format == CommandInterface::FormatFloat){ + f = luaL_optnumber(l, 2, 0); + } else { + t = luaL_optint(l, 2, 0); + } + //TODO Element ID check + //if (format == 3 && (t<0 || t>=PT_NUM)) + // return luaL_error(l, "Unrecognised element number '%d'", t); + } else { + name = (char*)luaL_optstring(l, 2, "dust"); + //if (!console_parse_type(name, &t, NULL)) + if((t = luacon_ci->GetParticleType(std::string(name)))==-1) + return luaL_error(l, "Unrecognised element '%s'", name); + } + if(i == -1 || (w != -1 && h != -1)){ + // Got a region + if(i == -1){ + i = 0; + y = 0; + w = XRES; + h = YRES; + } + if (i>=XRES || y>=YRES) + return luaL_error(l, "Coordinates out of range (%d,%d)", i, y); + x = i; + if(x+w > XRES) + w = XRES-x; + if(y+h > YRES) + h = YRES-y; + Particle * parts = luacon_sim->parts; + for (i = 0; i < NPART; i++) + { + if (parts[i].type) + { + nx = (int)(parts[i].x + .5f); + ny = (int)(parts[i].y + .5f); + if (nx >= x && nx < x+w && ny >= y && ny < y+h && (!partsel || partsel == parts[i].type)) + { + if(format == CommandInterface::FormatFloat){ + *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f; + } else { + *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t; + } + } + } + } + + } else { + // Got coords or particle index + if(i != -1 && y != -1){ + if (i>=XRES || y>=YRES) + return luaL_error(l, "Coordinates out of range (%d,%d)", i, y); + r = luacon_sim->pmap[y][i]; + if (!r || (partsel && partsel != luacon_sim->parts[r>>8].type)) + r = luacon_sim->photons[y][i]; + if (!r || (partsel && partsel != luacon_sim->parts[r>>8].type)) + return 0; + i = r>>8; + } + if (i < 0 || i >= NPART) + return luaL_error(l, "Invalid particle ID '%d'", i); + if (!luacon_sim->parts[i].type) + return 0; + if (partsel && partsel != luacon_sim->parts[i].type) + return 0; + if(format == CommandInterface::FormatFloat){ + *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f; + } else { + *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t; + } + } + return 0; +} + +int luatpt_set_wallmap(lua_State* l) +{ + int nx, ny, acount; + int x1, y1, width, height; + float value; + acount = lua_gettop(l); + + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + value = (float)luaL_optint(l, acount, 0); + + if(acount==5) //Draw rect + { + if(x1 > (XRES/CELL)) + x1 = (XRES/CELL); + if(y1 > (YRES/CELL)) + y1 = (YRES/CELL); + if(x1+width > (XRES/CELL)) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->bmap[ny][nx] = value; + } + } + else //Set point + { + if(x1 > (XRES/CELL)) + x1 = (XRES/CELL); + if(y1 > (YRES/CELL)) + y1 = (YRES/CELL); + luacon_sim->bmap[y1][x1] = value; + } + return 0; +} + +int luatpt_get_wallmap(lua_State* l) +{ + int nx, ny, acount; + int x1, y1, width, height; + float value; + acount = lua_gettop(l); + + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + + if(x1 > (XRES/CELL) || y1 > (YRES/CELL)) + return luaL_error(l, "Out of range"); + + lua_pushinteger(l, luacon_sim->bmap[y1][x1]); + return 1; +} + +int luatpt_set_elecmap(lua_State* l) +{ + int nx, ny, acount; + int x1, y1, width, height; + float value; + acount = lua_gettop(l); + + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + width = abs(luaL_optint(l, 3, XRES/CELL)); + height = abs(luaL_optint(l, 4, YRES/CELL)); + value = (float)luaL_optint(l, acount, 0); + + if(acount==5) //Draw rect + { + if(x1 > (XRES/CELL)) + x1 = (XRES/CELL); + if(y1 > (YRES/CELL)) + y1 = (YRES/CELL); + if(x1+width > (XRES/CELL)) + width = (XRES/CELL)-x1; + if(y1+height > (YRES/CELL)) + height = (YRES/CELL)-y1; + for (nx = x1; nx<x1+width; nx++) + for (ny = y1; ny<y1+height; ny++) + { + luacon_sim->emap[ny][nx] = value; + } + } + else //Set point + { + if(x1 > (XRES/CELL)) + x1 = (XRES/CELL); + if(y1 > (YRES/CELL)) + y1 = (YRES/CELL); + luacon_sim->emap[y1][x1] = value; + } + return 0; +} + +int luatpt_get_elecmap(lua_State* l) +{ + int nx, ny, acount; + int x1, y1, width, height; + float value; + acount = lua_gettop(l); + + x1 = abs(luaL_optint(l, 1, 0)); + y1 = abs(luaL_optint(l, 2, 0)); + + if(x1 > (XRES/CELL) || y1 > (YRES/CELL)) + return luaL_error(l, "Out of range"); + + lua_pushinteger(l, luacon_sim->emap[y1][x1]); + return 1; +} + +int luatpt_get_property(lua_State* l) +{ + int i, r, y; + char *prop; + prop = (char*)luaL_optstring(l, 1, ""); + i = luaL_optint(l, 2, 0); + y = luaL_optint(l, 3, -1); + if(y!=-1 && y < YRES && y >= 0 && i < XRES && i >= 0){ + r = luacon_sim->pmap[y][i]; + if (!r) + r = luacon_sim->photons[y][i]; + if (!r) + { + if (strcmp(prop,"type")==0){ + lua_pushinteger(l, 0); + return 1; + } + return luaL_error(l, "Particle does not exist"); + } + i = r>>8; + } + else if (y!=-1) + return luaL_error(l, "Coordinates out of range (%d,%d)", i, y); + if (i < 0 || i >= NPART) + return luaL_error(l, "Invalid particle ID '%d'", i); + if (luacon_sim->parts[i].type) + { + //TODO: Use particle_getproperty + if (strcmp(prop,"type")==0){ + lua_pushinteger(l, luacon_sim->parts[i].type); + return 1; + } + if (strcmp(prop,"life")==0){ + lua_pushinteger(l, luacon_sim->parts[i].life); + return 1; + } + if (strcmp(prop,"ctype")==0){ + lua_pushinteger(l, luacon_sim->parts[i].ctype); + return 1; + } + if (strcmp(prop,"temp")==0){ + lua_pushnumber(l, luacon_sim->parts[i].temp); + return 1; + } + if (strcmp(prop,"tmp")==0){ + lua_pushinteger(l, luacon_sim->parts[i].tmp); + return 1; + } + if (strcmp(prop,"tmp2")==0){ + lua_pushinteger(l, luacon_sim->parts[i].tmp2); + return 1; + } + if (strcmp(prop,"vy")==0){ + lua_pushnumber(l, (double)luacon_sim->parts[i].vy); + return 1; + } + if (strcmp(prop,"vx")==0){ + lua_pushnumber(l, (double)luacon_sim->parts[i].vx); + return 1; + } + if (strcmp(prop,"x")==0){ + lua_pushnumber(l, luacon_sim->parts[i].x); + return 1; + } + if (strcmp(prop,"y")==0){ + lua_pushnumber(l, luacon_sim->parts[i].y); + return 1; + } + if (strcmp(prop,"dcolour")==0){ + lua_pushinteger(l, luacon_sim->parts[i].dcolour); + return 1; + } + if (strcmp(prop,"dcolor")==0){ + lua_pushinteger(l, luacon_sim->parts[i].dcolour); + return 1; + } + if (strcmp(prop,"id")==0){ + lua_pushnumber(l, i); + return 1; + } + } + else if (strcmp(prop,"type")==0){ + lua_pushinteger(l, 0); + return 1; + } + return luaL_error(l, "Particle does not exist"); +} + +int luatpt_drawpixel(lua_State* l) +{ + int x, y, r, g, b, a; + x = luaL_optint(l, 1, 0); + y = luaL_optint(l, 2, 0); + r = luaL_optint(l, 3, 255); + g = luaL_optint(l, 4, 255); + b = luaL_optint(l, 5, 255); + a = luaL_optint(l, 6, 255); + + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y); + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->blendpixel(x, y, r, g, b, a); + return 0; +} + +int luatpt_drawrect(lua_State* l) +{ + int x, y, w, h, r, g, b, a; + x = luaL_optint(l, 1, 0); + y = luaL_optint(l, 2, 0); + w = luaL_optint(l, 3, 10)+1; + h = luaL_optint(l, 4, 10)+1; + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y); + if(x+w > XRES+BARSIZE) + w = XRES+BARSIZE-x; + if(y+h > YRES+MENUSIZE) + h = YRES+MENUSIZE-y; + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->drawrect(x, y, w, h, r, g, b, a); + return 0; +} + +int luatpt_fillrect(lua_State* l) +{ + int x,y,w,h,r,g,b,a; + x = luaL_optint(l, 1, 0)+1; + y = luaL_optint(l, 2, 0)+1; + w = luaL_optint(l, 3, 10)+1; + h = luaL_optint(l, 4, 10)+1; + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) + return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y); + if(x+w > XRES+BARSIZE) + w = XRES+BARSIZE-x; + if(y+h > YRES+MENUSIZE) + h = YRES+MENUSIZE-y; + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->fillrect(x, y, w, h, r, g, b, a); + return 0; +} + +int luatpt_drawline(lua_State* l) +{ + int x1,y1,x2,y2,r,g,b,a; + x1 = luaL_optint(l, 1, 0); + y1 = luaL_optint(l, 2, 0); + x2 = luaL_optint(l, 3, 10); + y2 = luaL_optint(l, 4, 10); + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + //Don't need to check coordinates, as they are checked in blendpixel + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->draw_line(x1, y1, x2, y2, r, g, b, a); + return 0; +} + +int luatpt_textwidth(lua_State* l) +{ + char * string; + int strwidth = 0; + string = (char*)luaL_optstring(l, 1, ""); + strwidth = Graphics::textwidth(string); + lua_pushinteger(l, strwidth); + return 1; +} + +int luatpt_get_name(lua_State* l) +{ + if (luacon_model->GetUser().ID){ + lua_pushstring(l, luacon_model->GetUser().Username.c_str()); + return 1; + } + lua_pushstring(l, ""); + return 1; +} + +int luatpt_set_shortcuts(lua_State* l) +{ + return luaL_error(l, "set_shortcuts: deprecated"); +} + +int luatpt_delete(lua_State* l) +{ + int arg1, arg2; + arg1 = abs(luaL_optint(l, 1, 0)); + arg2 = luaL_optint(l, 2, -1); + if(arg2 == -1 && arg1 < NPART){ + luacon_sim->kill_part(arg1); + return 0; + } + arg2 = abs(arg2); + if(arg2 < YRES && arg1 < XRES){ + luacon_sim->delete_part(arg1, arg2, 0); + return 0; + } + return luaL_error(l,"Invalid coordinates or particle ID"); +} + +int luatpt_register_step(lua_State* l) +{ + int ref, i, ifree = -1; + if(lua_isfunction(l, 1)){ + for(i = 0; i<6; i++){ + if(!step_functions[i]){ + if (ifree<0) ifree = i; + } else { + lua_rawgeti(l, LUA_REGISTRYINDEX, step_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + lua_pop(l, 1); + return luaL_error(l, "Function already registered"); + } + lua_pop(l, 1); + } + } + if (ifree>=0) + { + ref = luaL_ref(l, LUA_REGISTRYINDEX); + step_functions[ifree] = ref; + return 0; + } + else return luaL_error(l, "Step function limit reached"); + } + return 0; +} +int luatpt_unregister_step(lua_State* l) +{ + int i; + if(lua_isfunction(l, 1)){ + for(i = 0; i<6; i++){ + if (step_functions[i]){ + lua_rawgeti(l, LUA_REGISTRYINDEX, step_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + lua_pop(l, 1); + luaL_unref(l, LUA_REGISTRYINDEX, step_functions[i]); + step_functions[i] = 0; + } + else lua_pop(l, 1); + } + } + } + return 0; +} +int luatpt_register_keypress(lua_State* l) +{ + int *newfunctions, i; + if(lua_isfunction(l, 1)){ + for(i = 0; i<keypress_function_count; i++){ + lua_rawgeti(l, LUA_REGISTRYINDEX, keypress_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + lua_pop(l, 1); + return luaL_error(l, "Function already registered"); + } + lua_pop(l, 1); + } + newfunctions = (int*)calloc(keypress_function_count+1, sizeof(int)); + if(keypress_functions){ + memcpy(newfunctions, keypress_functions, keypress_function_count*sizeof(int)); + free(keypress_functions); + } + newfunctions[keypress_function_count] = luaL_ref(l, LUA_REGISTRYINDEX); + keypress_function_count++; + keypress_functions = newfunctions; + } + return 0; +} +int luatpt_unregister_keypress(lua_State* l) +{ + int *newfunctions, i, functionindex = -1; + if(lua_isfunction(l, 1)){ + for(i = 0; i<keypress_function_count; i++){ + lua_rawgeti(l, LUA_REGISTRYINDEX, keypress_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + functionindex = i; + } + lua_pop(l, 1); + } + } + if(functionindex != -1){ + luaL_unref(l, LUA_REGISTRYINDEX, keypress_functions[functionindex]); + if(functionindex != keypress_function_count-1){ + memmove(keypress_functions+functionindex+1, keypress_functions+functionindex+1, (keypress_function_count-functionindex-1)*sizeof(int)); + } + if(keypress_function_count-1 > 0){ + newfunctions = (int*)calloc(keypress_function_count-1, sizeof(int)); + memcpy(newfunctions, keypress_functions, (keypress_function_count-1)*sizeof(int)); + free(keypress_functions); + keypress_functions = newfunctions; + } else { + free(keypress_functions); + keypress_functions = NULL; + } + keypress_function_count--; + } else { + return luaL_error(l, "Function not registered"); + } + return 0; +} +int luatpt_register_mouseclick(lua_State* l) +{ + int *newfunctions, i; + if(lua_isfunction(l, 1)){ + for(i = 0; i<mouseclick_function_count; i++){ + lua_rawgeti(l, LUA_REGISTRYINDEX, mouseclick_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + lua_pop(l, 1); + return luaL_error(l, "Function already registered"); + } + lua_pop(l, 1); + } + newfunctions = (int*)calloc(mouseclick_function_count+1, sizeof(int)); + if(mouseclick_functions){ + memcpy(newfunctions, mouseclick_functions, mouseclick_function_count*sizeof(int)); + free(mouseclick_functions); + } + newfunctions[mouseclick_function_count] = luaL_ref(l, LUA_REGISTRYINDEX); + mouseclick_function_count++; + mouseclick_functions = newfunctions; + } + return 0; +} +int luatpt_unregister_mouseclick(lua_State* l) +{ + int *newfunctions, i, functionindex = -1; + if(lua_isfunction(l, 1)){ + for(i = 0; i<mouseclick_function_count; i++){ + lua_rawgeti(l, LUA_REGISTRYINDEX, mouseclick_functions[i]); + if(lua_equal(l, 1, lua_gettop(l))){ + functionindex = i; + } + lua_pop(l, 1); + } + } + if(functionindex != -1){ + luaL_unref(l, LUA_REGISTRYINDEX, mouseclick_functions[functionindex]); + if(functionindex != mouseclick_function_count-1){ + memmove(mouseclick_functions+functionindex+1, mouseclick_functions+functionindex+1, (mouseclick_function_count-functionindex-1)*sizeof(int)); + } + if(mouseclick_function_count-1 > 0){ + newfunctions = (int*)calloc(mouseclick_function_count-1, sizeof(int)); + memcpy(newfunctions, mouseclick_functions, (mouseclick_function_count-1)*sizeof(int)); + free(mouseclick_functions); + mouseclick_functions = newfunctions; + } else { + free(mouseclick_functions); + mouseclick_functions = NULL; + } + mouseclick_function_count--; + } else { + return luaL_error(l, "Function not registered"); + } + return 0; +} +int luatpt_input(lua_State* l) +{ + std::string prompt, title, result, shadow, text; + title = std::string(luaL_optstring(l, 1, "Title")); + prompt = std::string(luaL_optstring(l, 2, "Enter some text:")); + text = std::string(luaL_optstring(l, 3, "")); + shadow = std::string(luaL_optstring(l, 4, "")); + + result = TextPrompt::Blocking(title, prompt, text, shadow, false); + + lua_pushstring(l, result.c_str()); + return 1; +} +int luatpt_message_box(lua_State* l) +{ + std::string title = std::string(luaL_optstring(l, 1, "Title")); + std::string message = std::string(luaL_optstring(l, 2, "Message")); + new InformationMessage(title, message); + return 0; +} +int luatpt_get_numOfParts(lua_State* l) +{ + lua_pushinteger(l, luacon_sim->parts_lastActiveIndex); + return 1; +} +int luatpt_start_getPartIndex(lua_State* l) +{ + getPartIndex_curIdx = -1; + return 1; +} +int luatpt_next_getPartIndex(lua_State* l) +{ + while(1) + { + getPartIndex_curIdx++; + if(getPartIndex_curIdx >= NPART) + { + getPartIndex_curIdx = 0; + lua_pushboolean(l, 0); + return 1; + } + if(luacon_sim->parts[getPartIndex_curIdx].type) + break; + + } + + lua_pushboolean(l, 1); + return 1; +} +int luatpt_getPartIndex(lua_State* l) +{ + if(getPartIndex_curIdx < 0) + { + lua_pushinteger(l, 0); + return 1; + } + lua_pushinteger(l, getPartIndex_curIdx); + return 1; +} +int luatpt_hud(lua_State* l) +{ + /*int hudstate; + hudstate = luaL_optint(l, 1, 0); + hud_enable = (hudstate==0?0:1); + return 0;*/ + //TODO IMPLEMENT + return 0; +} +int luatpt_gravity(lua_State* l) +{ + int gravstate; + gravstate = luaL_optint(l, 1, 0); + if(gravstate) + luacon_sim->grav->start_grav_async(); + else + luacon_sim->grav->stop_grav_async(); + return 0; +} +int luatpt_airheat(lua_State* l) +{ + int aheatstate; + aheatstate = luaL_optint(l, 1, 0); + luacon_sim->aheat_enable = (aheatstate==0?0:1); + return 0; +} +int luatpt_active_menu(lua_State* l) +{ + int menuid; + menuid = luaL_optint(l, 1, -1); + if (menuid < SC_TOTAL && menuid >= 0) + luacon_model->SetActiveMenu(luacon_model->GetMenuList()[menuid]); + else + return luaL_error(l, "Invalid menu"); + return 0; +} +int luatpt_decorations_enable(lua_State* l) +{ + int decostate; + decostate = luaL_optint(l, 1, 0); + luacon_model->SetDecoration(decostate==0?false:true); + return 0; +} + +int luatpt_heat(lua_State* l) +{ + int heatstate; + heatstate = luaL_optint(l, 1, 0); + luacon_sim->legacy_enable = (heatstate==1?0:1); + return 0; +} +int luatpt_cmode_set(lua_State* l) +{ + //TODO IMPLEMENT + return luaL_error(l, "cmode_set: Deprecated"); +} +int luatpt_setfire(lua_State* l) +{ + int firesize = luaL_optint(l, 2, 4); + float fireintensity = (float)luaL_optnumber(l, 1, 1.0f); + luacon_model->GetRenderer()->prepare_alpha(firesize, fireintensity); + return 0; +} +int luatpt_setdebug(lua_State* l) +{ + return luaL_error(l, "setdebug: Deprecated"); +} +int luatpt_setfpscap(lua_State* l) +{ + int fpscap = luaL_optint(l, 1, 0); + if (fpscap < 2) + return luaL_error(l, "fps cap too small"); + ui::Engine::Ref().FpsLimit = fpscap; + return 0; +} +int luatpt_getscript(lua_State* l) +{ + char *filedata = NULL, *fileuri = NULL, *filename = NULL, *lastError = NULL, *luacommand = NULL; + std::string fileauthor = "", fileid = ""; + int len, ret,run_script; + FILE * outputfile; + + fileauthor = std::string(luaL_optstring(l, 1, "")); + fileid = std::string(luaL_optstring(l, 2, "")); + run_script = luaL_optint(l, 3, 0); + if(!fileauthor.length() || !fileid.length()) + goto fin; + if(!ConfirmPrompt::Blocking("Do you want to install script?", fileid, "Install")) + goto fin; + + fileuri = new char[strlen(SCRIPTSERVER)+fileauthor.length()+fileid.length()+44]; + sprintf(fileuri, "http://" SCRIPTSERVER "/GetScript.api?Author=%s&Filename=%s", fileauthor.c_str(), fileid.c_str()); + + //filedata = http_auth_get(fileuri, svf_user_id, NULL, svf_session_id, &ret, &len); + filedata = http_auth_get(fileuri, NULL, NULL, NULL, &ret, &len); + + if(len <= 0 || !filedata) + { + lastError = "Server did not return data."; + goto fin; + } + if(ret != 200) + { + lastError = http_ret_text(ret); + goto fin; + } + + filename = new char[fileauthor.length()+fileid.length()+strlen(PATH_SEP)+strlen(LOCAL_LUA_DIR)+6]; + sprintf(filename, LOCAL_LUA_DIR PATH_SEP "%s_%s.lua", fileauthor.c_str(), fileid.c_str()); + + Client::Ref().MakeDirectory(LOCAL_LUA_DIR); + + outputfile = fopen(filename, "r"); + if(outputfile) + { + fclose(outputfile); + outputfile = NULL; + if(ConfirmPrompt::Blocking("File already exists, overwrite?", filename, "Overwrite")) + { + outputfile = fopen(filename, "w"); + } + else + { + goto fin; + } + } + else + { + outputfile = fopen(filename, "w"); + } + + if(!outputfile) + { + lastError = "Unable to write to file"; + goto fin; + } + + + fputs(filedata, outputfile); + fclose(outputfile); + outputfile = NULL; + if(run_script) + { + luacommand = new char[strlen(filename)+20]; + sprintf(luacommand,"dofile(\"%s\")",filename); + luaL_dostring (l, luacommand); + } + +fin: + if(filedata) free(filedata); + if(fileuri) delete[] fileuri; + if(filename) delete[] filename; + if(luacommand) delete[] luacommand; + luacommand = NULL; + + if(lastError) return luaL_error(l, lastError); + return 0; +} + +int luatpt_setwindowsize(lua_State* l) +{ + int scale = luaL_optint(l,1,1), kiosk = luaL_optint(l,2,0); + if (scale!=2) scale = 1; + if (kiosk!=1) kiosk = 0; + ui::Engine::Ref().SetScale(scale); + ui::Engine::Ref().SetFullscreen(kiosk); + return 0; +} + +int screenshotIndex = 0; + +int luatpt_screenshot(lua_State* l) +{ + //TODO Implement + int captureUI = luaL_optint(l, 1, 0); + std::vector<char> data; + if(captureUI) + { + VideoBuffer screenshot(ui::Engine::Ref().g->DumpFrame()); + data = format::VideoBufferToPNG(screenshot); + } + else + { + VideoBuffer screenshot(luacon_ren->DumpFrame()); + data = format::VideoBufferToPNG(screenshot); + } + std::stringstream filename; + filename << "screenshot_"; + filename << std::setfill('0') << std::setw(6) << (screenshotIndex++); + filename << ".png"; + Client::Ref().WriteFile(data, filename.str()); + return 0; +} + diff --git a/src/cat/LuaBit.cpp b/src/cat/LuaBit.cpp new file mode 100644 index 0000000..c55f45a --- /dev/null +++ b/src/cat/LuaBit.cpp @@ -0,0 +1,192 @@ +/* +** Lua BitOp -- a bit operations library for Lua 5.1/5.2. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2012 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#define LUA_BITOP_VERSION "1.0.2" + +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#ifdef _MSC_VER +/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include <stdint.h> +#endif + +typedef int32_t SBits; +typedef uint32_t UBits; + +typedef union { + lua_Number n; +#ifdef LUA_NUMBER_DOUBLE + uint64_t b; +#else + UBits b; +#endif +} BitNum; + +/* Convert argument to bit type. */ +static UBits barg(lua_State *L, int idx) +{ + BitNum bn; + UBits b; +#if LUA_VERSION_NUM < 502 + bn.n = lua_tonumber(L, idx); +#else + bn.n = luaL_checknumber(L, idx); +#endif +#if defined(LUA_NUMBER_DOUBLE) + bn.n += 6755399441055744.0; /* 2^52+2^51 */ +#ifdef SWAPPED_DOUBLE + b = (UBits)(bn.b >> 32); +#else + b = (UBits)bn.b; +#endif +#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ + defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ + defined(LUA_NUMBER_LLONG) + if (sizeof(UBits) == sizeof(lua_Number)) + b = bn.b; + else + b = (UBits)(SBits)bn.n; +#elif defined(LUA_NUMBER_FLOAT) +#error "A 'float' lua_Number type is incompatible with this library" +#else +#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" +#endif +#if LUA_VERSION_NUM < 502 + if (b == 0 && !lua_isnumber(L, idx)) { + luaL_typerror(L, idx, "number"); + } +#endif + return b; +} + +/* Return bit type. */ +#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; + +static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } +static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } + +#define BIT_OP(func, opr) \ + static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ + for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } +BIT_OP(bit_band, &=) +BIT_OP(bit_bor, |=) +BIT_OP(bit_bxor, ^=) + +#define bshl(b, n) (b << n) +#define bshr(b, n) (b >> n) +#define bsar(b, n) ((SBits)b >> n) +#define brol(b, n) ((b << n) | (b >> (32-n))) +#define bror(b, n) ((b << (32-n)) | (b >> n)) +#define BIT_SH(func, fn) \ + static int func(lua_State *L) { \ + UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } +BIT_SH(bit_lshift, bshl) +BIT_SH(bit_rshift, bshr) +BIT_SH(bit_arshift, bsar) +BIT_SH(bit_rol, brol) +BIT_SH(bit_ror, bror) + +static int bit_bswap(lua_State *L) +{ + UBits b = barg(L, 1); + b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); + BRET(b) +} + +static int bit_tohex(lua_State *L) +{ + UBits b = barg(L, 1); + SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); + const char *hexdigits = "0123456789abcdef"; + char buf[8]; + int i; + if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } + if (n > 8) n = 8; + for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } + lua_pushlstring(L, buf, (size_t)n); + return 1; +} + +static const struct luaL_Reg bit_funcs[] = { + { "tobit", bit_tobit }, + { "bnot", bit_bnot }, + { "band", bit_band }, + { "bor", bit_bor }, + { "bxor", bit_bxor }, + { "lshift", bit_lshift }, + { "rshift", bit_rshift }, + { "arshift", bit_arshift }, + { "rol", bit_rol }, + { "ror", bit_ror }, + { "bswap", bit_bswap }, + { "tohex", bit_tohex }, + { NULL, NULL } +}; + +/* Signed right-shifts are implementation-defined per C89/C99. +** But the de facto standard are arithmetic right-shifts on two's +** complement CPUs. This behaviour is required here, so test for it. +*/ +#define BAD_SAR (bsar(-8, 2) != (SBits)-2) + +int luaopen_bit(lua_State *L) +{ + UBits b; + lua_pushnumber(L, (lua_Number)1437217655L); + b = barg(L, -1); + if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ + const char *msg = "compiled with incompatible luaconf.h"; +#ifdef LUA_NUMBER_DOUBLE +#ifdef _WIN32 + if (b == (UBits)1610612736L) + msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; +#endif + if (b == (UBits)1127743488L) + msg = "not compiled with SWAPPED_DOUBLE"; +#endif + if (BAD_SAR) + msg = "arithmetic right-shift broken"; + luaL_error(L, "bit library self-test failed (%s)", msg); + } +#if LUA_VERSION_NUM < 502 + luaL_register(L, "bit", bit_funcs); +#else + luaL_newlib(L, bit_funcs); +#endif + return 1; +} + diff --git a/src/cat/LuaBit.h b/src/cat/LuaBit.h new file mode 100644 index 0000000..6d9c068 --- /dev/null +++ b/src/cat/LuaBit.h @@ -0,0 +1,32 @@ +/* +** Lua BitOp -- a bit operations library for Lua 5.1/5.2. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2012 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#define LUA_BITOP_VERSION "1.0.2" + +int luaopen_bit(lua_State *L); + diff --git a/src/cat/LuaButton.cpp b/src/cat/LuaButton.cpp new file mode 100644 index 0000000..01ca875 --- /dev/null +++ b/src/cat/LuaButton.cpp @@ -0,0 +1,114 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaButton.h" +#include "LuaScriptInterface.h" +#include "interface/Button.h" + +const char LuaButton::className[] = "Button"; + +#define method(class, name) {#name, &class::name} +Luna<LuaButton>::RegType LuaButton::methods[] = { + method(LuaButton, action), + method(LuaButton, text), + method(LuaButton, position), + method(LuaButton, size), + method(LuaButton, visible), + method(LuaButton, enabled), + {0, 0} +}; + +LuaButton::LuaButton(lua_State * l) : + LuaComponent(l), + actionFunction(0) +{ + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + std::string text = luaL_optstring(l, 5, ""); + std::string toolTip = luaL_optstring(l, 6, ""); + + button = new ui::Button(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, toolTip); + component = button; + class ClickAction : public ui::ButtonAction + { + LuaButton * luaButton; + public: + ClickAction(LuaButton * luaButton) : luaButton(luaButton) {} + void ActionCallback(ui::Button * sender) + { + luaButton->triggerAction(); + } + }; + button->SetActionCallback(new ClickAction(this)); +} + +int LuaButton::enabled(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TBOOLEAN); + button->Enabled = lua_toboolean(l, 1); + return 0; + } + else + { + lua_pushboolean(l, button->Enabled); + return 1; + } +} + +int LuaButton::action(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + actionFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + actionFunction = 0; + } + return 0; +} + +int LuaButton::text(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TSTRING); + button->SetText(lua_tostring(l, 1)); + return 0; + } + else + { + lua_pushstring(l, button->GetText().c_str()); + return 1; + } +} + +void LuaButton::triggerAction() +{ + if(actionFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, actionFunction); + lua_rawgeti(l, LUA_REGISTRYINDEX, UserData); + if (lua_pcall(l, 1, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +LuaButton::~LuaButton() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaButton.h b/src/cat/LuaButton.h new file mode 100644 index 0000000..012779d --- /dev/null +++ b/src/cat/LuaButton.h @@ -0,0 +1,33 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class Button; +} + +class LuaScriptInterface; + +class LuaButton: public LuaComponent +{ + ui::Button * button; + int actionFunction; + void triggerAction(); + int action(lua_State * l); + int text(lua_State * l); + int enabled(lua_State * l); +public: + static const char className[]; + static Luna<LuaButton>::RegType methods[]; + + LuaButton(lua_State * l); + ~LuaButton(); +};
\ No newline at end of file diff --git a/src/cat/LuaCheckbox.cpp b/src/cat/LuaCheckbox.cpp new file mode 100644 index 0000000..844573e --- /dev/null +++ b/src/cat/LuaCheckbox.cpp @@ -0,0 +1,114 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaCheckbox.h" +#include "LuaScriptInterface.h" +#include "interface/Checkbox.h" + +const char LuaCheckbox::className[] = "Checkbox"; + +#define method(class, name) {#name, &class::name} +Luna<LuaCheckbox>::RegType LuaCheckbox::methods[] = { + method(LuaCheckbox, action), + method(LuaCheckbox, text), + method(LuaCheckbox, position), + method(LuaCheckbox, size), + method(LuaCheckbox, visible), + method(LuaCheckbox, checked), + {0, 0} +}; + +LuaCheckbox::LuaCheckbox(lua_State * l) : + LuaComponent(l), + actionFunction(0) +{ + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + std::string text = luaL_optstring(l, 5, ""); + + checkbox = new ui::Checkbox(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, ""); + component = checkbox; + class ClickAction : public ui::CheckboxAction + { + LuaCheckbox * luaCheckbox; + public: + ClickAction(LuaCheckbox * luaCheckbox) : luaCheckbox(luaCheckbox) {} + void ActionCallback(ui::Checkbox * sender) + { + luaCheckbox->triggerAction(); + } + }; + checkbox->SetActionCallback(new ClickAction(this)); +} + +int LuaCheckbox::checked(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TBOOLEAN); + checkbox->SetChecked(lua_toboolean(l, 1)); + return 0; + } + else + { + lua_pushboolean(l, checkbox->GetChecked()); + return 1; + } +} + +int LuaCheckbox::action(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + actionFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + actionFunction = 0; + } + return 0; +} + +int LuaCheckbox::text(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TSTRING); + checkbox->SetText(lua_tostring(l, 1)); + return 0; + } + else + { + lua_pushstring(l, checkbox->GetText().c_str()); + return 1; + } +} + +void LuaCheckbox::triggerAction() +{ + if(actionFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, actionFunction); + lua_rawgeti(l, LUA_REGISTRYINDEX, UserData); + lua_pushboolean(l, checkbox->GetChecked()); + if (lua_pcall(l, 2, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +LuaCheckbox::~LuaCheckbox() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaCheckbox.h b/src/cat/LuaCheckbox.h new file mode 100644 index 0000000..479cab2 --- /dev/null +++ b/src/cat/LuaCheckbox.h @@ -0,0 +1,33 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class Checkbox; +} + +class LuaScriptInterface; + +class LuaCheckbox: public LuaComponent +{ + ui::Checkbox * checkbox; + int actionFunction; + void triggerAction(); + int action(lua_State * l); + int checked(lua_State * l); + int text(lua_State * l); +public: + static const char className[]; + static Luna<LuaCheckbox>::RegType methods[]; + + LuaCheckbox(lua_State * l); + ~LuaCheckbox(); +};
\ No newline at end of file diff --git a/src/cat/LuaComponent.cpp b/src/cat/LuaComponent.cpp new file mode 100644 index 0000000..8c2d3a4 --- /dev/null +++ b/src/cat/LuaComponent.cpp @@ -0,0 +1,82 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaComponent.h" +#include "LuaScriptInterface.h" +#include "interface/Component.h" + + +LuaComponent::LuaComponent(lua_State * l) +{ + this->l = l; + + lua_pushstring(l, "Luacon_ci"); + lua_gettable(l, LUA_REGISTRYINDEX); + ci = (LuaScriptInterface*)lua_touserdata(l, -1); + lua_pop(l, 1); +} + +int LuaComponent::position(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + luaL_checktype(l, 2, LUA_TNUMBER); + component->Position = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2)); + return 0; + } + else + { + lua_pushinteger(l, component->Position.X); + lua_pushinteger(l, component->Position.Y); + return 2; + } +} + +int LuaComponent::size(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + luaL_checktype(l, 2, LUA_TNUMBER); + component->Size = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2)); + component->Invalidate(); + return 0; + } + else + { + lua_pushinteger(l, component->Size.X); + lua_pushinteger(l, component->Size.Y); + return 2; + } +} + +int LuaComponent::visible(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TBOOLEAN); + component->Visible = lua_toboolean(l, 1); + return 0; + } + else + { + lua_pushboolean(l, component->Visible); + return 1; + } +} + +LuaComponent::~LuaComponent() +{ + if(component->GetParentWindow()) + component->GetParentWindow()->RemoveComponent(component); + delete component; +}
\ No newline at end of file diff --git a/src/cat/LuaComponent.h b/src/cat/LuaComponent.h new file mode 100644 index 0000000..9e11b12 --- /dev/null +++ b/src/cat/LuaComponent.h @@ -0,0 +1,33 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" + +namespace ui +{ + class Component; +} + +class LuaScriptInterface; + +class LuaComponent +{ +protected: + ui::Component * component; + lua_State * l; + int position(lua_State * l); + int size(lua_State * l); + int visible(lua_State * l); +public: + LuaScriptInterface * ci; + int UserData; + + ui::Component * GetComponent() { return component; } + LuaComponent(lua_State * l); + ~LuaComponent(); +};
\ No newline at end of file diff --git a/src/cat/LuaLabel.cpp b/src/cat/LuaLabel.cpp new file mode 100644 index 0000000..e2ca56d --- /dev/null +++ b/src/cat/LuaLabel.cpp @@ -0,0 +1,56 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaScriptInterface.h" +#include "LuaLabel.h" +#include "interface/Label.h" + +const char LuaLabel::className[] = "Label"; + +#define method(class, name) {#name, &class::name} +Luna<LuaLabel>::RegType LuaLabel::methods[] = { + method(LuaLabel, text), + method(LuaLabel, position), + method(LuaLabel, size), + method(LuaLabel, visible), + {0, 0} +}; + +LuaLabel::LuaLabel(lua_State * l) : + LuaComponent(l) +{ + this->l = l; + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + std::string text = luaL_optstring(l, 5, ""); + + label = new ui::Label(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text); + component = label; +} + +int LuaLabel::text(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TSTRING); + label->SetText(lua_tostring(l, 1)); + return 0; + } + else + { + lua_pushstring(l, label->GetText().c_str()); + return 1; + } +} + +LuaLabel::~LuaLabel() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaLabel.h b/src/cat/LuaLabel.h new file mode 100644 index 0000000..a80ea4f --- /dev/null +++ b/src/cat/LuaLabel.h @@ -0,0 +1,29 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class Label; +} + +class LuaScriptInterface; + +class LuaLabel: public LuaComponent +{ + ui::Label * label; + int text(lua_State * l); +public: + static const char className[]; + static Luna<LuaLabel>::RegType methods[]; + + LuaLabel(lua_State * l); + ~LuaLabel(); +};
\ No newline at end of file diff --git a/src/cat/LuaLuna.h b/src/cat/LuaLuna.h new file mode 100644 index 0000000..1d5d937 --- /dev/null +++ b/src/cat/LuaLuna.h @@ -0,0 +1,160 @@ +#pragma once +//http://lua-users.org/wiki/SimplerCppBinding + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +} + +template <typename T> class Luna +{ + typedef struct { T *pT; } userdataType; +public: + typedef int (T::*mfp)(lua_State *L); + typedef struct { const char *name; mfp mfunc; } RegType; + + static void Register(lua_State *L) + { + lua_newtable(L); + int methods = lua_gettop(L); + + luaL_newmetatable(L, T::className); + int metatable = lua_gettop(L); + + // store method table in globals so that + // scripts can add functions written in Lua. + lua_pushstring(L, T::className); + lua_pushvalue(L, methods); + lua_settable(L, LUA_GLOBALSINDEX); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methods); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methods); + lua_settable(L, metatable); + + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, tostring_T); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_T); + lua_settable(L, metatable); + + lua_newtable(L); // mt for method table + int mt = lua_gettop(L); + lua_pushliteral(L, "__call"); + lua_pushcfunction(L, new_T); + lua_pushliteral(L, "new"); + lua_pushvalue(L, -2); // dup new_T function + lua_settable(L, methods); // add new_T to method table + lua_settable(L, mt); // mt.__call = new_T + lua_setmetatable(L, methods); + + // fill method table with methods from class T + for (RegType *l = T::methods; l->name; l++) + { + /* edited by Snaily: shouldn't it be const RegType *l ... ? */ + lua_pushstring(L, l->name); + lua_pushlightuserdata(L, (void*)l); + lua_pushcclosure(L, thunk, 1); + lua_settable(L, methods); + } + + lua_pop(L, 2); // drop metatable and method table + } + + // get userdata from Lua stack and return pointer to T object + static T * check(lua_State * L, int narg) + { + userdataType *ud = static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); + if(!ud) + luaL_typerror(L, narg, T::className); + return ud->pT; // pointer to T object + } + + static void * tryGet(lua_State * L, int narg) + { + if(checkType(L, narg, T::className)) + { + userdataType *ud = static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); + if(!ud) + luaL_typerror(L, narg, T::className); + return ud; // pointer to T object + } + else + { + return NULL; + } + } + + static bool checkType (lua_State * L, int idx, const char *name) + { + // returns true if a userdata is of a certain type + int res; + if (lua_type(L, idx) != LUA_TUSERDATA) return false; + lua_getmetatable(L, idx); + luaL_newmetatable (L, name); + res = lua_equal(L, -2, -1); + lua_pop(L, 2); // pop both tables (metatables) off + return res; + } + + static inline T * get(void * userData) + { + return ((userdataType*)userData)->pT; + } + +private: + Luna(); // hide default constructor + + // member function dispatcher + static int thunk(lua_State * L) + { + // stack has userdata, followed by method args + T *obj = check(L, 1); // get 'self', or if you prefer, 'this' + lua_remove(L, 1); // remove self so member function args start at index 1 + // get member function from upvalue + RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1))); + return (obj->*(l->mfunc))(L); // call member function + } + + // create a new T object and + // push onto the Lua stack a userdata containing a pointer to T object + static int new_T(lua_State * L) + { + lua_remove(L, 1); // use classname:new(), instead of classname.new() + + T *obj = new T(L); // call constructor for T objects + userdataType *ud = static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType))); + ud->pT = obj; // store pointer to object in userdata + + obj->UserData = luaL_ref(L, LUA_REGISTRYINDEX); + lua_rawgeti(L, LUA_REGISTRYINDEX, obj->UserData); + + luaL_getmetatable(L, T::className); // lookup metatable in Lua registry + lua_setmetatable(L, -2); + return 1; // userdata containing pointer to T object + } + + // garbage collection metamethod + static int gc_T(lua_State *L) + { + userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1)); + T *obj = ud->pT; + delete obj; // call destructor for T objects + return 0; + } + + static int tostring_T (lua_State * L) + { + char buff[32]; + userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1)); + T *obj = ud->pT; + sprintf(buff, "%p", obj); + lua_pushfstring(L, "%s (%s)", T::className, buff); + return 1; + } +};
\ No newline at end of file diff --git a/src/cat/LuaProgressBar.cpp b/src/cat/LuaProgressBar.cpp new file mode 100644 index 0000000..71b8f7b --- /dev/null +++ b/src/cat/LuaProgressBar.cpp @@ -0,0 +1,71 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaProgressBar.h" +#include "LuaScriptInterface.h" +#include "interface/ProgressBar.h" + +const char LuaProgressBar::className[] = "ProgressBar"; + +#define method(class, name) {#name, &class::name} +Luna<LuaProgressBar>::RegType LuaProgressBar::methods[] = { + method(LuaProgressBar, position), + method(LuaProgressBar, size), + method(LuaProgressBar, visible), + method(LuaProgressBar, progress), + method(LuaProgressBar, status), + {0, 0} +}; + +LuaProgressBar::LuaProgressBar(lua_State * l) : + LuaComponent(l) +{ + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + int value = luaL_optinteger(l, 5, 0); + std::string status = luaL_optstring(l, 6, ""); + + progressBar = new ui::ProgressBar(ui::Point(posX, posY), ui::Point(sizeX, sizeY), value, status); + component = progressBar; +} + +int LuaProgressBar::progress(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + progressBar->SetProgress(lua_tointeger(l, 1)); + return 0; + } + else + { + lua_pushinteger(l, progressBar->GetProgress()); + return 1; + } +} + +int LuaProgressBar::status(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + progressBar->SetStatus(std::string(lua_tostring(l, 1))); + return 0; + } + else + { + lua_pushstring(l, progressBar->GetStatus().c_str()); + return 1; + } +} + +LuaProgressBar::~LuaProgressBar() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaProgressBar.h b/src/cat/LuaProgressBar.h new file mode 100644 index 0000000..9de56e7 --- /dev/null +++ b/src/cat/LuaProgressBar.h @@ -0,0 +1,30 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class ProgressBar; +} + +class LuaScriptInterface; + +class LuaProgressBar: public LuaComponent +{ + ui::ProgressBar * progressBar; + int progress(lua_State * l); + int status(lua_State * l); +public: + static const char className[]; + static Luna<LuaProgressBar>::RegType methods[]; + + LuaProgressBar(lua_State * l); + ~LuaProgressBar(); +};
\ No newline at end of file diff --git a/src/cat/LuaScriptHelper.h b/src/cat/LuaScriptHelper.h new file mode 100644 index 0000000..37920b5 --- /dev/null +++ b/src/cat/LuaScriptHelper.h @@ -0,0 +1,144 @@ +/* + * LuaScriptHelper.h + * + * Created on: Feb 12, 2012 + * Author: Simon + */ + +#ifndef LUASCRIPTHELPER_H_ +#define LUASCRIPTHELPER_H_ + +extern GameModel * luacon_model; +extern Simulation * luacon_sim; +extern LuaScriptInterface * luacon_ci; +extern Graphics * luacon_g; +extern Renderer * luacon_ren; + +extern bool *luacon_currentCommand; +extern std::string *luacon_lastError; + +extern int *lua_el_func, *lua_el_mode, *lua_gr_func; + +extern int getPartIndex_curIdx; +extern int step_functions[6];//[6] = {0, 0, 0, 0, 0, 0}; +extern int keypress_function_count;// = 0; +extern int *keypress_functions;// = NULL; +extern int mouseclick_function_count;// = 0; +extern int *mouseclick_functions;// = NULL; +extern int tptProperties; //Table for some TPT properties +extern int tptPropertiesVersion; +extern int tptElements; //Table for TPT element names +extern int tptParts, tptPartsMeta, tptElementTransitions, tptPartsCData, tptPartMeta, tptPart, cIndex; + +void luacon_hook(lua_State *L, lua_Debug *ar); +int luacon_step(int mx, int my, int selectl, int selectr, int bsx, int bsy); +int luacon_mouseevent(int mx, int my, int mb, int event, int mouse_wheel); +int luacon_keyevent(int key, int modifier, int event); +int luacon_eval(char *command); +int luacon_part_update(int t, int i, int x, int y, int surround_space, int nt); +char *luacon_geterror(); +void luacon_close(); +int luacon_partsread(lua_State* l); +int luacon_partswrite(lua_State* l); +int luacon_partread(lua_State* l); +int luacon_partwrite(lua_State* l); +int luacon_elementread(lua_State* l); +int luacon_elementwrite(lua_State* l); +int luacon_transitionread(lua_State* l); +int luacon_transitionwrite(lua_State* l); +int luacon_particle_getproperty(char * key, int * format); +int luacon_transition_getproperty(char * key, int * format); +int luacon_element_getproperty(char * key, int * format, unsigned int * modified_stuff); +//int process_command_lua(pixel *vid_buf, char *console, char *console_error); + +//Interface +int luatpt_test(lua_State* l); +int luatpt_getelement(lua_State *l); + +int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS); +int luatpt_graphics_func(lua_State *l); + +int luacon_elementReplacement(UPDATE_FUNC_ARGS); +int luatpt_element_func(lua_State *l); + +int luatpt_error(lua_State* l); +int luatpt_drawtext(lua_State* l); + +int luatpt_create(lua_State* l); + +int luatpt_setpause(lua_State* l); + +int luatpt_togglepause(lua_State* l); + +int luatpt_togglewater(lua_State* l); + +int luatpt_setconsole(lua_State* l); +int luatpt_log(lua_State* l); + +int luatpt_set_pressure(lua_State* l); + +int luatpt_set_gravity(lua_State* l); +int luatpt_reset_gravity_field(lua_State* l); + +int luatpt_reset_velocity(lua_State* l); + +int luatpt_reset_spark(lua_State* l); + +int luatpt_set_property(lua_State* l); + +int luatpt_get_property(lua_State* l); + +int luatpt_set_wallmap(lua_State* l); + +int luatpt_get_wallmap(lua_State* l); + +int luatpt_set_elecmap(lua_State* l); + +int luatpt_get_elecmap(lua_State* l); + +int luatpt_drawpixel(lua_State* l); + +int luatpt_drawrect(lua_State* l); + +int luatpt_fillrect(lua_State* l); + +int luatpt_drawline(lua_State* l); + +int luatpt_textwidth(lua_State* l); +int luatpt_get_name(lua_State* l); + +int luatpt_set_shortcuts(lua_State* l); + +int luatpt_delete(lua_State* l); +int luatpt_register_step(lua_State* l); +int luatpt_unregister_step(lua_State* l); +int luatpt_register_keypress(lua_State* l); +int luatpt_unregister_keypress(lua_State* l); +int luatpt_register_mouseclick(lua_State* l); +int luatpt_unregister_mouseclick(lua_State* l); +int luatpt_input(lua_State* l); +int luatpt_message_box(lua_State* l); +int luatpt_get_numOfParts(lua_State* l); +int luatpt_start_getPartIndex(lua_State* l); +int luatpt_next_getPartIndex(lua_State* l); +int luatpt_getPartIndex(lua_State* l); +int luatpt_hud(lua_State* l); +int luatpt_gravity(lua_State* l); +int luatpt_airheat(lua_State* l); +int luatpt_active_menu(lua_State* l); +int luatpt_decorations_enable(lua_State* l); + +int luatpt_heat(lua_State* l); +int luatpt_cmode_set(lua_State* l); +int luatpt_setfire(lua_State* l); +int luatpt_setdebug(lua_State* l); + +int luatpt_setfpscap(lua_State* l); + +int luatpt_getscript(lua_State* l); + +int luatpt_setwindowsize(lua_State* l); + +int luatpt_screenshot(lua_State* l); + +#endif /* LUASCRIPTHELPER_H_ */ diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp new file mode 100644 index 0000000..7faf943 --- /dev/null +++ b/src/cat/LuaScriptInterface.cpp @@ -0,0 +1,1706 @@ +/* + * LuaScriptInterface.cpp + * + * Created on: Feb 11, 2012 + * Author: Simon + */ + +#include <string> +#include <iomanip> +#include <vector> +#include <algorithm> +#include <locale> +#include <fstream> +#include "Config.h" +#include "Format.h" +#include "LuaLuna.h" +#include "LuaScriptInterface.h" +#include "TPTScriptInterface.h" +#include "dialogues/ErrorMessage.h" +#include "dialogues/InformationMessage.h" +#include "dialogues/TextPrompt.h" +#include "dialogues/ConfirmPrompt.h" +#include "simulation/Simulation.h" +#include "game/GameModel.h" +#include "LuaScriptHelper.h" +#include "client/HTTP.h" + +//#include "virtualmachine/VirtualMachine.h" +#include "pim/Parser.h" +#include "pim/Machine.h" + +#include "LuaBit.h" + +#include "LuaWindow.h" +#include "LuaButton.h" +#include "LuaLabel.h" +#include "LuaTextbox.h" +#include "LuaCheckbox.h" +#include "LuaSlider.h" +#include "LuaProgressBar.h" + +#ifdef __unix__ +#include <unistd.h> +#endif + +extern "C" +{ +#ifdef WIN +#include <direct.h> +#endif +#include <sys/stat.h> +#include <dirent.h> +#include <time.h> +} + +GameModel * luacon_model; +Simulation * luacon_sim; +LuaScriptInterface * luacon_ci; +Graphics * luacon_g; +Renderer * luacon_ren; + +bool *luacon_currentCommand; +std::string *luacon_lastError; + +int *lua_el_func, *lua_el_mode, *lua_gr_func; + +int getPartIndex_curIdx; +int step_functions[6] = {0, 0, 0, 0, 0, 0}; +int keypress_function_count = 0; +int *keypress_functions = NULL; +int mouseclick_function_count = 0; +int *mouseclick_functions = NULL; +int tptProperties; //Table for some TPT properties +int tptPropertiesVersion; +int tptElements; //Table for TPT element names +int tptParts, tptPartsMeta, tptElementTransitions, tptPartsCData, tptPartMeta, tptPart, cIndex; + +LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): + CommandInterface(c, m), + currentCommand(false), + legacy(new TPTScriptInterface(c, m)) +{ + luacon_model = m; + luacon_sim = m->GetSimulation(); + luacon_g = ui::Engine::Ref().g; + luacon_ren = m->GetRenderer(); + luacon_ci = this; + + //New TPT API + l = lua_open(); + luaL_openlibs(l); + luaopen_bit(l); + + lua_pushstring(l, "Luacon_ci"); + lua_pushlightuserdata(l, this); + lua_settable(l, LUA_REGISTRYINDEX); + + initSimulationAPI(); + initInterfaceAPI(); + initRendererAPI(); + initElementsAPI(); + initVirtualMachineAPI(); + initGraphicsAPI(); + initFileSystemAPI(); + + //Old TPT API + int i = 0, j; + char tmpname[12]; + int currentElementMeta, currentElement; + const static struct luaL_reg tptluaapi [] = { + {"test", &luatpt_test}, + {"drawtext", &luatpt_drawtext}, + {"create", &luatpt_create}, + {"set_pause", &luatpt_setpause}, + {"toggle_pause", &luatpt_togglepause}, + {"set_console", &luatpt_setconsole}, + {"log", &luatpt_log}, + {"set_pressure", &luatpt_set_pressure}, + {"set_gravity", &luatpt_set_gravity}, + {"reset_gravity_field", &luatpt_reset_gravity_field}, + {"reset_velocity", &luatpt_reset_velocity}, + {"reset_spark", &luatpt_reset_spark}, + {"set_property", &luatpt_set_property}, + {"get_property", &luatpt_get_property}, + {"set_wallmap", &luatpt_set_wallmap}, + {"get_wallmap", &luatpt_get_wallmap}, + {"set_elecmap", &luatpt_set_elecmap}, + {"get_elecmap", &luatpt_get_elecmap}, + {"drawpixel", &luatpt_drawpixel}, + {"drawrect", &luatpt_drawrect}, + {"fillrect", &luatpt_fillrect}, + {"drawline", &luatpt_drawline}, + {"textwidth", &luatpt_textwidth}, + {"get_name", &luatpt_get_name}, + {"set_shortcuts", &luatpt_set_shortcuts}, + {"delete", &luatpt_delete}, + {"register_step", &luatpt_register_step}, + {"unregister_step", &luatpt_unregister_step}, + {"register_mouseclick", &luatpt_register_mouseclick}, + {"unregister_mouseclick", &luatpt_unregister_mouseclick}, + {"register_keypress", &luatpt_register_keypress}, + {"unregister_keypress", &luatpt_unregister_keypress}, + {"register_mouseevent", &luatpt_register_mouseclick}, + {"unregister_mouseevent", &luatpt_unregister_mouseclick}, + {"register_keyevent", &luatpt_register_keypress}, + {"unregister_keyevent", &luatpt_unregister_keypress}, + {"input", &luatpt_input}, + {"message_box", &luatpt_message_box}, + {"get_numOfParts", &luatpt_get_numOfParts}, + {"start_getPartIndex", &luatpt_start_getPartIndex}, + {"next_getPartIndex", &luatpt_next_getPartIndex}, + {"getPartIndex", &luatpt_getPartIndex}, + {"hud", &luatpt_hud}, + {"newtonian_gravity", &luatpt_gravity}, + {"ambient_heat", &luatpt_airheat}, + {"active_menu", &luatpt_active_menu}, + {"decorations_enable", &luatpt_decorations_enable}, + {"display_mode", &luatpt_cmode_set}, + {"throw_error", &luatpt_error}, + {"heat", &luatpt_heat}, + {"setfire", &luatpt_setfire}, + {"setdebug", &luatpt_setdebug}, + {"setfpscap",&luatpt_setfpscap}, + {"getscript",&luatpt_getscript}, + {"setwindowsize",&luatpt_setwindowsize}, + {"watertest",&luatpt_togglewater}, + {"screenshot",&luatpt_screenshot}, + {"element",&luatpt_getelement}, + {"element_func",&luatpt_element_func}, + {"graphics_func",&luatpt_graphics_func}, + {NULL,NULL} + }; + + luacon_mousedown = false; + luacon_mousebutton = 0; + + luacon_currentCommand = ¤tCommand; + luacon_lastError = &lastError; + + //Replace print function with our screen logging thingy + lua_pushcfunction(l, luatpt_log); + lua_setglobal(l, "print"); + + //Register all tpt functions + luaL_register(l, "tpt", tptluaapi); + + tptProperties = lua_gettop(l); + + lua_pushinteger(l, 0); + lua_setfield(l, tptProperties, "mousex"); + lua_pushinteger(l, 0); + lua_setfield(l, tptProperties, "mousey"); + lua_pushinteger(l, 0); + lua_setfield(l, tptProperties, "selectedl"); + lua_pushinteger(l, 0); + lua_setfield(l, tptProperties, "selectedr"); + + lua_newtable(l); + tptPropertiesVersion = lua_gettop(l); + lua_pushinteger(l, SAVE_VERSION); + lua_setfield(l, tptPropertiesVersion, "major"); + lua_pushinteger(l, MINOR_VERSION); + lua_setfield(l, tptPropertiesVersion, "minor"); + lua_pushinteger(l, BUILD_NUM); + lua_setfield(l, tptPropertiesVersion, "build"); + lua_setfield(l, tptProperties, "version"); + + lua_sethook(l, &luacon_hook, LUA_MASKCOUNT, 200); +#ifdef FFI + //LuaJIT's ffi gives us direct access to parts data, no need for nested metatables. HOWEVER, this is in no way safe, it's entirely possible for someone to try to read parts[-10] + lua_pushlightuserdata(l, parts); + lua_setfield(l, tptProperties, "partsdata"); + + luaL_dostring (l, "ffi = require(\"ffi\")\n\ +ffi.cdef[[\n\ +typedef struct { int type; int life, ctype; float x, y, vx, vy; float temp; float pavg[2]; int flags; int tmp; int tmp2; unsigned int dcolour; } particle;\n\ +]]\n\ +tpt.parts = ffi.cast(\"particle *\", tpt.partsdata)\n\ +ffi = nil\n\ +tpt.partsdata = nil"); + //Since ffi is REALLY REALLY dangrous, we'll remove it from the environment completely (TODO) + //lua_pushstring(l, "parts"); + //tptPartsCData = lua_gettable(l, tptProperties); +#else + lua_newtable(l); + tptParts = lua_gettop(l); + lua_newtable(l); + tptPartsMeta = lua_gettop(l); + lua_pushcfunction(l, luacon_partswrite); + lua_setfield(l, tptPartsMeta, "__newindex"); + lua_pushcfunction(l, luacon_partsread); + lua_setfield(l, tptPartsMeta, "__index"); + lua_setmetatable(l, tptParts); + lua_setfield(l, tptProperties, "parts"); + + lua_newtable(l); + tptPart = lua_gettop(l); + lua_newtable(l); + tptPartMeta = lua_gettop(l); + lua_pushcfunction(l, luacon_partwrite); + lua_setfield(l, tptPartMeta, "__newindex"); + lua_pushcfunction(l, luacon_partread); + lua_setfield(l, tptPartMeta, "__index"); + lua_setmetatable(l, tptPart); + + tptPart = luaL_ref(l, LUA_REGISTRYINDEX); +#endif + + lua_newtable(l); + tptElements = lua_gettop(l); + for(i = 1; i < PT_NUM; i++) + { + for(j = 0; j < strlen(luacon_sim->elements[i].Name); j++) + tmpname[j] = tolower(luacon_sim->elements[i].Name[j]); + tmpname[strlen(luacon_sim->elements[i].Name)] = 0; + + lua_newtable(l); + currentElement = lua_gettop(l); + lua_pushinteger(l, i); + lua_setfield(l, currentElement, "id"); + + lua_newtable(l); + currentElementMeta = lua_gettop(l); + lua_pushcfunction(l, luacon_elementwrite); + lua_setfield(l, currentElementMeta, "__newindex"); + lua_pushcfunction(l, luacon_elementread); + lua_setfield(l, currentElementMeta, "__index"); + lua_setmetatable(l, currentElement); + + lua_setfield(l, tptElements, tmpname); + } + lua_setfield(l, tptProperties, "el"); + + lua_newtable(l); + tptElementTransitions = lua_gettop(l); + for(i = 1; i < PT_NUM; i++) + { + for(j = 0; j < strlen(luacon_sim->elements[i].Name); j++) + tmpname[j] = tolower(luacon_sim->elements[i].Name[j]); + tmpname[strlen(luacon_sim->elements[i].Name)] = 0; + + lua_newtable(l); + currentElement = lua_gettop(l); + lua_newtable(l); + currentElementMeta = lua_gettop(l); + lua_pushinteger(l, i); + lua_setfield(l, currentElement, "value"); + lua_pushcfunction(l, luacon_transitionwrite); + lua_setfield(l, currentElementMeta, "__newindex"); + lua_pushcfunction(l, luacon_transitionread); + lua_setfield(l, currentElementMeta, "__index"); + lua_setmetatable(l, currentElement); + + lua_setfield(l, tptElementTransitions, tmpname); + } + lua_setfield(l, tptProperties, "eltransition"); + + lua_el_func = (int*)calloc(PT_NUM, sizeof(int)); + lua_el_mode = (int*)calloc(PT_NUM, sizeof(int)); + lua_gr_func = (int*)calloc(PT_NUM, sizeof(int)); + for(i = 0; i < PT_NUM; i++) + { + lua_el_mode[i] = 0; + } + +} + +void LuaScriptInterface::Init() +{ + if(Client::Ref().FileExists("autorun.lua")) + if(luacon_eval("dofile(\"autorun.lua\")")) + luacon_ci->Log(CommandInterface::LogError, luacon_geterror()); +} + +void LuaScriptInterface::SetWindow(ui::Window * window) +{ + Window = window; +} + +//// Begin Interface API + +void LuaScriptInterface::initInterfaceAPI() +{ + struct luaL_reg interfaceAPIMethods [] = { + {"showWindow", interface_showWindow}, + {"closeWindow", interface_closeWindow}, + {"addComponent", interface_addComponent}, + {NULL, NULL} + }; + luaL_register(l, "interface", interfaceAPIMethods); + + //Ren shortcut + lua_getglobal(l, "interface"); + lua_setglobal(l, "ui"); + + Luna<LuaWindow>::Register(l); + Luna<LuaButton>::Register(l); + Luna<LuaLabel>::Register(l); + Luna<LuaTextbox>::Register(l); + Luna<LuaCheckbox>::Register(l); + Luna<LuaSlider>::Register(l); + Luna<LuaProgressBar>::Register(l); +} + +int LuaScriptInterface::interface_addComponent(lua_State * l) +{ + void * luaComponent = NULL; + ui::Component * component = NULL; + if(luaComponent = Luna<LuaButton>::tryGet(l, 1)) + component = Luna<LuaButton>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaLabel>::tryGet(l, 1)) + component = Luna<LuaLabel>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaTextbox>::tryGet(l, 1)) + component = Luna<LuaTextbox>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaCheckbox>::tryGet(l, 1)) + component = Luna<LuaCheckbox>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaSlider>::tryGet(l, 1)) + component = Luna<LuaSlider>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaProgressBar>::tryGet(l, 1)) + component = Luna<LuaProgressBar>::get(luaComponent)->GetComponent(); + else + luaL_typerror(l, 1, "Component"); + if(luacon_ci->Window && component) + luacon_ci->Window->AddComponent(component); + return 0; +} + +int LuaScriptInterface::interface_showWindow(lua_State * l) +{ + LuaWindow * window = Luna<LuaWindow>::check(l, 1); + if(window && ui::Engine::Ref().GetWindow()!=window->GetWindow()) + ui::Engine::Ref().ShowWindow(window->GetWindow()); + return 0; +} + +int LuaScriptInterface::interface_closeWindow(lua_State * l) +{ + LuaWindow * window = Luna<LuaWindow>::check(l, 1); + if(window && ui::Engine::Ref().GetWindow()==window->GetWindow()) + ui::Engine::Ref().CloseWindow(); + return 0; +} + +//// Begin Simulation API + +void LuaScriptInterface::initSimulationAPI() +{ + //Methods + struct luaL_reg simulationAPIMethods [] = { + {"partNeighbours", simulation_partNeighbours}, + {"partChangeType", simulation_partChangeType}, + {"partCreate", simulation_partCreate}, + {"partKill", simulation_partKill}, + {NULL, NULL} + }; + luaL_register(l, "simulation", simulationAPIMethods); + int simulationAPI = lua_gettop(l); + + //Sim shortcut + lua_getglobal(l, "simulation"); + lua_setglobal(l, "sim"); + +} + +int LuaScriptInterface::simulation_partNeighbours(lua_State * l) +{ + int ids = 0; + if(lua_gettop(l) == 4) + { + int x = lua_tointeger(l, 1), y = lua_tointeger(l, 2), r = lua_tointeger(l, 3), t = lua_tointeger(l, 4), rx, ry, n; + for (rx = -r; rx <= r; rx++) + for (ry = -r; ry <= r; ry++) + if (x+rx >= 0 && y+ry >= 0 && x+rx < XRES && y+ry < YRES && (rx || ry)) + { + n = luacon_sim->pmap[y+ry][x+rx]; + if(n && (n&0xFF) == t) + { + ids++; + lua_pushinteger(l, n>>8); + } + } + + } + else + { + int x = lua_tointeger(l, 1), y = lua_tointeger(l, 2), r = lua_tointeger(l, 3), rx, ry, n; + for (rx = -r; rx <= r; rx++) + for (ry = -r; ry <= r; ry++) + if (x+rx >= 0 && y+ry >= 0 && x+rx < XRES && y+ry < YRES && (rx || ry)) + { + n = luacon_sim->pmap[y+ry][x+rx]; + if(n) + { + ids++; + lua_pushinteger(l, n>>8); + } + } + } + return ids; +} + +int LuaScriptInterface::simulation_partChangeType(lua_State * l) +{ + int partIndex = lua_tointeger(l, 1), x, y; + if(partIndex < 0 || partIndex >= NPART || !luacon_sim->parts[partIndex].type) + return 0; + luacon_sim->part_change_type(partIndex, luacon_sim->parts[partIndex].x+0.5f, luacon_sim->parts[partIndex].y+0.5f, lua_tointeger(l, 2)); + return 0; +} + +int LuaScriptInterface::simulation_partCreate(lua_State * l) +{ + int newID = lua_tointeger(l, 1); + if(newID >= NPART || newID < -3) + { + lua_pushinteger(l, -1); + return 1; + } + lua_pushinteger(l, luacon_sim->create_part(newID, lua_tointeger(l, 2), lua_tointeger(l, 3), lua_tointeger(l, 4))); + return 1; +} + +int LuaScriptInterface::simulation_partKill(lua_State * l) +{ + if(lua_gettop(l)==2) + luacon_sim->delete_part(lua_tointeger(l, 1), lua_tointeger(l, 2), 0); + else + luacon_sim->kill_part(lua_tointeger(l, 1)); + return 0; +} + + +//// Begin Renderer API + +void LuaScriptInterface::initRendererAPI() +{ + //Methods + struct luaL_reg rendererAPIMethods [] = { + {"renderModes", renderer_renderModes}, + {"displayModes", renderer_displayModes}, + {"colourMode", renderer_colourMode}, + {"colorMode", renderer_colourMode}, //Duplicate of above to make americans happy + {"decorations", renderer_decorations}, + {NULL, NULL} + }; + luaL_register(l, "renderer", rendererAPIMethods); + + //Ren shortcut + lua_getglobal(l, "renderer"); + lua_setglobal(l, "ren"); + + int rendererAPI = lua_gettop(l); + + //Static values + //Particle pixel modes/fire mode/effects + lua_pushinteger(l, PMODE); lua_setfield(l, rendererAPI, "PMODE"); + lua_pushinteger(l, PMODE_NONE); lua_setfield(l, rendererAPI, "PMODE_NONE"); + lua_pushinteger(l, PMODE_FLAT); lua_setfield(l, rendererAPI, "PMODE_FLAT"); + lua_pushinteger(l, PMODE_BLOB); lua_setfield(l, rendererAPI, "PMODE_BLOB"); + lua_pushinteger(l, PMODE_BLUR); lua_setfield(l, rendererAPI, "PMODE_BLUR"); + lua_pushinteger(l, PMODE_GLOW); lua_setfield(l, rendererAPI, "PMODE_GLOW"); + lua_pushinteger(l, PMODE_SPARK); lua_setfield(l, rendererAPI, "PMODE_SPARK"); + lua_pushinteger(l, PMODE_FLARE); lua_setfield(l, rendererAPI, "PMODE_FLARE"); + lua_pushinteger(l, PMODE_LFLARE); lua_setfield(l, rendererAPI, "PMODE_LFLARE"); + lua_pushinteger(l, PMODE_ADD); lua_setfield(l, rendererAPI, "PMODE_ADD"); + lua_pushinteger(l, PMODE_BLEND); lua_setfield(l, rendererAPI, "PMODE_BLEND"); + lua_pushinteger(l, PSPEC_STICKMAN); lua_setfield(l, rendererAPI, "PSPEC_STICKMAN"); + lua_pushinteger(l, OPTIONS); lua_setfield(l, rendererAPI, "OPTIONS"); + lua_pushinteger(l, NO_DECO); lua_setfield(l, rendererAPI, "NO_DECO"); + lua_pushinteger(l, DECO_FIRE); lua_setfield(l, rendererAPI, "DECO_FIRE"); + lua_pushinteger(l, FIREMODE); lua_setfield(l, rendererAPI, "FIREMODE"); + lua_pushinteger(l, FIRE_ADD); lua_setfield(l, rendererAPI, "FIRE_ADD"); + lua_pushinteger(l, FIRE_BLEND); lua_setfield(l, rendererAPI, "FIRE_BLEND"); + lua_pushinteger(l, EFFECT); lua_setfield(l, rendererAPI, "EFFECT"); + lua_pushinteger(l, EFFECT_GRAVIN); lua_setfield(l, rendererAPI, "EFFECT_GRAVIN"); + lua_pushinteger(l, EFFECT_GRAVOUT); lua_setfield(l, rendererAPI, "EFFECT_GRAVOUT"); + lua_pushinteger(l, EFFECT_LINES); lua_setfield(l, rendererAPI, "EFFECT_LINES"); + lua_pushinteger(l, EFFECT_DBGLINES); lua_setfield(l, rendererAPI, "EFFECT_DBGLINES"); + + //Display/Render/Colour modes + lua_pushinteger(l, RENDER_EFFE); lua_setfield(l, rendererAPI, "RENDER_EFFE"); + lua_pushinteger(l, RENDER_FIRE); lua_setfield(l, rendererAPI, "RENDER_FIRE"); + lua_pushinteger(l, RENDER_GLOW); lua_setfield(l, rendererAPI, "RENDER_GLOW"); + lua_pushinteger(l, RENDER_BLUR); lua_setfield(l, rendererAPI, "RENDER_BLUR"); + lua_pushinteger(l, RENDER_BLOB); lua_setfield(l, rendererAPI, "RENDER_BLOB"); + lua_pushinteger(l, RENDER_BASC); lua_setfield(l, rendererAPI, "RENDER_BASC"); + lua_pushinteger(l, RENDER_NONE); lua_setfield(l, rendererAPI, "RENDER_NONE"); + lua_pushinteger(l, COLOUR_HEAT); lua_setfield(l, rendererAPI, "COLOUR_HEAT"); + lua_pushinteger(l, COLOUR_LIFE); lua_setfield(l, rendererAPI, "COLOUR_LIFE"); + lua_pushinteger(l, COLOUR_GRAD); lua_setfield(l, rendererAPI, "COLOUR_GRAD"); + lua_pushinteger(l, COLOUR_BASC); lua_setfield(l, rendererAPI, "COLOUR_BASC"); + lua_pushinteger(l, COLOUR_DEFAULT); lua_setfield(l, rendererAPI, "COLOUR_DEFAULT"); + lua_pushinteger(l, DISPLAY_AIRC); lua_setfield(l, rendererAPI, "DISPLAY_AIRC"); + lua_pushinteger(l, DISPLAY_AIRP); lua_setfield(l, rendererAPI, "DISPLAY_AIRP"); + lua_pushinteger(l, DISPLAY_AIRV); lua_setfield(l, rendererAPI, "DISPLAY_AIRV"); + lua_pushinteger(l, DISPLAY_AIRH); lua_setfield(l, rendererAPI, "DISPLAY_AIRH"); + lua_pushinteger(l, DISPLAY_AIR); lua_setfield(l, rendererAPI, "DISPLAY_AIR"); + lua_pushinteger(l, DISPLAY_WARP); lua_setfield(l, rendererAPI, "DISPLAY_WARP"); + lua_pushinteger(l, DISPLAY_PERS); lua_setfield(l, rendererAPI, "DISPLAY_PERS"); + lua_pushinteger(l, DISPLAY_EFFE); lua_setfield(l, rendererAPI, "DISPLAY_EFFE"); +} + +//get/set render modes list +int LuaScriptInterface::renderer_renderModes(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + int size = 0; + luaL_checktype(l, 1, LUA_TTABLE); + size = luaL_getn(l, 1); + + std::vector<unsigned int> renderModes; + for(int i = 1; i <= size; i++) + { + lua_rawgeti(l, 1, i); + renderModes.push_back(lua_tointeger(l, -1)); + lua_pop(l, 1); + } + luacon_ren->SetRenderMode(renderModes); + return 0; + } + else + { + lua_newtable(l); + std::vector<unsigned int> renderModes = luacon_ren->GetRenderMode(); + int i = 1; + for(std::vector<unsigned int>::iterator iter = renderModes.begin(), end = renderModes.end(); iter != end; ++iter) + { + lua_pushinteger(l, *iter); + lua_rawseti(l, -2, i++); + } + return 1; + } +} + +int LuaScriptInterface::renderer_displayModes(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + int size = 0; + luaL_checktype(l, 1, LUA_TTABLE); + size = luaL_getn(l, 1); + + std::vector<unsigned int> displayModes; + for(int i = 1; i <= size; i++) + { + lua_rawgeti(l, 1, i); + displayModes.push_back(lua_tointeger(l, -1)); + lua_pop(l, 1); + } + luacon_ren->SetDisplayMode(displayModes); + return 0; + } + else + { + lua_newtable(l); + std::vector<unsigned int> displayModes = luacon_ren->GetDisplayMode(); + int i = 1; + for(std::vector<unsigned int>::iterator iter = displayModes.begin(), end = displayModes.end(); iter != end; ++iter) + { + lua_pushinteger(l, *iter); + lua_rawseti(l, -2, i++); + } + return 1; + } +} + +int LuaScriptInterface::renderer_colourMode(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + luacon_ren->SetColourMode(lua_tointeger(l, 1)); + return 0; + } + else + { + lua_pushinteger(l, luacon_ren->GetColourMode()); + return 1; + } +} + +int LuaScriptInterface::renderer_decorations(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luacon_ren->decorations_enable = lua_toboolean(l, 1); + return 0; + } + else + { + lua_pushboolean(l, luacon_ren->decorations_enable); + return 1; + } +} + +void LuaScriptInterface::initElementsAPI() +{ + //Methods + struct luaL_reg elementsAPIMethods [] = { + {"allocate", elements_allocate}, + {"element", elements_element}, + {"property", elements_property}, + {"free", elements_free}, + {"loadDefault", elements_loadDefault}, + {NULL, NULL} + }; + luaL_register(l, "elements", elementsAPIMethods); + + //elem shortcut + lua_getglobal(l, "elements"); + lua_setglobal(l, "elem"); + + int elementsAPI = lua_gettop(l); + + //Static values + //Element types/properties/states + lua_pushinteger(l, TYPE_PART); lua_setfield(l, elementsAPI, "TYPE_PART"); + lua_pushinteger(l, TYPE_LIQUID); lua_setfield(l, elementsAPI, "TYPE_LIQUID"); + lua_pushinteger(l, TYPE_SOLID); lua_setfield(l, elementsAPI, "TYPE_SOLID"); + lua_pushinteger(l, TYPE_GAS); lua_setfield(l, elementsAPI, "TYPE_GAS"); + lua_pushinteger(l, TYPE_ENERGY); lua_setfield(l, elementsAPI, "TYPE_ENERGY"); + lua_pushinteger(l, PROP_CONDUCTS); lua_setfield(l, elementsAPI, "PROP_CONDUCTS"); + lua_pushinteger(l, PROP_BLACK); lua_setfield(l, elementsAPI, "PROP_BLACK"); + lua_pushinteger(l, PROP_NEUTPENETRATE); lua_setfield(l, elementsAPI, "PROP_NEUTPENETRATE"); + lua_pushinteger(l, PROP_NEUTABSORB); lua_setfield(l, elementsAPI, "PROP_NEUTABSORB"); + lua_pushinteger(l, PROP_NEUTPASS); lua_setfield(l, elementsAPI, "PROP_NEUTPASS"); + lua_pushinteger(l, PROP_DEADLY); lua_setfield(l, elementsAPI, "PROP_DEADLY"); + lua_pushinteger(l, PROP_HOT_GLOW); lua_setfield(l, elementsAPI, "PROP_HOT_GLOW"); + lua_pushinteger(l, PROP_LIFE); lua_setfield(l, elementsAPI, "PROP_LIFE"); + lua_pushinteger(l, PROP_RADIOACTIVE); lua_setfield(l, elementsAPI, "PROP_RADIOACTIVE"); + lua_pushinteger(l, PROP_LIFE_DEC); lua_setfield(l, elementsAPI, "PROP_LIFE_DEC"); + lua_pushinteger(l, PROP_LIFE_KILL); lua_setfield(l, elementsAPI, "PROP_LIFE_KILL"); + lua_pushinteger(l, PROP_LIFE_KILL_DEC); lua_setfield(l, elementsAPI, "PROP_LIFE_KILL_DEC"); + lua_pushinteger(l, PROP_SPARKSETTLE); lua_setfield(l, elementsAPI, "PROP_SPARKSETTLE"); + lua_pushinteger(l, PROP_NOAMBHEAT); lua_setfield(l, elementsAPI, "PROP_NOAMBHEAT"); + lua_pushinteger(l, FLAG_STAGNANT); lua_setfield(l, elementsAPI, "FLAG_STAGNANT"); + lua_pushinteger(l, FLAG_SKIPMOVE); lua_setfield(l, elementsAPI, "FLAG_SKIPMOVE"); + lua_pushinteger(l, FLAG_MOVABLE); lua_setfield(l, elementsAPI, "FLAG_MOVABLE"); + lua_pushinteger(l, ST_NONE); lua_setfield(l, elementsAPI, "ST_NONE"); + lua_pushinteger(l, ST_SOLID); lua_setfield(l, elementsAPI, "ST_SOLID"); + lua_pushinteger(l, ST_LIQUID); lua_setfield(l, elementsAPI, "ST_LIQUID"); + lua_pushinteger(l, ST_GAS); lua_setfield(l, elementsAPI, "ST_GAS"); + + lua_pushinteger(l, SC_WALL); lua_setfield(l, elementsAPI, "SC_WALL"); + lua_pushinteger(l, SC_ELEC); lua_setfield(l, elementsAPI, "SC_ELEC"); + lua_pushinteger(l, SC_POWERED); lua_setfield(l, elementsAPI, "SC_POWERED"); + lua_pushinteger(l, SC_FORCE); lua_setfield(l, elementsAPI, "SC_FORCE"); + lua_pushinteger(l, SC_EXPLOSIVE); lua_setfield(l, elementsAPI, "SC_EXPLOSIVE"); + lua_pushinteger(l, SC_GAS); lua_setfield(l, elementsAPI, "SC_GAS"); + lua_pushinteger(l, SC_LIQUID); lua_setfield(l, elementsAPI, "SC_LIQUID"); + lua_pushinteger(l, SC_POWDERS); lua_setfield(l, elementsAPI, "SC_POWDERS"); + lua_pushinteger(l, SC_SOLIDS); lua_setfield(l, elementsAPI, "SC_SOLIDS"); + lua_pushinteger(l, SC_NUCLEAR); lua_setfield(l, elementsAPI, "SC_NUCLEAR"); + lua_pushinteger(l, SC_SPECIAL); lua_setfield(l, elementsAPI, "SC_SPECIAL"); + lua_pushinteger(l, SC_LIFE); lua_setfield(l, elementsAPI, "SC_LIFE"); + lua_pushinteger(l, SC_TOOL); lua_setfield(l, elementsAPI, "SC_TOOL"); + lua_pushinteger(l, SC_DECO); lua_setfield(l, elementsAPI, "SC_DECO"); + lua_pushinteger(l, SC_SENSOR); lua_setfield(l, elementsAPI, "SC_SENSOR"); + + //Element identifiers + for(int i = 0; i < PT_NUM; i++) + { + if(luacon_sim->elements[i].Enabled) + { + lua_pushinteger(l, i); + lua_setfield(l, elementsAPI, luacon_sim->elements[i].Identifier); + } + } +} + +pim::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM]; + +int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) +{ + pim::VirtualMachine * machine = updateVirtualMachines[parts[i].type]; + + machine->CSPush(i); + machine->CSPush(x); + machine->CSPush(y); + machine->Call(0); + + + /*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; + + vm::word w; + int argAddr = 0, argCount = 5; + vMachine->sim = sim; + + vMachine->OpPUSH(w); //Pointless null in stack + w.int4 = (argCount + 2) * sizeof(vm::word); + vMachine->OpENTER(w); + argAddr = 8; + + //Arguments + w.int4 = i; vMachine->Marshal(argAddr, w); argAddr += 4; + w.int4 = x; vMachine->Marshal(argAddr, w); argAddr += 4; + w.int4 = y; vMachine->Marshal(argAddr, w); argAddr += 4; + w.int4 = nt; vMachine->Marshal(argAddr, w); argAddr += 4; + w.int4 = surround_space; vMachine->Marshal(argAddr, w); argAddr += 4; + + w.int4 = 0; + vMachine->Push(w); + + vMachine->OpCALL(w); + vMachine->Run(); + w.int4 = (argCount + 2) * sizeof(vm::word); + vMachine->OpLEAVE(w); + vMachine->OpPOP(w); //Pop pointless null + vMachine->End();*/ + + return 0; +} + +int LuaScriptInterface::elements_loadDefault(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + int id = lua_tointeger(l, 1); + if(id < 0 || id >= PT_NUM) + return luaL_error(l, "Invalid element"); + + lua_getglobal(l, "elements"); + lua_pushnil(l); + lua_setfield(l, -2, luacon_sim->elements[id].Identifier); + + std::vector<Element> elementList = GetElements(); + if(id < elementList.size()) + luacon_sim->elements[id] = elementList[id]; + else + luacon_sim->elements[id] = Element(); + + lua_pushinteger(l, id); + lua_setfield(l, -2, luacon_sim->elements[id].Identifier); + lua_pop(l, 1); + } + else + { + std::vector<Element> elementList = GetElements(); + for(int i = 0; i < PT_NUM; i++) + { + if(i < elementList.size()) + luacon_sim->elements[i] = elementList[i]; + else + luacon_sim->elements[i] = Element(); + } + lua_pushnil(l); + lua_setglobal(l, "elements"); + lua_pushnil(l); + lua_setglobal(l, "elem"); + + lua_getglobal(l, "package"); + lua_getfield(l, -1, "loaded"); + lua_pushnil(l); + lua_setfield(l, -2, "elements"); + + luacon_ci->initElementsAPI(); + } + + luacon_model->BuildMenus(); + luacon_sim->init_can_move(); + std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item()); + +} + +int LuaScriptInterface::elements_allocate(lua_State * l) +{ + std::string group, id, identifier; + luaL_checktype(l, 1, LUA_TSTRING); + luaL_checktype(l, 2, LUA_TSTRING); + group = std::string(lua_tostring(l, 1)); + std::transform(group.begin(), group.end(), group.begin(), ::toupper); + id = std::string(lua_tostring(l, 2)); + std::transform(id.begin(), id.end(), id.begin(), ::toupper); + + if(group == "DEFAULT") + return luaL_error(l, "You cannot create elements in the 'default' group."); + + identifier = group + "_PT_" + id; + + for(int i = 0; i < PT_NUM; i++) + { + if(luacon_sim->elements[i].Enabled && std::string(luacon_sim->elements[i].Identifier) == identifier) + return luaL_error(l, "Element identifier already in use"); + } + + int newID = -1; + for(int i = PT_NUM-1; i >= 0; i--) + { + if(!luacon_sim->elements[i].Enabled) + { + newID = i; + luacon_sim->elements[i] = Element(); + luacon_sim->elements[i].Enabled = true; + luacon_sim->elements[i].Identifier = strdup(identifier.c_str()); + break; + } + } + + if(newID != -1) + { + lua_getglobal(l, "elements"); + lua_pushinteger(l, newID); + lua_setfield(l, -2, identifier.c_str()); + lua_pop(l, 1); + } + + lua_pushinteger(l, newID); + return 1; +} + +int LuaScriptInterface::elements_element(lua_State * l) +{ + int args = lua_gettop(l); + int id; + luaL_checktype(l, 1, LUA_TNUMBER); + id = lua_tointeger(l, 1); + + if(id < 0 || id >= PT_NUM || !luacon_sim->elements[id].Enabled) + return luaL_error(l, "Invalid element"); + + if(args > 1) + { + luaL_checktype(l, 2, LUA_TTABLE); + std::vector<StructProperty> properties = Element::GetProperties(); + //Write values from native data to a table + for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter) + { + lua_getfield(l, -1, (*iter).Name.c_str()); + if(lua_type(l, -1) != LUA_TNIL) + { + intptr_t offset = (*iter).Offset; + switch((*iter).Type) + { + case StructProperty::ParticleType: + case StructProperty::Integer: + *((int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); + break; + case StructProperty::UInteger: + *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); + break; + case StructProperty::Float: + *((float*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tonumber(l, -1); + break; + case StructProperty::Char: + *((char*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); + break; + case StructProperty::UChar: + *((unsigned char*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); + break; + case StructProperty::String: + *((char**)(((unsigned char*)&luacon_sim->elements[id])+offset)) = strdup(lua_tostring(l, -1)); + break; + case StructProperty::Colour: +#if PIXELSIZE == 4 + *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); +#else + *((unsigned short*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, -1); +#endif + break; + } + lua_pop(l, 1); + } + } + + lua_getfield(l, -1, "Update"); + if(lua_type(l, -1) == LUA_TFUNCTION) + { + lua_el_func[id] = luaL_ref(l, LUA_REGISTRYINDEX); + luacon_sim->elements[id].Update = &luacon_elementReplacement; + } + else if(lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1)) + { + lua_el_func[id] = 0; + luacon_sim->elements[id].Update = NULL; + } + else + lua_pop(l, 1); + + lua_getfield(l, -1, "Graphics"); + if(lua_type(l, -1) == LUA_TFUNCTION) + { + lua_el_func[id] = luaL_ref(l, LUA_REGISTRYINDEX); + luacon_sim->elements[id].Graphics = &luacon_graphicsReplacement; + } + else if(lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1)) + { + lua_el_func[id] = 0; + luacon_sim->elements[id].Graphics = NULL; + } + else + lua_pop(l, 1); + + luacon_model->BuildMenus(); + luacon_sim->init_can_move(); + std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item()); + + lua_pop(l, 1); + return 0; + } + else + { + std::vector<StructProperty> properties = Element::GetProperties(); + //Write values from native data to a table + lua_newtable(l); + for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter) + { + intptr_t offset = (*iter).Offset; + switch((*iter).Type) + { + case StructProperty::ParticleType: + case StructProperty::Integer: + lua_pushinteger(l, *((int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::UInteger: + lua_pushinteger(l, *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Float: + lua_pushnumber(l, *((float*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Char: + lua_pushinteger(l, *((char*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::UChar: + lua_pushinteger(l, *((unsigned char*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::String: + lua_pushstring(l, *((char**)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Colour: +#if PIXELSIZE == 4 + lua_pushinteger(l, *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); +#else + lua_pushinteger(l, *((unsigned short*)(((unsigned char*)&luacon_sim->elements[id])+offset))); +#endif + break; + default: + lua_pushnil(l); + } + lua_setfield(l, -2, (*iter).Name.c_str()); + } + return 1; + } +} + +int LuaScriptInterface::elements_property(lua_State * l) +{ + int args = lua_gettop(l); + int id; + std::string propertyName; + luaL_checktype(l, 1, LUA_TNUMBER); + id = lua_tointeger(l, 1); + luaL_checktype(l, 2, LUA_TSTRING); + propertyName = std::string(lua_tostring(l, 2)); + + if(id < 0 || id >= PT_NUM || !luacon_sim->elements[id].Enabled) + return luaL_error(l, "Invalid element"); + + + + if(args > 2) + { + StructProperty property; + bool propertyFound = false; + std::vector<StructProperty> properties = Element::GetProperties(); + + for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter) + { + if((*iter).Name == propertyName) + { + property = *iter; + propertyFound = true; + break; + } + } + + if(propertyFound) + { + if(lua_type(l, 3) != LUA_TNIL) + { + intptr_t offset = property.Offset; + switch(property.Type) + { + case StructProperty::ParticleType: + case StructProperty::Integer: + *((int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + break; + case StructProperty::UInteger: + *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + break; + case StructProperty::Float: + *((float*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tonumber(l, 3); + break; + case StructProperty::Char: + *((char*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + break; + case StructProperty::UChar: + *((unsigned char*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + break; + case StructProperty::String: + *((char**)(((unsigned char*)&luacon_sim->elements[id])+offset)) = strdup(lua_tostring(l, 3)); + break; + case StructProperty::Colour: + #if PIXELSIZE == 4 + *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + #else + *((unsigned short*)(((unsigned char*)&luacon_sim->elements[id])+offset)) = lua_tointeger(l, 3); + #endif + break; + } + } + + luacon_model->BuildMenus(); + luacon_sim->init_can_move(); + std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item()); + + return 0; + } + else if(propertyName == "Update") + { + if(lua_type(l, 3) == LUA_TFUNCTION) + { + lua_pushvalue(l, 3); + lua_el_func[id] = luaL_ref(l, LUA_REGISTRYINDEX); + luacon_sim->elements[id].Update = &luacon_elementReplacement; + } + else if(lua_type(l, 3) == LUA_TLIGHTUSERDATA) + { + updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); + luacon_sim->elements[id].Update = &updateVM; + } + else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3)) + { + lua_el_func[id] = 0; + luacon_sim->elements[id].Update = NULL; + } + } + else if(propertyName == "Graphics") + { + if(lua_type(l, 3) == LUA_TFUNCTION) + { + lua_pushvalue(l, 3); + lua_el_func[id] = luaL_ref(l, LUA_REGISTRYINDEX); + luacon_sim->elements[id].Graphics = &luacon_graphicsReplacement; + } + else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, -1)) + { + lua_el_func[id] = 0; + luacon_sim->elements[id].Graphics = NULL; + } + std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item()); + } + else + return luaL_error(l, "Invalid element property"); + } + else + { + StructProperty property; + bool propertyFound = false; + std::vector<StructProperty> properties = Element::GetProperties(); + + for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter) + { + if((*iter).Name == propertyName) + { + property = *iter; + propertyFound = true; + break; + } + } + + if(propertyFound) + { + intptr_t offset = property.Offset; + switch(property.Type) + { + case StructProperty::ParticleType: + case StructProperty::Integer: + lua_pushinteger(l, *((int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::UInteger: + lua_pushinteger(l, *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Float: + lua_pushnumber(l, *((float*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Char: + lua_pushinteger(l, *((char*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::UChar: + lua_pushinteger(l, *((unsigned char*)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::String: + lua_pushstring(l, *((char**)(((unsigned char*)&luacon_sim->elements[id])+offset))); + break; + case StructProperty::Colour: +#if PIXELSIZE == 4 + lua_pushinteger(l, *((unsigned int*)(((unsigned char*)&luacon_sim->elements[id])+offset))); +#else + lua_pushinteger(l, *((unsigned short*)(((unsigned char*)&luacon_sim->elements[id])+offset))); +#endif + break; + default: + lua_pushnil(l); + } + return 1; + } + else + return luaL_error(l, "Invalid element property"); + } +} + +int LuaScriptInterface::elements_free(lua_State * l) +{ + int id; + luaL_checktype(l, 1, LUA_TNUMBER); + id = lua_tointeger(l, 1); + + if(id < 0 || id >= PT_NUM || !luacon_sim->elements[id].Enabled) + return luaL_error(l, "Invalid element"); + + std::string identifier = luacon_sim->elements[id].Identifier; + if(identifier.length()>7 && identifier.substr(0, 7) == "DEFAULT") + return luaL_error(l, "Cannot free default elements"); + + luacon_sim->elements[id].Enabled = false; + + lua_getglobal(l, "elements"); + lua_pushnil(l); + lua_setfield(l, -2, identifier.c_str()); + lua_pop(l, 1); + + return 0; +} + +void LuaScriptInterface::initVirtualMachineAPI() +{ + //Methods + struct luaL_reg vmAPIMethods [] = { + {"loadProgram", virtualMachine_loadProgram}, + {NULL, NULL} + }; + luaL_register(l, "virtualMachine", vmAPIMethods); + + //elem shortcut + lua_getglobal(l, "virtualMachine"); + lua_setglobal(l, "vm"); + + int vmAPI = lua_gettop(l); +} + +int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) +{ + /*luaL_checktype(l, 1, LUA_TSTRING); + + vm::VirtualMachine * newVM = new vm::VirtualMachine(1); + try + { + const char * tempString = lua_tostring(l, 1); + int tempStringLength = lua_strlen(l, 1); + std::vector<char> programData(tempString, tempString+tempStringLength); + newVM->LoadProgram(programData); + } + catch(std::exception & e) + { + return luaL_error(l, "Unable to load program"); + } + lua_pushlightuserdata(l, newVM);*/ + std::string programSource(lua_tostring(l, 1)); + std::stringstream input(programSource); + + + pim::compiler::Parser * parser = new pim::compiler::Parser(input); + + std::vector<unsigned char> programData = parser->Compile(); + + pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim); + machine->LoadProgram(programData); + + lua_pushlightuserdata(l, machine); + return 1; +} + +void LuaScriptInterface::initGraphicsAPI() +{ + //Methods + struct luaL_reg graphicsAPIMethods [] = { + {"textSize", graphics_textSize}, + {"drawText", graphics_drawText}, + {"drawLine", graphics_drawLine}, + {"drawRect", graphics_drawRect}, + {"fillRect", graphics_fillRect}, + {NULL, NULL} + }; + luaL_register(l, "graphics", graphicsAPIMethods); + + //elem shortcut + lua_getglobal(l, "graphics"); + lua_setglobal(l, "gfx"); + + int graphicsAPI = lua_gettop(l); + + lua_pushinteger(l, XRES+BARSIZE); lua_setfield(l, graphicsAPI, "WIDTH"); + lua_pushinteger(l, YRES+MENUSIZE); lua_setfield(l, graphicsAPI, "HEIGHT"); +} + +int LuaScriptInterface::graphics_textSize(lua_State * l) +{ + char * text; + int width, height; + text = (char*)lua_tostring(l, 1); + Graphics::textsize(text, width, height); + + lua_pushinteger(l, width); + lua_pushinteger(l, height); + return 2; +} + +int LuaScriptInterface::graphics_drawText(lua_State * l) +{ + char * text; + int x, y, r, g, b, a; + x = lua_tointeger(l, 1); + y = lua_tointeger(l, 2); + text = (char*)lua_tostring(l, 3); + r = luaL_optint(l, 4, 255); + g = luaL_optint(l, 5, 255); + b = luaL_optint(l, 6, 255); + a = luaL_optint(l, 7, 255); + + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + + luacon_g->drawtext(x, y, text, r, g, b, a); + return 0; +} + +int LuaScriptInterface::graphics_drawLine(lua_State * l) +{ + int x1, y1, x2, y2, r, g, b, a; + x1 = lua_tointeger(l, 1); + y1 = lua_tointeger(l, 2); + x2 = lua_tointeger(l, 3); + y2 = lua_tointeger(l, 4); + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->draw_line(x1, y1, x2, y2, r, g, b, a); + return 0; +} + +int LuaScriptInterface::graphics_drawRect(lua_State * l) +{ + int x, y, w, h, r, g, b, a; + x = lua_tointeger(l, 1); + y = lua_tointeger(l, 2); + w = lua_tointeger(l, 3); + h = lua_tointeger(l, 4); + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->drawrect(x, y, w, h, r, g, b, a); + return 0; +} + +int LuaScriptInterface::graphics_fillRect(lua_State * l) +{ + int x, y, w, h, r, g, b, a; + x = lua_tointeger(l, 1); + y = lua_tointeger(l, 2); + w = lua_tointeger(l, 3); + h = lua_tointeger(l, 4); + r = luaL_optint(l, 5, 255); + g = luaL_optint(l, 6, 255); + b = luaL_optint(l, 7, 255); + a = luaL_optint(l, 8, 255); + + if (r<0) r = 0; + if (r>255) r = 255; + if (g<0) g = 0; + if (g>255) g = 255; + if (b<0) b = 0; + if (b>255) b = 255; + if (a<0) a = 0; + if (a>255) a = 255; + luacon_g->fillrect(x, y, w, h, r, g, b, a); + return 0; +} + +void LuaScriptInterface::initFileSystemAPI() +{ + //Methods + struct luaL_reg fileSystemAPIMethods [] = { + {"list", fileSystem_list}, + {"exists", fileSystem_exists}, + {"isFile", fileSystem_isFile}, + {"isDirectory", fileSystem_isDirectory}, + {"makeDirectory", fileSystem_makeDirectory}, + {"removeDirectory", fileSystem_removeDirectory}, + {"removeFile", fileSystem_removeFile}, + {"move", fileSystem_move}, + {"copy", fileSystem_copy}, + {NULL, NULL} + }; + luaL_register(l, "fileSystem", fileSystemAPIMethods); + + //elem shortcut + lua_getglobal(l, "fileSystem"); + lua_setglobal(l, "fs"); + + int fileSystemAPI = lua_gettop(l); +} + +int LuaScriptInterface::fileSystem_list(lua_State * l) +{ + const char * directoryName = lua_tostring(l, 1); + + int index = 1; + lua_newtable(l); + + DIR * directory; + struct dirent * entry; + + directory = opendir(directoryName); + if (directory != NULL) + { + while (entry = readdir(directory)) + { + if(strncmp(entry->d_name, "..", 3) && strncmp(entry->d_name, ".", 2)) + { + lua_pushstring(l, entry->d_name); + lua_rawseti(l, -2, index++); + } + } + closedir(directory); + } + else + { + lua_pushnil(l); + } + + return 1; +} + +int LuaScriptInterface::fileSystem_exists(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + + bool exists = false; +#ifdef WIN + struct _stat s; + if(_stat(filename, &s) == 0) +#else + struct stat s; + if(stat(filename, &s) == 0) +#endif + { + if(s.st_mode & S_IFDIR) + { + exists = true; + } + else if(s.st_mode & S_IFREG) + { + exists = true; + } + else + { + exists = true; + } + } + else + { + exists = false; + } + + lua_pushboolean(l, exists); + return 1; +} + +int LuaScriptInterface::fileSystem_isFile(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + + bool exists = false; +#ifdef WIN + struct _stat s; + if(_stat(filename, &s) == 0) +#else + struct stat s; + if(stat(filename, &s) == 0) +#endif + { + if(s.st_mode & S_IFDIR) + { + exists = true; + } + else if(s.st_mode & S_IFREG) + { + exists = false; + } + else + { + exists = false; + } + } + else + { + exists = false; + } + + lua_pushboolean(l, exists); + return 1; +} + +int LuaScriptInterface::fileSystem_isDirectory(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + + bool exists = false; +#ifdef WIN + struct _stat s; + if(_stat(filename, &s) == 0) +#else + struct stat s; + if(stat(filename, &s) == 0) +#endif + { + if(s.st_mode & S_IFDIR) + { + exists = false; + } + else if(s.st_mode & S_IFREG) + { + exists = true; + } + else + { + exists = false; + } + } + else + { + exists = false; + } + + lua_pushboolean(l, exists); + return 1; +} + +int LuaScriptInterface::fileSystem_makeDirectory(lua_State * l) +{ + const char * dirname = lua_tostring(l, 1); + + int ret = 0; + ret = Client::Ref().MakeDirectory(dirname); + lua_pushboolean(l, ret == 0); + return 1; +} + +int LuaScriptInterface::fileSystem_removeDirectory(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + + int ret = 0; +#ifdef WIN + ret = _rmdir(filename); +#else + ret = rmdir(filename); +#endif + lua_pushboolean(l, ret == 0); + return 1; +} + +int LuaScriptInterface::fileSystem_removeFile(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + + int ret = 0; +#ifdef WIN + ret = _unlink(filename); +#else + ret = unlink(filename); +#endif + lua_pushboolean(l, ret == 0); + return 1; +} + +int LuaScriptInterface::fileSystem_move(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + const char * newFilename = lua_tostring(l, 2); + int ret = 0; + + ret = rename(filename, newFilename); + + lua_pushboolean(l, ret == 0); + return 1; +} + +int LuaScriptInterface::fileSystem_copy(lua_State * l) +{ + const char * filename = lua_tostring(l, 1); + const char * newFilename = lua_tostring(l, 2); + int ret = 0; + + try + { + std::ifstream source(filename, std::ios::binary); + std::ofstream dest(newFilename, std::ios::binary); + source.exceptions(std::ifstream::failbit | std::ifstream::badbit); + dest.exceptions(std::ifstream::failbit | std::ifstream::badbit); + + std::istreambuf_iterator<char> begin_source(source); + std::istreambuf_iterator<char> end_source; + std::ostreambuf_iterator<char> begin_dest(dest); + std::copy(begin_source, end_source, begin_dest); + + source.close(); + dest.close(); + + ret = 0; + } + catch (std::exception & e) + { + ret = 1; + } + + lua_pushboolean(l, ret == 0); + return 1; +} + + +bool LuaScriptInterface::OnBrushChanged(int brushType, int rx, int ry) +{ + luacon_brushx = rx; + luacon_brushy = ry; + return true; +} + +bool LuaScriptInterface::OnMouseMove(int x, int y, int dx, int dy) +{ + luacon_mousex = x; + luacon_mousey = y; + return true; +} + +bool LuaScriptInterface::OnMouseDown(int x, int y, unsigned button) +{ + luacon_mousedown = true; + luacon_mousebutton = button; + return luacon_mouseevent(x, y, button, LUACON_MDOWN, 0); +} + +bool LuaScriptInterface::OnMouseUp(int x, int y, unsigned button) +{ + luacon_mousedown = false; + return luacon_mouseevent(x, y, button, LUACON_MUP, 0); +} + +bool LuaScriptInterface::OnMouseWheel(int x, int y, int d) +{ + return luacon_mouseevent(x, y, luacon_mousedown?luacon_mousebutton:0, 0, d); +} + +bool LuaScriptInterface::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + int modifiers = 0; + if(shift) + modifiers |= 0x001; + if(ctrl) + modifiers |= 0x040; + if(alt) + modifiers |= 0x100; + return luacon_keyevent(key, modifiers, LUACON_KDOWN); +} + +bool LuaScriptInterface::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + int modifiers = 0; + if(shift) + modifiers |= 0x001; + if(ctrl) + modifiers |= 0x040; + if(alt) + modifiers |= 0x100; + return luacon_keyevent(key, modifiers, LUACON_KUP); +} + +void LuaScriptInterface::OnTick() +{ + ui::Engine::Ref().LastTick(clock()); + if(luacon_mousedown) + luacon_mouseevent(luacon_mousex, luacon_mousey, luacon_mousebutton, LUACON_MPRESS, 0); + luacon_step(luacon_mousex, luacon_mousey, luacon_selectedl, luacon_selectedr, luacon_brushx, luacon_brushy); +} + +int LuaScriptInterface::Command(std::string command) +{ + if(command[0] == '!') + { + lastError = ""; + int ret = legacy->Command(command.substr(1)); + lastError = legacy->GetLastError(); + return ret; + } + else + { + int ret; + lastError = ""; + currentCommand = true; + ui::Engine::Ref().LastTick(clock()); + if((ret = luaL_dostring(l, command.c_str()))) + { + lastError = luacon_geterror(); + //Log(LogError, lastError); + } + currentCommand = false; + return ret; + } +} + +std::string LuaScriptInterface::FormatCommand(std::string command) +{ + if(command[0] == '!') + { + return "!"+legacy->FormatCommand(command.substr(1)); + } + else + return command; +} + +LuaScriptInterface::~LuaScriptInterface() { + delete legacy; +} diff --git a/src/cat/LuaScriptInterface.h b/src/cat/LuaScriptInterface.h new file mode 100644 index 0000000..bf7d277 --- /dev/null +++ b/src/cat/LuaScriptInterface.h @@ -0,0 +1,128 @@ +/* + * LuaScriptInterface.h + * + * Created on: Feb 11, 2012 + * Author: Simon + */ + +#ifndef LUASCRIPTINTERFACE_H_ +#define LUASCRIPTINTERFACE_H_ + +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include "CommandInterface.h" +#include "simulation/Simulation.h" + +namespace ui +{ + class Window; +} + +namespace pim +{ + class VirtualMachine; +} + + +//Because lua only has bindings for C, we're going to have to go outside "outside" the LuaScriptInterface, this means we can only have one instance :( + +#define LOCAL_LUA_DIR "Lua" + +#define LUACON_MDOWN 1 +#define LUACON_MUP 2 +#define LUACON_MPRESS 3 +#define LUACON_KDOWN 1 +#define LUACON_KUP 2 + +//Bitmasks for things that might need recalculating after changes to tpt.el +#define LUACON_EL_MODIFIED_CANMOVE 0x1 +#define LUACON_EL_MODIFIED_GRAPHICS 0x2 +#define LUACON_EL_MODIFIED_MENUS 0x4 + +class TPTScriptInterface; +class LuaScriptInterface: public CommandInterface +{ + int luacon_mousex, luacon_mousey, luacon_selectedl, luacon_selectedr, luacon_mousebutton, luacon_brushx, luacon_brushy; + bool luacon_mousedown; + bool currentCommand; + TPTScriptInterface * legacy; + + //Simulation + void initSimulationAPI(); + static int simulation_partNeighbours(lua_State * l); + static int simulation_partChangeType(lua_State * l); + static int simulation_partCreate(lua_State * l); + static int simulation_partKill(lua_State * l); + + //Renderer + void initRendererAPI(); + static int renderer_renderModes(lua_State * l); + static int renderer_displayModes(lua_State * l); + static int renderer_colourMode(lua_State * l); + static int renderer_decorations(lua_State * l); + + //Elements + static pim::VirtualMachine * updateVirtualMachines[PT_NUM]; + static int updateVM(UPDATE_FUNC_ARGS); + // + void initElementsAPI(); + static int elements_allocate(lua_State * l); + static int elements_element(lua_State * l); + static int elements_property(lua_State * l); + static int elements_loadDefault(lua_State * l); + static int elements_free(lua_State * l); + + //Interface + void initInterfaceAPI(); + static int interface_showWindow(lua_State * l); + static int interface_closeWindow(lua_State * l); + static int interface_addComponent(lua_State * l); + + //VM + void initVirtualMachineAPI(); + static int virtualMachine_loadProgram(lua_State * l); + + void initGraphicsAPI(); + static int graphics_textSize(lua_State * l); + static int graphics_drawText(lua_State * l); + static int graphics_drawLine(lua_State * l); + static int graphics_drawRect(lua_State * l); + static int graphics_fillRect(lua_State * l); + + void initFileSystemAPI(); + static int fileSystem_list(lua_State * l); + static int fileSystem_exists(lua_State * l); + static int fileSystem_isFile(lua_State * l); + static int fileSystem_isDirectory(lua_State * l); + static int fileSystem_makeDirectory(lua_State * l); + static int fileSystem_removeDirectory(lua_State * l); + static int fileSystem_removeFile(lua_State * l); + static int fileSystem_move(lua_State * l); + static int fileSystem_copy(lua_State * l); + +public: + ui::Window * Window; + lua_State *l; + LuaScriptInterface(GameController * c, GameModel * m); + virtual bool OnBrushChanged(int brushType, int rx, int ry); + virtual bool OnMouseMove(int x, int y, int dx, int dy); + virtual bool OnMouseDown(int x, int y, unsigned button); + virtual bool OnMouseUp(int x, int y, unsigned button); + virtual bool OnMouseWheel(int x, int y, int d); + virtual bool OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual bool OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual void OnTick(); + virtual void Init(); + virtual void SetWindow(ui::Window * window); + virtual int Command(std::string command); + virtual std::string FormatCommand(std::string command); + virtual ~LuaScriptInterface(); +}; + + +#endif /* LUASCRIPTINTERFACE_H_ */ diff --git a/src/cat/LuaSlider.cpp b/src/cat/LuaSlider.cpp new file mode 100644 index 0000000..0fedbfb --- /dev/null +++ b/src/cat/LuaSlider.cpp @@ -0,0 +1,112 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaSlider.h" +#include "LuaScriptInterface.h" +#include "interface/Slider.h" + +const char LuaSlider::className[] = "Slider"; + +#define method(class, name) {#name, &class::name} +Luna<LuaSlider>::RegType LuaSlider::methods[] = { + method(LuaSlider, onValueChanged), + method(LuaSlider, position), + method(LuaSlider, size), + method(LuaSlider, visible), + method(LuaSlider, value), + method(LuaSlider, steps), + {0, 0} +}; + +LuaSlider::LuaSlider(lua_State * l) : + LuaComponent(l), + onValueChangedFunction(0) +{ + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + int steps = luaL_optinteger(l, 5, 10); + + slider = new ui::Slider(ui::Point(posX, posY), ui::Point(sizeX, sizeY), steps); + component = slider; + class ValueAction : public ui::SliderAction + { + LuaSlider * luaSlider; + public: + ValueAction(LuaSlider * luaSlider) : luaSlider(luaSlider) {} + void ValueChangedCallback(ui::Slider * sender) + { + luaSlider->triggerOnValueChanged(); + } + }; + slider->SetActionCallback(new ValueAction(this)); +} + +int LuaSlider::steps(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + slider->SetSteps(lua_tointeger(l, 1)); + return 0; + } + else + { + lua_pushinteger(l, slider->GetSteps()); + return 1; + } +} + +int LuaSlider::onValueChanged(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onValueChangedFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onValueChangedFunction = 0; + } + return 0; +} + +int LuaSlider::value(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + slider->SetValue(lua_tointeger(l, 1)); + return 0; + } + else + { + lua_pushinteger(l, slider->GetValue()); + return 1; + } +} + +void LuaSlider::triggerOnValueChanged() +{ + if(onValueChangedFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onValueChangedFunction); + lua_rawgeti(l, LUA_REGISTRYINDEX, UserData); + lua_pushinteger(l, slider->GetValue()); + if (lua_pcall(l, 2, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +LuaSlider::~LuaSlider() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaSlider.h b/src/cat/LuaSlider.h new file mode 100644 index 0000000..f9f327e --- /dev/null +++ b/src/cat/LuaSlider.h @@ -0,0 +1,33 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class Slider; +} + +class LuaScriptInterface; + +class LuaSlider: public LuaComponent +{ + ui::Slider * slider; + int onValueChangedFunction; + void triggerOnValueChanged(); + int onValueChanged(lua_State * l); + int steps(lua_State * l); + int value(lua_State * l); +public: + static const char className[]; + static Luna<LuaSlider>::RegType methods[]; + + LuaSlider(lua_State * l); + ~LuaSlider(); +};
\ No newline at end of file diff --git a/src/cat/LuaTextbox.cpp b/src/cat/LuaTextbox.cpp new file mode 100644 index 0000000..fa5753c --- /dev/null +++ b/src/cat/LuaTextbox.cpp @@ -0,0 +1,116 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaScriptInterface.h" +#include "LuaTextbox.h" +#include "interface/Textbox.h" + +const char LuaTextbox::className[] = "Textbox"; + +#define method(class, name) {#name, &class::name} +Luna<LuaTextbox>::RegType LuaTextbox::methods[] = { + method(LuaTextbox, text), + method(LuaTextbox, readonly), + method(LuaTextbox, onTextChanged), + method(LuaTextbox, position), + method(LuaTextbox, size), + method(LuaTextbox, visible), + {0, 0} +}; + +LuaTextbox::LuaTextbox(lua_State * l) : + LuaComponent(l), + onTextChangedFunction(0) +{ + this->l = l; + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + std::string text = luaL_optstring(l, 5, ""); + std::string placeholder = luaL_optstring(l, 6, ""); + + textbox = new ui::Textbox(ui::Point(posX, posY), ui::Point(sizeX, sizeY), text, placeholder); + textbox->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + class TextChangedAction : public ui::TextboxAction + { + LuaTextbox * t; + public: + TextChangedAction(LuaTextbox * t) : t(t) {} + void TextChangedCallback(ui::Textbox * sender) + { + t->triggerOnTextChanged(); + } + }; + textbox->SetActionCallback(new TextChangedAction(this)); + component = textbox; +} + +int LuaTextbox::readonly(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TBOOLEAN); + textbox->ReadOnly = lua_toboolean(l, 1); + return 0; + } + else + { + lua_pushboolean(l, textbox->ReadOnly); + return 1; + } +} + +int LuaTextbox::onTextChanged(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onTextChangedFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onTextChangedFunction = 0; + } + return 0; +} + +void LuaTextbox::triggerOnTextChanged() +{ + if(onTextChangedFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onTextChangedFunction); + lua_rawgeti(l, LUA_REGISTRYINDEX, UserData); + if (lua_pcall(l, 1, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +int LuaTextbox::text(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TSTRING); + textbox->SetText(lua_tostring(l, 1)); + return 0; + } + else + { + lua_pushstring(l, textbox->GetText().c_str()); + return 1; + } +} + +LuaTextbox::~LuaTextbox() +{ +}
\ No newline at end of file diff --git a/src/cat/LuaTextbox.h b/src/cat/LuaTextbox.h new file mode 100644 index 0000000..437875f --- /dev/null +++ b/src/cat/LuaTextbox.h @@ -0,0 +1,33 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class Textbox; +} + +class LuaScriptInterface; + +class LuaTextbox: public LuaComponent +{ + int onTextChangedFunction; + ui::Textbox * textbox; + int text(lua_State * l); + int readonly(lua_State * l); + int onTextChanged(lua_State * l); + void triggerOnTextChanged(); +public: + static const char className[]; + static Luna<LuaTextbox>::RegType methods[]; + + LuaTextbox(lua_State * l); + ~LuaTextbox(); +};
\ No newline at end of file diff --git a/src/cat/LuaWindow.cpp b/src/cat/LuaWindow.cpp new file mode 100644 index 0000000..433e4d1 --- /dev/null +++ b/src/cat/LuaWindow.cpp @@ -0,0 +1,569 @@ +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +#include <iostream> +#include "LuaScriptInterface.h" +#include "LuaWindow.h" +#include "LuaButton.h" +#include "LuaLabel.h" +#include "LuaTextbox.h" +#include "LuaCheckbox.h" +#include "LuaSlider.h" +#include "LuaProgressBar.h" +#include "interface/Button.h" +#include "interface/Label.h" +#include "interface/Window.h" + +const char LuaWindow::className[] = "Window"; + +#define method(class, name) {#name, &class::name} +Luna<LuaWindow>::RegType LuaWindow::methods[] = { + method(LuaWindow, position), + method(LuaWindow, size), + method(LuaWindow, addComponent), + method(LuaWindow, onInitialized), + method(LuaWindow, onExit), + method(LuaWindow, onTick), + method(LuaWindow, onDraw), + method(LuaWindow, onFocus), + method(LuaWindow, onBlur), + method(LuaWindow, onTryExit), + method(LuaWindow, onTryOkay), + method(LuaWindow, onMouseMove), + method(LuaWindow, onMouseDown), + method(LuaWindow, onMouseUp), + method(LuaWindow, onMouseWheel), + method(LuaWindow, onKeyPress), + method(LuaWindow, onKeyRelease), + {0, 0} +}; + +LuaWindow::LuaWindow(lua_State * l) : + onInitializedFunction(0), + onExitFunction(0), + onTickFunction(0), + onDrawFunction(0), + onFocusFunction(0), + onBlurFunction(0), + onTryExitFunction(0), + onTryOkayFunction(0), + onMouseMoveFunction(0), + onMouseDownFunction(0), + onMouseUpFunction(0), + onMouseWheelFunction(0), + onKeyPressFunction(0), + onKeyReleaseFunction(0) +{ + this->l = l; + int posX = luaL_optinteger(l, 1, 0); + int posY = luaL_optinteger(l, 2, 0); + int sizeX = luaL_optinteger(l, 3, 10); + int sizeY = luaL_optinteger(l, 4, 10); + + lua_pushstring(l, "Luacon_ci"); + lua_gettable(l, LUA_REGISTRYINDEX); + ci = (LuaScriptInterface*)lua_touserdata(l, -1); + lua_pop(l, 1); + + class DrawnWindow : public ui::Window + { + LuaWindow * luaWindow; + public: + DrawnWindow(ui::Point position, ui::Point size, LuaWindow * luaWindow) : ui::Window(position, size), luaWindow(luaWindow) {} + virtual void OnDraw() + { + Graphics * g = ui::Engine::Ref().g; + g->clearrect(Position.X-2, Position.Y-2, Size.X+4, Size.Y+4); + g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 255, 255, 255, 255); + luaWindow->triggerOnDraw(); + } + virtual void OnInitialized() { luaWindow->triggerOnInitialized(); } + virtual void OnExit() { luaWindow->triggerOnExit(); } + virtual void OnTick(float dt) { luaWindow->triggerOnTick( dt); } + virtual void OnFocus() { luaWindow->triggerOnFocus(); } + virtual void OnBlur() { luaWindow->triggerOnBlur(); } + virtual void OnTryExit(ExitMethod) { luaWindow->triggerOnTryExit(); } + virtual void OnTryOkay(OkayMethod) { luaWindow->triggerOnTryOkay(); } + virtual void OnMouseMove(int x, int y, int dx, int dy) { luaWindow->triggerOnMouseMove(x, y, dx, dy); } + virtual void OnMouseDown(int x, int y, unsigned button) { luaWindow->triggerOnMouseDown(x, y, button); } + virtual void OnMouseUp(int x, int y, unsigned button) { luaWindow->triggerOnMouseUp(x, y, button); } + virtual void OnMouseWheel(int x, int y, int d) { luaWindow->triggerOnMouseWheel(x, y, d); } + virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) { luaWindow->triggerOnKeyPress(key, character, shift, ctrl, alt); } + virtual void OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) { luaWindow->triggerOnKeyRelease(key, character, shift, ctrl, alt); } + }; + + window = new DrawnWindow(ui::Point(posX, posY), ui::Point(sizeX, sizeY), this); +} + +int LuaWindow::addComponent(lua_State * l) +{ + void * luaComponent = NULL; + ui::Component * component = NULL; + if(luaComponent = Luna<LuaButton>::tryGet(l, 1)) + component = Luna<LuaButton>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaLabel>::tryGet(l, 1)) + component = Luna<LuaLabel>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaTextbox>::tryGet(l, 1)) + component = Luna<LuaTextbox>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaCheckbox>::tryGet(l, 1)) + component = Luna<LuaCheckbox>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaSlider>::tryGet(l, 1)) + component = Luna<LuaSlider>::get(luaComponent)->GetComponent(); + else if(luaComponent = Luna<LuaProgressBar>::tryGet(l, 1)) + component = Luna<LuaProgressBar>::get(luaComponent)->GetComponent(); + else + luaL_typerror(l, 1, "Component"); + if(component) + window->AddComponent(component); + return 0; +} + +int LuaWindow::position(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + luaL_checktype(l, 2, LUA_TNUMBER); + window->Position = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2)); + return 0; + } + else + { + lua_pushinteger(l, window->Position.X); + lua_pushinteger(l, window->Position.Y); + return 2; + } +} + +int LuaWindow::size(lua_State * l) +{ + int args = lua_gettop(l); + if(args) + { + luaL_checktype(l, 1, LUA_TNUMBER); + luaL_checktype(l, 2, LUA_TNUMBER); + window->Size = ui::Point(lua_tointeger(l, 1), lua_tointeger(l, 2)); + return 0; + } + else + { + lua_pushinteger(l, window->Size.X); + lua_pushinteger(l, window->Size.Y); + return 2; + } +} + +void LuaWindow::triggerOnInitialized() +{ + if(onInitializedFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onInitializedFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnExit() +{ + if(onExitFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onExitFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnTick(float dt) +{ + if(onTickFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onTickFunction); + lua_pushnumber(l, dt); + if(lua_pcall(l, 1, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnDraw() +{ + if(onDrawFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onDrawFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnFocus() +{ + if(onFocusFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onFocusFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnBlur() +{ + if(onBlurFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onBlurFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnTryExit() +{ + if(onTryExitFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onTryExitFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnTryOkay() +{ + if(onTryOkayFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onTryOkayFunction); + if(lua_pcall(l, 0, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnMouseMove(int x, int y, int dx, int dy) +{ + if(onMouseMoveFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseMoveFunction); + lua_pushinteger(l, x); + lua_pushinteger(l, y); + lua_pushinteger(l, dx); + lua_pushinteger(l, dy); + if(lua_pcall(l, 4, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnMouseDown(int x, int y, unsigned button) +{ + if(onMouseDownFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseDownFunction); + lua_pushinteger(l, x); + lua_pushinteger(l, y); + lua_pushinteger(l, button); + if(lua_pcall(l, 3, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnMouseUp(int x, int y, unsigned button) +{ + if(onMouseUpFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseUpFunction); + lua_pushinteger(l, x); + lua_pushinteger(l, y); + lua_pushinteger(l, button); + if(lua_pcall(l, 3, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnMouseWheel(int x, int y, int d) +{ + if(onMouseWheelFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onMouseWheelFunction); + lua_pushinteger(l, x); + lua_pushinteger(l, y); + lua_pushinteger(l, d); + if(lua_pcall(l, 3, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(onKeyPressFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onKeyPressFunction); + lua_pushinteger(l, key); + lua_pushinteger(l, character); + lua_pushboolean(l, shift); + lua_pushboolean(l, ctrl); + lua_pushboolean(l, alt); + if(lua_pcall(l, 5, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +void LuaWindow::triggerOnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if(onKeyReleaseFunction) + { + lua_rawgeti(l, LUA_REGISTRYINDEX, onKeyReleaseFunction); + lua_pushinteger(l, key); + lua_pushinteger(l, character); + lua_pushboolean(l, shift); + lua_pushboolean(l, ctrl); + lua_pushboolean(l, alt); + if(lua_pcall(l, 5, 0, 0)) + { + ci->Log(CommandInterface::LogError, lua_tostring(l, -1)); + } + } +} + +int LuaWindow::onInitialized(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onInitializedFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onInitializedFunction = 0; + } + return 0; +} + +int LuaWindow::onExit(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onExitFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onExitFunction = 0; + } + return 0; +} + +int LuaWindow::onTick(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onTickFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onTickFunction = 0; + } + return 0; +} + +int LuaWindow::onDraw(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onDrawFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onDrawFunction = 0; + } + return 0; +} + +int LuaWindow::onFocus(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onFocusFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onFocusFunction = 0; + } + return 0; +} + +int LuaWindow::onBlur(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onBlurFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onBlurFunction = 0; + } + return 0; +} + +int LuaWindow::onTryExit(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onTryExitFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onTryExitFunction = 0; + } + return 0; +} + +int LuaWindow::onTryOkay(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onTryOkayFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onTryOkayFunction = 0; + } + return 0; +} + +int LuaWindow::onMouseMove(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onMouseMoveFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onMouseMoveFunction = 0; + } + return 0; +} + +int LuaWindow::onMouseDown(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onMouseDownFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onMouseDownFunction = 0; + } + return 0; +} + +int LuaWindow::onMouseUp(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onMouseUpFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onMouseUpFunction = 0; + } + return 0; +} + +int LuaWindow::onMouseWheel(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onMouseWheelFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onMouseWheelFunction = 0; + } + return 0; +} + +int LuaWindow::onKeyPress(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onKeyPressFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onKeyPressFunction = 0; + } + return 0; +} + +int LuaWindow::onKeyRelease(lua_State * l) +{ + if(lua_type(l, 1) != LUA_TNIL) + { + luaL_checktype(l, 1, LUA_TFUNCTION); + lua_pushvalue(l, 1); + onKeyReleaseFunction = luaL_ref(l, LUA_REGISTRYINDEX); + } + else + { + onKeyReleaseFunction = 0; + } + return 0; +} + + +LuaWindow::~LuaWindow() +{ + if(ui::Engine::Ref().GetWindow() == window) + ui::Engine::Ref().CloseWindow(); + delete window; +}
\ No newline at end of file diff --git a/src/cat/LuaWindow.h b/src/cat/LuaWindow.h new file mode 100644 index 0000000..be6af92 --- /dev/null +++ b/src/cat/LuaWindow.h @@ -0,0 +1,81 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" + +#include "interface/Platform.h" +namespace ui +{ + class Window; +} + +class LuaScriptInterface; +class LuaWindow +{ + int onInitializedFunction; + int onExitFunction; + int onTickFunction; + int onDrawFunction; + int onFocusFunction; + int onBlurFunction; + int onTryExitFunction; + int onTryOkayFunction; + int onMouseMoveFunction; + int onMouseDownFunction; + int onMouseUpFunction; + int onMouseWheelFunction; + int onKeyPressFunction; + int onKeyReleaseFunction; + + ui::Window * window; + lua_State * l; + int position(lua_State * l); + int size(lua_State * l); + int addComponent(lua_State * l); + + //Set event handlers + int onInitialized(lua_State * l); + int onExit(lua_State * l); + int onTick(lua_State * l); + int onDraw(lua_State * l); + int onFocus(lua_State * l); + int onBlur(lua_State * l); + int onTryExit(lua_State * l); + int onTryOkay(lua_State * l); + int onMouseMove(lua_State * l); + int onMouseDown(lua_State * l); + int onMouseUp(lua_State * l); + int onMouseWheel(lua_State * l); + int onKeyPress(lua_State * l); + int onKeyRelease(lua_State * l); + + void triggerOnInitialized(); + void triggerOnExit(); + void triggerOnTick(float deltaTime); + void triggerOnDraw(); + void triggerOnFocus(); + void triggerOnBlur(); + void triggerOnTryExit(); + void triggerOnTryOkay(); + void triggerOnMouseMove(int x, int y, int dx, int dy); + void triggerOnMouseDown(int x, int y, unsigned button); + void triggerOnMouseUp(int x, int y, unsigned button); + void triggerOnMouseWheel(int x, int y, int d); + void triggerOnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + void triggerOnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + +public: + LuaScriptInterface * ci; + int UserData; + static const char className[]; + static Luna<LuaWindow>::RegType methods[]; + + ui::Window * GetWindow() { return window; } + LuaWindow(lua_State * l); + ~LuaWindow(); +};
\ No newline at end of file diff --git a/src/cat/TPTSTypes.cpp b/src/cat/TPTSTypes.cpp new file mode 100644 index 0000000..a8fa962 --- /dev/null +++ b/src/cat/TPTSTypes.cpp @@ -0,0 +1,113 @@ +/* + * TPTSTypes.cpp + * + * Created on: Feb 4, 2012 + * Author: Simon + */ + +#include <iostream> +#include <sstream> +#include <stdint.h> +#include "TPTSTypes.h" + +AnyType::AnyType(ValueType type_, void * value_): + type(type_), + value(value_) +{ +} + +ValueType AnyType::GetType() +{ + return type; +} + +AnyType::AnyType(const AnyType & v): + type(v.type), + value(v.value) +{ + if(type == TypeString) + { + value = new std::string(*((std::string*)value)); + } + else if(type == TypePoint) + { + value = new ui::Point(*((ui::Point*)value)); + } +} + +AnyType::operator NumberType() +{ + if(type != TypeNumber) + throw InvalidConversionException(type, TypeNumber); + else + return NumberType((intptr_t)value); +} + +AnyType::operator StringType() +{ + if(type == TypeNumber) + { + std::stringstream numberStream; + numberStream << ((NumberType*)this)->Value(); + return StringType(numberStream.str()); + } + else if(type == TypeString && value) + { + return StringType(*((std::string*)value)); + } + else + throw InvalidConversionException(type, TypeString); + +} + +AnyType::operator PointType() +{ + if(type == TypePoint) + { + return PointType(*((ui::Point*)value)); + } + else if(type == TypeString) + { + ui::Point thisPoint = *((ui::Point*)value); + std::stringstream pointStream; + pointStream << thisPoint.X << "," << thisPoint.Y; + return StringType(pointStream.str()); + } + else + throw InvalidConversionException(type, TypePoint); +} + +AnyType::~AnyType() +{ + if(type == TypeString || type == TypePoint) + delete value; +} + +//Number Type + +NumberType::NumberType(int number): AnyType(TypeNumber, (void*)number) { } + +int NumberType::Value() +{ + return (intptr_t)value; +} + +//String type + +StringType::StringType(std::string string): AnyType(TypeString, new std::string(string)) { } + +std::string StringType::Value() +{ + return std::string(*((std::string*)value)); +} + +//Point type + +PointType::PointType(ui::Point point): AnyType(TypePoint, new ui::Point(point)) { } + +PointType::PointType(int pointX, int pointY): AnyType(TypePoint, new ui::Point(pointX, pointY)) { } + +ui::Point PointType::Value() +{ + return ui::Point(*((ui::Point*)value)); +} diff --git a/src/cat/TPTSTypes.h b/src/cat/TPTSTypes.h new file mode 100644 index 0000000..dfea425 --- /dev/null +++ b/src/cat/TPTSTypes.h @@ -0,0 +1,119 @@ +/* + * TPTSTypes.h + * + * Created on: Feb 4, 2012 + * Author: Simon + */ + +#ifndef TPTSTYPES_H_ +#define TPTSTYPES_H_ + +#include <string> +#include <typeinfo> +#include "interface/Point.h" + +enum ValueType { TypeNumber, TypePoint, TypeString, TypeNull, TypeFunction }; + +class GeneralException +{ +protected: + std::string exception; +public: + GeneralException(std::string message){ + exception = message; + } + std::string GetExceptionMessage() { + return exception; + } +}; + + +class NumberType; +class StringType; +class PointType; + +class AnyType +{ +protected: + ValueType type; + void * value; +public: + AnyType(ValueType type_, void * value_); + AnyType(const AnyType & v); + operator NumberType(); + operator StringType(); + operator PointType(); + ValueType GetType(); + std::string TypeName() + { + switch(type) + { + case TypeNumber: + return "Number"; + case TypePoint: + return "Point"; + case TypeString: + return "String"; + case TypeNull: + return "Null"; + case TypeFunction: + return "Function"; + default: + return "Unknown"; + } + } + static std::string TypeName(ValueType type) + { + switch(type) + { + case TypeNumber: + return "Number"; + case TypePoint: + return "Point"; + case TypeString: + return "String"; + case TypeNull: + return "Null"; + case TypeFunction: + return "Function"; + default: + return "Unknown"; + } + } + ~AnyType(); +}; + +class InvalidConversionException: public GeneralException +{ +private: + ValueType from; + ValueType to; +public: + InvalidConversionException(ValueType from_, ValueType to_): + GeneralException("Invalid conversion from " + AnyType::TypeName(from_) + " to " + AnyType::TypeName(to_)), from(from_), to(to_) { + } +}; + +class NumberType: public AnyType +{ +public: + NumberType(int number); + int Value(); +}; + +class StringType: public AnyType +{ +public: + StringType(std::string string); + std::string Value(); +}; + +class PointType: public AnyType +{ +public: + PointType(ui::Point point); + PointType(int pointX, int pointY); + ui::Point Value(); +}; + +#endif /* TPTSTYPES_H_ */ diff --git a/src/cat/TPTScriptInterface.cpp b/src/cat/TPTScriptInterface.cpp new file mode 100644 index 0000000..684467f --- /dev/null +++ b/src/cat/TPTScriptInterface.cpp @@ -0,0 +1,488 @@ +/* + * TPTScriptInterface.cpp + * + * Created on: Feb 5, 2012 + * Author: Simon + */ + +#include <stack> +#include <iostream> +#include <string> +#include <deque> +#include <string.h> +#include <stdlib.h> +#include "TPTScriptInterface.h" +#include "game/GameModel.h" +#include "simulation/Air.h" + +TPTScriptInterface::TPTScriptInterface(GameController * c, GameModel * m): CommandInterface(c, m) +{ +} + +int TPTScriptInterface::Command(std::string command) +{ + lastError = ""; + std::deque<std::string> words; + std::deque<AnyType> commandWords; + int retCode; + + //Split command into words, put them on the stack + char * rawCommand; + rawCommand = (char*)calloc(command.length()+1, 1); + memcpy(rawCommand, (char*)command.c_str(), command.length()); + char * currentWord = rawCommand; + char * currentCommand = rawCommand; + while((currentCommand = strchr(currentCommand, ' '))) + { + currentCommand[0] = 0; + words.push_back(std::string(currentWord)); + currentWord = ++currentCommand; + } + words.push_back(std::string(currentWord)); + while(!words.empty()) + { + try + { + commandWords.push_back(eval(&words)); + } + catch (GeneralException & e) + { + retCode = -1; + lastError = e.GetExceptionMessage(); + break; + } + } + free(rawCommand); + if(commandWords.size()) + { + retCode = 0; + lastError = ((StringType)commandWords.front()).Value(); + } + + //Evaluate + return 0; +} + +ValueType TPTScriptInterface::testType(std::string word) +{ + int i = 0; + char * rawWord = (char *)word.c_str(); + //Function + if(word == "set") + return TypeFunction; + else if(word == "create") + return TypeFunction; + else if(word == "delete") + return TypeFunction; + else if(word == "kill") + return TypeFunction; + else if(word == "load") + return TypeFunction; + else if(word == "reset") + return TypeFunction; + else if(word == "bubble") + return TypeFunction; + else if(word == "quit") + return TypeFunction; + //Basic type + parseNumber: + for(i = 0; i < word.length(); i++) + { + if(!(rawWord[i] >= '0' && rawWord[i] <= '9') && rawWord[i] != '.' && !(rawWord[i] == '-' && !i)) + { + if(rawWord[i] == ',' && rawWord[i+1] >= '0' && rawWord[i+1] <= '9') + goto parsePoint; + else + goto parseString; + } + } + return TypeNumber; + parsePoint: + i++; + for(; i < word.length(); i++) + if(!(rawWord[i] >= '0' && rawWord[i] <= '9')) + { + goto parseString; + } + return TypePoint; + parseString: + return TypeString; +} + +AnyType TPTScriptInterface::eval(std::deque<std::string> * words) +{ + if(words->size() < 1) + return AnyType(TypeNull, NULL); + std::string word = words->front(); words->pop_front(); + char * rawWord = (char *)word.c_str(); + ValueType wordType = testType(word); + switch(wordType) + { + case TypeFunction: + if(word == "set") + return tptS_set(words); + else if(word == "create") + return tptS_create(words); + else if(word == "delete" || word == "kill") + return tptS_delete(words); + else if(word == "load") + return tptS_load(words); + else if(word == "reset") + return tptS_reset(words); + else if(word == "bubble") + return tptS_bubble(words); + else if(word == "quit") + return tptS_quit(words); + break; + case TypeNumber: + return NumberType(atoi(rawWord)); + case TypePoint: + { + int pointX, pointY; + sscanf(rawWord, "%d,%d", &pointX, &pointY); + return PointType(pointX, pointY); + } + case TypeString: + return StringType(word); + } +} + +std::string TPTScriptInterface::FormatCommand(std::string command) +{ + std::deque<std::string> words; + std::deque<AnyType> commandWords; + std::string outputData; + + //Split command into words, put them on the stack + char * rawCommand; + rawCommand = (char*)calloc(command.length()+1, 1); + memcpy(rawCommand, (char*)command.c_str(), command.length()); + char * currentWord = rawCommand; + char * currentCommand = rawCommand; + while((currentCommand = strchr(currentCommand, ' '))) + { + currentCommand[0] = 0; + words.push_back(std::string(currentWord)); + currentWord = ++currentCommand; + } + words.push_back(std::string(currentWord)); + free(rawCommand); + while(!words.empty()) + { + ValueType cType = testType(words.front()); + switch(cType) + { + case TypeFunction: + outputData += "\bt"; + break; + case TypeNumber: + case TypePoint: + outputData += "\bo"; + break; + case TypeString: + outputData += "\bg"; + break; + default: + outputData += "\bw"; + break; + } + outputData += words.front() + " "; + words.pop_front(); + } + return outputData; +} + +AnyType TPTScriptInterface::tptS_set(std::deque<std::string> * words) +{ + //Arguments from stack + StringType property = eval(words); + AnyType selector = eval(words); + AnyType value = eval(words); + + Simulation * sim = m->GetSimulation(); + unsigned char * partsBlock = (unsigned char*)&sim->parts[0]; + + int returnValue = 0; + + FormatType propertyFormat; + int propertyOffset = GetPropertyOffset(property.Value(), propertyFormat); + + if(propertyOffset==-1) + throw GeneralException("Invalid property"); + + //Selector + int newValue; + if(value.GetType() == TypeNumber) + newValue = ((NumberType)value).Value(); + else if(value.GetType() == TypeString) + { + newValue = GetParticleType(((StringType)value).Value()); + if (newValue < 0 || newValue >= PT_NUM) + { + if (((StringType)value).Value() == "GOLD" || ((StringType)value).Value() == "gold") + throw GeneralException("No, GOLD will not be an element"); + else + throw GeneralException("Invalid element"); + } + } + else + throw GeneralException("Invalid value for assignment"); + if (property.Value() == "type" && (newValue < 0 || newValue >= PT_NUM)) + throw GeneralException("Invalid element"); + + if(selector.GetType() == TypePoint || selector.GetType() == TypeNumber) + { + int partIndex = -1; + if(selector.GetType() == TypePoint) + { + ui::Point tempPoint = ((PointType)selector).Value(); + if(tempPoint.X<0 || tempPoint.Y<0 || tempPoint.Y >= YRES || tempPoint.X >= XRES) + throw GeneralException("Invalid position"); + + } + else + partIndex = ((NumberType)selector).Value(); + if(partIndex<0 || partIndex>NPART || sim->parts[partIndex].type==0) + throw GeneralException("Invalid particle"); + + switch(propertyFormat) + { + case FormatInt: + *((int*)(partsBlock+(partIndex*sizeof(Particle))+propertyOffset)) = newValue; + break; + case FormatFloat: + *((float*)(partsBlock+(partIndex*sizeof(Particle))+propertyOffset)) = newValue; + break; + } + returnValue = 1; + } + else if(selector.GetType() == TypeString && ((StringType)selector).Value() == "all") + { + switch(propertyFormat) + { + case FormatInt: + { + for(int j = 0; j < NPART; j++) + if(sim->parts[j].type) + { + returnValue++; + *((int*)(partsBlock+(j*sizeof(Particle))+propertyOffset)) = newValue; + } + } + break; + case FormatFloat: + { + for(int j = 0; j < NPART; j++) + if(sim->parts[j].type) + { + returnValue++; + *((float*)(partsBlock+(j*sizeof(Particle))+propertyOffset)) = newValue; + } + } + break; + } + } + else if(selector.GetType() == TypeString || selector.GetType() == TypeNumber) + { + int type; + if(selector.GetType() == TypeNumber) + type = ((NumberType)selector).Value(); + else if(selector.GetType() == TypeString) + type = GetParticleType(((StringType)selector).Value()); + + if(type<0 || type>=PT_NUM) + throw GeneralException("Invalid particle type"); + std::cout << propertyOffset << std::endl; + switch(propertyFormat) + { + case FormatInt: + { + for(int j = 0; j < NPART; j++) + if(sim->parts[j].type == type) + { + returnValue++; + *((int*)(partsBlock+(j*sizeof(Particle))+propertyOffset)) = newValue; + } + } + break; + case FormatFloat: + { + for(int j = 0; j < NPART; j++) + if(sim->parts[j].type == type) + { + returnValue++; + *((float*)(partsBlock+(j*sizeof(Particle))+propertyOffset)) = newValue; + } + } + break; + } + } + else + throw GeneralException("Invalid selector"); + return NumberType(returnValue); +} + +AnyType TPTScriptInterface::tptS_create(std::deque<std::string> * words) +{ + //Arguments from stack + AnyType createType = eval(words); + PointType position = eval(words); + + Simulation * sim = m->GetSimulation(); + + int type; + if(createType.GetType() == TypeNumber) + type = ((NumberType)createType).Value(); + else if(createType.GetType() == TypeString) + type = GetParticleType(((StringType)createType).Value()); + else + throw GeneralException("Invalid type"); + + if(type == -1) + throw GeneralException("Invalid particle type"); + + ui::Point tempPoint = position.Value(); + if(tempPoint.X<0 || tempPoint.Y<0 || tempPoint.Y >= YRES || tempPoint.X >= XRES) + throw GeneralException("Invalid position"); + + int returnValue = sim->create_part(-1, tempPoint.X, tempPoint.Y, type); + + return NumberType(returnValue); +} + +AnyType TPTScriptInterface::tptS_delete(std::deque<std::string> * words) +{ + //Arguments from stack + AnyType partRef = eval(words); + + Simulation * sim = m->GetSimulation(); + + if(partRef.GetType() == TypePoint) + { + ui::Point deletePoint = ((PointType)partRef).Value(); + if(deletePoint.X<0 || deletePoint.Y<0 || deletePoint.Y >= YRES || deletePoint.X >= XRES) + throw GeneralException("Invalid position"); + sim->delete_part(deletePoint.X, deletePoint.Y, 0); + } + else if(partRef.GetType() == TypeNumber) + { + int partIndex = ((NumberType)partRef).Value(); + if(partIndex < 0 || partIndex >= NPART) + throw GeneralException("Invalid particle index"); + sim->kill_part(partIndex); + } + else + throw GeneralException("Invalid particle reference"); + + return NumberType(0); +} + +AnyType TPTScriptInterface::tptS_load(std::deque<std::string> * words) +{ + //Arguments from stack + NumberType saveID = eval(words); + + c->OpenSavePreview(saveID.Value(), 0); + + return NumberType(0); +} + +AnyType TPTScriptInterface::tptS_bubble(std::deque<std::string> * words) +{ + //Arguments from stack + PointType bubblePosA = eval(words); + ui::Point bubblePos = bubblePosA.Value(); + + if(bubblePos.X<0 || bubblePos.Y<0 || bubblePos.Y >= YRES || bubblePos.X >= XRES) + throw GeneralException("Invalid position"); + + Simulation * sim = m->GetSimulation(); + + int first, rem1, rem2; + + first = sim->create_part(-1, bubblePos.X+18, bubblePos.Y, PT_SOAP); + rem1 = first; + + for (int i = 1; i<=30; i++) + { + rem2 = sim->create_part(-1, bubblePos.X+18*cosf(i/5.0), bubblePos.Y+18*sinf(i/5.0), PT_SOAP); + + sim->parts[rem1].ctype = 7; + sim->parts[rem1].tmp = rem2; + sim->parts[rem2].tmp2 = rem1; + + rem1 = rem2; + } + + sim->parts[rem1].ctype = 7; + sim->parts[rem1].tmp = first; + sim->parts[first].tmp2 = rem1; + sim->parts[first].ctype = 7; + + return NumberType(0); +} + +AnyType TPTScriptInterface::tptS_reset(std::deque<std::string> * words) +{ + //Arguments from stack + StringType reset = eval(words); + std::string resetStr = reset.Value(); + + Simulation * sim = m->GetSimulation(); + + if (resetStr == "pressure") + { + for (int nx = 0; nx < XRES/CELL; nx++) + for (int ny = 0; ny < YRES/CELL; ny++) + { + sim->air->pv[ny][nx] = 0; + } + } + else if (resetStr == "velocity") + { + for (int nx = 0; nx < XRES/CELL; nx++) + for (int ny = 0; ny < YRES/CELL; ny++) + { + sim->air->vx[ny][nx] = 0; + sim->air->vy[ny][nx] = 0; + } + } + else if (resetStr == "sparks") + { + for (int i = 0; i < NPART; i++) + { + if (sim->parts[i].type == PT_SPRK) + { + sim->parts[i].type = sim->parts[i].ctype; + sim->parts[i].life = 4; + } + } + } + else if (resetStr == "temp") + { + for (int i = 0; i < NPART; i++) + { + if (sim->parts[i].type) + { + sim->parts[i].temp = sim->elements[sim->parts[i].type].Temperature; + } + } + } + else + { + throw GeneralException("Unknown reset command"); + } + + return NumberType(0); +} + +AnyType TPTScriptInterface::tptS_quit(std::deque<std::string> * words) +{ + ui::Engine::Ref().Exit(); + + return NumberType(0); +} + +TPTScriptInterface::~TPTScriptInterface() { +} + diff --git a/src/cat/TPTScriptInterface.h b/src/cat/TPTScriptInterface.h new file mode 100644 index 0000000..12240fa --- /dev/null +++ b/src/cat/TPTScriptInterface.h @@ -0,0 +1,33 @@ +/* + * TPTScriptInterface.h + * + * Created on: Feb 5, 2012 + * Author: Simon + */ + +#ifndef TPTSCRIPTINTERFACE_H_ +#define TPTSCRIPTINTERFACE_H_ + +#include "CommandInterface.h" +#include "TPTSTypes.h" + +class TPTScriptInterface: public CommandInterface { +protected: + AnyType eval(std::deque<std::string> * words); + AnyType tptS_set(std::deque<std::string> * words); + AnyType tptS_create(std::deque<std::string> * words); + AnyType tptS_delete(std::deque<std::string> * words); + AnyType tptS_load(std::deque<std::string> * words); + AnyType tptS_reset(std::deque<std::string> * words); + AnyType tptS_bubble(std::deque<std::string> * words); + AnyType tptS_quit(std::deque<std::string> * words); + ValueType testType(std::string word); +public: + TPTScriptInterface(GameController * c, GameModel * m); + virtual void Tick() {} + virtual int Command(std::string command); + virtual std::string FormatCommand(std::string command); + virtual ~TPTScriptInterface(); +}; + +#endif /* TPTSCRIPTINTERFACE_H_ */ |
