mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-30 03:09:53 +02:00
Add a few more Lua functions
sim.replaceModeFlags sim.listCustomGol sim.addCustomGol sim.removeCustomGol tpt.perfectCircleBrush sim.floodDeco
This commit is contained in:
@@ -156,33 +156,10 @@ void GOLWindow::Validate()
|
|||||||
Client::Ref().SetPrefUnicode("CustomGOL.Name", nameString);
|
Client::Ref().SetPrefUnicode("CustomGOL.Name", nameString);
|
||||||
Client::Ref().SetPrefUnicode("CustomGOL.Rule", ruleString);
|
Client::Ref().SetPrefUnicode("CustomGOL.Rule", ruleString);
|
||||||
|
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
auto color1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
|
||||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
||||||
bool nameTaken = false;
|
AddCustomGol(ruleString, nameString, color1, color2);
|
||||||
for (auto gol : customGOLTypes)
|
|
||||||
{
|
|
||||||
auto parts = gol.FromUtf8().PartitionBy(' ');
|
|
||||||
if (parts.size())
|
|
||||||
{
|
|
||||||
if (parts[0] == nameString)
|
|
||||||
{
|
|
||||||
nameTaken = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newCustomGOLTypes.append(gol);
|
|
||||||
}
|
|
||||||
if (nameTaken)
|
|
||||||
{
|
|
||||||
new ErrorMessage("Could not add GOL type", "Name already taken");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb;
|
|
||||||
auto colour1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
|
|
||||||
auto colour2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
|
||||||
sb << nameString << " " << ruleString << " " << colour1 << " " << colour2;
|
|
||||||
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
|
||||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
|
||||||
tool->gameModel->SelectNextIdentifier = "DEFAULT_PT_LIFECUST_" + nameString.ToAscii();
|
tool->gameModel->SelectNextIdentifier = "DEFAULT_PT_LIFECUST_" + nameString.ToAscii();
|
||||||
tool->gameModel->SelectNextTool = toolSelection;
|
tool->gameModel->SelectNextTool = toolSelection;
|
||||||
}
|
}
|
||||||
|
@@ -1640,26 +1640,20 @@ void GameModel::SetPerfectCircle(bool perfectCircle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::RemoveCustomGOLType(const ByteString &identifier)
|
bool GameModel::RemoveCustomGOLType(const ByteString &identifier)
|
||||||
{
|
{
|
||||||
|
bool removedAny = false;
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
Json::Value newCustomGOLTypes(Json::arrayValue);
|
||||||
for (auto gol : customGOLTypes)
|
for (auto gol : customGOLTypes)
|
||||||
{
|
{
|
||||||
auto parts = gol.PartitionBy(' ');
|
auto parts = gol.PartitionBy(' ');
|
||||||
bool remove = false;
|
if (parts.size() && "DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
|
||||||
if (parts.size())
|
removedAny = true;
|
||||||
{
|
else
|
||||||
if ("DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
|
|
||||||
{
|
|
||||||
remove = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!remove)
|
|
||||||
{
|
|
||||||
newCustomGOLTypes.append(gol);
|
newCustomGOLTypes.append(gol);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
||||||
BuildMenus();
|
BuildMenus();
|
||||||
|
return removedAny;
|
||||||
}
|
}
|
||||||
|
@@ -238,7 +238,7 @@ public:
|
|||||||
void AddNotification(Notification * notification);
|
void AddNotification(Notification * notification);
|
||||||
void RemoveNotification(Notification * notification);
|
void RemoveNotification(Notification * notification);
|
||||||
|
|
||||||
void RemoveCustomGOLType(const ByteString &identifier);
|
bool RemoveCustomGOLType(const ByteString &identifier);
|
||||||
|
|
||||||
ByteString SelectNextIdentifier;
|
ByteString SelectNextIdentifier;
|
||||||
int SelectNextTool;
|
int SelectNextTool;
|
||||||
|
@@ -1523,4 +1523,16 @@ int luatpt_record(lua_State* l)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int luatpt_perfectCircle(lua_State* l)
|
||||||
|
{
|
||||||
|
if (!lua_gettop(l))
|
||||||
|
{
|
||||||
|
lua_pushboolean(l, luacon_model->GetPerfectCircle());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
luaL_checktype(l, 1, LUA_TBOOLEAN);
|
||||||
|
luacon_model->SetPerfectCircle(lua_toboolean(l, 1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -135,5 +135,6 @@ int luatpt_setwindowsize(lua_State* l);
|
|||||||
int luatpt_screenshot(lua_State* l);
|
int luatpt_screenshot(lua_State* l);
|
||||||
int luatpt_record(lua_State* l);
|
int luatpt_record(lua_State* l);
|
||||||
|
|
||||||
|
int luatpt_perfectCircle(lua_State* l);
|
||||||
|
|
||||||
#endif /* LUASCRIPTHELPER_H_ */
|
#endif /* LUASCRIPTHELPER_H_ */
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "simulation/ElementCommon.h"
|
#include "simulation/ElementCommon.h"
|
||||||
#include "simulation/ElementClasses.h"
|
#include "simulation/ElementClasses.h"
|
||||||
#include "simulation/ElementGraphics.h"
|
#include "simulation/ElementGraphics.h"
|
||||||
|
#include "simulation/GOLString.h"
|
||||||
#include "simulation/Simulation.h"
|
#include "simulation/Simulation.h"
|
||||||
#include "simulation/ToolClasses.h"
|
#include "simulation/ToolClasses.h"
|
||||||
|
|
||||||
@@ -217,6 +218,7 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
|||||||
{"get_clipboard", &platform_clipboardCopy},
|
{"get_clipboard", &platform_clipboardCopy},
|
||||||
{"set_clipboard", &platform_clipboardPaste},
|
{"set_clipboard", &platform_clipboardPaste},
|
||||||
{"setdrawcap", &luatpt_setdrawcap},
|
{"setdrawcap", &luatpt_setdrawcap},
|
||||||
|
{"perfectCircleBrush", &luatpt_perfectCircle},
|
||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -822,6 +824,7 @@ void LuaScriptInterface::initSimulationAPI()
|
|||||||
{"decoBox", simulation_decoBox},
|
{"decoBox", simulation_decoBox},
|
||||||
{"decoColor", simulation_decoColor},
|
{"decoColor", simulation_decoColor},
|
||||||
{"decoColour", simulation_decoColor},
|
{"decoColour", simulation_decoColor},
|
||||||
|
{"floodDeco", simulation_floodDeco},
|
||||||
{"clearSim", simulation_clearSim},
|
{"clearSim", simulation_clearSim},
|
||||||
{"clearRect", simulation_clearRect},
|
{"clearRect", simulation_clearRect},
|
||||||
{"resetTemp", simulation_resetTemp},
|
{"resetTemp", simulation_resetTemp},
|
||||||
@@ -852,6 +855,10 @@ void LuaScriptInterface::initSimulationAPI()
|
|||||||
{"framerender", simulation_framerender},
|
{"framerender", simulation_framerender},
|
||||||
{"gspeed", simulation_gspeed},
|
{"gspeed", simulation_gspeed},
|
||||||
{"takeSnapshot", simulation_takeSnapshot},
|
{"takeSnapshot", simulation_takeSnapshot},
|
||||||
|
{"replaceModeFlags", simulation_replaceModeFlags},
|
||||||
|
{"listCustomGol", simulation_listCustomGol},
|
||||||
|
{"addCustomGol", simulation_addCustomGol},
|
||||||
|
{"removeCustomGol", simulation_removeCustomGol},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
luaL_register(l, "simulation", simulationAPIMethods);
|
luaL_register(l, "simulation", simulationAPIMethods);
|
||||||
@@ -1684,6 +1691,24 @@ int LuaScriptInterface::simulation_decoColor(lua_State * l)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LuaScriptInterface::simulation_floodDeco(lua_State * l)
|
||||||
|
{
|
||||||
|
int x = luaL_checkinteger(l, 1);
|
||||||
|
int y = luaL_checkinteger(l, 2);
|
||||||
|
int r = luaL_checkinteger(l, 3);
|
||||||
|
int g = luaL_checkinteger(l, 4);
|
||||||
|
int b = luaL_checkinteger(l, 5);
|
||||||
|
int a = luaL_checkinteger(l, 6);
|
||||||
|
|
||||||
|
if (x < 0 || x >= XRES || y < 0 || y >= YRES)
|
||||||
|
return luaL_error(l, "coordinates out of range (%d,%d)", x, y);
|
||||||
|
|
||||||
|
// hilariously broken, intersects with console and all Lua graphics
|
||||||
|
pixel loc = luacon_ren->vid[x + y * WINDOWW];
|
||||||
|
luacon_sim->ApplyDecorationFill(luacon_ren, x, y, r, g, b, a, PIXR(loc), PIXG(loc), PIXB(loc));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int LuaScriptInterface::simulation_clearSim(lua_State * l)
|
int LuaScriptInterface::simulation_clearSim(lua_State * l)
|
||||||
{
|
{
|
||||||
luacon_controller->ClearSim();
|
luacon_controller->ClearSim();
|
||||||
@@ -2244,6 +2269,86 @@ int LuaScriptInterface::simulation_takeSnapshot(lua_State * l)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LuaScriptInterface::simulation_replaceModeFlags(lua_State *l)
|
||||||
|
{
|
||||||
|
if (lua_gettop(l) == 0)
|
||||||
|
{
|
||||||
|
lua_pushinteger(l, luacon_controller->GetReplaceModeFlags());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
unsigned int flags = luaL_checkinteger(l, 1);
|
||||||
|
if (flags & ~(REPLACE_MODE | SPECIFIC_DELETE))
|
||||||
|
return luaL_error(l, "Invalid flags");
|
||||||
|
if ((flags & REPLACE_MODE) && (flags & SPECIFIC_DELETE))
|
||||||
|
return luaL_error(l, "Cannot set replace mode and specific delete at the same time");
|
||||||
|
luacon_controller->SetReplaceModeFlags(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaScriptInterface::simulation_listCustomGol(lua_State *l)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
lua_newtable(l);
|
||||||
|
for (auto &cgol : luacon_sim->GetCustomGol())
|
||||||
|
{
|
||||||
|
lua_newtable(l);
|
||||||
|
lua_pushstring(l, cgol.nameString.ToUtf8().c_str());
|
||||||
|
lua_setfield(l, -2, "name");
|
||||||
|
lua_pushstring(l, cgol.ruleString.ToUtf8().c_str());
|
||||||
|
lua_setfield(l, -2, "rulestr");
|
||||||
|
lua_pushnumber(l, cgol.rule);
|
||||||
|
lua_setfield(l, -2, "rule");
|
||||||
|
lua_pushnumber(l, cgol.colour1);
|
||||||
|
lua_setfield(l, -2, "color1");
|
||||||
|
lua_pushnumber(l, cgol.colour2);
|
||||||
|
lua_setfield(l, -2, "color2");
|
||||||
|
lua_rawseti(l, -2, ++i);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaScriptInterface::simulation_addCustomGol(lua_State *l)
|
||||||
|
{
|
||||||
|
int rule;
|
||||||
|
String ruleString;
|
||||||
|
if (lua_isnumber(l, 1))
|
||||||
|
{
|
||||||
|
rule = luaL_checkinteger(l, 1);
|
||||||
|
ruleString = SerialiseGOLRule(rule);
|
||||||
|
rule = ParseGOLString(ruleString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ruleString = ByteString(luaL_checkstring(l, 1)).FromUtf8();
|
||||||
|
rule = ParseGOLString(ruleString);
|
||||||
|
}
|
||||||
|
String nameString = ByteString(luaL_checkstring(l, 2)).FromUtf8();
|
||||||
|
unsigned int color1 = luaL_checkinteger(l, 3);
|
||||||
|
unsigned int color2 = luaL_checkinteger(l, 4);
|
||||||
|
|
||||||
|
if (nameString.empty() || !ValidateGOLName(nameString))
|
||||||
|
return luaL_error(l, "Invalid name provided");
|
||||||
|
if (rule == -1)
|
||||||
|
return luaL_error(l, "Invalid rule provided");
|
||||||
|
if (luacon_sim->GetCustomGOLByRule(rule))
|
||||||
|
return luaL_error(l, "This Custom GoL rule already exists");
|
||||||
|
|
||||||
|
if (!AddCustomGol(ruleString, nameString, color1, color2))
|
||||||
|
return luaL_error(l, "Duplicate name, cannot add");
|
||||||
|
luacon_model->BuildMenus();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaScriptInterface::simulation_removeCustomGol(lua_State *l)
|
||||||
|
{
|
||||||
|
ByteString nameString = luaL_checkstring(l, 1);
|
||||||
|
bool removedAny = luacon_model->RemoveCustomGOLType("DEFAULT_PT_LIFECUST_" + nameString);
|
||||||
|
if (removedAny)
|
||||||
|
luacon_model->BuildMenus();
|
||||||
|
lua_pushboolean(l, removedAny);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//// Begin Renderer API
|
//// Begin Renderer API
|
||||||
|
|
||||||
void LuaScriptInterface::initRendererAPI()
|
void LuaScriptInterface::initRendererAPI()
|
||||||
|
@@ -84,6 +84,7 @@ class LuaScriptInterface: public CommandInterface
|
|||||||
static int simulation_decoLine(lua_State * l);
|
static int simulation_decoLine(lua_State * l);
|
||||||
static int simulation_decoBox(lua_State * l);
|
static int simulation_decoBox(lua_State * l);
|
||||||
static int simulation_decoColor(lua_State * l);
|
static int simulation_decoColor(lua_State * l);
|
||||||
|
static int simulation_floodDeco(lua_State * l);
|
||||||
static int simulation_clearSim(lua_State * l);
|
static int simulation_clearSim(lua_State * l);
|
||||||
static int simulation_clearRect(lua_State * l);
|
static int simulation_clearRect(lua_State * l);
|
||||||
static int simulation_resetTemp(lua_State * l);
|
static int simulation_resetTemp(lua_State * l);
|
||||||
@@ -112,6 +113,11 @@ class LuaScriptInterface: public CommandInterface
|
|||||||
static int simulation_framerender(lua_State * l);
|
static int simulation_framerender(lua_State * l);
|
||||||
static int simulation_gspeed(lua_State * l);
|
static int simulation_gspeed(lua_State * l);
|
||||||
static int simulation_takeSnapshot(lua_State *l);
|
static int simulation_takeSnapshot(lua_State *l);
|
||||||
|
static int simulation_replaceModeFlags(lua_State *l);
|
||||||
|
static int simulation_listCustomGol(lua_State *l);
|
||||||
|
static int simulation_addCustomGol(lua_State *l);
|
||||||
|
static int simulation_removeCustomGol(lua_State *l);
|
||||||
|
|
||||||
|
|
||||||
//Renderer
|
//Renderer
|
||||||
void initRendererAPI();
|
void initRendererAPI();
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "GOLString.h"
|
#include "GOLString.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
|
||||||
int ParseGOLString(const String &value)
|
int ParseGOLString(const String &value)
|
||||||
{
|
{
|
||||||
@@ -93,3 +94,30 @@ String SerialiseGOLRule(int rule)
|
|||||||
}
|
}
|
||||||
return golName.Build();
|
return golName.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
||||||
|
{
|
||||||
|
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||||
|
Json::Value newCustomGOLTypes(Json::arrayValue);
|
||||||
|
bool nameTaken = false;
|
||||||
|
for (auto gol : customGOLTypes)
|
||||||
|
{
|
||||||
|
auto parts = gol.FromUtf8().PartitionBy(' ');
|
||||||
|
if (parts.size())
|
||||||
|
{
|
||||||
|
if (parts[0] == nameString)
|
||||||
|
{
|
||||||
|
nameTaken = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newCustomGOLTypes.append(gol);
|
||||||
|
}
|
||||||
|
if (nameTaken)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
StringBuilder sb;
|
||||||
|
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
||||||
|
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
||||||
|
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@@ -6,3 +6,4 @@
|
|||||||
bool ValidateGOLName(const String &value);
|
bool ValidateGOLName(const String &value);
|
||||||
int ParseGOLString(const String &value);
|
int ParseGOLString(const String &value);
|
||||||
String SerialiseGOLRule(int rule);
|
String SerialiseGOLRule(int rule);
|
||||||
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
||||||
|
@@ -241,6 +241,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
const CustomGOLData *GetCustomGOLByRule(int rule) const;
|
const CustomGOLData *GetCustomGOLByRule(int rule) const;
|
||||||
|
const std::vector<CustomGOLData> GetCustomGol() { return customGol; }
|
||||||
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
|
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user