Make GameModel tool list persistent

That is, it's not thrown away and rebuilt every time the underlying set of tools changes (the "derivation" approach). Rather, changes to the underlying set are applied to GameModel's list (the "persistent" approach).

Normally, I'd prefer the derivation approach if its overhead is small enough, which in this case it would be. However, this change, among a few others, is done in preparation for exposing tool functionality to Lua. The Lua side will use persistent numeric identifiers to refer to tools, which means at least Lua tools would need to follow the persistent approach, at which point it makes more sense for all tools to do so, than a hybrid approach.
This commit is contained in:
Tamás Bálint Misius 2024-09-14 12:15:27 +02:00
parent c1a859c106
commit ff4500620e
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
7 changed files with 293 additions and 266 deletions

View File

@ -1099,7 +1099,7 @@ int GameController::GetNumMenus(bool onlyEnabled)
void GameController::RebuildFavoritesMenu()
{
gameModel->BuildFavoritesMenu();
gameModel->BuildMenus();
}
Tool * GameController::GetActiveTool(int selection)
@ -1326,24 +1326,15 @@ void GameController::OpenProfile()
void GameController::OpenElementSearch()
{
std::vector<Tool*> toolList;
std::vector<Menu*> menuList = gameModel->GetMenuList();
for (auto i = 0U; i < menuList.size(); ++i)
std::vector<Tool *> toolList;
for (auto &ptr : gameModel->GetTools())
{
if (i == SC_FAVORITES)
if (!ptr)
{
continue;
}
auto *mm = menuList[i];
if(!mm)
continue;
std::vector<Tool*> menuToolList = mm->GetToolList();
if(!menuToolList.size())
continue;
toolList.insert(toolList.end(), menuToolList.begin(), menuToolList.end());
toolList.push_back(ptr.get());
}
std::vector<Tool*> hiddenTools = gameModel->GetUnlistedTools();
toolList.insert(toolList.end(), hiddenTools.begin(), hiddenTools.end());
new ElementSearchActivity(this, toolList);
}

View File

