This engine has a dynamic state. A state is the value of all the fields in all the traits at any given moment. Since the module developer is free to add fields (key/value pairs) to new or existing traits, it follows that the state is not fixed but dynamic.
The dynamic state must be transferred to the C++ part of the engine. Since state is a Lua table, transferring the state means that C++ must have a representation of a Lua table. It is not necessary to have a complete representation, only this:
Only those values of the table that may change are needed, so no meta values or function values.
The data type for a C++ Lua table looks like this:
class Table;
typedef std::variant<int, std::string> Leftside;
typedef std::variant<int, double, bool, std::string, Table> Rightside;
class Table : public std::map<Leftside, Rightside> {};
It is used like this:
Counter::Leftside left;
Counter::Rightside right;
Counter::Table table;
table[left] = right;
Note that the right side can be another Table (nested table).
Even if the state is dynamic the values that the C++ part need to render a counter must be fixed. This means for example that the value of the x,y coordinates of a counter must be identified. The coordinates must have a fixed position so that they may be found by the C++ part. struct State is a subset of the fields in the dynamic state.
struct State // the subset of fields needed to render the counter/card
{
int x;
int y;
bool moved; // only true if trait
int degrees; // only not zero if trait
std::string image; // name of current (flipped) image
int zorder; // position in a stack
// masks
// labels
};
These fields are assigned values from the dynamic state table. C++ needs to know where to find them.
// constructor for map
Counter::Counter(int id, Table *state)
{
this->id = id;
Counter::counters[this->id] = this;
this->name = std::to_string(id);
this->state.x = (int)std::get<double>((*state)["x"]);
this->state.y = (int)std::get<double>((*state)["y"]);
Table images = std::get<Table>(std::get<Table>((*state)["Image"])["images"]);
int index = (int)std::get<double>(std::get<Table>((*state)["Image"])["imageIndex"]);
this->state.image = std::get<std::string>(images[index]);
// optional fields
if ((*state).find("MarkMoved") != (*state).end())
this->state.moved = std::get<bool>(std::get<Table>((*state)["MarkMoved"])["moved"]);
else
this->state.moved = false;
if ((*state).find("Rotate") != (*state).end())
this->state.degrees = (int)std::get<double>(std::get<Table>((*state)["Rotate"])["degrees"]);
else
this->state.degrees = 0;
if ((*state).find("zorder") != (*state).end())
this->state.zorder = (int)std::get<double>((*state)["zorder"]);
else
this->state.zorder = topZorder();
.
.
.
Code found in a new branch here.
CPLUS_INCLUDE_PATH=/home/me/Qt/6.6.2/gcc_64/include;export CPLUS_INCLUDE_PATH
LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/home/me/Qt/6.6.2/gcc_64/lib;export LD_LIBRARY_PATH
g++ -Wall -o main main.cpp luau.cpp counter.cpp window.cpp frame.cpp overlay.cpp io.cpp scale.cpp -I/home/me/luau/VM/include -I/home/me/luau/Compiler/include -I/home/me/Qt/6.6.2/gcc_64/include/QtWidgets -Wl,--copy-dt-needed-entries -L/home/me/Qt/6.6.2/gcc_64/lib -lQt6Core -lQt6Widgets -L/home/me/luau -lLuau.VM -lLuau.Compiler -lLuau.Ast -lisocline