summaryrefslogtreecommitdiff
path: root/src/cat
diff options
context:
space:
mode:
authorSimon 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)
commit058a2edd75debbd0297f92572316daa704bd379f (patch)
treead303f091f9a08b209b91eb34a9fcad996a3de69 /src/cat
parente3594aba9e05c6865d396418c028049cda92c2f3 (diff)
parent7a21ae192fe19868539956f3fe28e62b2c7c4429 (diff)
downloadpowder-058a2edd75debbd0297f92572316daa704bd379f.zip
powder-058a2edd75debbd0297f92572316daa704bd379f.tar.gz
Merge branch 'master' of github.com:FacialTurd/PowderToypp
Diffstat (limited to 'src/cat')
-rw-r--r--src/cat/CommandInterface.cpp118
-rw-r--r--src/cat/CommandInterface.h44
-rw-r--r--src/cat/LegacyLuaAPI.cpp1828
-rw-r--r--src/cat/LuaBit.cpp192
-rw-r--r--src/cat/LuaBit.h32
-rw-r--r--src/cat/LuaButton.cpp114
-rw-r--r--src/cat/LuaButton.h33
-rw-r--r--src/cat/LuaCheckbox.cpp114
-rw-r--r--src/cat/LuaCheckbox.h33
-rw-r--r--src/cat/LuaComponent.cpp82
-rw-r--r--src/cat/LuaComponent.h33
-rw-r--r--src/cat/LuaLabel.cpp56
-rw-r--r--src/cat/LuaLabel.h29
-rw-r--r--src/cat/LuaLuna.h160
-rw-r--r--src/cat/LuaProgressBar.cpp71
-rw-r--r--src/cat/LuaProgressBar.h30
-rw-r--r--src/cat/LuaScriptHelper.h144
-rw-r--r--src/cat/LuaScriptInterface.cpp1706
-rw-r--r--src/cat/LuaScriptInterface.h128
-rw-r--r--src/cat/LuaSlider.cpp112
-rw-r--r--src/cat/LuaSlider.h33
-rw-r--r--src/cat/LuaTextbox.cpp116
-rw-r--r--src/cat/LuaTextbox.h33
-rw-r--r--src/cat/LuaWindow.cpp569
-rw-r--r--src/cat/LuaWindow.h81
-rw-r--r--src/cat/TPTSTypes.cpp113
-rw-r--r--src/cat/TPTSTypes.h119
-rw-r--r--src/cat/TPTScriptInterface.cpp488
-rw-r--r--src/cat/TPTScriptInterface.h33
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 = &currentCommand;
+ 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_ */