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(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 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> interactiveAreas; + std::shared_ptr 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);