209 lines
6.3 KiB
C++
209 lines
6.3 KiB
C++
#include "Tool.h"
|
|
|
|
#include "prefs/GlobalPrefs.h"
|
|
#include "client/Client.h"
|
|
#include "common/tpt-rand.h"
|
|
#include "simulation/GOLString.h"
|
|
#include "simulation/Simulation.h"
|
|
|
|
#include "gui/Style.h"
|
|
#include "gui/interface/Button.h"
|
|
#include "gui/interface/Label.h"
|
|
#include "gui/interface/Textbox.h"
|
|
#include "gui/interface/Window.h"
|
|
#include "gui/colourpicker/ColourPickerActivity.h"
|
|
#include "gui/dialogues/ErrorMessage.h"
|
|
#include "gui/game/GameModel.h"
|
|
|
|
#include "graphics/Graphics.h"
|
|
|
|
class GOLWindow: public ui::Window
|
|
{
|
|
ui::Colour highColour, lowColour;
|
|
ui::Button *highColourButton, *lowColourButton;
|
|
ui::Textbox *nameField, *ruleField;
|
|
GameModel &gameModel;
|
|
Simulation *sim;
|
|
int toolSelection;
|
|
|
|
void updateGradient();
|
|
void validate();
|
|
|
|
public:
|
|
GOLWindow(GameModel &gameModel, Simulation *sim, int toolSelection, int rule, RGB<uint8_t> colour1, RGB<uint8_t> colour2);
|
|
|
|
virtual ~GOLWindow()
|
|
{}
|
|
|
|
void OnDraw() override;
|
|
void OnTryExit(ExitMethod method) override;
|
|
};
|
|
|
|
GOLWindow::GOLWindow(GameModel &gameModel_, Simulation *sim_, int toolSelection, int rule, RGB<uint8_t> colour1, RGB<uint8_t> colour2):
|
|
ui::Window(ui::Point(-1, -1), ui::Point(200, 108)),
|
|
highColour(colour1.WithAlpha(0xFF)),
|
|
lowColour(colour2.WithAlpha(0xFF)),
|
|
gameModel(gameModel_),
|
|
sim(sim_),
|
|
toolSelection(toolSelection)
|
|
{
|
|
highColour.Alpha = 255;
|
|
lowColour.Alpha = 255;
|
|
ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 14), "Edit custom GOL type");
|
|
messageLabel->SetTextColour(style::Colour::InformationTitle);
|
|
messageLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
|
messageLabel->Appearance.VerticalAlign = ui::Appearance::AlignTop;
|
|
AddComponent(messageLabel);
|
|
|
|
auto *okayButton = new ui::Button(ui::Point(0, Size.Y-17), ui::Point(Size.X, 17), "OK");
|
|
okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
|
okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
|
okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200);
|
|
okayButton->SetActionCallback({ [this] {
|
|
if (nameField->GetText().length() && ruleField->GetText().length())
|
|
{
|
|
CloseActiveWindow();
|
|
validate();
|
|
SelfDestruct();
|
|
}
|
|
} });
|
|
AddComponent(okayButton);
|
|
SetOkayButton(okayButton);
|
|
|
|
nameField = new ui::Textbox(ui::Point(8, 25), ui::Point(Size.X-16, 16), "", "[name]");
|
|
nameField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
|
nameField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
|
nameField->SetLimit(7);
|
|
AddComponent(nameField);
|
|
FocusComponent(nameField);
|
|
|
|
ruleField = new ui::Textbox(ui::Point(8, 46), ui::Point(Size.X-16, 16), "", "[rule]");
|
|
ruleField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
|
ruleField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
|
AddComponent(ruleField);
|
|
FocusComponent(ruleField);
|
|
|
|
highColourButton = new ui::Button(ui::Point(8, 67), ui::Point(16, 16), "");
|
|
highColourButton->SetActionCallback({ [this] {
|
|
new ColourPickerActivity(highColour, [this](ui::Colour colour) {
|
|
highColour = colour;
|
|
updateGradient();
|
|
});
|
|
} });
|
|
AddComponent(highColourButton);
|
|
|
|
lowColourButton = new ui::Button(ui::Point(Size.X - 24, 67), ui::Point(16, 16), "");
|
|
lowColourButton->SetActionCallback({ [this] {
|
|
new ColourPickerActivity(lowColour, [this](ui::Colour colour) {
|
|
lowColour = colour;
|
|
updateGradient();
|
|
});
|
|
} });
|
|
AddComponent(lowColourButton);
|
|
|
|
if (rule)
|
|
{
|
|
ruleField->SetText(SerialiseGOLRule(rule));
|
|
nameField->SetText("");
|
|
}
|
|
else
|
|
{
|
|
auto &prefs = GlobalPrefs::Ref();
|
|
ruleField->SetText(prefs.Get("CustomGOL.Rule", String("B3/S23")));
|
|
nameField->SetText(prefs.Get("CustomGOL.Name", String("CGOL")));
|
|
highColour.Red = interfaceRng.between(0x80, 0xFF);
|
|
highColour.Green = interfaceRng.between(0x80, 0xFF);
|
|
highColour.Blue = interfaceRng.between(0x80, 0xFF);
|
|
highColour.Alpha = 0xFF;
|
|
lowColour.Red = interfaceRng.between(0x00, 0x7F);
|
|
lowColour.Green = interfaceRng.between(0x00, 0x7F);
|
|
lowColour.Blue = interfaceRng.between(0x00, 0x7F);
|
|
lowColour.Alpha = 0xFF;
|
|
}
|
|
updateGradient();
|
|
|
|
MakeActiveWindow();
|
|
}
|
|
|
|
void GOLWindow::updateGradient()
|
|
{
|
|
highColourButton->Appearance.BackgroundInactive = highColour;
|
|
highColourButton->Appearance.BackgroundHover = highColour;
|
|
lowColourButton->Appearance.BackgroundInactive = lowColour;
|
|
lowColourButton->Appearance.BackgroundHover = lowColour;
|
|
}
|
|
|
|
void GOLWindow::validate()
|
|
{
|
|
auto nameString = nameField->GetText();
|
|
auto ruleString = ruleField->GetText();
|
|
if (!ValidateGOLName(nameString))
|
|
{
|
|
new ErrorMessage("Could not add GOL type", "Invalid name provided");
|
|
return;
|
|
}
|
|
nameString = nameString.ToUpper();
|
|
int rule = ParseGOLString(ruleString);
|
|
if (rule == -1)
|
|
{
|
|
new ErrorMessage("Could not add GOL type", "Invalid rule provided");
|
|
return;
|
|
}
|
|
if (sim->GetCustomGOLByRule(rule))
|
|
{
|
|
new ErrorMessage("Could not add GOL type", "This Custom GoL rule already exists");
|
|
return;
|
|
}
|
|
ruleString = SerialiseGOLRule(rule); // * Make it canonical.
|
|
|
|
{
|
|
auto &prefs = GlobalPrefs::Ref();
|
|
Prefs::DeferWrite dw(prefs);
|
|
prefs.Set("CustomGOL.Name", nameString);
|
|
prefs.Set("CustomGOL.Rule", ruleString);
|
|
}
|
|
|
|
auto color1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
|
|
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
|
if (!AddCustomGol(ruleString, nameString, color1, color2))
|
|
{
|
|
new ErrorMessage("Could not add GOL type", "Name already taken");
|
|
return;
|
|
}
|
|
|
|
gameModel.SelectNextIdentifier = "DEFAULT_PT_LIFECUST_" + nameString.ToAscii();
|
|
gameModel.SelectNextTool = toolSelection;
|
|
}
|
|
|
|
void GOLWindow::OnTryExit(ExitMethod method)
|
|
{
|
|
CloseActiveWindow();
|
|
SelfDestruct();
|
|
}
|
|
|
|
void GOLWindow::OnDraw()
|
|
{
|
|
Graphics * g = GetGraphics();
|
|
|
|
g->DrawFilledRect(RectSized(Position - Vec2{ 1, 1 }, Size + Vec2{ 2, 2 }), 0x000000_rgb);
|
|
g->DrawRect(RectSized(Position, Size), 0xC8C8C8_rgb);
|
|
|
|
int width = Size.X - 60;
|
|
for (int xx = 0; xx < width; ++xx)
|
|
{
|
|
auto f = xx / (float)width;
|
|
for (int yy = 0; yy < 16; ++yy)
|
|
{
|
|
auto rr = int(highColour.Red * (1.f - f) + lowColour.Red * f);
|
|
auto gg = int(highColour.Green * (1.f - f) + lowColour.Green * f);
|
|
auto bb = int(highColour.Blue * (1.f - f) + lowColour.Blue * f);
|
|
g->DrawPixel(Position + Vec2{ xx + 30, yy + 67 }, RGB<uint8_t>(rr, gg, bb));
|
|
}
|
|
}
|
|
}
|
|
|
|
void GOLTool::OpenWindow(Simulation *sim, int toolSelection, int rule, RGB<uint8_t> colour1, RGB<uint8_t> colour2)
|
|
{
|
|
new GOLWindow(gameModel, sim, toolSelection, rule, colour1, colour2);
|
|
}
|