Add a few more Lua functions

sim.replaceModeFlags
sim.listCustomGol
sim.addCustomGol
sim.removeCustomGol
tpt.perfectCircleBrush
sim.floodDeco
This commit is contained in:
jacob1 2021-08-27 23:57:55 -04:00
parent 63fe8e46b2
commit 44590d82e9
No known key found for this signature in database
GPG Key ID: 4E58A32D510E1995
10 changed files with 164 additions and 39 deletions

View File

@ -156,33 +156,10 @@ void GOLWindow::Validate()
Client::Ref().SetPrefUnicode("CustomGOL.Name", nameString);
Client::Ref().SetPrefUnicode("CustomGOL.Rule", ruleString);
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)
{
new ErrorMessage("Could not add GOL type", "Name already taken");
return;
}
auto color1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
AddCustomGol(ruleString, nameString, color1, color2);
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->SelectNextTool = toolSelection;
}

View File

@ -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");
Json::Value newCustomGOLTypes(Json::arrayValue);
for (auto gol : customGOLTypes)
{
auto parts = gol.PartitionBy(' ');
bool remove = false;
if (parts.size())
{
if ("DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
{
remove = true;
}
}
if (!remove)
{
if (parts.size() && "DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
removedAny = true;
else
newCustomGOLTypes.append(gol);
}
}
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
BuildMenus();
return removedAny;
}

View File

@ -238,7 +238,7 @@ public:
void AddNotification(Notification * notification);
void RemoveNotification(Notification * notification);
void RemoveCustomGOLType(const ByteString &identifier);
bool RemoveCustomGOLType(const ByteString &identifier);
ByteString SelectNextIdentifier;
int SelectNextTool;

View File

@ -1523,4 +1523,16 @@ int luatpt_record(lua_State* l)
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

View File

@ -135,5 +135,6 @@ int luatpt_setwindowsize(lua_State* l);
int luatpt_screenshot(lua_State* l);
int luatpt_record(lua_State* l);
int luatpt_perfectCircle(lua_State* l);
#endif /* LUASCRIPTHELPER_H_ */

View File

@ -34,6 +34,7 @@
#include "simulation/ElementCommon.h"
#include "simulation/ElementClasses.h"
#include "simulation/ElementGraphics.h"
#include "simulation/GOLString.h"
#include "simulation/Simulation.h"
#include "simulation/ToolClasses.h"
@ -217,6 +218,7 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
{"get_clipboard", &platform_clipboardCopy},
{"set_clipboard", &platform_clipboardPaste},
{"setdrawcap", &luatpt_setdrawcap},
{"perfectCircleBrush", &luatpt_perfectCircle},
{NULL,NULL}
};
@ -822,6 +824,7 @@ void LuaScriptInterface::initSimulationAPI()
{"decoBox", simulation_decoBox},
{"decoColor", simulation_decoColor},
{"decoColour", simulation_decoColor},
{"floodDeco", simulation_floodDeco},
{"clearSim", simulation_clearSim},
{"clearRect", simulation_clearRect},
{"resetTemp", simulation_resetTemp},
@ -852,6 +855,10 @@ void LuaScriptInterface::initSimulationAPI()
{"framerender", simulation_framerender},
{"gspeed", simulation_gspeed},
{"takeSnapshot", simulation_takeSnapshot},
{"replaceModeFlags", simulation_replaceModeFlags},
{"listCustomGol", simulation_listCustomGol},
{"addCustomGol", simulation_addCustomGol},
{"removeCustomGol", simulation_removeCustomGol},
{NULL, NULL}
};
luaL_register(l, "simulation", simulationAPIMethods);
@ -1684,6 +1691,24 @@ int LuaScriptInterface::simulation_decoColor(lua_State * l)
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)
{
luacon_controller->ClearSim();
@ -2244,6 +2269,86 @@ int LuaScriptInterface::simulation_takeSnapshot(lua_State * l)
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
void LuaScriptInterface::initRendererAPI()

View File

@ -84,6 +84,7 @@ class LuaScriptInterface: public CommandInterface
static int simulation_decoLine(lua_State * l);
static int simulation_decoBox(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_clearRect(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_gspeed(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
void initRendererAPI();

View File

@ -1,4 +1,5 @@
#include "GOLString.h"
#include "client/Client.h"
int ParseGOLString(const String &value)
{
@ -93,3 +94,30 @@ String SerialiseGOLRule(int rule)
}
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;
}

View File

@ -6,3 +6,4 @@
bool ValidateGOLName(const String &value);
int ParseGOLString(const String &value);
String SerialiseGOLRule(int rule);
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);

View File

@ -241,6 +241,7 @@ private:
public:
const CustomGOLData *GetCustomGOLByRule(int rule) const;
const std::vector<CustomGOLData> GetCustomGol() { return customGol; }
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
private: