From 95ff89f62206b62f9fff19a37280b2a7c27bbf0d Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sun, 3 Dec 2023 00:58:00 +0100 Subject: [PATCH 1/3] search spells --- client/PlayerLocalState.h | 6 +- client/windows/CSpellWindow.cpp | 150 ++++++++++++++++++-------------- client/windows/CSpellWindow.h | 5 ++ 3 files changed, 95 insertions(+), 66 deletions(-) diff --git a/client/PlayerLocalState.h b/client/PlayerLocalState.h index 85a367f21..aed9b836c 100644 --- a/client/PlayerLocalState.h +++ b/client/PlayerLocalState.h @@ -42,7 +42,9 @@ public: { //on which page we left spellbook int spellbookLastPageBattle = 0; - int spellbokLastPageAdvmap = 0; + int spellbookLastPageAdvmap = 0; + std::string spellbookLastFilterBattle = ""; + std::string spellbookLastFilterAdvmap = ""; int spellbookLastTabBattle = 4; int spellbookLastTabAdvmap = 4; @@ -50,7 +52,7 @@ public: void serialize(Handler & h, const int version) { h & spellbookLastPageBattle; - h & spellbokLastPageAdvmap; + h & spellbookLastPageAdvmap; h & spellbookLastTabBattle; h & spellbookLastTabAdvmap; } diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index bbd104fd4..46ac78642 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -124,70 +124,13 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m offL = offR = offT = offB = offRM = 0; spellsPerPage = 12; } + pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y)); - //initializing castable spells - mySpells.reserve(CGI->spellh->objects.size()); - for(const CSpell * spell : CGI->spellh->objects) - { - if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell)) - mySpells.push_back(spell); - } - std::sort(mySpells.begin(), mySpells.end(), spellsorter); - - //initializing sizes of spellbook's parts - for(auto & elem : sitesPerTabAdv) - elem = 0; - for(auto & elem : sitesPerTabBattle) - elem = 0; - - for(const auto spell : mySpells) - { - int * sitesPerOurTab = spell->isCombat() ? sitesPerTabBattle : sitesPerTabAdv; - - ++sitesPerOurTab[4]; - - spell->forEachSchool([&sitesPerOurTab](const SpellSchool & school, bool & stop) - { - ++sitesPerOurTab[school]; - }); - } - if(sitesPerTabAdv[4] % spellsPerPage == 0) - sitesPerTabAdv[4]/=spellsPerPage; - else - sitesPerTabAdv[4] = sitesPerTabAdv[4]/spellsPerPage + 1; - - for(int v=0; v<4; ++v) - { - if(sitesPerTabAdv[v] <= spellsPerPage - 2) - sitesPerTabAdv[v] = 1; - else - { - if((sitesPerTabAdv[v] - spellsPerPage - 2) % spellsPerPage == 0) - sitesPerTabAdv[v] = (sitesPerTabAdv[v] - spellsPerPage - 2) / spellsPerPage + 1; - else - sitesPerTabAdv[v] = (sitesPerTabAdv[v] - spellsPerPage - 2) / spellsPerPage + 2; - } - } - - if(sitesPerTabBattle[4] % spellsPerPage == 0) - sitesPerTabBattle[4]/=spellsPerPage; - else - sitesPerTabBattle[4] = sitesPerTabBattle[4]/spellsPerPage + 1; - - for(int v=0; v<4; ++v) - { - if(sitesPerTabBattle[v] <= spellsPerPage - 2) - sitesPerTabBattle[v] = 1; - else - { - if((sitesPerTabBattle[v] - spellsPerPage - 2) % spellsPerPage == 0) - sitesPerTabBattle[v] = (sitesPerTabBattle[v] - spellsPerPage - 2) / spellsPerPage + 1; - else - sitesPerTabBattle[v] = (sitesPerTabBattle[v] - spellsPerPage - 2) / spellsPerPage + 2; - } - } + searchBox = std::make_shared<CTextInput>(Rect(10, isBigSpellbook ? 8 : 20, pos.w-20, 16), FONT_MEDIUM, std::bind(&CSpellWindow::searchInput, this)); + searchBox->setText(battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastFilterBattle : myInt->localState->spellbookSettings.spellbookLastFilterAdvmap); + processSpells(); //numbers of spell pages computed @@ -253,7 +196,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m selectedTab = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap; schoolTab->setFrame(selectedTab, 0); - int cp = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap; + int cp = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbookLastPageAdvmap; // spellbook last page battle index is not reset after battle, so this needs to stay here vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1)); setCurrentPage(cp); @@ -296,10 +239,89 @@ std::shared_ptr<IImage> CSpellWindow::createBigSpellBook() return GH.renderHandler().createImage(canvas.getInternalSurface()); } +void CSpellWindow::searchInput() +{ + processSpells(); + + int cp = 0; + // spellbook last page battle index is not reset after battle, so this needs to stay here + vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1)); + setCurrentPage(cp); + computeSpellsPerArea(); +} + +void CSpellWindow::processSpells() +{ + mySpells.clear(); + + //initializing castable spells + mySpells.reserve(CGI->spellh->objects.size()); + for(const CSpell * spell : CGI->spellh->objects) + { + if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell) && boost::algorithm::contains(boost::algorithm::to_lower_copy(spell->getNameTranslated()), boost::algorithm::to_lower_copy(searchBox->getText()))) + mySpells.push_back(spell); + } + std::sort(mySpells.begin(), mySpells.end(), spellsorter); + + //initializing sizes of spellbook's parts + for(auto & elem : sitesPerTabAdv) + elem = 0; + for(auto & elem : sitesPerTabBattle) + elem = 0; + + for(const auto spell : mySpells) + { + int * sitesPerOurTab = spell->isCombat() ? sitesPerTabBattle : sitesPerTabAdv; + + ++sitesPerOurTab[4]; + + spell->forEachSchool([&sitesPerOurTab](const SpellSchool & school, bool & stop) + { + ++sitesPerOurTab[school]; + }); + } + if(sitesPerTabAdv[4] % spellsPerPage == 0) + sitesPerTabAdv[4]/=spellsPerPage; + else + sitesPerTabAdv[4] = sitesPerTabAdv[4]/spellsPerPage + 1; + + for(int v=0; v<4; ++v) + { + if(sitesPerTabAdv[v] <= spellsPerPage - 2) + sitesPerTabAdv[v] = 1; + else + { + if((sitesPerTabAdv[v] - spellsPerPage - 2) % spellsPerPage == 0) + sitesPerTabAdv[v] = (sitesPerTabAdv[v] - spellsPerPage - 2) / spellsPerPage + 1; + else + sitesPerTabAdv[v] = (sitesPerTabAdv[v] - spellsPerPage - 2) / spellsPerPage + 2; + } + } + + if(sitesPerTabBattle[4] % spellsPerPage == 0) + sitesPerTabBattle[4]/=spellsPerPage; + else + sitesPerTabBattle[4] = sitesPerTabBattle[4]/spellsPerPage + 1; + + for(int v=0; v<4; ++v) + { + if(sitesPerTabBattle[v] <= spellsPerPage - 2) + sitesPerTabBattle[v] = 1; + else + { + if((sitesPerTabBattle[v] - spellsPerPage - 2) % spellsPerPage == 0) + sitesPerTabBattle[v] = (sitesPerTabBattle[v] - spellsPerPage - 2) / spellsPerPage + 1; + else + sitesPerTabBattle[v] = (sitesPerTabBattle[v] - spellsPerPage - 2) / spellsPerPage + 2; + } + } +} + void CSpellWindow::fexitb() { (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap) = selectedTab; - (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap) = currentPage; + (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbookLastPageAdvmap) = currentPage; + (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastFilterBattle : myInt->localState->spellbookSettings.spellbookLastFilterAdvmap) = searchBox->getText(); close(); } @@ -595,7 +617,7 @@ void CSpellWindow::SpellArea::clickPressed(const Point & cursorPosition) auto guard = vstd::makeScopeGuard([this]() { owner->myInt->localState->spellbookSettings.spellbookLastTabAdvmap = owner->selectedTab; - owner->myInt->localState->spellbookSettings.spellbokLastPageAdvmap = owner->currentPage; + owner->myInt->localState->spellbookSettings.spellbookLastPageAdvmap = owner->currentPage; }); if(mySpell->getTargetType() == spells::AimType::LOCATION) diff --git a/client/windows/CSpellWindow.h b/client/windows/CSpellWindow.h index 941de6428..a9915f82e 100644 --- a/client/windows/CSpellWindow.h +++ b/client/windows/CSpellWindow.h @@ -26,6 +26,7 @@ class CLabel; class CGStatusBar; class CPlayerInterface; class CSpellWindow; +class CTextInput; /// The spell window class CSpellWindow : public CWindowObject @@ -80,6 +81,8 @@ class CSpellWindow : public CWindowObject std::vector<std::shared_ptr<InteractiveArea>> interactiveAreas; + std::shared_ptr<CTextInput> searchBox; + bool isBigSpellbook; int spellsPerPage; int offL; @@ -99,6 +102,8 @@ class CSpellWindow : public CWindowObject const CGHeroInstance * myHero; //hero whose spells are presented CPlayerInterface * myInt; + void processSpells(); + void searchInput(); void computeSpellsPerArea(); //recalculates spellAreas::mySpell void setCurrentPage(int value); From dfb10bdfcb22f85aa5ea34966aa1e57315820546 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Fri, 8 Dec 2023 22:52:34 +0100 Subject: [PATCH 2/3] search rectangle --- Mods/vcmi/config/vcmi/english.json | 2 ++ Mods/vcmi/config/vcmi/german.json | 2 ++ client/PlayerLocalState.h | 2 -- client/windows/CSpellWindow.cpp | 22 ++++++++++++++++++---- client/windows/CSpellWindow.h | 3 +++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index 242099ee7..c7f1af0b6 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -54,6 +54,8 @@ "vcmi.radialWheel.moveDown" : "Move down", "vcmi.radialWheel.moveBottom" : "Move to bottom", + "vcmi.spellBook.search" : "search...", + "vcmi.mainMenu.serverConnecting" : "Connecting...", "vcmi.mainMenu.serverAddressEnter" : "Enter address:", "vcmi.mainMenu.serverConnectionFailed" : "Failed to connect", diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json index 07d13f06d..19376f89d 100644 --- a/Mods/vcmi/config/vcmi/german.json +++ b/Mods/vcmi/config/vcmi/german.json @@ -54,6 +54,8 @@ "vcmi.radialWheel.moveDown" : "Nach unten bewegen", "vcmi.radialWheel.moveBottom" : "Ganz nach unten bewegen", + "vcmi.spellBook.search" : "suchen...", + "vcmi.mainMenu.serverConnecting" : "Verbinde...", "vcmi.mainMenu.serverAddressEnter" : "Addresse eingeben:", "vcmi.mainMenu.serverConnectionFailed" : "Verbindung fehlgeschlagen", diff --git a/client/PlayerLocalState.h b/client/PlayerLocalState.h index aed9b836c..10b65fc1b 100644 --- a/client/PlayerLocalState.h +++ b/client/PlayerLocalState.h @@ -43,8 +43,6 @@ public: //on which page we left spellbook int spellbookLastPageBattle = 0; int spellbookLastPageAdvmap = 0; - std::string spellbookLastFilterBattle = ""; - std::string spellbookLastFilterAdvmap = ""; int spellbookLastTabBattle = 4; int spellbookLastTabAdvmap = 4; diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index 46ac78642..4cb3d215f 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -127,8 +127,19 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y)); - searchBox = std::make_shared<CTextInput>(Rect(10, isBigSpellbook ? 8 : 20, pos.w-20, 16), FONT_MEDIUM, std::bind(&CSpellWindow::searchInput, this)); - searchBox->setText(battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastFilterBattle : myInt->localState->spellbookSettings.spellbookLastFilterAdvmap); + if(settings["general"]["enableUiEnhancements"].Bool()) + { + Rect r(90, isBigSpellbook ? 480 : 420, isBigSpellbook ? 160 : 110, 16); + const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75); + const ColorRGBA borderColor = ColorRGBA(128, 100, 75); + const ColorRGBA grayedColor = ColorRGBA(158, 130, 105); + searchBoxRectangle = std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor); + searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, CGI->generaltexth->translate("vcmi.spellBook.search")); + + searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, std::bind(&CSpellWindow::searchInput, this)); + searchBox->removeFocus(); + searchBox->setText(""); + } processSpells(); @@ -241,6 +252,9 @@ std::shared_ptr<IImage> CSpellWindow::createBigSpellBook() void CSpellWindow::searchInput() { + if(searchBox) + searchBoxDescription->setEnabled(searchBox->getText().empty()); + processSpells(); int cp = 0; @@ -258,7 +272,8 @@ void CSpellWindow::processSpells() mySpells.reserve(CGI->spellh->objects.size()); for(const CSpell * spell : CGI->spellh->objects) { - if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell) && boost::algorithm::contains(boost::algorithm::to_lower_copy(spell->getNameTranslated()), boost::algorithm::to_lower_copy(searchBox->getText()))) + bool searchTextFound = !searchBox || boost::algorithm::contains(boost::algorithm::to_lower_copy(spell->getNameTranslated()), boost::algorithm::to_lower_copy(searchBox->getText())); + if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell) && searchTextFound) mySpells.push_back(spell); } std::sort(mySpells.begin(), mySpells.end(), spellsorter); @@ -321,7 +336,6 @@ void CSpellWindow::fexitb() { (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap) = selectedTab; (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbookLastPageAdvmap) = currentPage; - (myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastFilterBattle : myInt->localState->spellbookSettings.spellbookLastFilterAdvmap) = searchBox->getText(); close(); } diff --git a/client/windows/CSpellWindow.h b/client/windows/CSpellWindow.h index a9915f82e..16401a752 100644 --- a/client/windows/CSpellWindow.h +++ b/client/windows/CSpellWindow.h @@ -27,6 +27,7 @@ class CGStatusBar; class CPlayerInterface; class CSpellWindow; class CTextInput; +class TransparentFilledRectangle; /// The spell window class CSpellWindow : public CWindowObject @@ -82,6 +83,8 @@ class CSpellWindow : public CWindowObject std::vector<std::shared_ptr<InteractiveArea>> interactiveAreas; std::shared_ptr<CTextInput> searchBox; + std::shared_ptr<TransparentFilledRectangle> searchBoxRectangle; + std::shared_ptr<CLabel> searchBoxDescription; bool isBigSpellbook; int spellsPerPage; From 77505af71b6899dc6d4e580350ec71773ceba0a1 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sun, 17 Dec 2023 22:17:32 +0100 Subject: [PATCH 3/3] remove removefoucs --- client/windows/CSpellWindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index 4cb3d215f..b35f0a8c7 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -137,8 +137,6 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, CGI->generaltexth->translate("vcmi.spellBook.search")); searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, std::bind(&CSpellWindow::searchInput, this)); - searchBox->removeFocus(); - searchBox->setText(""); } processSpells();