mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
commit
abf9d1017e
@ -15,6 +15,8 @@
|
||||
"vcmi.adventureMap.monsterLevel" : "\n\nLevel %LEVEL %TOWN %ATTACK_TYPE unit",
|
||||
"vcmi.adventureMap.monsterMeleeType" : "melee",
|
||||
"vcmi.adventureMap.monsterRangedType" : "ranged",
|
||||
"vcmi.adventureMap.search.hover" : "Search map object",
|
||||
"vcmi.adventureMap.search.help" : "Select object to search on map.",
|
||||
|
||||
"vcmi.adventureMap.confirmRestartGame" : "Are you sure you want to restart the game?",
|
||||
"vcmi.adventureMap.noTownWithMarket" : "There are no available marketplaces!",
|
||||
|
@ -15,6 +15,8 @@
|
||||
"vcmi.adventureMap.monsterLevel" : "\n\nStufe %LEVEL %TOWN-Einheit (%ATTACK_TYPE)",
|
||||
"vcmi.adventureMap.monsterMeleeType" : "Nahkampf",
|
||||
"vcmi.adventureMap.monsterRangedType" : "Fernkampf",
|
||||
"vcmi.adventureMap.search.hover" : "Suche Kartenobjekt",
|
||||
"vcmi.adventureMap.search.help" : "Wähle Objekt das gesucht werden soll.",
|
||||
|
||||
"vcmi.adventureMap.confirmRestartGame" : "Seid Ihr sicher, dass Ihr das Spiel neu starten wollt?",
|
||||
"vcmi.adventureMap.noTownWithMarket" : "Kein Marktplatz verfügbar!",
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "../windows/CKingdomInterface.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../windows/CMarketWindow.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/settings/SettingsMainWindow.h"
|
||||
#include "AdventureMapInterface.h"
|
||||
#include "AdventureOptions.h"
|
||||
@ -36,11 +37,14 @@
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/pathfinder/CGPathNode.h"
|
||||
#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||
|
||||
AdventureMapShortcuts::AdventureMapShortcuts(AdventureMapInterface & owner)
|
||||
: owner(owner)
|
||||
, state(EAdventureState::NOT_INITIALIZED)
|
||||
, mapLevel(0)
|
||||
, searchLast("")
|
||||
, searchPos(0)
|
||||
{}
|
||||
|
||||
void AdventureMapShortcuts::setState(EAdventureState newState)
|
||||
@ -109,7 +113,9 @@ std::vector<AdventureMapShortcutState> AdventureMapShortcuts::getShortcuts()
|
||||
{ EShortcut::ADVENTURE_MOVE_HERO_EE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, 0}); } },
|
||||
{ EShortcut::ADVENTURE_MOVE_HERO_NW, optionHeroSelected(), [this]() { this->moveHeroDirectional({-1, -1}); } },
|
||||
{ EShortcut::ADVENTURE_MOVE_HERO_NN, optionHeroSelected(), [this]() { this->moveHeroDirectional({ 0, -1}); } },
|
||||
{ EShortcut::ADVENTURE_MOVE_HERO_NE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, -1}); } }
|
||||
{ EShortcut::ADVENTURE_MOVE_HERO_NE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, -1}); } },
|
||||
{ EShortcut::ADVENTURE_SEARCH, optionSidePanelActive(),[this]() { this->search(false); } },
|
||||
{ EShortcut::ADVENTURE_SEARCH_CONTINUE, optionSidePanelActive(),[this]() { this->search(true); } }
|
||||
};
|
||||
return result;
|
||||
}
|
||||
@ -457,6 +463,62 @@ void AdventureMapShortcuts::zoom( int distance)
|
||||
owner.hotkeyZoom(distance, false);
|
||||
}
|
||||
|
||||
void AdventureMapShortcuts::search(bool next)
|
||||
{
|
||||
// get all relevant objects
|
||||
std::vector<ObjectInstanceID> visitableObjInstances;
|
||||
for(auto & obj : LOCPLINT->cb->getAllVisitableObjs())
|
||||
if(obj->ID != MapObjectID::MONSTER && obj->ID != MapObjectID::HERO && obj->ID != MapObjectID::TOWN)
|
||||
visitableObjInstances.push_back(obj->id);
|
||||
|
||||
// count of elements for each group (map is already sorted)
|
||||
std::map<std::string, int> mapObjCount;
|
||||
for(auto & obj : visitableObjInstances)
|
||||
mapObjCount[{ LOCPLINT->cb->getObjInstance(obj)->getObjectName() }]++;
|
||||
|
||||
// convert to vector for indexed access
|
||||
std::vector<std::pair<std::string, int>> textCountList;
|
||||
for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr)
|
||||
textCountList.push_back(*itr);
|
||||
|
||||
// get pos of last selection
|
||||
int lastSel = 0;
|
||||
for(int i = 0; i < textCountList.size(); i++)
|
||||
if(textCountList[i].first == searchLast)
|
||||
lastSel = i;
|
||||
|
||||
// create texts
|
||||
std::vector<std::string> texts;
|
||||
for(auto & obj : textCountList)
|
||||
texts.push_back(obj.first + " (" + std::to_string(obj.second) + ")");
|
||||
|
||||
// function to center element from list on map
|
||||
auto selectObjOnMap = [this, textCountList, visitableObjInstances](int index)
|
||||
{
|
||||
auto selObj = textCountList[index].first;
|
||||
|
||||
// filter for matching objects
|
||||
std::vector<ObjectInstanceID> selVisitableObjInstances;
|
||||
for(auto & obj : visitableObjInstances)
|
||||
if(selObj == LOCPLINT->cb->getObjInstance(obj)->getObjectName())
|
||||
selVisitableObjInstances.push_back(obj);
|
||||
|
||||
if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj)
|
||||
searchPos++;
|
||||
else
|
||||
searchPos = 0;
|
||||
|
||||
auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]);
|
||||
owner.centerOnObject(objInst);
|
||||
searchLast = objInst->getObjectName();
|
||||
};
|
||||
|
||||
if(next)
|
||||
selectObjOnMap(lastSel);
|
||||
else
|
||||
GH.windows().createAndPushWindow<CObjectListWindow>(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), [selectObjOnMap](int index){ selectObjOnMap(index); }, lastSel, std::vector<std::shared_ptr<IImage>>(), true);
|
||||
}
|
||||
|
||||
void AdventureMapShortcuts::nextObject()
|
||||
{
|
||||
const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero();
|
||||
|
@ -33,6 +33,9 @@ class AdventureMapShortcuts
|
||||
EAdventureState state;
|
||||
int mapLevel;
|
||||
|
||||
std::string searchLast;
|
||||
int searchPos;
|
||||
|
||||
void showOverview();
|
||||
void worldViewBack();
|
||||
void worldViewScale1x();
|
||||
@ -71,6 +74,7 @@ class AdventureMapShortcuts
|
||||
void nextTown();
|
||||
void nextObject();
|
||||
void zoom( int distance);
|
||||
void search(bool next);
|
||||
void moveHeroDirectional(const Point & direction);
|
||||
|
||||
public:
|
||||
|
@ -161,6 +161,8 @@ enum class EShortcut
|
||||
ADVENTURE_RESTART_GAME,
|
||||
ADVENTURE_TO_MAIN_MENU,
|
||||
ADVENTURE_QUIT_GAME,
|
||||
ADVENTURE_SEARCH,
|
||||
ADVENTURE_SEARCH_CONTINUE,
|
||||
|
||||
// Move hero one tile in specified direction. Bound to cursors & numpad buttons
|
||||
ADVENTURE_MOVE_HERO_SW,
|
||||
|
@ -209,6 +209,8 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const
|
||||
{"adventureZoomIn", EShortcut::ADVENTURE_ZOOM_IN },
|
||||
{"adventureZoomOut", EShortcut::ADVENTURE_ZOOM_OUT },
|
||||
{"adventureZoomReset", EShortcut::ADVENTURE_ZOOM_RESET },
|
||||
{"adventureSearch", EShortcut::ADVENTURE_SEARCH },
|
||||
{"adventureSearchContinue", EShortcut::ADVENTURE_SEARCH_CONTINUE },
|
||||
{"battleToggleHeroesStats", EShortcut::BATTLE_TOGGLE_HEROES_STATS},
|
||||
{"battleToggleQueue", EShortcut::BATTLE_TOGGLE_QUEUE },
|
||||
{"battleUseCreatureSpell", EShortcut::BATTLE_USE_CREATURE_SPELL },
|
||||
|
@ -185,6 +185,9 @@ void CListBox::scrollTo(size_t which)
|
||||
//scroll down
|
||||
else if (first + items.size() <= which && which < totalSize)
|
||||
moveToPos(which - items.size() + 1);
|
||||
|
||||
if(slider)
|
||||
slider->scrollTo(which);
|
||||
}
|
||||
|
||||
void CListBox::moveToPos(size_t which)
|
||||
|
@ -1480,39 +1480,47 @@ void CObjectListWindow::CItem::showPopupWindow(const Point & cursorPosition)
|
||||
parent->onPopup(index);
|
||||
}
|
||||
|
||||
CObjectListWindow::CObjectListWindow(const std::vector<int> & _items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection, std::vector<std::shared_ptr<IImage>> images)
|
||||
CObjectListWindow::CObjectListWindow(const std::vector<int> & _items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection, std::vector<std::shared_ptr<IImage>> images, bool searchBoxEnabled)
|
||||
: CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPGATE")),
|
||||
onSelect(Callback),
|
||||
selected(initialSelection),
|
||||
images(images)
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
addUsedEvents(KEYBOARD);
|
||||
|
||||
items.reserve(_items.size());
|
||||
|
||||
for(int id : _items)
|
||||
{
|
||||
items.push_back(std::make_pair(id, LOCPLINT->cb->getObjInstance(ObjectInstanceID(id))->getObjectName()));
|
||||
}
|
||||
itemsVisible = items;
|
||||
|
||||
init(titleWidget_, _title, _descr);
|
||||
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
||||
list->scrollTo(initialSelection - 4); // -4 is for centering (list have 9 elements)
|
||||
}
|
||||
|
||||
CObjectListWindow::CObjectListWindow(const std::vector<std::string> & _items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection, std::vector<std::shared_ptr<IImage>> images)
|
||||
CObjectListWindow::CObjectListWindow(const std::vector<std::string> & _items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection, std::vector<std::shared_ptr<IImage>> images, bool searchBoxEnabled)
|
||||
: CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPGATE")),
|
||||
onSelect(Callback),
|
||||
selected(initialSelection),
|
||||
images(images)
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
addUsedEvents(KEYBOARD);
|
||||
|
||||
items.reserve(_items.size());
|
||||
|
||||
for(size_t i=0; i<_items.size(); i++)
|
||||
items.push_back(std::make_pair(int(i), _items[i]));
|
||||
itemsVisible = items;
|
||||
|
||||
init(titleWidget_, _title, _descr);
|
||||
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
||||
list->scrollTo(initialSelection - 4); // -4 is for centering (list have 9 elements)
|
||||
}
|
||||
|
||||
void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr)
|
||||
void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled)
|
||||
{
|
||||
titleWidget = titleWidget_;
|
||||
|
||||
@ -1527,24 +1535,51 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
|
||||
titleWidget->pos.y =75 + pos.y - titleWidget->pos.h/2;
|
||||
}
|
||||
list = std::make_shared<CListBox>(std::bind(&CObjectListWindow::genItem, this, _1),
|
||||
Point(14, 151), Point(0, 25), 9, items.size(), 0, 1, Rect(262, -32, 256, 256) );
|
||||
Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) );
|
||||
list->setRedrawParent(true);
|
||||
|
||||
ok = std::make_shared<CButton>(Point(15, 402), AnimationPath::builtin("IOKAY.DEF"), CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), EShortcut::GLOBAL_ACCEPT);
|
||||
ok->block(!list->size());
|
||||
|
||||
if(!searchBoxEnabled)
|
||||
return;
|
||||
|
||||
Rect r(50, 90, pos.w - 100, 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, ETextAlignment::CENTER, true);
|
||||
searchBox->setCallback([this](const std::string & text){
|
||||
searchBoxDescription->setEnabled(text.empty());
|
||||
|
||||
itemsVisible.clear();
|
||||
for(auto & item : items)
|
||||
if(boost::algorithm::contains(boost::algorithm::to_lower_copy(item.second), boost::algorithm::to_lower_copy(text)))
|
||||
itemsVisible.push_back(item);
|
||||
|
||||
selected = 0;
|
||||
list->resize(itemsVisible.size());
|
||||
list->scrollTo(0);
|
||||
ok->block(!itemsVisible.size());
|
||||
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CObjectListWindow::genItem(size_t index)
|
||||
{
|
||||
if(index < items.size())
|
||||
return std::make_shared<CItem>(this, index, items[index].second);
|
||||
if(index < itemsVisible.size())
|
||||
return std::make_shared<CItem>(this, index, itemsVisible[index].second);
|
||||
return std::shared_ptr<CIntObject>();
|
||||
}
|
||||
|
||||
void CObjectListWindow::elementSelected()
|
||||
{
|
||||
std::function<void(int)> toCall = onSelect;//save
|
||||
int where = items[selected].first; //required variables
|
||||
int where = itemsVisible[selected].first; //required variables
|
||||
close();//then destroy window
|
||||
toCall(where);//and send selected object
|
||||
}
|
||||
@ -1600,14 +1635,14 @@ void CObjectListWindow::keyPressed(EShortcut key)
|
||||
sel = 0;
|
||||
|
||||
break; case EShortcut::MOVE_LAST:
|
||||
sel = static_cast<int>(items.size());
|
||||
sel = static_cast<int>(itemsVisible.size());
|
||||
|
||||
break; default:
|
||||
return;
|
||||
}
|
||||
|
||||
vstd::abetween<int>(sel, 0, items.size()-1);
|
||||
list->scrollTo(sel);
|
||||
vstd::abetween<int>(sel, 0, itemsVisible.size()-1);
|
||||
list->scrollTo(sel - 4); // -4 is for centering (list have 9 elements)
|
||||
changeSelection(sel);
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ class IImage;
|
||||
class VideoWidget;
|
||||
class VideoWidgetOnce;
|
||||
class GraphicalPrimitiveCanvas;
|
||||
class TransparentFilledRectangle;
|
||||
|
||||
enum class EUserEvent;
|
||||
|
||||
@ -186,9 +187,14 @@ class CObjectListWindow : public CWindowObject
|
||||
std::shared_ptr<CButton> ok;
|
||||
std::shared_ptr<CButton> exit;
|
||||
|
||||
std::vector< std::pair<int, std::string> > items;//all items present in list
|
||||
std::shared_ptr<CTextInput> searchBox;
|
||||
std::shared_ptr<TransparentFilledRectangle> searchBoxRectangle;
|
||||
std::shared_ptr<CLabel> searchBoxDescription;
|
||||
|
||||
void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr);
|
||||
std::vector< std::pair<int, std::string> > items; //all items present in list
|
||||
std::vector< std::pair<int, std::string> > itemsVisible; //visible items present in list
|
||||
|
||||
void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled);
|
||||
void exitPressed();
|
||||
public:
|
||||
size_t selected;//index of currently selected item
|
||||
@ -200,8 +206,8 @@ public:
|
||||
/// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item
|
||||
/// Image can be nullptr
|
||||
///item names will be taken from map objects
|
||||
CObjectListWindow(const std::vector<int> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection = 0, std::vector<std::shared_ptr<IImage>> images = {});
|
||||
CObjectListWindow(const std::vector<std::string> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection = 0, std::vector<std::shared_ptr<IImage>> images = {});
|
||||
CObjectListWindow(const std::vector<int> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection = 0, std::vector<std::shared_ptr<IImage>> images = {}, bool searchBoxEnabled = false);
|
||||
CObjectListWindow(const std::vector<std::string> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback, size_t initialSelection = 0, std::vector<std::shared_ptr<IImage>> images = {}, bool searchBoxEnabled = false);
|
||||
|
||||
std::shared_ptr<CIntObject> genItem(size_t index);
|
||||
void elementSelected();//call callback and close this window
|
||||
|
@ -56,6 +56,8 @@
|
||||
"adventureZoomIn": "Keypad +",
|
||||
"adventureZoomOut": "Keypad -",
|
||||
"adventureZoomReset": "Backspace",
|
||||
"adventureSearch": "Ctrl+F",
|
||||
"adventureSearchContinue": "Alt+F",
|
||||
"battleAutocombat": "A",
|
||||
"battleAutocombatEnd": "Q",
|
||||
"battleCastSpell": "C",
|
||||
|
@ -479,6 +479,17 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getVisitableObjs(int3
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<ConstTransitivePtr<CGObjectInstance>> CGameInfoCallback::getAllVisitableObjs() const
|
||||
{
|
||||
std::vector<ConstTransitivePtr<CGObjectInstance>> ret;
|
||||
for(auto & obj : gs->map->objects)
|
||||
if(obj->isVisitable() && obj->ID != Obj::EVENT && isVisible(obj))
|
||||
ret.push_back(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const CGObjectInstance * CGameInfoCallback::getTopObj (int3 pos) const
|
||||
{
|
||||
return vstd::backOrNull(getVisitableObjs(pos));
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "int3.h"
|
||||
#include "ResourceSet.h" // for Res
|
||||
#include "ConstTransitivePtr.h"
|
||||
|
||||
#define ASSERT_IF_CALLED_WITH_PLAYER if(!getPlayerID()) {logGlobal->error(BOOST_CURRENT_FUNCTION); assert(0);}
|
||||
|
||||
@ -189,6 +190,7 @@ public:
|
||||
const CGObjectInstance * getObj(ObjectInstanceID objid, bool verbose = true) const override;
|
||||
virtual std::vector <const CGObjectInstance * > getBlockingObjs(int3 pos)const;
|
||||
std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos, bool verbose = true) const override;
|
||||
std::vector<ConstTransitivePtr<CGObjectInstance>> getAllVisitableObjs() const;
|
||||
virtual std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
|
||||
virtual const CGObjectInstance * getTopObj (int3 pos) const;
|
||||
virtual PlayerColor getOwner(ObjectInstanceID heroID) const;
|
||||
|
@ -358,7 +358,7 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObj
|
||||
return mapObjectTypes.front()->objectTypeHandlers.front();
|
||||
|
||||
auto subID = subtype.getNum();
|
||||
if (type == Obj::PRISON || type == Obj::HERO_PLACEHOLDER)
|
||||
if (type == Obj::PRISON || type == Obj::HERO_PLACEHOLDER || type == Obj::SPELL_SCROLL)
|
||||
subID = 0;
|
||||
auto result = mapObjectTypes.at(type.getNum())->objectTypeHandlers.at(subID);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user