@ -51,7 +51,7 @@ HistoryEntry::~HistoryEntry()
}
GameModel::GameModel():
activeMenu(-1),
activeMenu(SC_POWDERS),
currentBrush(0),
currentUser(0, ""),
toolStrength(1.0f),
@ -137,12 +137,11 @@ GameModel::GameModel():
currentUser = Client::Ref().GetAuthUser();
}
LoadCustomGol();
BuildMenus();
perfectCircle = prefs.Get("PerfectCircleBrush", true);
BuildBrushList();
InitTools();
//Set default decoration colour
unsigned char colourR = std::max(std::min(prefs.Get("Decoration.Red", 200), 255), 0);
unsigned char colourG = std::max(std::min(prefs.Get("Decoration.Green", 100), 255), 0);
@ -193,12 +192,6 @@ GameModel::~GameModel()
prefs.Set("Decoration.Alpha", (int)colour.Alpha);
}
for (size_t i = 0; i < menuList.size(); i++)
{
if (i == SC_FAVORITES)
menuList[i]->ClearTools();
delete menuList[i];
}
delete sim;
delete ren;
//if(activeTools)
@ -233,182 +226,6 @@ void GameModel::BuildQuickOptionMenu(GameController * controller)
UpdateQuickOptions();
}
void GameModel::BuildMenus()
{
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
auto &builtinGol = SimulationData::builtinGol;
int lastMenu = -1;
if(activeMenu != -1)
lastMenu = activeMenu;
std::array<ByteString, NUM_TOOLINDICES> activeToolIdentifiers;
if(regularToolset[0])
activeToolIdentifiers[0] = regularToolset[0]->Identifier;
if(regularToolset[1])
activeToolIdentifiers[1] = regularToolset[1]->Identifier;
if(regularToolset[2])
activeToolIdentifiers[2] = regularToolset[2]->Identifier;
if(regularToolset[3])
activeToolIdentifiers[3] = regularToolset[3]->Identifier;
//Empty current menus
for (size_t i = 0; i < menuList.size(); i++)
{
if (i == SC_FAVORITES)
menuList[i]->ClearTools();
delete menuList[i];
}
menuList.clear();
toolList.clear();
extraElementTools.clear();
elementTools.clear();
tools.clear();
//Create menus
for (auto &section : sd.msections)
{
menuList.push_back(new Menu(section.icon, section.name, section.doshow));
}
//Build menus from Simulation elements
for(int i = 0; i < PT_NUM; i++)
{
if(elements[i].Enabled)
{
Tool * tempTool;
if(i == PT_LIGH)
{
tempTool = AddTool<Element_LIGH_Tool>(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
}
else if(i == PT_TESC)
{
tempTool = AddTool<Element_TESC_Tool>(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
}
else if(i == PT_STKM || i == PT_FIGH || i == PT_STKM2)
{
tempTool = AddTool<PlopTool>(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
}
else
{
tempTool = AddTool<ElementTool>(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
}
if (elements[i].MenuSection >= 0 && elements[i].MenuSection < int(sd.msections.size()) && elements[i].MenuVisible)
{
menuList[elements[i].MenuSection]->AddTool(tempTool);
}
else
{
extraElementTools.push_back(tempTool);
}
elementTools.push_back(tempTool);
}
}
//Build menu for GOL types
for(int i = 0; i < NGOL; i++)
{
Tool * tempTool = AddTool<ElementTool>(PT_LIFE|PMAPID(i), builtinGol[i].name, builtinGol[i].description, builtinGol[i].colour, "DEFAULT_PT_LIFE_"+builtinGol[i].name.ToAscii());
menuList[SC_LIFE]->AddTool(tempTool);
}
for (auto &gd : sd.GetCustomGol())
{
Tool * tempTool = AddTool<ElementTool>(PT_LIFE|PMAPID(gd.rule), gd.nameString, "Custom GOL type: " + SerialiseGOLRule(gd.rule), gd.colour1, "DEFAULT_PT_LIFECUST_"+gd.nameString.ToAscii(), nullptr);
menuList[SC_LIFE]->AddTool(tempTool);
}
//Build other menus from wall data
for(int i = 0; i < UI_WALLCOUNT; i++)
{
Tool * tempTool = AddTool<WallTool>(i, sd.wtypes[i].descs, sd.wtypes[i].colour, sd.wtypes[i].identifier, sd.wtypes[i].textureGen);
menuList[SC_WALL]->AddTool(tempTool);
}
//Build menu for tools
for (auto &tool : ::GetTools())
{
menuList[SC_TOOL]->AddTool(AddTool<SimTool>(tool));
}
//Add special sign and prop tools
menuList[SC_TOOL]->AddTool(AddTool<PropertyTool>(*this));
menuList[SC_TOOL]->AddTool(AddTool<SignTool>(*this));
menuList[SC_TOOL]->AddTool(AddTool<SampleTool>(*this));
menuList[SC_LIFE]->AddTool(AddTool<GOLTool>(*this));
//Add decoration tools to menu
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_ADD, "ADD", "Colour blending: Add.", 0x000000_rgb, "DEFAULT_DECOR_ADD"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_SUBTRACT, "SUB", "Colour blending: Subtract.", 0x000000_rgb, "DEFAULT_DECOR_SUB"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_MULTIPLY, "MUL", "Colour blending: Multiply.", 0x000000_rgb, "DEFAULT_DECOR_MUL"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_DIVIDE, "DIV", "Colour blending: Divide." , 0x000000_rgb, "DEFAULT_DECOR_DIV"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_SMUDGE, "SMDG", "Smudge tool, blends surrounding deco together.", 0x000000_rgb, "DEFAULT_DECOR_SMDG"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_CLEAR, "CLR", "Erase any set decoration.", 0x000000_rgb, "DEFAULT_DECOR_CLR"));
menuList[SC_DECO]->AddTool(AddTool<DecorationTool>(view, DECO_DRAW, "SET", "Draw decoration (No blending).", 0x000000_rgb, "DEFAULT_DECOR_SET"));
SetColourSelectorColour(colour); // update tool colors
decoToolset[0] = GetToolFromIdentifier("DEFAULT_DECOR_SET");
decoToolset[1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR");
decoToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE");
decoToolset[3] = GetToolFromIdentifier("DEFAULT_PT_NONE");
regularToolset[0] = GetToolFromIdentifier(activeToolIdentifiers[0]);
regularToolset[1] = GetToolFromIdentifier(activeToolIdentifiers[1]);
regularToolset[2] = GetToolFromIdentifier(activeToolIdentifiers[2]);
regularToolset[3] = GetToolFromIdentifier(activeToolIdentifiers[3]);
//Set default tools
if (!regularToolset[0])
regularToolset[0] = GetToolFromIdentifier("DEFAULT_PT_DUST");
if (!regularToolset[1])
regularToolset[1] = GetToolFromIdentifier("DEFAULT_PT_NONE");
if (!regularToolset[2])
regularToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE");
if (!regularToolset[3])
regularToolset[3] = GetToolFromIdentifier("DEFAULT_PT_NONE");
lastTool = activeTools[0];
//Set default menu
activeMenu = SC_POWDERS;
if(lastMenu != -1)
activeMenu = lastMenu;
if(activeMenu != -1)
toolList = menuList[activeMenu]->GetToolList();
else
toolList = std::vector<Tool*>();
notifyMenuListChanged();
notifyToolListChanged();
notifyActiveToolsChanged();
notifyLastToolChanged();
//Build menu for favorites
BuildFavoritesMenu();
}
void GameModel::BuildFavoritesMenu()
{
menuList[SC_FAVORITES]->ClearTools();
std::vector<ByteString> favList = Favorite::Ref().GetFavoritesList();
for (size_t i = 0; i < favList.size(); i++)
{
Tool *tool = GetToolFromIdentifier(favList[i]);
if (tool)
menuList[SC_FAVORITES]->AddTool(tool);
}
if (activeMenu == SC_FAVORITES)
toolList = menuList[SC_FAVORITES]->GetToolList();
notifyMenuListChanged();
notifyToolListChanged();
notifyActiveToolsChanged();
notifyLastToolChanged();
}
void GameModel::BuildBrushList()
{
ui::Point radius{ 4, 4 };
@ -444,21 +261,15 @@ void GameModel::BuildBrushList()
Tool *GameModel::GetToolFromIdentifier(ByteString const &identifier)
{
for (auto *menu : menuList)
for (auto &ptr : tools)
{
for (auto *tool : menu->GetToolList())
if (!ptr)
{
if (identifier == tool->Identifier)
{
return tool;
}
continue;
}
}
for (auto *extra : extraElementTools)
{
if (identifier == extra->Identifier)
if (ptr->Identifier == identifier)
{
return extra;
return ptr.get();
}
}
return nullptr;
@ -809,7 +620,7 @@ void GameModel::AddObserver(GameView * observer){
observer->NotifySaveChanged(this);
observer->NotifyBrushChanged(this);
observer->NotifyMenuListChanged(this);
observer->NotifyToolListChanged(this);
observer->NotifyActiveMenuToolListChanged(this);
observer->NotifyUserChanged(this);
observer->NotifyZoomChanged(this);
observer->NotifyColourSelectorVisibilityChanged(this);
@ -834,8 +645,7 @@ float GameModel::GetToolStrength()
void GameModel::SetActiveMenu(int menuID)
{
activeMenu = menuID;
toolList = menuList[menuID]->GetToolList();
notifyToolListChanged();
notifyActiveMenuToolListChanged();
if(menuID == SC_DECO)
{
@ -855,14 +665,14 @@ void GameModel::SetActiveMenu(int menuID)
}
}
std::vector<Tool*> GameModel::GetUnlistedTools()
std::vector<Tool *> GameModel::GetActiveMenuToolList()
{
return extraElementTools;
}
std::vector<Tool*> GameModel::GetToolList()
{
return toolList;
std::vector<Tool *> activeMenuToolList;
if (activeMenu >= 0 && activeMenu < int(menuList.size()))
{
activeMenuToolList = menuList[activeMenu]->GetToolList();
}
return activeMenuToolList;
}
int GameModel::GetActiveMenu()
@ -870,17 +680,6 @@ int GameModel::GetActiveMenu()
return activeMenu;
}
//Get an element tool from an element ID
Tool * GameModel::GetElementTool(int elementID)
{
for(std::vector<Tool*>::iterator iter = elementTools.begin(), end = elementTools.end(); iter != end; ++iter)
{
if((*iter)->ToolID == elementID)
return *iter;
}
return NULL;
}
Tool * GameModel::GetActiveTool(int selection)
{
return activeTools[selection];
@ -897,9 +696,14 @@ std::vector<QuickOption*> GameModel::GetQuickOptions()
return quickOptions;
}
std::vector<Menu*> GameModel::GetMenuList()
std::vector<Menu *> GameModel::GetMenuList()
{
return menuList;
std::vector<Menu *> ptrs;
for (auto &ptr : menuList)
{
ptrs.push_back(ptr.get());
}
return ptrs;
}
SaveInfo *GameModel::GetSave() // non-owning
@ -1498,11 +1302,11 @@ void GameModel::notifyMenuListChanged()
}
}
void GameModel::notifyToolListChanged()
void GameModel::notifyActiveMenuToolListChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
observers[i]->NotifyToolListChanged(this);
observers[i]->NotifyActiveMenuToolListChanged(this);
}
}
@ -1623,6 +1427,7 @@ bool GameModel::AddCustomGol(String ruleString, String nameString, RGB<uint8_t>
auto newCustomGol = sd.GetCustomGol();
newCustomGol.push_back(*gd);
sd.SetCustomGOL(newCustomGol);
AllocCustomGolTool(*gd);
SaveCustomGol();
BuildMenus();
return true;
@ -1649,6 +1454,7 @@ bool GameModel::RemoveCustomGol(const ByteString &identifier)
if (removedAny)
{
sd.SetCustomGOL(newCustomGol);
FreeTool(GetToolFromIdentifier(identifier));
BuildMenus();
SaveCustomGol();
}
@ -1688,6 +1494,7 @@ void GameModel::LoadCustomGol()
if (auto gd = CheckCustomGol(ruleString, nameString, color1, color2))
{
newCustomGol.push_back(*gd);
AllocCustomGolTool(*gd);
}
else
{
@ -1783,3 +1590,230 @@ Tool *GameModel::GetToolByIndex(int index)
}
return tools[index].get();
}
void GameModel::SanitizeToolsets()
{
if (!decoToolset [0]) decoToolset [0] = GetToolFromIdentifier("DEFAULT_DECOR_SET");
if (!decoToolset [1]) decoToolset [1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR");
if (!decoToolset [2]) decoToolset [2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE");
if (!decoToolset [3]) decoToolset [3] = GetToolFromIdentifier("DEFAULT_PT_NONE" );
if (!regularToolset[0]) regularToolset[0] = GetToolFromIdentifier("DEFAULT_PT_DUST" );
if (!regularToolset[1]) regularToolset[1] = GetToolFromIdentifier("DEFAULT_PT_NONE" );
if (!regularToolset[2]) regularToolset[2] = GetToolFromIdentifier("DEFAULT_UI_SAMPLE");
if (!regularToolset[3]) regularToolset[3] = GetToolFromIdentifier("DEFAULT_PT_NONE" );
if (!lastTool)
{
lastTool = activeTools[0];
}
}
void GameModel::DeselectTool(ByteString identifier)
{
auto *tool = GetToolFromIdentifier(identifier);
for (auto &slot : decoToolset)
{
if (slot == tool)
{
slot = nullptr;
}
}
for (auto &slot : regularToolset)
{
if (slot == tool)
{
slot = nullptr;
}
}
if (lastTool == tool)
{
lastTool = nullptr;
}
SanitizeToolsets();
}
void GameModel::AllocTool(std::unique_ptr<Tool> tool)
{
std::optional<int> index;
for (int i = 0; i < int(tools.size()); ++i)
{
if (!tools[i])
{
index = i;
break;
}
}
if (!index)
{
index = int(tools.size());
tools.emplace_back();
}
tools[*index] = std::move(tool);
}
void GameModel::FreeTool(Tool *tool)
{
auto index = GetToolIndex(tool);
if (!index)
{
return;
}
auto &ptr = tools[*index];
DeselectTool(ptr->Identifier);
ptr.reset();
}
std::optional<int> GameModel::GetToolIndex(Tool *tool)
{
if (tool)
{
for (int i = 0; i < int(tools.size()); ++i)
{
if (tools[i].get() == tool)
{
return i;
}
}
}
return std::nullopt;
}
void GameModel::AllocCustomGolTool(const CustomGOLData &gd)
{
AllocTool(std::make_unique<ElementTool>(PMAP(gd.rule, PT_LIFE), gd.nameString, "Custom GOL type: " + SerialiseGOLRule(gd.rule), gd.colour1, "DEFAULT_PT_LIFECUST_" + gd.nameString.ToAscii(), nullptr));
}
void GameModel::AllocElementTool(int element)
{
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
auto &elem = elements[element];
FreeTool(GetToolFromIdentifier(elem.Identifier));
switch (element)
{
case PT_LIGH:
AllocTool(std::make_unique<Element_LIGH_Tool>(element, elem.Name, elem.Description, elem.Colour, elem.Identifier, elem.IconGenerator));
break;
case PT_TESC:
AllocTool(std::make_unique<Element_TESC_Tool>(element, elem.Name, elem.Description, elem.Colour, elem.Identifier, elem.IconGenerator));
break;
case PT_STKM:
case PT_FIGH:
case PT_STKM2:
AllocTool(std::make_unique<PlopTool>(element, elem.Name, elem.Description, elem.Colour, elem.Identifier, elem.IconGenerator));
break;
default:
AllocTool(std::make_unique<ElementTool>(element, elem.Name, elem.Description, elem.Colour, elem.Identifier, elem.IconGenerator));
break;
}
}
void GameModel::InitTools()
{
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
auto &builtinGol = SimulationData::builtinGol;
for (int i = 0; i < PT_NUM; ++i)
{
if (elements[i].Enabled)
{
AllocElementTool(i);
}
}
for (int i = 0; i < NGOL; ++i)
{
AllocTool(std::make_unique<ElementTool>(PMAP(i, PT_LIFE), builtinGol[i].name, builtinGol[i].description, builtinGol[i].colour, "DEFAULT_PT_LIFE_" + builtinGol[i].name.ToAscii()));
}
for (int i = 0; i < UI_WALLCOUNT; ++i)
{
AllocTool(std::make_unique<WallTool>(i, sd.wtypes[i].descs, sd.wtypes[i].colour, sd.wtypes[i].identifier, sd.wtypes[i].textureGen));
}
for (auto &tool : ::GetTools())
{
AllocTool(std::make_unique<SimTool>(tool));
}
AllocTool(std::make_unique<DecorationTool>(view, DECO_ADD , "ADD" , "Colour blending: Add." , 0x000000_rgb, "DEFAULT_DECOR_ADD" ));
AllocTool(std::make_unique<DecorationTool>(view, DECO_SUBTRACT, "SUB" , "Colour blending: Subtract." , 0x000000_rgb, "DEFAULT_DECOR_SUB" ));
AllocTool(std::make_unique<DecorationTool>(view, DECO_MULTIPLY, "MUL" , "Colour blending: Multiply." , 0x000000_rgb, "DEFAULT_DECOR_MUL" ));
AllocTool(std::make_unique<DecorationTool>(view, DECO_DIVIDE , "DIV" , "Colour blending: Divide." , 0x000000_rgb, "DEFAULT_DECOR_DIV" ));
AllocTool(std::make_unique<DecorationTool>(view, DECO_SMUDGE , "SMDG", "Smudge tool, blends surrounding deco together.", 0x000000_rgb, "DEFAULT_DECOR_SMDG"));
AllocTool(std::make_unique<DecorationTool>(view, DECO_CLEAR , "CLR" , "Erase any set decoration." , 0x000000_rgb, "DEFAULT_DECOR_CLR" ));
AllocTool(std::make_unique<DecorationTool>(view, DECO_DRAW , "SET" , "Draw decoration (No blending)." , 0x000000_rgb, "DEFAULT_DECOR_SET" ));
AllocTool(std::make_unique<PropertyTool>(*this));
AllocTool(std::make_unique<SignTool>(*this));
AllocTool(std::make_unique<SampleTool>(*this));
AllocTool(std::make_unique<GOLTool>(*this));
LoadCustomGol();
SanitizeToolsets();
lastTool = activeTools[0];
BuildMenus();
}
void GameModel::BuildMenus()
{
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
menuList.clear();
for (auto &section : sd.msections)
{
menuList.push_back(std::make_unique<Menu>(section.icon, section.name, section.doshow));
}
for (auto &elem : elements)
{
if (elem.Enabled)
{
if (elem.MenuSection >= 0 && elem.MenuSection < int(sd.msections.size()) && elem.MenuVisible)
{
menuList[elem.MenuSection]->AddTool(GetToolFromIdentifier(elem.Identifier));
}
}
}
for (auto &ptr : tools)
{
if (!ptr)
{
continue;
}
if (ptr->Identifier.BeginsWith("DEFAULT_PT_LIFE_") ||
ptr->Identifier.BeginsWith("DEFAULT_PT_LIFECUST_"))
{
menuList[SC_LIFE]->AddTool(ptr.get());
}
if (ptr->Identifier.BeginsWith("DEFAULT_WL_"))
{
menuList[SC_WALL]->AddTool(ptr.get());
}
if (ptr->Identifier.Contains("_TOOL_"))
{
menuList[SC_TOOL]->AddTool(ptr.get());
}
if (ptr->Identifier.BeginsWith("DEFAULT_DECOR_"))
{
menuList[SC_DECO]->AddTool(ptr.get());
}
}
for (auto &fav : Favorite::Ref().GetFavoritesList())
{
if (auto *tool = GetToolFromIdentifier(fav))
{
menuList[SC_FAVORITES]->AddTool(tool);
}
}
menuList[SC_TOOL]->AddTool(GetToolFromIdentifier("DEFAULT_UI_PROPERTY"));
menuList[SC_TOOL]->AddTool(GetToolFromIdentifier("DEFAULT_UI_SIGN"));
menuList[SC_TOOL]->AddTool(GetToolFromIdentifier("DEFAULT_UI_SAMPLE"));
menuList[SC_LIFE]->AddTool(GetToolFromIdentifier("DEFAULT_UI_ADDLIFE"));
notifyMenuListChanged();
notifyActiveMenuToolListChanged();
notifyActiveToolsChanged();
notifyLastToolChanged();
}

View File

@ -59,36 +59,25 @@ private:
std::unique_ptr<GameSave> transformedPlaceSave;
std::deque<String> consoleLog;
std::vector<GameView*> observers;
std::vector<Tool*> toolList;
std::vector<std::unique_ptr<Tool>> tools;
template<class ToolType, class... Args>
ToolType *AddTool(Args &&...args)
{
auto ptr = std::make_unique<ToolType>(std::forward<Args>(args)...);
auto raw = ptr.get();
tools.push_back(std::move(ptr));
return raw;
}
//All tools that are associated with elements
std::vector<Tool*> elementTools;
//Tools that are present in elementTools, but don't have an associated menu and need to be freed manually
std::vector<Tool*> extraElementTools;
void SanitizeToolsets();
void DeselectTool(ByteString identifier);
void InitTools();
Simulation * sim;
Renderer * ren;
RendererSettings rendererSettings;
std::vector<Menu*> menuList;
std::vector<std::unique_ptr<Menu>> menuList;
std::vector<QuickOption*> quickOptions;
int activeMenu;
int currentBrush;
std::vector<std::unique_ptr<Brush>> brushList;
std::unique_ptr<SaveInfo> currentSave;
std::unique_ptr<SaveFile> currentFile;
Tool * lastTool;
Tool ** activeTools;
Tool *lastTool = nullptr;
Tool **activeTools = nullptr;
std::array<Tool *, NUM_TOOLINDICES> decoToolset;
std::array<Tool *, NUM_TOOLINDICES> regularToolset;
User currentUser;
@ -121,7 +110,7 @@ private:
void notifySaveChanged();
void notifyBrushChanged();
void notifyMenuListChanged();
void notifyToolListChanged();
void notifyActiveMenuToolListChanged();
void notifyActiveToolsChanged();
void notifyUserChanged();
void notifyZoomChanged();
@ -188,7 +177,6 @@ public:
String GetInfoTip();
void BuildMenus();
void BuildFavoritesMenu();
void BuildBrushList();
void BuildQuickOptionMenu(GameController * controller);
@ -210,9 +198,12 @@ public:
Tool * GetLastTool();
void SetLastTool(Tool * newTool);
Tool *GetToolFromIdentifier(ByteString const &identifier);
Tool * GetElementTool(int elementID);
std::vector<Tool*> GetToolList();
std::vector<Tool*> GetUnlistedTools();
std::optional<int> GetToolIndex(Tool *tool);
std::vector<Tool *> GetActiveMenuToolList();
void AllocTool(std::unique_ptr<Tool> tool);
void AllocElementTool(int element);
void AllocCustomGolTool(const CustomGOLData &gd);
void FreeTool(Tool *tool);
const std::vector<std::unique_ptr<Tool>> &GetTools()
{

View File

@ -534,7 +534,7 @@ void GameView::NotifyLastToolChanged(GameModel * sender)
}
}
void GameView::NotifyToolListChanged(GameModel * sender)
void GameView::NotifyActiveMenuToolListChanged(GameModel * sender)
{
for (size_t i = 0; i < menuButtons.size(); i++)
{
@ -553,7 +553,7 @@ void GameView::NotifyToolListChanged(GameModel * sender)
delete toolButtons[i];
}
toolButtons.clear();
std::vector<Tool*> toolList = sender->GetToolList();
std::vector<Tool*> toolList = sender->GetActiveMenuToolList();
int currentX = 0;
for (size_t i = 0; i < toolList.size(); i++)
{
@ -729,7 +729,7 @@ void GameView::NotifyColourSelectorColourChanged(GameModel * sender)
{
colourPicker->Appearance.BackgroundInactive = sender->GetColourSelectorColour();
colourPicker->Appearance.BackgroundHover = sender->GetColourSelectorColour();
NotifyToolListChanged(sender);
NotifyActiveMenuToolListChanged(sender);
}
void GameView::NotifyRendererChanged(GameModel * sender)

View File

@ -215,7 +215,7 @@ public:
void NotifySaveChanged(GameModel * sender);
void NotifyBrushChanged(GameModel * sender);
void NotifyMenuListChanged(GameModel * sender);
void NotifyToolListChanged(GameModel * sender);
void NotifyActiveMenuToolListChanged(GameModel * sender);
void NotifyActiveToolsChanged(GameModel * sender);
void NotifyUserChanged(GameModel * sender);
void NotifyZoomChanged(GameModel * sender);

View File

@ -64,8 +64,9 @@ void SampleTool::Draw(Simulation * sim, Brush const &brush, ui::Point position)
}
else
{
if (auto elementTool = gameModel.GetElementTool(part->type))
gameModel.SetActiveTool(0, elementTool);
auto &sd = SimulationData::Ref();
auto &elements = sd.elements;
gameModel.SetActiveTool(0, gameModel.GetToolFromIdentifier(elements[part->type].Identifier));
}
}
}

View File

@ -399,6 +399,7 @@ static int allocate(lua_State *L)
lsi->customCanMove[elem][newID] = 0;
lsi->customCanMove[newID][elem] = 0;
}
lsi->gameModel->AllocElementTool(newID);
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
}
@ -524,6 +525,7 @@ static int element(lua_State *L)
sd.graphicscache[id].isready = 0;
}
lsi->gameModel->AllocElementTool(id);
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
@ -591,6 +593,7 @@ static int property(lua_State *L)
manageElementIdentifier(L, id, false);
LuaSetProperty(L, *prop, propertyAddress, 3);
manageElementIdentifier(L, id, true);
lsi->gameModel->AllocElementTool(id);
lsi->gameModel->BuildMenus();
lsi->InitCustomCanMove();
sd.graphicscache[id].isready = 0;
@ -745,12 +748,14 @@ static int ffree(lua_State *L)
}
}
auto *lsi = GetLSI();
{
auto &sd = SimulationData::Ref();
std::unique_lock lk(sd.elementGraphicsMx);
sd.elements[id].Enabled = false;
}
auto *lsi = GetLSI();
lsi->customElements[id] = {};
lsi->gameModel->FreeTool(lsi->gameModel->GetToolFromIdentifier(identifier));
lsi->gameModel->BuildMenus();
lua_getglobal(L, "elements");
@ -777,7 +782,7 @@ static int loadDefault(lua_State *L)
auto &builtinElements = GetElements();
auto *lsi = GetLSI();
{
auto loadDefaultOne = [L, &elements, &builtinElements](int id) {
auto loadDefaultOne = [lsi, L, &elements, &builtinElements](int id) {
lua_getglobal(L, "elements");
ByteString identifier = elements[id].Identifier;
tpt_lua_pushByteString(L, identifier);
@ -786,9 +791,14 @@ static int loadDefault(lua_State *L)
manageElementIdentifier(L, id, false);
if (id < (int)builtinElements.size())
{
elements[id] = builtinElements[id];
}
else
{
elements[id] = Element();
lsi->gameModel->FreeTool(lsi->gameModel->GetToolFromIdentifier(identifier));
}
manageElementIdentifier(L, id, true);
tpt_lua_pushByteString(L, identifier);