From 2371e3e9a221cf95fccaf3b6d0a411978c0c4428 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 16 Dec 2022 00:46:36 +0400 Subject: [PATCH] Interface builder refactored --- client/gui/InterfaceObjectConfigurable.cpp | 302 +++++++++++++-------- client/gui/InterfaceObjectConfigurable.h | 32 ++- client/lobby/RandomMapTab.cpp | 43 ++- client/lobby/RandomMapTab.h | 15 + 4 files changed, 265 insertions(+), 127 deletions(-) diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index 6c8c64f38..ddce4753e 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -57,7 +57,7 @@ void InterfaceObjectConfigurable::init(const JsonNode &config) } } -std::string InterfaceObjectConfigurable::buildText(const JsonNode & config) const +std::string InterfaceObjectConfigurable::readText(const JsonNode & config) const { if(config.isNull()) return ""; @@ -69,145 +69,207 @@ std::string InterfaceObjectConfigurable::buildText(const JsonNode & config) cons return config.String(); } -std::shared_ptr InterfaceObjectConfigurable::buildWidget(const JsonNode & config) +Point InterfaceObjectConfigurable::readPosition(const JsonNode & config) const +{ + Point p; + p.x = config["x"].Integer(); + p.y = config["y"].Integer(); + return p; +} + +ETextAlignment InterfaceObjectConfigurable::readTextAlignment(const JsonNode & config) const +{ + if(!config.isNull()) + { + if(config.String() == "center") + return ETextAlignment::CENTER; + if(config.String() == "left") + return ETextAlignment::TOPLEFT; + if(config.String() == "right") + return ETextAlignment::BOTTOMRIGHT; + } + return ETextAlignment::CENTER; +} + +SDL_Color InterfaceObjectConfigurable::readColor(const JsonNode & config) const +{ + if(!config.isNull()) + { + if(config.String() == "yellow") + return Colors::YELLOW; + if(config.String() == "white") + return Colors::WHITE; + if(config.String() == "gold") + return Colors::METALLIC_GOLD; + if(config.String() == "green") + return Colors::GREEN; + if(config.String() == "orange") + return Colors::ORANGE; + if(config.String() == "bright-yellow") + return Colors::BRIGHT_YELLOW; + } + return Colors::DEFAULT_KEY_COLOR; + +} +EFonts InterfaceObjectConfigurable::readFont(const JsonNode & config) const +{ + if(!config.isNull()) + { + if(config.String() == "big") + return EFonts::FONT_BIG; + if(config.String() == "medium") + return EFonts::FONT_MEDIUM; + if(config.String() == "small") + return EFonts::FONT_SMALL; + if(config.String() == "tiny") + return EFonts::FONT_TINY; + } + return EFonts::FONT_TIMES; +} + +std::pair InterfaceObjectConfigurable::readHintText(const JsonNode & config) const +{ + std::pair result; + if(!config.isNull()) + { + if(config.isNumber()) + return CGI->generaltexth->zelp[config.Integer()]; + + if(config.getType() == JsonNode::JsonType::DATA_STRUCT) + { + result.first = config["hover"].String(); + result.second = config["help"].String(); + return result; + } + if(config.getType() == JsonNode::JsonType::DATA_STRING) + { + result.first = result.second = config.String(); + } + } + return result; +} + +std::shared_ptr InterfaceObjectConfigurable::buildPicture(const JsonNode & config) const +{ + auto image = readText(config["image"]); + auto position = readPosition(config["position"]); + return std::make_shared(image, position.x, position.y); +} + +std::shared_ptr InterfaceObjectConfigurable::buildLabel(const JsonNode & config) const +{ + auto font = readFont(config["font"]); + auto alignment = readTextAlignment(config["alignment"]); + auto color = readColor(config["color"]); + auto text = readText(config["text"]); + auto position = readPosition(config["position"]); + return std::make_shared(position.x, position.y, font, alignment, color, text); +} + +std::shared_ptr InterfaceObjectConfigurable::buildToggleGroup(const JsonNode & config) const +{ + auto position = readPosition(config["position"]); + auto group = std::make_shared(0); + group->pos += position; + if(!config["items"].isNull()) + { + SObjectConstruction obj__i(group.get()); + int itemIdx = -1; + for(const auto & item : config["items"].Vector()) + { + itemIdx = item["index"].isNull() ? itemIdx + 1 : item["index"].Integer(); + group->addToggle(itemIdx, std::dynamic_pointer_cast(buildWidget(item))); + } + } + if(!config["selected"].isNull()) + group->setSelected(config["selected"].Integer()); + if(!config["callback"].isNull()) + group->addCallback(callbacks.at(config["callback"].String())); + return group; +} + +std::shared_ptr InterfaceObjectConfigurable::buildToggleButton(const JsonNode & config) const +{ + auto position = readPosition(config["position"]); + auto image = config["image"].String(); + auto zelp = readHintText(config["zelp"]); + auto button = std::make_shared(position, image, zelp); + if(!config["selected"].isNull()) + button->setSelected(config["selected"].Bool()); + if(!config["imageOrder"].isNull()) + { + auto imgOrder = config["imageOrder"].Vector(); + assert(imgOrder.size() >= 4); + button->setImageOrder(imgOrder[0].Integer(), imgOrder[1].Integer(), imgOrder[2].Integer(), imgOrder[3].Integer()); + } + if(!config["callback"].isNull()) + button->addCallback(callbacks.at(config["callback"].String())); + return button; +} + +std::shared_ptr InterfaceObjectConfigurable::buildButton(const JsonNode & config) const +{ + auto position = readPosition(config["position"]); + auto image = config["image"].String(); + auto zelp = readHintText(config["zelp"]); + auto button = std::make_shared(position, image, zelp); + if(!config["items"].isNull()) + { + for(const auto & item : config["items"].Vector()) + { + button->addOverlay(buildWidget(item)); + } + } + if(!config["callback"].isNull()) + button->addCallback(std::bind(callbacks.at(config["callback"].String()), 0)); + return button; +} + +std::shared_ptr InterfaceObjectConfigurable::buildLabelGroup(const JsonNode & config) const +{ + auto font = readFont(config["font"]); + auto alignment = readTextAlignment(config["alignment"]); + auto color = readColor(config["color"]); + auto group = std::make_shared(font, alignment, color); + if(!config["items"].isNull()) + { + for(const auto & item : config["items"].Vector()) + { + auto position = readPosition(item["position"]); + auto text = readText(item["text"]); + group->add(position.x, position.y, text); + } + } + return group; +} + +std::shared_ptr InterfaceObjectConfigurable::buildWidget(const JsonNode & config) const { assert(!config.isNull()); auto type = config["type"].String(); - - int x = 0, y = 0; - if(!config["position"].isNull()) - { - x = config["position"]["x"].Integer(); - y = config["position"]["y"].Integer(); - } - - std::string image; - std::string text = buildText(config["text"]); - auto alignment = EAlignment::CENTER; - auto color = Colors::DEFAULT_KEY_COLOR; - auto font = EFonts::FONT_TIMES; - - if(!config["image"].isNull()) - image = config["image"].String(); - if(!config["alignment"].isNull()) - { - if(config["alignment"].String() == "left") - alignment = EAlignment::TOPLEFT; - if(config["alignment"].String() == "center") - alignment = EAlignment::CENTER; - if(config["alignment"].String() == "right") - alignment = EAlignment::BOTTOMRIGHT; - } - if(!config["color"].isNull()) - { - if(config["color"].String() == "yellow") - color = Colors::YELLOW; - if(config["color"].String() == "white") - color = Colors::WHITE; - if(config["color"].String() == "gold") - color = Colors::METALLIC_GOLD; - if(config["color"].String() == "green") - color = Colors::GREEN; - if(config["color"].String() == "orange") - color = Colors::ORANGE; - if(config["color"].String() == "bright-yellow") - color = Colors::BRIGHT_YELLOW; - } - if(!config["font"].isNull()) - { - if(config["font"].String() == "big") - font = EFonts::FONT_BIG; - if(config["font"].String() == "medium") - font = EFonts::FONT_MEDIUM; - if(config["font"].String() == "small") - font = EFonts::FONT_SMALL; - if(config["font"].String() == "tiny") - font = EFonts::FONT_TINY; - } - - if(type == "picture") { - return std::make_shared(image, x, y); + return buildPicture(config); } if(type == "label") { - return std::make_shared(x, y, font, alignment, color, text); + return buildLabel(config); } if(type == "toggleGroup") { - auto group = std::make_shared(0); - group->pos.x += x; - group->pos.y += y; - if(!config["items"].isNull()) - { - SObjectConstruction obj__i(group.get()); - int itemIdx = -1; - for(const auto & item : config["items"].Vector()) - { - itemIdx = item["index"].isNull() ? itemIdx + 1 : item["index"].Integer(); - group->addToggle(itemIdx, std::dynamic_pointer_cast(buildWidget(item))); - } - } - if(!config["selected"].isNull()) - group->setSelected(config["selected"].Integer()); - if(!config["callback"].isNull()) - group->addCallback(callbacks[config["callback"].String()]); - return group; + return buildToggleGroup(config); } if(type == "toggleButton") { - std::pair zelp; - if(!config["zelp"].isNull()) - zelp = CGI->generaltexth->zelp[config["zelp"].Integer()]; - auto button = std::make_shared(Point(x, y), image, zelp); - if(!config["selected"].isNull()) - button->setSelected(config["selected"].Bool()); - if(!config["imageOrder"].isNull()) - { - auto imgOrder = config["imageOrder"].Vector(); - assert(imgOrder.size() >= 4); - button->setImageOrder(imgOrder[0].Integer(), imgOrder[1].Integer(), imgOrder[2].Integer(), imgOrder[3].Integer()); - } - if(!config["callback"].isNull()) - button->addCallback(callbacks[config["callback"].String()]); - return button; + return buildToggleButton(config); } if(type == "button") { - std::pair zelp; - if(!config["zelp"].isNull()) - zelp = CGI->generaltexth->zelp[config["zelp"].Integer()]; - auto button = std::make_shared(Point(x, y), image, zelp); - if(!config["items"].isNull()) - { - for(const auto & item : config["items"].Vector()) - { - button->addOverlay(buildWidget(item)); - } - } - if(!config["callback"].isNull()) - button->addCallback(std::bind(callbacks[config["callback"].String()], 0)); - return button; + return buildButton(config); } if(type == "labelGroup") { - auto group = std::make_shared(font, alignment, color); - if(!config["items"].isNull()) - { - for(const auto & item : config["items"].Vector()) - { - if(!item["position"].isNull()) - { - x = item["position"]["x"].Integer(); - y = item["position"]["y"].Integer(); - } - if(!item["text"].isNull()) - text = buildText(item["text"]); - group->add(x, y, text); - } - } - return group; + return buildLabelGroup(config); } return std::shared_ptr(nullptr); } diff --git a/client/gui/InterfaceObjectConfigurable.h b/client/gui/InterfaceObjectConfigurable.h index 48501d03b..51f23d7be 100644 --- a/client/gui/InterfaceObjectConfigurable.h +++ b/client/gui/InterfaceObjectConfigurable.h @@ -14,6 +14,13 @@ #include "../../lib/JsonNode.h" +class CPicture; +class CLabel; +class CToggleGroup; +class CToggleButton; +class CButton; +class CLabelGroup; + class InterfaceObjectConfigurable: public CIntObject { public: @@ -35,12 +42,29 @@ protected: return std::dynamic_pointer_cast(iter->second); } +private: //field deserializers + //basic serializers + Point readPosition(const JsonNode &) const; + ETextAlignment readTextAlignment(const JsonNode &) const; + SDL_Color readColor(const JsonNode &) const; + EFonts readFont(const JsonNode &) const; + std::string readText(const JsonNode &) const; + std::pair readHintText(const JsonNode &) const; + + //basic widgets + std::shared_ptr buildPicture(const JsonNode &) const; + std::shared_ptr buildLabel(const JsonNode &) const; + std::shared_ptr buildToggleGroup(const JsonNode &) const; + std::shared_ptr buildToggleButton(const JsonNode &) const; + std::shared_ptr buildButton(const JsonNode &) const; + std::shared_ptr buildLabelGroup(const JsonNode &) const; + + + std::shared_ptr buildWidget(const JsonNode & config) const; + + private: std::map> widgets; std::map> callbacks; - - std::shared_ptr buildWidget(const JsonNode & config); - - std::string buildText(const JsonNode & param) const; }; diff --git a/client/lobby/RandomMapTab.cpp b/client/lobby/RandomMapTab.cpp index 3667341cd..dca4cc604 100644 --- a/client/lobby/RandomMapTab.cpp +++ b/client/lobby/RandomMapTab.cpp @@ -100,9 +100,23 @@ RandomMapTab::RandomMapTab(): //new callbacks available only from mod addCallback("templateSelection", [&](int) { - GH.pushInt(std::make_shared(this, int3{mapGenOptions->getWidth(), mapGenOptions->getHeight(), 1 + mapGenOptions->getHasTwoLevels()})); + GH.pushIntT(this, int3{mapGenOptions->getWidth(), mapGenOptions->getHeight(), 1 + mapGenOptions->getHasTwoLevels()}); }); + addCallback("teamAlignments", [&](int) + { + GH.pushIntT(this); + }); + + for(auto road : VLC->terrainTypeHandler->roads()) + { + std::string cbRoadType = "selectRoad_" + road.fileName; + addCallback(cbRoadType, [&](bool on) + { + //TODO: support road types + }); + } + init(config); @@ -293,7 +307,7 @@ TemplatesDropBox::ListItem::ListItem(TemplatesDropBox * _dropBox, Point position dropBox(_dropBox) { OBJ_CONSTRUCTION; - labelName = std::make_shared(0, 0, FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE); + labelName = std::make_shared(0, 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE); labelName->setAutoRedraw(false); hoverImage = std::make_shared("List10Sl", 0, 0); @@ -352,6 +366,9 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab * randomMapTab, int3 size): curItems.insert(curItems.begin(), nullptr); //default template OBJ_CONSTRUCTION; + pos = randomMapTab->pos.topLeft(); + pos.w = randomMapTab->pos.w; + pos.h = randomMapTab->pos.h; background = std::make_shared("List10Bk", 158, 76); int positionsToShow = 10; @@ -362,7 +379,6 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab * randomMapTab, int3 size): slider = std::make_shared(Point(212 + 158, 76), 252, std::bind(&TemplatesDropBox::sliderMove, this, _1), positionsToShow, (int)curItems.size(), 0, false, CSlider::BLUE); updateListItems(); - pos = background->pos; } void TemplatesDropBox::sliderMove(int slidPos) @@ -410,3 +426,24 @@ void TemplatesDropBox::setTemplate(const CRmgTemplate * tmpl) assert(GH.topInt().get() == this); GH.popInt(GH.topInt()); } + +TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab * randomMapTab): + CIntObject(), + randomMapTab(randomMapTab) +{ + OBJ_CONSTRUCTION; + + pos.w = 300; + pos.h = 300; + background = std::make_shared("Bl3DCvex", pos); + center(pos); + + buttonOk = std::make_shared(Point(43, 240), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], [](){}); + buttonCancel = std::make_shared(Point(193, 240), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [&]() + { + assert(GH.topInt().get() == this); + GH.popInt(GH.topInt()); + }, SDLK_ESCAPE); + + +} diff --git a/client/lobby/RandomMapTab.h b/client/lobby/RandomMapTab.h index d30cc16cd..df6530142 100644 --- a/client/lobby/RandomMapTab.h +++ b/client/lobby/RandomMapTab.h @@ -85,3 +85,18 @@ private: std::vector curItems; }; + +class TeamAlignmentsWidget: public CIntObject +{ +public: + TeamAlignmentsWidget(RandomMapTab * randomMapTab); + +private: + + RandomMapTab * randomMapTab; + + std::shared_ptr background; + std::shared_ptr labels; + std::shared_ptr buttonOk, buttonCancel; + std::vector> teams; +};