mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-11 11:31:52 +02:00
Encapsulation of WindowHandler state
This commit is contained in:
parent
7838190ef4
commit
051a4a3c17
@ -623,8 +623,7 @@ static void quitApplication()
|
||||
CSH->endGameplay();
|
||||
}
|
||||
|
||||
GH.windows().listInt.clear();
|
||||
GH.windows().objsToBlit.clear();
|
||||
GH.windows().clear();
|
||||
|
||||
CMM.reset();
|
||||
|
||||
|
@ -169,15 +169,16 @@ void CPlayerInterface::initGameInterface(std::shared_ptr<Environment> ENV, std::
|
||||
void CPlayerInterface::playerStartsTurn(PlayerColor player)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if (!vstd::contains (GH.windows().listInt, adventureInt))
|
||||
|
||||
if(GH.windows().findInts<AdventureMapInterface>().empty())
|
||||
{
|
||||
// after map load - remove all active windows and replace them with adventure map
|
||||
GH.windows().popInts ((int)GH.windows().listInt.size());
|
||||
GH.windows().pushInt (adventureInt);
|
||||
GH.windows().clear();
|
||||
GH.windows().pushInt(adventureInt);
|
||||
}
|
||||
|
||||
// remove all dialogs that do not expect query answer
|
||||
while (GH.windows().listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.windows().listInt.front().get()))
|
||||
while (GH.windows().topInt() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.windows().topInt().get()))
|
||||
GH.windows().popInts(1);
|
||||
|
||||
if (player != playerID && LOCPLINT == this)
|
||||
@ -538,17 +539,15 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
|
||||
castleInt->heroes->update();
|
||||
castleInt->redraw();
|
||||
}
|
||||
for (auto isa : GH.windows().listInt)
|
||||
|
||||
for (auto ki : GH.windows().findInts<CKingdomInterface>())
|
||||
{
|
||||
CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa.get());
|
||||
if (ki)
|
||||
{
|
||||
ki->townChanged(town);
|
||||
ki->updateGarrisons();
|
||||
ki->redraw();
|
||||
}
|
||||
ki->townChanged(town);
|
||||
ki->updateGarrisons();
|
||||
ki->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -590,17 +589,13 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
|
||||
adventureInt->onTownChanged(town);
|
||||
}
|
||||
|
||||
for (auto & elem : GH.windows().listInt)
|
||||
{
|
||||
CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(elem.get());
|
||||
if (cgh)
|
||||
cgh->updateGarrisons();
|
||||
for (auto cgh : GH.windows().findInts<CGarrisonHolder>())
|
||||
cgh->updateGarrisons();
|
||||
|
||||
if (CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(elem.get()))
|
||||
{
|
||||
if (vstd::contains(objs, cmw->hero))
|
||||
cmw->garrisonChanged();
|
||||
}
|
||||
for (auto cmw : GH.windows().findInts<CTradeWindow>())
|
||||
{
|
||||
if (vstd::contains(objs, cmw->hero))
|
||||
cmw->garrisonChanged();
|
||||
}
|
||||
|
||||
GH.windows().totalRedraw();
|
||||
@ -1016,7 +1011,7 @@ void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &t
|
||||
waitWhileDialog(); //Fix for mantis #98
|
||||
adventureInt->showInfoBoxMessage(components, text, timer);
|
||||
|
||||
if (makingTurn && GH.windows().listInt.size() && LOCPLINT == this)
|
||||
if (makingTurn && GH.windows().count() > 0 && LOCPLINT == this)
|
||||
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
|
||||
return;
|
||||
}
|
||||
@ -1057,7 +1052,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
|
||||
}
|
||||
std::shared_ptr<CInfoWindow> temp = CInfoWindow::create(text, playerID, components);
|
||||
|
||||
if (makingTurn && GH.windows().listInt.size() && LOCPLINT == this)
|
||||
if (makingTurn && GH.windows().count() > 0 && LOCPLINT == this)
|
||||
{
|
||||
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
|
||||
showingDialog->set(true);
|
||||
@ -1206,14 +1201,11 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
|
||||
else if(castleInterface)
|
||||
castleInterface->creaturesChangedEventHandler();
|
||||
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa.get());
|
||||
if (ki && townObj)
|
||||
if (townObj)
|
||||
for (auto ki : GH.windows().findInts<CKingdomInterface>())
|
||||
ki->townChanged(townObj);
|
||||
}
|
||||
}
|
||||
else if(town && GH.windows().listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1
|
||||
else if(town && GH.windows().count() > 0 && (town->ID == Obj::CREATURE_GENERATOR1
|
||||
|| town->ID == Obj::CREATURE_GENERATOR4 || town->ID == Obj::WAR_MACHINE_FACTORY))
|
||||
{
|
||||
CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.windows().topInt().get());
|
||||
@ -1594,7 +1586,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
|
||||
if(adventureInt)
|
||||
{
|
||||
GH.terminate_cond->setn(true);
|
||||
GH.windows().popInts(GH.windows().listInt.size());
|
||||
GH.windows().popInts(GH.windows().count());
|
||||
adventureInt.reset();
|
||||
}
|
||||
}
|
||||
@ -1809,12 +1801,9 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
if (artWin)
|
||||
artWin->artifactRemoved(al);
|
||||
}
|
||||
|
||||
for(auto artWin : GH.windows().findInts<CArtifactHolder>())
|
||||
artWin->artifactRemoved(al);
|
||||
|
||||
waitWhileDialog();
|
||||
}
|
||||
@ -1834,12 +1823,9 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
redraw = false;
|
||||
}
|
||||
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
if (artWin)
|
||||
artWin->artifactMoved(src, dst, redraw);
|
||||
}
|
||||
for(auto artWin : GH.windows().findInts<CArtifactHolder>())
|
||||
artWin->artifactMoved(src, dst, redraw);
|
||||
|
||||
waitWhileDialog();
|
||||
}
|
||||
|
||||
@ -1853,12 +1839,9 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
if (artWin)
|
||||
artWin->artifactAssembled(al);
|
||||
}
|
||||
|
||||
for(auto artWin : GH.windows().findInts<CArtifactHolder>())
|
||||
artWin->artifactAssembled(al);
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
@ -1866,12 +1849,9 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
if (artWin)
|
||||
artWin->artifactDisassembled(al);
|
||||
}
|
||||
|
||||
for(auto artWin : GH.windows().findInts<CArtifactHolder>())
|
||||
artWin->artifactDisassembled(al);
|
||||
}
|
||||
|
||||
void CPlayerInterface::waitForAllDialogs(bool unlockPim)
|
||||
|
@ -770,8 +770,7 @@ void CClient::removeGUI()
|
||||
if(GH.windows().topInt())
|
||||
GH.windows().topInt()->deactivate();
|
||||
adventureInt.reset();
|
||||
GH.windows().listInt.clear();
|
||||
GH.windows().objsToBlit.clear();
|
||||
GH.windows().clear();
|
||||
GH.statusbar.reset();
|
||||
logGlobal->info("Removed GUI.");
|
||||
|
||||
|
@ -196,14 +196,8 @@ void ClientCommandManager::handleNotDialogCommand()
|
||||
|
||||
void ClientCommandManager::handleGuiCommand()
|
||||
{
|
||||
for(const auto & child : GH.windows().listInt)
|
||||
{
|
||||
const auto childPtr = child.get();
|
||||
if(const CIntObject * obj = dynamic_cast<const CIntObject*>(childPtr))
|
||||
printInfoAboutInterfaceObject(obj, 0);
|
||||
else
|
||||
printCommandMessage(std::string(typeid(childPtr).name()) + "\n");
|
||||
}
|
||||
for(const auto & child : GH.windows().findInts<CIntObject>())
|
||||
printInfoAboutInterfaceObject(child.get(), 0);
|
||||
}
|
||||
|
||||
void ClientCommandManager::handleConvertTextCommand()
|
||||
|
@ -57,7 +57,7 @@ void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientDisconnected(LobbyClient
|
||||
|
||||
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
|
||||
{
|
||||
if(GH.windows().listInt.size())
|
||||
if(GH.windows().count() > 0)
|
||||
GH.windows().popInts(1);
|
||||
}
|
||||
|
||||
|
@ -21,30 +21,29 @@
|
||||
|
||||
void WindowHandler::popInt(std::shared_ptr<IShowActivatable> top)
|
||||
{
|
||||
assert(listInt.front() == top);
|
||||
assert(windowsStack.back() == top);
|
||||
top->deactivate();
|
||||
disposed.push_back(top);
|
||||
listInt.pop_front();
|
||||
objsToBlit -= top;
|
||||
if(!listInt.empty())
|
||||
listInt.front()->activate();
|
||||
windowsStack.pop_back();
|
||||
if(!windowsStack.empty())
|
||||
windowsStack.back()->activate();
|
||||
|
||||
totalRedraw();
|
||||
}
|
||||
|
||||
void WindowHandler::pushInt(std::shared_ptr<IShowActivatable> newInt)
|
||||
{
|
||||
assert(newInt);
|
||||
assert(!vstd::contains(listInt, newInt)); // do not add same object twice
|
||||
assert(!vstd::contains(windowsStack, newInt)); // do not add same object twice
|
||||
|
||||
//a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway)
|
||||
screenBuf = screen2;
|
||||
|
||||
if(!listInt.empty())
|
||||
listInt.front()->deactivate();
|
||||
listInt.push_front(newInt);
|
||||
if(!windowsStack.empty())
|
||||
windowsStack.back()->deactivate();
|
||||
windowsStack.push_back(newInt);
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
newInt->activate();
|
||||
objsToBlit.push_back(newInt);
|
||||
totalRedraw();
|
||||
}
|
||||
|
||||
@ -53,36 +52,35 @@ void WindowHandler::popInts(int howMany)
|
||||
if(!howMany)
|
||||
return; //senseless but who knows...
|
||||
|
||||
assert(listInt.size() >= howMany);
|
||||
listInt.front()->deactivate();
|
||||
assert(windowsStack.size() >= howMany);
|
||||
windowsStack.back()->deactivate();
|
||||
for(int i = 0; i < howMany; i++)
|
||||
{
|
||||
objsToBlit -= listInt.front();
|
||||
disposed.push_back(listInt.front());
|
||||
listInt.pop_front();
|
||||
disposed.push_back(windowsStack.back());
|
||||
windowsStack.pop_back();
|
||||
}
|
||||
|
||||
if(!listInt.empty())
|
||||
if(!windowsStack.empty())
|
||||
{
|
||||
listInt.front()->activate();
|
||||
windowsStack.back()->activate();
|
||||
totalRedraw();
|
||||
}
|
||||
GH.fakeMouseMove();
|
||||
}
|
||||
|
||||
std::shared_ptr<IShowActivatable> WindowHandler::topInt()
|
||||
std::shared_ptr<IShowActivatable> WindowHandler::topInt() const
|
||||
{
|
||||
if(listInt.empty())
|
||||
return std::shared_ptr<IShowActivatable>();
|
||||
else
|
||||
return listInt.front();
|
||||
if(windowsStack.empty())
|
||||
return nullptr;
|
||||
|
||||
return windowsStack.back();
|
||||
}
|
||||
|
||||
void WindowHandler::totalRedraw()
|
||||
{
|
||||
CSDL_Ext::fillSurface(screen2, Colors::BLACK);
|
||||
|
||||
for(auto & elem : objsToBlit)
|
||||
for(auto & elem : windowsStack)
|
||||
elem->showAll(screen2);
|
||||
CSDL_Ext::blitAt(screen2, 0, 0, screen);
|
||||
}
|
||||
@ -90,22 +88,21 @@ void WindowHandler::totalRedraw()
|
||||
void WindowHandler::simpleRedraw()
|
||||
{
|
||||
//update only top interface and draw background
|
||||
if(objsToBlit.size() > 1)
|
||||
if(windowsStack.size() > 1)
|
||||
CSDL_Ext::blitAt(screen2, 0, 0, screen); //blit background
|
||||
if(!objsToBlit.empty())
|
||||
objsToBlit.back()->show(screen); //blit active interface/window
|
||||
if(!windowsStack.empty())
|
||||
windowsStack.back()->show(screen); //blit active interface/window
|
||||
}
|
||||
|
||||
void WindowHandler::onScreenResize()
|
||||
{
|
||||
for(const auto & entry : listInt)
|
||||
for(const auto & entry : windowsStack)
|
||||
{
|
||||
auto intObject = std::dynamic_pointer_cast<CIntObject>(entry);
|
||||
|
||||
if(intObject)
|
||||
intObject->onScreenResize();
|
||||
}
|
||||
|
||||
totalRedraw();
|
||||
}
|
||||
|
||||
@ -113,3 +110,14 @@ void WindowHandler::onFrameRendered()
|
||||
{
|
||||
disposed.clear();
|
||||
}
|
||||
|
||||
size_t WindowHandler::count() const
|
||||
{
|
||||
return windowsStack.size();
|
||||
}
|
||||
|
||||
void WindowHandler::clear()
|
||||
{
|
||||
windowsStack.clear();
|
||||
disposed.clear();
|
||||
}
|
||||
|
@ -13,15 +13,14 @@ class IShowActivatable;
|
||||
|
||||
class WindowHandler
|
||||
{
|
||||
public:
|
||||
/// list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
|
||||
std::list<std::shared_ptr<IShowActivatable>> listInt;
|
||||
/// list of interfaces. front = bottom-most (background), back = top-most (foreground)
|
||||
/// (includes adventure map, window interfaces, all kind of active dialogs, and so on)
|
||||
std::vector<std::shared_ptr<IShowActivatable>> windowsStack;
|
||||
|
||||
/// Temporary list of recently popped windows
|
||||
std::vector<std::shared_ptr<IShowActivatable>> disposed;
|
||||
|
||||
// objs to blit
|
||||
std::vector<std::shared_ptr<IShowActivatable>> objsToBlit;
|
||||
|
||||
public:
|
||||
/// forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
|
||||
void totalRedraw();
|
||||
|
||||
@ -33,12 +32,10 @@ public:
|
||||
|
||||
/// deactivate old top interface, activates this one and pushes to the top
|
||||
void pushInt(std::shared_ptr<IShowActivatable> newInt);
|
||||
|
||||
/// creates window of class T and pushes it to the top
|
||||
template <typename T, typename ... Args>
|
||||
void pushIntT(Args && ... args)
|
||||
{
|
||||
auto newInt = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
pushInt(newInt);
|
||||
}
|
||||
void pushIntT(Args && ... args);
|
||||
|
||||
/// pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
|
||||
void popInts(int howMany);
|
||||
@ -47,8 +44,41 @@ public:
|
||||
void popInt(std::shared_ptr<IShowActivatable> top);
|
||||
|
||||
/// returns top interface
|
||||
std::shared_ptr<IShowActivatable> topInt();
|
||||
|
||||
std::shared_ptr<IShowActivatable> topInt() const;
|
||||
|
||||
/// should be called after frame has been rendered to screen
|
||||
void onFrameRendered();
|
||||
|
||||
/// returns current number of windows in the stack
|
||||
size_t count() const;
|
||||
|
||||
/// erases all currently existing windows from the stacl
|
||||
void clear();
|
||||
|
||||
/// returns all existing windows of selected type
|
||||
template <typename T>
|
||||
std::vector<std::shared_ptr<T>> findInts() const;
|
||||
};
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
void WindowHandler::pushIntT(Args && ... args)
|
||||
{
|
||||
auto newInt = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
pushInt(newInt);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<std::shared_ptr<T>> WindowHandler::findInts() const
|
||||
{
|
||||
std::vector<std::shared_ptr<T>> result;
|
||||
|
||||
for (auto const & window : windowsStack)
|
||||
{
|
||||
std::shared_ptr<T> casted = std::dynamic_pointer_cast<T>(window);
|
||||
|
||||
if (casted)
|
||||
result.push_back(casted);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ void CMainMenu::update()
|
||||
if(CMM != this->shared_from_this()) //don't update if you are not a main interface
|
||||
return;
|
||||
|
||||
if(GH.windows().listInt.empty())
|
||||
if(GH.windows().count() == 0)
|
||||
{
|
||||
GH.windows().pushInt(CMM);
|
||||
GH.windows().pushInt(menu);
|
||||
@ -523,7 +523,7 @@ void CSimpleJoinScreen::leaveScreen()
|
||||
textTitle->setText("Closing...");
|
||||
CSH->state = EClientState::CONNECTION_CANCELLED;
|
||||
}
|
||||
else if(GH.windows().listInt.size() && GH.windows().listInt.front().get() == this)
|
||||
else if(GH.windows().topInt().get() == this)
|
||||
{
|
||||
close();
|
||||
}
|
||||
@ -553,7 +553,7 @@ void CSimpleJoinScreen::connectThread(const std::string & addr, ui16 port)
|
||||
else
|
||||
CSH->justConnectToServer(addr, port);
|
||||
|
||||
if(GH.windows().listInt.size() && GH.windows().listInt.front().get() == this)
|
||||
if(GH.windows().topInt().get() == this)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ void ScreenHandler::initializeScreenBuffers()
|
||||
throw std::runtime_error("Unable to copy surface\n");
|
||||
}
|
||||
|
||||
if (GH.windows().listInt.size() > 1)
|
||||
if (GH.windows().count() > 1)
|
||||
screenBuf = screen2;
|
||||
else
|
||||
screenBuf = screen;
|
||||
|
@ -314,18 +314,17 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
|
||||
|
||||
//if we have exchange window with this curHero open
|
||||
bool noDismiss=false;
|
||||
for(auto isa : GH.windows().listInt)
|
||||
{
|
||||
if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa.get()))
|
||||
{
|
||||
for(int g=0; g < cew->heroInst.size(); ++g)
|
||||
if(cew->heroInst[g] == curHero)
|
||||
noDismiss = true;
|
||||
}
|
||||
|
||||
if(dynamic_cast<CKingdomInterface*>(isa.get()))
|
||||
noDismiss = true;
|
||||
for(auto cew : GH.windows().findInts<CExchangeWindow>())
|
||||
{
|
||||
for(int g=0; g < cew->heroInst.size(); ++g)
|
||||
if(cew->heroInst[g] == curHero)
|
||||
noDismiss = true;
|
||||
}
|
||||
|
||||
for(auto ki : GH.windows().findInts<CKingdomInterface>())
|
||||
noDismiss = true;
|
||||
|
||||
//if player only have one hero and no towns
|
||||
if(!LOCPLINT->cb->howManyTowns() && LOCPLINT->cb->howManyHeroes() == 1)
|
||||
noDismiss = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user