1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Gui cleanup4 (#446)

* use smart pointers for almost all widget fields
* use SDL2 texture for cursor
* a lot af small tweaks and formatting
* removed CompImage class, it is actually useless as long as regular SDLImage support margins
* CGuiHandler: use smart pointers for [push|pop]Int
This commit is contained in:
Alexander Shishkin 2018-07-25 01:36:48 +03:00 committed by ArseniyShestakov
parent 7c8b74a806
commit 75f8c8b29a
62 changed files with 706 additions and 1296 deletions

View File

@ -166,7 +166,7 @@ bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
return true; return true;
} }
int CBattleCallback::battleMakeAction(BattleAction* action) int CBattleCallback::battleMakeAction(const BattleAction * action)
{ {
assert(action->actionType == EActionType::HERO_SPELL); assert(action->actionType == EActionType::HERO_SPELL);
MakeCustomAction mca(*action); MakeCustomAction mca(*action);

View File

@ -36,8 +36,8 @@ public:
bool waitTillRealize; //if true, request functions will return after they are realized by server bool waitTillRealize; //if true, request functions will return after they are realized by server
bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback! bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback!
//battle //battle
virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack virtual int battleMakeAction(const BattleAction * action) = 0;//for casting spells by hero - DO NOT use it for moving active stack
virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions virtual bool battleMakeTacticAction(BattleAction * action) = 0; // performs tactic phase actions
}; };
class IGameActionCallback class IGameActionCallback
@ -88,7 +88,7 @@ protected:
public: public:
CBattleCallback(boost::optional<PlayerColor> Player, CClient *C); CBattleCallback(boost::optional<PlayerColor> Player, CClient *C);
int battleMakeAction(BattleAction* action) override;//for casting spells by hero - DO NOT use it for moving active stack int battleMakeAction(const BattleAction * action) override;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) override; // performs tactic phase actions bool battleMakeTacticAction(BattleAction * action) override; // performs tactic phase actions
friend class CCallback; friend class CCallback;

View File

@ -57,7 +57,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
if (format==PCX8B) if (format==PCX8B)
{ {
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); ret = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
it = 0xC; it = 0xC;
for (int i=0; i<height; i++) for (int i=0; i<height; i++)
@ -89,7 +89,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
int gmask = 0x00ff00; int gmask = 0x00ff00;
int rmask = 0xff0000; int rmask = 0xff0000;
#endif #endif
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0); ret = SDL_CreateRGBSurface(0, width, height, 24, rmask, gmask, bmask, 0);
//it == 0xC; //it == 0xC;
for (int i=0; i<height; i++) for (int i=0; i<height; i++)

View File

@ -118,32 +118,13 @@ static void mainLoop();
void init() void init()
{ {
CStopWatch tmh, pomtime; CStopWatch tmh;
loadDLLClasses(); loadDLLClasses();
const_cast<CGameInfo*>(CGI)->setFromLib(); const_cast<CGameInfo*>(CGI)->setFromLib();
logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff()); logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff());
if(!settings["session"]["headless"].Bool())
{
pomtime.getDiff();
CCS->curh = new CCursorHandler();
graphics = new Graphics(); // should be before curh->init()
CCS->curh->initCursor();
CCS->curh->show();
logGlobal->info("Screen handler: %d ms", pomtime.getDiff());
pomtime.getDiff();
graphics->load();
logGlobal->info("\tMain graphics: %d ms", pomtime.getDiff());
logGlobal->info("Initializing game graphics: %d ms", tmh.getDiff());
CMessage::init();
logGlobal->info("Message handler: %d ms", tmh.getDiff());
}
} }
static void prog_version() static void prog_version()
@ -466,8 +447,10 @@ int main(int argc, char * argv[])
playIntro(); playIntro();
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255);
SDL_RenderClear(mainRenderer); SDL_RenderClear(mainRenderer);
SDL_RenderPresent(mainRenderer);
} }
SDL_RenderPresent(mainRenderer);
#ifndef VCMI_NO_THREADED_LOAD #ifndef VCMI_NO_THREADED_LOAD
#ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds #ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds
{ {
@ -480,6 +463,27 @@ int main(int argc, char * argv[])
} }
#endif // ANDROID #endif // ANDROID
#endif // THREADED #endif // THREADED
if(!settings["session"]["headless"].Bool())
{
pomtime.getDiff();
CCS->curh = new CCursorHandler();
graphics = new Graphics(); // should be before curh->init()
CCS->curh->initCursor();
logGlobal->info("Screen handler: %d ms", pomtime.getDiff());
pomtime.getDiff();
graphics->load();//must be after Content loading but should be in main thread
logGlobal->info("Main graphics: %d ms", pomtime.getDiff());
CMessage::init();
logGlobal->info("Message handler: %d ms", pomtime.getDiff());
CCS->curh->show();
}
logGlobal->info("Initialization of VCMI (together): %d ms", total.getDiff()); logGlobal->info("Initialization of VCMI (together): %d ms", total.getDiff());
session["autoSkip"].Bool() = vm.count("autoSkip"); session["autoSkip"].Bool() = vm.count("autoSkip");
@ -500,7 +504,7 @@ int main(int argc, char * argv[])
} }
else else
{ {
GH.curInt = CMainMenu::create(); GH.curInt = CMainMenu::create().get();
} }
if(!settings["session"]["headless"].Bool()) if(!settings["session"]["headless"].Bool())
@ -786,9 +790,9 @@ void processCommand(const std::string &message)
} }
else if(cn == "gui") else if(cn == "gui")
{ {
for(const IShowActivatable *child : GH.listInt) for(auto child : GH.listInt)
{ {
if(const CIntObject *obj = dynamic_cast<const CIntObject *>(child)) if(const CIntObject *obj = dynamic_cast<const CIntObject *>(child.get()))
printInfoAboutIntObject(obj, 0); printInfoAboutIntObject(obj, 0);
else else
std::cout << typeid(*child).name() << std::endl; std::cout << typeid(*child).name() << std::endl;
@ -970,9 +974,9 @@ void processCommand(const std::string &message)
//plays intro, ends when intro is over or button has been pressed (handles events) //plays intro, ends when intro is over or button has been pressed (handles events)
void playIntro() void playIntro()
{ {
if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 0, 1, screen, true, true)) if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 0, 1, true, true))
{ {
CCS->videoh->openAndPlayVideo("AZVS.SMK", 0, 1, screen, true, true); CCS->videoh->openAndPlayVideo("AZVS.SMK", 0, 1, true, true);
} }
} }
@ -1044,18 +1048,6 @@ static void cleanupRenderer()
SDL_DestroyTexture(screenTexture); SDL_DestroyTexture(screenTexture);
screenTexture = nullptr; screenTexture = nullptr;
} }
if(nullptr != mainRenderer)
{
SDL_DestroyRenderer(mainRenderer);
mainRenderer = nullptr;
}
if(nullptr != mainWindow)
{
SDL_DestroyWindow(mainWindow);
mainWindow = nullptr;
}
} }
static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIndex) static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIndex)
@ -1080,47 +1072,85 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
} }
bool bufOnScreen = (screenBuf == screen); bool bufOnScreen = (screenBuf == screen);
bool realFullscreen = settings["video"]["realFullscreen"].Bool();
cleanupRenderer(); cleanupRenderer();
bool realFullscreen = settings["video"]["realFullscreen"].Bool(); if(nullptr == mainWindow)
#ifdef VCMI_ANDROID
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN);
#else
if(fullscreen)
{ {
if(realFullscreen)
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), w, h, SDL_WINDOW_FULLSCREEN); #ifdef VCMI_ANDROID
else //in windowed full-screen mode use desktop resolution mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN);
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP); #else
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
if(fullscreen)
{
if(realFullscreen)
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), w, h, SDL_WINDOW_FULLSCREEN);
else //in windowed full-screen mode use desktop resolution
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
}
else
{
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), w, h, 0);
}
#endif
if(nullptr == mainWindow)
{
throw std::runtime_error("Unable to create window\n");
}
//create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible
mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0);
if(nullptr == mainRenderer)
{
throw std::runtime_error("Unable to create renderer\n");
}
SDL_RendererInfo info;
SDL_GetRendererInfo(mainRenderer, &info);
logGlobal->info("Created renderer %s", info.name);
} }
else else
{ {
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), w, h, 0); #ifndef VCMI_ANDROID
}
if(fullscreen)
{
if(realFullscreen)
{
SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN);
SDL_DisplayMode mode;
SDL_GetDesktopDisplayMode(displayIndex, &mode);
mode.w = w;
mode.h = h;
SDL_SetWindowDisplayMode(mainWindow, &mode);
}
else
{
SDL_SetWindowFullscreen(mainWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex));
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
}
else
{
SDL_SetWindowFullscreen(mainWindow, 0);
SDL_SetWindowSize(mainWindow, w, h);
SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex));
}
#endif #endif
if(nullptr == mainWindow)
{
throw std::runtime_error("Unable to create window\n");
} }
//create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible
mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0);
if(nullptr == mainRenderer)
{
throw std::runtime_error("Unable to create renderer\n");
}
SDL_RendererInfo info;
SDL_GetRendererInfo(mainRenderer, &info);
logGlobal->info("Created renderer %s", info.name);
if(!(fullscreen && realFullscreen)) if(!(fullscreen && realFullscreen))
{ {
SDL_RenderSetLogicalSize(mainRenderer, w, h); SDL_RenderSetLogicalSize(mainRenderer, w, h);
@ -1270,7 +1300,7 @@ static void handleEvent(SDL_Event & ev)
}; };
if(epilogue.hasPrologEpilog) if(epilogue.hasPrologEpilog)
{ {
GH.pushInt(new CPrologEpilogVideo(epilogue, finisher)); GH.pushIntT<CPrologEpilogVideo>(epilogue, finisher);
} }
else else
{ {
@ -1306,6 +1336,13 @@ static void handleEvent(SDL_Event & ev)
} }
return; return;
} }
//preprocessing
if(ev.type == SDL_MOUSEMOTION)
{
CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
}
{ {
boost::unique_lock<boost::mutex> lock(eventsM); boost::unique_lock<boost::mutex> lock(eventsM);
events.push(ev); events.push(ev);
@ -1349,6 +1386,19 @@ void handleQuit(bool ask)
if(!settings["session"]["headless"].Bool()) if(!settings["session"]["headless"].Bool())
{ {
cleanupRenderer(); cleanupRenderer();
if(nullptr != mainRenderer)
{
SDL_DestroyRenderer(mainRenderer);
mainRenderer = nullptr;
}
if(nullptr != mainWindow)
{
SDL_DestroyWindow(mainWindow);
mainWindow = nullptr;
}
SDL_Quit(); SDL_Quit();
} }

View File

@ -97,7 +97,7 @@ void CMessage::dispose()
SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor) SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor)
{ {
//prepare surface //prepare surface
SDL_Surface * ret = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); SDL_Surface * ret = SDL_CreateRGBSurface(0, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
for (int i=0; i<w; i+=background->w)//background for (int i=0; i<w; i+=background->w)//background
{ {
for (int j=0; j<h; j+=background->h) for (int j=0; j<h; j+=background->h)

View File

@ -19,16 +19,13 @@ class CComponent;
/// Class which draws formatted text messages and generates chat windows /// Class which draws formatted text messages and generates chat windows
class CMessage class CMessage
{ {
public:
//Function usd only in CMessage.cpp
static std::pair<int,int> getMaxSizes(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight);
/// Draw border on exiting surface
static void drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0);
/// Draw simple dialog box (borders and background only) /// Draw simple dialog box (borders and background only)
static SDL_Surface * drawDialogBox(int w, int h, PlayerColor playerColor = PlayerColor(1)); static SDL_Surface * drawDialogBox(int w, int h, PlayerColor playerColor = PlayerColor(1));
public:
/// Draw border on exiting surface
static void drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0);
static void drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player); static void drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player);
/// split text in lines /// split text in lines

View File

@ -121,8 +121,8 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
playerID=Player; playerID=Player;
human=true; human=true;
currentSelection = nullptr; currentSelection = nullptr;
castleInt = nullptr;
battleInt = nullptr; battleInt = nullptr;
castleInt = nullptr;
makingTurn = false; makingTurn = false;
showingDialog = new CondSh<bool>(false); showingDialog = new CondSh<bool>(false);
cingconsole = new CInGameConsole(); cingconsole = new CInGameConsole();
@ -150,9 +150,7 @@ void CPlayerInterface::init(std::shared_ptr<CCallback> CB)
initializeHeroTownList(); initializeHeroTownList();
// always recreate advmap interface to avoid possible memory-corruption bugs // always recreate advmap interface to avoid possible memory-corruption bugs
if (adventureInt) adventureInt.reset(new CAdvMapInt());
delete adventureInt;
adventureInt = new CAdvMapInt();
} }
void CPlayerInterface::yourTurn() void CPlayerInterface::yourTurn()
{ {
@ -464,11 +462,13 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
} }
void CPlayerInterface::openTownWindow(const CGTownInstance * town) void CPlayerInterface::openTownWindow(const CGTownInstance * town)
{ {
if (castleInt) if(castleInt)
castleInt->close(); castleInt->close();
castleInt = nullptr;
castleInt = new CCastleInterface(town); auto newCastleInt = std::make_shared<CCastleInterface>(town);
GH.pushInt(castleInt);
GH.pushInt(newCastleInt);
} }
int3 CPlayerInterface::repairScreenPos(int3 pos) int3 CPlayerInterface::repairScreenPos(int3 pos)
@ -496,7 +496,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if (which == 4) if (which == 4)
{ {
if (CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(GH.topInt())) if (CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(GH.topInt().get()))
ctw->setExpToLevel(); ctw->setExpToLevel();
} }
else if (which < GameConstants::PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4) else if (which < GameConstants::PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
@ -506,7 +506,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
CUniversityWindow* cuw = dynamic_cast<CUniversityWindow*>(GH.topInt()); CUniversityWindow* cuw = dynamic_cast<CUniversityWindow*>(GH.topInt().get());
if (cuw) //university window is open if (cuw) //university window is open
{ {
GH.totalRedraw(); GH.totalRedraw();
@ -529,7 +529,7 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
void CPlayerInterface::receivedResource() void CPlayerInterface::receivedResource()
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if (CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt())) if (CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt().get()))
mw->resourceChanged(); mw->resourceChanged();
GH.totalRedraw(); GH.totalRedraw();
@ -540,21 +540,21 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::Pr
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog(); waitWhileDialog();
CCS->soundh->playSound(soundBase::heroNewLevel); CCS->soundh->playSound(soundBase::heroNewLevel);
GH.pushIntT<CLevelWindow>(hero, pskill, skills, [=](ui32 selection)
CLevelWindow *lw = new CLevelWindow(hero,pskill,skills, {
[=](ui32 selection){ cb->selectionMade(selection, queryID); }); cb->selectionMade(selection, queryID);
GH.pushInt(lw); });
} }
void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog(); waitWhileDialog();
CCS->soundh->playSound(soundBase::heroNewLevel); CCS->soundh->playSound(soundBase::heroNewLevel);
GH.pushIntT<CStackWindow>(commander, skills, [=](ui32 selection)
GH.pushInt(new CStackWindow(commander, skills, [=](ui32 selection)
{ {
cb->selectionMade(selection, queryID); cb->selectionMade(selection, queryID);
})); });
} }
void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
@ -578,17 +578,17 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
adventureInt->heroList.update(); adventureInt->heroList.update();
adventureInt->updateNextHero(nullptr); adventureInt->updateNextHero(nullptr);
if (CCastleInterface *c = castleInt) if(castleInt)
{ {
c->garr->selectSlot(nullptr); castleInt->garr->selectSlot(nullptr);
c->garr->setArmy(town->getUpperArmy(), 0); castleInt->garr->setArmy(town->getUpperArmy(), 0);
c->garr->setArmy(town->visitingHero, 1); castleInt->garr->setArmy(town->visitingHero, 1);
c->garr->recreateSlots(); castleInt->garr->recreateSlots();
c->heroes->update(); castleInt->heroes->update();
} }
for (IShowActivatable *isa : GH.listInt) for (auto isa : GH.listInt)
{ {
CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa); CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa.get());
if (ki) if (ki)
{ {
ki->townChanged(town); ki->townChanged(town);
@ -632,11 +632,11 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
for (auto & elem : GH.listInt) for (auto & elem : GH.listInt)
{ {
CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(elem); CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(elem.get());
if (cgh) if (cgh)
cgh->updateGarrisons(); cgh->updateGarrisons();
if (CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(elem)) if (CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(elem.get()))
{ {
if (vstd::contains(objs, cmw->hero)) if (vstd::contains(objs, cmw->hero))
cmw->garrisonChanged(); cmw->garrisonChanged();
@ -739,7 +739,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
continue; continue;
} }
CCreatureAnimation * animation = iter->second; auto animation = iter->second;
if(unit->alive() && animation->isDead()) if(unit->alive() && animation->isDead())
animation->setType(CCreatureAnim::HOLDING); animation->setType(CCreatureAnim::HOLDING);
@ -905,8 +905,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br)
if (!battleInt) if (!battleInt)
{ {
auto resWindow = new CBattleResultWindow(*br, *this); GH.pushIntT<CBattleResultWindow>(*br, *this);
GH.pushInt(resWindow);
// #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it. // #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it.
// Otherwise NewTurn causes freeze. // Otherwise NewTurn causes freeze.
waitWhileDialog(); waitWhileDialog();
@ -1129,7 +1128,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
{ {
return; return;
} }
CInfoWindow *temp = CInfoWindow::create(text, playerID, components); std::shared_ptr<CInfoWindow> temp = CInfoWindow::create(text, playerID, components);
if (makingTurn && GH.listInt.size() && LOCPLINT == this) if (makingTurn && GH.listInt.size() && LOCPLINT == this)
{ {
@ -1164,22 +1163,6 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<vo
CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID); CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID);
} }
void CPlayerInterface::showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
std::string str;
text.toString(str);
stopMovement();
showingDialog->setn(true);
std::vector<std::shared_ptr<CComponent>> intComps;
for (auto & component : components)
intComps.push_back(std::make_shared<CComponent>(component));
CInfoWindow::showOkDialog(str, intComps, onOk, playerID);
}
void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel ) void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel )
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
@ -1212,11 +1195,9 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
int charperline = 35; int charperline = 35;
if (pom.size() > 1) if (pom.size() > 1)
charperline = 50; charperline = 50;
auto temp = new CSelWindow(text, playerID, charperline, intComps, pom, askID); GH.pushIntT<CSelWindow>(text, playerID, charperline, intComps, pom, askID);
GH.pushInt(temp);
intComps[0]->clickLeft(true, false); intComps[0]->clickLeft(true, false);
} }
} }
void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
@ -1256,13 +1237,12 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component
for(auto item : objects) for(auto item : objects)
tempList.push_back(item.getNum()); tempList.push_back(item.getNum());
CComponent * localIconC = new CComponent(icon); CComponent localIconC(icon);
std::shared_ptr<CIntObject> localIcon = localIconC->image; std::shared_ptr<CIntObject> localIcon = localIconC.image;
localIconC->removeChild(localIcon.get(), false); localIconC.removeChild(localIcon.get(), false);
delete localIconC;
CObjectListWindow * wnd = new CObjectListWindow(tempList, localIcon, localTitle, localDescription, selectCallback); std::shared_ptr<CObjectListWindow> wnd = std::make_shared<CObjectListWindow>(tempList, localIcon, localTitle, localDescription, selectCallback);
wnd->onExit = cancelCallback; wnd->onExit = cancelCallback;
GH.pushInt(wnd); GH.pushInt(wnd);
} }
@ -1289,7 +1269,7 @@ void CPlayerInterface::tileHidden(const std::unordered_set<int3, ShashInt3> &pos
void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
GH.pushInt(new CHeroWindow(hero)); GH.pushIntT<CHeroWindow>(hero);
} }
void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
@ -1297,13 +1277,13 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if (const CGTownInstance * townObj = dynamic_cast<const CGTownInstance*>(town)) if (const CGTownInstance * townObj = dynamic_cast<const CGTownInstance*>(town))
{ {
CFortScreen *fs = dynamic_cast<CFortScreen*>(GH.topInt()); CFortScreen *fs = dynamic_cast<CFortScreen*>(GH.topInt().get());
if (fs) if (fs)
fs->creaturesChanged(); fs->creaturesChanged();
for (IShowActivatable *isa : GH.listInt) for(auto isa : GH.listInt)
{ {
CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa); CKingdomInterface *ki = dynamic_cast<CKingdomInterface*>(isa.get());
if (ki && townObj) if (ki && townObj)
ki->townChanged(townObj); ki->townChanged(townObj);
} }
@ -1311,7 +1291,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
else if (GH.listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1 else if (GH.listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1
|| town->ID == Obj::CREATURE_GENERATOR4 || town->ID == Obj::WAR_MACHINE_FACTORY)) || town->ID == Obj::CREATURE_GENERATOR4 || town->ID == Obj::WAR_MACHINE_FACTORY))
{ {
CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.topInt()); CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.topInt().get());
if (crw && crw->dwelling == town) if (crw && crw->dwelling == town)
crw->availableCreaturesChanged(); crw->availableCreaturesChanged();
} }
@ -1434,7 +1414,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
waitForAllDialogs(); waitForAllDialogs();
auto cgw = new CGarrisonWindow(up,down,removableUnits); auto cgw = std::make_shared<CGarrisonWindow>(up, down, removableUnits);
cgw->quit->addCallback(onEnd); cgw->quit->addCallback(onEnd);
GH.pushInt(cgw); GH.pushInt(cgw);
} }
@ -1497,7 +1477,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
GH.pushInt(new CExchangeWindow(hero1, hero2, query)); GH.pushIntT<CExchangeWindow>(hero1, hero2, query);
} }
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop) void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
@ -1551,9 +1531,11 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog(); waitWhileDialog();
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1); }; auto recruitCb = [=](CreatureID id, int count)
CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, recruitCb); {
GH.pushInt(cr); LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1);
};
GH.pushIntT<CRecruitmentWindow>(dwelling, level, dst, recruitCb);
} }
void CPlayerInterface::waitWhileDialog(bool unlockPim) void CPlayerInterface::waitWhileDialog(bool unlockPim)
@ -1576,8 +1558,7 @@ void CPlayerInterface::showShipyardDialog(const IShipyard *obj)
auto state = obj->shipyardStatus(); auto state = obj->shipyardStatus();
std::vector<si32> cost; std::vector<si32> cost;
obj->getBoatCost(cost); obj->getBoatCost(cost);
CShipyardWindow *csw = new CShipyardWindow(cost, state, obj->getBoatType(), [=](){ cb->buildBoat(obj); }); GH.pushIntT<CShipyardWindow>(cost, state, obj->getBoatType(), [=](){ cb->buildBoat(obj); });
GH.pushInt(csw);
} }
void CPlayerInterface::newObject( const CGObjectInstance * obj ) void CPlayerInterface::newObject( const CGObjectInstance * obj )
@ -2159,7 +2140,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
adventureInt->deactivate(); adventureInt->deactivate();
if (GH.topInt() == adventureInt) if (GH.topInt() == adventureInt)
GH.popInt(adventureInt); GH.popInt(adventureInt);
vstd::clear_pointer(adventureInt); adventureInt.reset();
} }
} }
@ -2201,7 +2182,7 @@ void CPlayerInterface::showPuzzleMap()
double ratio = 0; double ratio = 0;
int3 grailPos = cb->getGrailPos(&ratio); int3 grailPos = cb->getGrailPos(&ratio);
GH.pushInt(new CPuzzleWindow(grailPos, ratio)); GH.pushIntT<CPuzzleWindow>(grailPos, ratio);
} }
void CPlayerInterface::viewWorldMap() void CPlayerInterface::viewWorldMap()
@ -2213,8 +2194,8 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if(dynamic_cast<CSpellWindow *>(GH.topInt())) if(dynamic_cast<CSpellWindow *>(GH.topInt().get()))
GH.popIntTotally(GH.topInt()); GH.popInts(1);
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK) if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
eraseCurrentPathOf(caster, false); eraseCurrentPathOf(caster, false);
@ -2287,7 +2268,7 @@ void CPlayerInterface::acceptTurn()
if (settings["session"]["autoSkip"].Bool()) if (settings["session"]["autoSkip"].Bool())
{ {
centerView = false; centerView = false;
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt())) while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
iw->close(); iw->close();
} }
waitWhileDialog(); waitWhileDialog();
@ -2328,7 +2309,7 @@ void CPlayerInterface::acceptTurn()
if(settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed()) if(settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed())
{ {
if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt())) if(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
iw->close(); iw->close();
adventureInt->fendTurn(); adventureInt->fendTurn();
@ -2425,54 +2406,51 @@ void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInsta
{ {
//EEMarketMode mode = market->availableModes().front(); //EEMarketMode mode = market->availableModes().front();
if (market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL) if (market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL)
GH.pushInt(new CAltarWindow(market, visitor, EMarketMode::ARTIFACT_EXP)); GH.pushIntT<CAltarWindow>(market, visitor, EMarketMode::ARTIFACT_EXP);
else if (market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD) else if (market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD)
GH.pushInt(new CAltarWindow(market, visitor, EMarketMode::CREATURE_EXP)); GH.pushIntT<CAltarWindow>(market, visitor, EMarketMode::CREATURE_EXP);
} }
else else
GH.pushInt(new CMarketplaceWindow(market, visitor, market->availableModes().front())); {
GH.pushIntT<CMarketplaceWindow>(market, visitor, market->availableModes().front());
}
} }
void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
auto cuw = new CUniversityWindow(visitor, market); GH.pushIntT<CUniversityWindow>(visitor, market);
GH.pushInt(cuw);
} }
void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
auto chfw = new CHillFortWindow(visitor, object); GH.pushIntT<CHillFortWindow>(visitor, object);
GH.pushInt(chfw);
} }
void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket * bm) void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket * bm)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if (CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(GH.topInt())) if (CMarketplaceWindow *cmw = dynamic_cast<CMarketplaceWindow*>(GH.topInt().get()))
cmw->artifactsChanged(false); cmw->artifactsChanged(false);
} }
void CPlayerInterface::showTavernWindow(const CGObjectInstance *townOrTavern) void CPlayerInterface::showTavernWindow(const CGObjectInstance *townOrTavern)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
auto tv = new CTavernWindow(townOrTavern); GH.pushIntT<CTavernWindow>(townOrTavern);
GH.pushInt(tv);
} }
void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj) void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
auto tgw = new CThievesGuildWindow(obj); GH.pushIntT<CThievesGuildWindow>(obj);
GH.pushInt(tgw);
} }
void CPlayerInterface::showQuestLog() void CPlayerInterface::showQuestLog()
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
CQuestLog * ql = new CQuestLog (LOCPLINT->cb->getMyQuests()); GH.pushIntT<CQuestLog>(LOCPLINT->cb->getMyQuests());
GH.pushInt (ql);
} }
void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj) void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj)
@ -2529,9 +2507,9 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection(); adventureInt->infoBar.showSelection();
for (IShowActivatable *isa : GH.listInt) for(auto isa : GH.listInt)
{ {
auto artWin = dynamic_cast<CArtifactHolder*>(isa); auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
if (artWin) if (artWin)
artWin->artifactRemoved(al); artWin->artifactRemoved(al);
} }
@ -2541,9 +2519,9 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection(); adventureInt->infoBar.showSelection();
for (IShowActivatable *isa : GH.listInt) for(auto isa : GH.listInt)
{ {
auto artWin = dynamic_cast<CArtifactHolder*>(isa); auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
if (artWin) if (artWin)
artWin->artifactMoved(src, dst); artWin->artifactMoved(src, dst);
} }
@ -2554,9 +2532,9 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection(); adventureInt->infoBar.showSelection();
for (IShowActivatable *isa : GH.listInt) for(auto isa : GH.listInt)
{ {
auto artWin = dynamic_cast<CArtifactHolder*>(isa); auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
if (artWin) if (artWin)
artWin->artifactAssembled(al); artWin->artifactAssembled(al);
} }
@ -2566,9 +2544,9 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->infoBar.showSelection(); adventureInt->infoBar.showSelection();
for (IShowActivatable *isa : GH.listInt) for(auto isa : GH.listInt)
{ {
auto artWin = dynamic_cast<CArtifactHolder*>(isa); auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
if (artWin) if (artWin)
artWin->artifactDisassembled(al); artWin->artifactDisassembled(al);
} }
@ -2585,7 +2563,7 @@ void CPlayerInterface::playerStartsTurn(PlayerColor player)
else else
{ {
adventureInt->infoBar.showSelection(); adventureInt->infoBar.showSelection();
while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front())) //don't remove dialogs that expect query answer while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front().get())) //don't remove dialogs that expect query answer
GH.popInts(1); GH.popInts(1);
} }
@ -2820,7 +2798,7 @@ void CPlayerInterface::updateAmbientSounds(bool resetAll)
CCS->soundh->ambientStopAllChannels(); CCS->soundh->ambientStopAllChannels();
return; return;
} }
else if(!dynamic_cast<CAdvMapInt *>(GH.topInt())) else if(!dynamic_cast<CAdvMapInt *>(GH.topInt().get()))
{ {
return; return;
} }

View File

@ -82,7 +82,7 @@ public:
std::shared_ptr<CCallback> cb; //to communicate with engine std::shared_ptr<CCallback> cb; //to communicate with engine
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr) const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones) std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> towns; //our towns on the adventure map std::vector<const CGTownInstance *> towns; //our towns on the adventure map
@ -217,7 +217,6 @@ public:
void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component); void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component);
void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0); void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0);
void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text); void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
void showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk);
void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>()); void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>());
void stopMovement(); void stopMovement();

View File

@ -494,12 +494,12 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
{ {
if(CMM) if(CMM)
{ {
GH.curInt = CMM; GH.curInt = CMM.get();
CMM->enable(); CMM->enable();
} }
else else
{ {
GH.curInt = CMainMenu::create(); GH.curInt = CMainMenu::create().get();
} }
} }
} }
@ -566,7 +566,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
else else
startLocalServerAndConnect(); startLocalServerAndConnect();
while(!settings["session"]["headless"].Bool() && !dynamic_cast<CLobbyScreen *>(GH.topInt())) while(!settings["session"]["headless"].Bool() && !dynamic_cast<CLobbyScreen *>(GH.topInt().get()))
boost::this_thread::sleep(boost::posix_time::milliseconds(50)); boost::this_thread::sleep(boost::posix_time::milliseconds(50));
while(!mi || mapInfo->fileURI != CSH->mi->fileURI) while(!mi || mapInfo->fileURI != CSH->mi->fileURI)
{ {

View File

@ -396,7 +396,7 @@ void CVideoPlayer::close()
} }
// Plays a video. Only works for overlays. // Plays a video. Only works for overlays.
bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
{ {
// Note: either the windows player or the linux player is // Note: either the windows player or the linux player is
// broken. Compensate here until the bug is found. // broken. Compensate here until the bug is found.
@ -407,11 +407,10 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
while(nextFrame()) while(nextFrame())
{ {
if(stopOnKey && keyDown()) if(stopOnKey && keyDown())
return false; return false;
SDL_RenderCopy(mainRenderer, texture, NULL, &pos); SDL_RenderCopy(mainRenderer, texture, nullptr, &pos);
SDL_RenderPresent(mainRenderer); SDL_RenderPresent(mainRenderer);
// Wait 3 frames // Wait 3 frames
@ -423,10 +422,10 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
return true; return true;
} }
bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey, bool scale) bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, bool stopOnKey, bool scale)
{ {
open(name, false, true, scale); open(name, false, true, scale);
bool ret = playVideo(x, y, dst, stopOnKey); bool ret = playVideo(x, y, stopOnKey);
close(); close();
return ret; return ret;
} }

View File

@ -31,7 +31,7 @@ public:
std::string fname; //name of current video file (empty if idle) std::string fname; //name of current video file (empty if idle)
virtual void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true){} virtual void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true){}
virtual bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) virtual bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false)
{ {
return false; return false;
} }
@ -111,7 +111,7 @@ class CVideoPlayer : public IMainVideoPlayer
int refreshCount; int refreshCount;
bool doLoop; // loop through video bool doLoop; // loop through video
bool playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey); bool playVideo(int x, int y, bool stopOnKey);
bool open(std::string fname, bool loop, bool useOverlay = false, bool scale = false); bool open(std::string fname, bool loop, bool useOverlay = false, bool scale = false);
public: public:
@ -128,7 +128,7 @@ public:
void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true
// Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played) // Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played)
bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) override; bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false) override;
//TODO: //TODO:
bool wait() override {return false;}; bool wait() override {return false;};

View File

@ -491,14 +491,11 @@ void CClient::battleStarted(const BattleInfo * info)
if(!settings["session"]["headless"].Bool()) if(!settings["session"]["headless"].Bool())
{ {
Rect battleIntRect((screen->w - 800)/2, (screen->h - 600)/2, 800, 600);
if(!!att || !!def) if(!!att || !!def)
{ {
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, GH.pushIntT<CBattleInterface>(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, battleIntRect, att, def);
Rect((screen->w - 800)/2,
(screen->h - 600)/2, 800, 600), att, def);
GH.pushInt(bi);
} }
else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool())
{ {
@ -506,11 +503,7 @@ void CClient::battleStarted(const BattleInfo * info)
auto spectratorInt = std::dynamic_pointer_cast<CPlayerInterface>(playerint[PlayerColor::SPECTATOR]); auto spectratorInt = std::dynamic_pointer_cast<CPlayerInterface>(playerint[PlayerColor::SPECTATOR]);
spectratorInt->cb->setBattle(info); spectratorInt->cb->setBattle(info);
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, GH.pushIntT<CBattleInterface>(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, battleIntRect, att, def, spectratorInt);
Rect((screen->w - 800) / 2,
(screen->h - 600) / 2, 800, 600), att, def, spectratorInt);
GH.pushInt(bi);
} }
} }

View File

@ -35,7 +35,7 @@ bool LobbyClientConnected::applyOnLobbyHandler(CServerHandler * handler)
{ {
handler->c->connectionID = clientId; handler->c->connectionID = clientId;
if(!settings["session"]["headless"].Bool()) if(!settings["session"]["headless"].Bool())
GH.pushInt(new CLobbyScreen(static_cast<ESelectionScreen>(handler->screenType))); GH.pushIntT<CLobbyScreen>(static_cast<ESelectionScreen>(handler->screenType));
handler->state = EClientState::LOBBY; handler->state = EClientState::LOBBY;
return true; return true;
} }
@ -60,7 +60,7 @@ bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler)
void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
{ {
GH.popIntTotally(lobby); GH.popInts(1);
} }
void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
@ -114,7 +114,7 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
{ {
GH.pushInt(new CLoadingScreen(std::bind(&CServerHandler::startGameplay, handler))); GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, handler));
} }
bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler)
@ -128,7 +128,7 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler *
{ {
if(!lobby->bonusSel && handler->si->campState && handler->state == EClientState::LOBBY_CAMPAIGN) if(!lobby->bonusSel && handler->si->campState && handler->state == EClientState::LOBBY_CAMPAIGN)
{ {
lobby->bonusSel = new CBonusSelection(); lobby->bonusSel = std::make_shared<CBonusSelection>();
GH.pushInt(lobby->bonusSel); GH.pushInt(lobby->bonusSel);
} }

View File

@ -207,7 +207,7 @@ bool CDefenceAnimation::init()
if (!rangedAttack && getMyAnimType() != CCreatureAnim::DEFENCE) if (!rangedAttack && getMyAnimType() != CCreatureAnim::DEFENCE)
{ {
float frameLength = AnimationControls::getCreatureAnimationSpeed( float frameLength = AnimationControls::getCreatureAnimationSpeed(
stack->getCreature(), owner->creAnims[stack->ID], getMyAnimType()); stack->getCreature(), owner->creAnims[stack->ID].get(), getMyAnimType());
timeToWait = myAnim->framesInGroup(getMyAnimType()) * frameLength / 2; timeToWait = myAnim->framesInGroup(getMyAnimType()) * frameLength / 2;

View File

@ -39,7 +39,7 @@ public:
class CBattleStackAnimation : public CBattleAnimation class CBattleStackAnimation : public CBattleAnimation
{ {
public: public:
CCreatureAnimation * myAnim; //animation for our stack, managed by CBattleInterface std::shared_ptr<CCreatureAnimation> myAnim; //animation for our stack, managed by CBattleInterface
const CStack * stack; //id of stack whose animation it is const CStack * stack; //id of stack whose animation it is
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack); CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);

View File

@ -47,7 +47,7 @@
CondSh<bool> CBattleInterface::animsAreDisplayed(false); CondSh<bool> CBattleInterface::animsAreDisplayed(false);
CondSh<BattleAction *> CBattleInterface::givenCommand(nullptr); CondSh<BattleAction *> CBattleInterface::givenCommand(nullptr);
static void onAnimationFinished(const CStack *stack, CCreatureAnimation *anim) static void onAnimationFinished(const CStack *stack, std::shared_ptr<CCreatureAnimation> anim)
{ {
if (anim->isIdle()) if (anim->isIdle())
{ {
@ -92,36 +92,37 @@ void CBattleInterface::addNewAnim(CBattleAnimation *anim)
} }
CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet *army2, CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet *army2,
const CGHeroInstance *hero1, const CGHeroInstance *hero2, const CGHeroInstance *hero1, const CGHeroInstance *hero2,
const SDL_Rect & myRect, const SDL_Rect & myRect,
std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> spectatorInt) std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> spectatorInt)
: background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), : background(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1), activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1),
currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellToCast(nullptr), sp(nullptr), currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellToCast(nullptr), sp(nullptr),
creatureSpellToCast(-1), creatureSpellToCast(-1),
siegeH(nullptr), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0), siegeH(nullptr), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0),
myTurn(false), resWindow(nullptr), moveStarted(false), moveSoundHander(-1), bresult(nullptr) myTurn(false), moveStarted(false), moveSoundHander(-1), bresult(nullptr)
{ {
OBJ_CONSTRUCTION; OBJ_CONSTRUCTION;
if(spectatorInt) if(spectatorInt)
{
curInt = spectatorInt; curInt = spectatorInt;
}
else if(!curInt) else if(!curInt)
{ {
//May happen when we are defending during network MP game -> attacker interface is just not present //May happen when we are defending during network MP game -> attacker interface is just not present
curInt = defenderInt; curInt = defenderInt;
} }
animsAreDisplayed.setn(false); animsAreDisplayed.setn(false);
pos = myRect; pos = myRect;
strongInterest = true; strongInterest = true;
givenCommand.setn(nullptr); givenCommand.setn(nullptr);
//hot-seat -> check tactics for both players (defender may be local human) //hot-seat -> check tactics for both players (defender may be local human)
if (attackerInt && attackerInt->cb->battleGetTacticDist()) if(attackerInt && attackerInt->cb->battleGetTacticDist())
tacticianInterface = attackerInt; tacticianInterface = attackerInt;
else if (defenderInt && defenderInt->cb->battleGetTacticDist()) else if(defenderInt && defenderInt->cb->battleGetTacticDist())
tacticianInterface = defenderInt; tacticianInterface = defenderInt;
//if we found interface of player with tactics, then enter tactics mode //if we found interface of player with tactics, then enter tactics mode
@ -138,7 +139,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
else else
embedQueue = screen->h < 700 || queueSize == "small"; embedQueue = screen->h < 700 || queueSize == "small";
queue = new CStackQueue(embedQueue, this); queue = std::make_shared<CStackQueue>(embedQueue, this);
if(!embedQueue) if(!embedQueue)
{ {
if (settings["battle"]["showQueue"].Bool()) if (settings["battle"]["showQueue"].Bool())
@ -150,24 +151,24 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
//preparing siege info //preparing siege info
const CGTownInstance *town = curInt->cb->battleGetDefendedTown(); const CGTownInstance *town = curInt->cb->battleGetDefendedTown();
if (town && town->hasFort()) if(town && town->hasFort())
{ {
siegeH = new SiegeHelper(town, this); siegeH = new SiegeHelper(town, this);
} }
curInt->battleInt = this; CPlayerInterface::battleInt = this;
//initializing armies //initializing armies
this->army1 = army1; this->army1 = army1;
this->army2 = army2; this->army2 = army2;
std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks(true); std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks(true);
for (const CStack *s : stacks) for(const CStack * s : stacks)
{ {
unitAdded(s); unitAdded(s);
} }
//preparing menu background and terrain //preparing menu background and terrain
if (siegeH) if(siegeH)
{ {
background = BitmapHandler::loadBitmap( siegeH->getSiegeName(0), false ); background = BitmapHandler::loadBitmap( siegeH->getSiegeName(0), false );
ui8 siegeLevel = curInt->cb->battleGetSiegeLevel(); ui8 siegeLevel = curInt->cb->battleGetSiegeLevel();
@ -204,9 +205,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
} }
} }
//preparing menu background
//graphics->blueToPlayersAdv(menu, hero1->tempOwner);
//preparing graphics for displaying amounts of creatures //preparing graphics for displaying amounts of creatures
amountNormal = BitmapHandler::loadBitmap("CMNUMWIN.BMP"); amountNormal = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
CSDL_Ext::alphaTransform(amountNormal); CSDL_Ext::alphaTransform(amountNormal);
@ -224,77 +222,68 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
CSDL_Ext::alphaTransform(amountEffNeutral); CSDL_Ext::alphaTransform(amountEffNeutral);
transformPalette(amountEffNeutral, 1.00, 1.00, 0.18); transformPalette(amountEffNeutral, 1.00, 1.00, 0.18);
////blitting menu background and terrain
// blitAt(background, pos.x, pos.y);
// blitAt(menu, pos.x, 556 + pos.y);
//preparing buttons and console //preparing buttons and console
bOptions = new CButton (Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o); bOptions = std::make_shared<CButton>(Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleInterface::bOptionsf,this), SDLK_o);
bSurrender = new CButton (Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s); bSurrender = std::make_shared<CButton>(Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&CBattleInterface::bSurrenderf,this), SDLK_s);
bFlee = new CButton (Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r); bFlee = std::make_shared<CButton>(Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&CBattleInterface::bFleef,this), SDLK_r);
bAutofight = new CButton (Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a); bAutofight = std::make_shared<CButton>(Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&CBattleInterface::bAutofightf,this), SDLK_a);
bSpell = new CButton (Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c); bSpell = std::make_shared<CButton>(Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&CBattleInterface::bSpellf,this), SDLK_c);
bWait = new CButton (Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w); bWait = std::make_shared<CButton>(Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&CBattleInterface::bWaitf,this), SDLK_w);
bDefence = new CButton (Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleInterface::bDefencef,this), SDLK_d); bDefence = std::make_shared<CButton>(Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&CBattleInterface::bDefencef,this), SDLK_d);
bDefence->assignedKeys.insert(SDLK_SPACE); bDefence->assignedKeys.insert(SDLK_SPACE);
bConsoleUp = new CButton (Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP); bConsoleUp = std::make_shared<CButton>(Point(624, 561), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP);
bConsoleDown = new CButton (Point(624, 580), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN); bConsoleDown = std::make_shared<CButton>(Point(624, 580), "ComSlide.def", std::make_pair("", ""), std::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN);
bConsoleDown->setImageOrder(2, 3, 4, 5); bConsoleDown->setImageOrder(2, 3, 4, 5);
console = new CBattleConsole();
console = std::make_shared<CBattleConsole>();
console->pos.x += 211; console->pos.x += 211;
console->pos.y += 560; console->pos.y += 560;
console->pos.w = 406; console->pos.w = 406;
console->pos.h = 38; console->pos.h = 38;
if (tacticsMode) if(tacticsMode)
{ {
btactNext = new CButton(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE); btactNext = std::make_shared<CButton>(Point(213, 560), "icm011.def", std::make_pair("", ""), [&](){ bTacticNextStack(nullptr);}, SDLK_SPACE);
btactEnd = new CButton(Point(419, 560), "icm012.def", std::make_pair("", ""), [&](){ bEndTacticPhase();}, SDLK_RETURN); btactEnd = std::make_shared<CButton>(Point(419, 560), "icm012.def", std::make_pair("", ""), [&](){ bEndTacticPhase();}, SDLK_RETURN);
menu = BitmapHandler::loadBitmap("COPLACBR.BMP"); menu = BitmapHandler::loadBitmap("COPLACBR.BMP");
} }
else else
{ {
menu = BitmapHandler::loadBitmap("CBAR.BMP"); menu = BitmapHandler::loadBitmap("CBAR.BMP");
btactEnd = btactNext = nullptr;
} }
graphics->blueToPlayersAdv(menu, curInt->playerID); graphics->blueToPlayersAdv(menu, curInt->playerID);
//loading hero animations //loading hero animations
if (hero1) // attacking hero if(hero1) // attacking hero
{ {
std::string battleImage; std::string battleImage;
if ( hero1->sex ) if(hero1->sex)
battleImage = hero1->type->heroClass->imageBattleFemale; battleImage = hero1->type->heroClass->imageBattleFemale;
else else
battleImage = hero1->type->heroClass->imageBattleMale; battleImage = hero1->type->heroClass->imageBattleMale;
attackingHero = new CBattleHero(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this); attackingHero = std::make_shared<CBattleHero>(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this);
auto img = attackingHero->animation->getImage(0, 0, true); auto img = attackingHero->animation->getImage(0, 0, true);
if(img) if(img)
attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19); attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19);
} }
else
{
attackingHero = nullptr; if(hero2) // defending hero
}
if (hero2) // defending hero
{ {
std::string battleImage; std::string battleImage;
if ( hero2->sex ) if(hero2->sex)
battleImage = hero2->type->heroClass->imageBattleFemale; battleImage = hero2->type->heroClass->imageBattleFemale;
else else
battleImage = hero2->type->heroClass->imageBattleMale; battleImage = hero2->type->heroClass->imageBattleMale;
defendingHero = new CBattleHero(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this); defendingHero = std::make_shared<CBattleHero>(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this);
auto img = defendingHero->animation->getImage(0, 0, true); auto img = defendingHero->animation->getImage(0, 0, true);
if(img) if(img)
defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19); defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19);
} }
else
{
defendingHero = nullptr;
}
//preparing cells and hexes //preparing cells and hexes
cellBorder = BitmapHandler::loadBitmap("CCELLGRD.BMP"); cellBorder = BitmapHandler::loadBitmap("CCELLGRD.BMP");
@ -303,7 +292,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
CSDL_Ext::alphaTransform(cellShade); CSDL_Ext::alphaTransform(cellShade);
for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h) for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h)
{ {
auto hex = new CClickableHex(); auto hex = std::make_shared<CClickableHex>();
hex->myNumber = h; hex->myNumber = h;
hex->pos = hexPosition(h); hex->pos = hexPosition(h);
hex->accessible = true; hex->accessible = true;
@ -385,8 +374,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
} }
} }
for (auto hex : bfield) for(auto hex : bfield)
addChild(hex); addChild(hex.get());
if (tacticsMode) if (tacticsMode)
bTacticNextStack(); bTacticNextStack();
@ -412,7 +401,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
CBattleInterface::~CBattleInterface() CBattleInterface::~CBattleInterface()
{ {
curInt->battleInt = nullptr; CPlayerInterface::battleInt = nullptr;
givenCommand.cond.notify_all(); //that two lines should make any activeStack waiting thread to finish givenCommand.cond.notify_all(); //that two lines should make any activeStack waiting thread to finish
if (active) //dirty fix for #485 if (active) //dirty fix for #485
@ -427,31 +416,11 @@ CBattleInterface::~CBattleInterface()
SDL_FreeSurface(amountEffNeutral); SDL_FreeSurface(amountEffNeutral);
SDL_FreeSurface(cellBorders); SDL_FreeSurface(cellBorders);
SDL_FreeSurface(backgroundWithHexes); SDL_FreeSurface(backgroundWithHexes);
delete bOptions;
delete bSurrender;
delete bFlee;
delete bAutofight;
delete bSpell;
delete bWait;
delete bDefence;
for (auto hex : bfield)
delete hex;
delete bConsoleUp;
delete bConsoleDown;
delete console;
delete attackingHero;
delete defendingHero;
delete queue;
SDL_FreeSurface(cellBorder); SDL_FreeSurface(cellBorder);
SDL_FreeSurface(cellShade); SDL_FreeSurface(cellShade);
for (auto & elem : creAnims)
delete elem.second;
delete siegeH; delete siegeH;
//TODO: play AI tracks if battle was during AI turn //TODO: play AI tracks if battle was during AI turn
@ -588,7 +557,7 @@ void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key)
} }
void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent) void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
{ {
auto hexItr = std::find_if (bfield.begin(), bfield.end(), [](const CClickableHex *hex) auto hexItr = std::find_if(bfield.begin(), bfield.end(), [](std::shared_ptr<CClickableHex> hex)
{ {
return hex->hovered && hex->strictHovered; return hex->hovered && hex->strictHovered;
}); });
@ -786,8 +755,7 @@ void CBattleInterface::bOptionsf()
Rect tempRect = genRect(431, 481, 160, 84); Rect tempRect = genRect(431, 481, 160, 84);
tempRect += pos.topLeft(); tempRect += pos.topLeft();
auto optionsWin = new CBattleOptionsWindow(tempRect, this); GH.pushIntT<CBattleOptionsWindow>(tempRect, this);
GH.pushInt(optionsWin);
} }
void CBattleInterface::bSurrenderf() void CBattleInterface::bSurrenderf()
@ -900,7 +868,7 @@ void CBattleInterface::bSpellf()
if(spellCastProblem == ESpellCastProblem::OK) if(spellCastProblem == ESpellCastProblem::OK)
{ {
GH.pushInt(new CSpellWindow(myHero, curInt.get())); GH.pushIntT<CSpellWindow>(myHero, curInt.get());
} }
else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED) else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
{ {
@ -1276,13 +1244,13 @@ void CBattleInterface::displayBattleFinished()
CCS->curh->changeGraphic(ECursor::ADVENTURE,0); CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
if(settings["session"]["spectate"].Bool() && settings["session"]["spectate-skip-battle-result"].Bool()) if(settings["session"]["spectate"].Bool() && settings["session"]["spectate-skip-battle-result"].Bool())
{ {
GH.popIntTotally(this); close();
return; return;
} }
resWindow = new CBattleResultWindow(*bresult, *this->curInt); GH.pushInt(std::make_shared<CBattleResultWindow>(*bresult, *(this->curInt)));
GH.pushInt(resWindow);
curInt->waitWhileDialog(); // Avoid freeze when AI end turn after battle. Check bug #1897 curInt->waitWhileDialog(); // Avoid freeze when AI end turn after battle. Check bug #1897
CPlayerInterface::battleInt = nullptr;
} }
void CBattleInterface::spellCast(const BattleSpellCast * sc) void CBattleInterface::spellCast(const BattleSpellCast * sc)
@ -1436,7 +1404,7 @@ void CBattleInterface::setHeroAnimation(ui8 side, int phase)
void CBattleInterface::castThisSpell(SpellID spellID) void CBattleInterface::castThisSpell(SpellID spellID)
{ {
spellToCast = new BattleAction(); spellToCast = std::make_shared<BattleAction>();
spellToCast->actionType = EActionType::HERO_SPELL; spellToCast->actionType = EActionType::HERO_SPELL;
spellToCast->actionSubtype = spellID; //spell number spellToCast->actionSubtype = spellID; //spell number
spellToCast->stackNumber = (attackingHeroInstance->tempOwner == curInt->playerID) ? -1 : -2; spellToCast->stackNumber = (attackingHeroInstance->tempOwner == curInt->playerID) ? -1 : -2;
@ -1453,7 +1421,7 @@ void CBattleInterface::castThisSpell(SpellID spellID)
if (spellSelMode == NO_LOCATION) //user does not have to select location if (spellSelMode == NO_LOCATION) //user does not have to select location
{ {
spellToCast->aimToHex(BattleHex::INVALID); spellToCast->aimToHex(BattleHex::INVALID);
curInt->cb->battleMakeAction(spellToCast); curInt->cb->battleMakeAction(spellToCast.get());
endCastingSpell(); endCastingSpell();
} }
else else
@ -1680,15 +1648,15 @@ void CBattleInterface::activateStack()
void CBattleInterface::endCastingSpell() void CBattleInterface::endCastingSpell()
{ {
if (spellDestSelectMode) if(spellDestSelectMode)
{ {
vstd::clear_pointer(spellToCast); spellToCast.reset();
sp = nullptr; sp = nullptr;
spellDestSelectMode = false; spellDestSelectMode = false;
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER); CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
if (activeStack) if(activeStack)
{ {
getPossibleActionsForStack(activeStack, false); //restore actions after they were cleared getPossibleActionsForStack(activeStack, false); //restore actions after they were cleared
myTurn = true; myTurn = true;
@ -1696,7 +1664,7 @@ void CBattleInterface::endCastingSpell()
} }
else else
{ {
if (activeStack) if(activeStack)
{ {
getPossibleActionsForStack(activeStack, false); getPossibleActionsForStack(activeStack, false);
GH.fakeMouseMove(); GH.fakeMouseMove();
@ -2419,7 +2387,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
{ {
cursorFrame = ECursor::COMBAT_QUERY; cursorFrame = ECursor::COMBAT_QUERY;
consoleMsg = (boost::format(CGI->generaltexth->allTexts[297]) % shere->getName()).str(); consoleMsg = (boost::format(CGI->generaltexth->allTexts[297]) % shere->getName()).str();
realizeAction = [=](){ GH.pushInt(new CStackWindow(shere, false)); }; realizeAction = [=](){ GH.pushIntT<CStackWindow>(shere, false); };
break; break;
} }
} }
@ -2511,7 +2479,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
spellToCast->aimToHex(myNumber); spellToCast->aimToHex(myNumber);
break; break;
} }
curInt->cb->battleMakeAction(spellToCast); curInt->cb->battleMakeAction(spellToCast.get());
endCastingSpell(); endCastingSpell();
} }
selectedStack = nullptr; selectedStack = nullptr;

View File

@ -106,7 +106,7 @@ struct CatapultProjectileInfo
/// Big class which handles the overall battle interface actions and it is also responsible for /// Big class which handles the overall battle interface actions and it is also responsible for
/// drawing everything correctly. /// drawing everything correctly.
class CBattleInterface : public CIntObject class CBattleInterface : public WindowBase
{ {
enum PossibleActions // actions performed at l-click enum PossibleActions // actions performed at l-click
{ {
@ -121,14 +121,26 @@ class CBattleInterface : public CIntObject
private: private:
SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes; SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes;
CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell, std::shared_ptr<CButton> bOptions;
* bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd; std::shared_ptr<CButton> bSurrender;
CBattleConsole *console; std::shared_ptr<CButton> bFlee;
CBattleHero *attackingHero, *defendingHero; //fighting heroes std::shared_ptr<CButton> bAutofight;
CStackQueue *queue; std::shared_ptr<CButton> bSpell;
std::shared_ptr<CButton> bWait;
std::shared_ptr<CButton> bDefence;
std::shared_ptr<CButton> bConsoleUp;
std::shared_ptr<CButton> bConsoleDown;
std::shared_ptr<CButton> btactNext;
std::shared_ptr<CButton> btactEnd;
std::shared_ptr<CBattleConsole> console;
std::shared_ptr<CBattleHero> attackingHero;
std::shared_ptr<CBattleHero> defendingHero;
std::shared_ptr<CStackQueue> queue;
const CCreatureSet *army1, *army2; //copy of initial armies (for result window) const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance; const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID) std::map<int32_t, std::shared_ptr<CCreatureAnimation>> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
std::map<int, std::shared_ptr<CAnimation>> idToProjectile; std::map<int, std::shared_ptr<CAnimation>> idToProjectile;
@ -154,7 +166,7 @@ private:
bool stackCanCastSpell; //if true, active stack could possibly cast some target spell bool stackCanCastSpell; //if true, active stack could possibly cast some target spell
bool creatureCasting; //if true, stack currently aims to cats a spell bool creatureCasting; //if true, stack currently aims to cats a spell
bool spellDestSelectMode; //if true, player is choosing destination for his spell - only for GUI / console bool spellDestSelectMode; //if true, player is choosing destination for his spell - only for GUI / console
BattleAction *spellToCast; //spell for which player is choosing destination std::shared_ptr<BattleAction> spellToCast; //spell for which player is choosing destination
const CSpell *sp; //spell pointer for convenience const CSpell *sp; //spell pointer for convenience
si32 creatureSpellToCast; si32 creatureSpellToCast;
std::vector<PossibleActions> possibleActions; //all actions possible to call at the moment by player std::vector<PossibleActions> possibleActions; //all actions possible to call at the moment by player
@ -284,11 +296,10 @@ public:
int getAnimSpeed() const; //speed of animation; range 1..100 int getAnimSpeed() const; //speed of animation; range 1..100
CPlayerInterface *getCurrentPlayerInterface() const; CPlayerInterface *getCurrentPlayerInterface() const;
std::vector<CClickableHex*> bfield; //11 lines, 17 hexes on each std::vector<std::shared_ptr<CClickableHex>> bfield; //11 lines, 17 hexes on each
SDL_Surface *cellBorder, *cellShade; SDL_Surface *cellBorder, *cellShade;
bool myTurn; //if true, interface is active (commands can be ordered) bool myTurn; //if true, interface is active (commands can be ordered)
CBattleResultWindow *resWindow; //window of end of battle
bool moveStarted; //if true, the creature that is already moving is going to make its first step bool moveStarted; //if true, the creature that is already moving is going to make its first step
int moveSoundHander; // sound handler used when moving a unit int moveSoundHander; // sound handler used when moving a unit

View File

@ -212,7 +212,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
} }
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
GH.pushInt(new CSpellWindow(myHero, myOwner->getCurrentPlayerInterface())); GH.pushIntT<CSpellWindow>(myHero, myOwner->getCurrentPlayerInterface());
} }
} }
@ -230,7 +230,7 @@ void CBattleHero::clickRight(tribool down, bool previousState)
{ {
auto h = flip ? myOwner->defendingHeroInstance : myOwner->attackingHeroInstance; auto h = flip ? myOwner->defendingHeroInstance : myOwner->attackingHeroInstance;
targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE); targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE);
GH.pushInt(new CHeroInfoWindow(targetHero, &windowPosition)); GH.pushIntT<CHeroInfoWindow>(targetHero, &windowPosition);
} }
} }
@ -391,7 +391,7 @@ void CBattleOptionsWindow::bDefaultf()
void CBattleOptionsWindow::bExitf() void CBattleOptionsWindow::bExitf()
{ {
GH.popIntTotally(this); close();
} }
CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner) CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner)
@ -560,8 +560,10 @@ void CBattleResultWindow::show(SDL_Surface * to)
void CBattleResultWindow::bExitf() void CBattleResultWindow::bExitf()
{ {
CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon CPlayerInterface &intTmp = owner; //copy reference because "this" will be destructed soon
GH.popIntTotally(this);
if(dynamic_cast<CBattleInterface*>(GH.topInt())) close();
if(dynamic_cast<CBattleInterface*>(GH.topInt().get()))
GH.popInts(1); //pop battle interface if present GH.popInts(1); //pop battle interface if present
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle, //Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
@ -689,11 +691,10 @@ void CClickableHex::clickRight(tribool down, bool previousState)
const CStack * myst = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber); //stack info const CStack * myst = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber); //stack info
if(hovered && strictHovered && myst!=nullptr) if(hovered && strictHovered && myst!=nullptr)
{ {
if(!myst->alive()) return; if(!myst->alive()) return;
if(down) if(down)
{ {
GH.pushInt(new CStackWindow(myst, true)); GH.pushIntT<CStackWindow>(myst, true);
} }
} }
} }

View File

@ -89,7 +89,7 @@ public:
}; };
/// Class which manages the battle options window /// Class which manages the battle options window
class CBattleOptionsWindow : public CIntObject class CBattleOptionsWindow : public WindowBase
{ {
private: private:
std::shared_ptr<CPicture> background; std::shared_ptr<CPicture> background;
@ -106,7 +106,7 @@ public:
}; };
/// Class which is responsible for showing the battle result window /// Class which is responsible for showing the battle result window
class CBattleResultWindow : public CIntObject class CBattleResultWindow : public WindowBase
{ {
private: private:
std::shared_ptr<CPicture> background; std::shared_ptr<CPicture> background;

View File

@ -34,10 +34,10 @@ SDL_Color AnimationControls::getNoBorder()
return creatureNoBorder; return creatureNoBorder;
} }
CCreatureAnimation * AnimationControls::getAnimation(const CCreature * creature) std::shared_ptr<CCreatureAnimation> AnimationControls::getAnimation(const CCreature * creature)
{ {
auto func = std::bind(&AnimationControls::getCreatureAnimationSpeed, creature, _1, _2); auto func = std::bind(&AnimationControls::getCreatureAnimationSpeed, creature, _1, _2);
return new CCreatureAnimation(creature->animDefName, func); return std::make_shared<CCreatureAnimation>(creature->animDefName, func);
} }
float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t group) float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t group)

View File

@ -25,7 +25,7 @@ namespace AnimationControls
SDL_Color getNoBorder(); SDL_Color getNoBorder();
/// creates animation object with preset speed control /// creates animation object with preset speed control
CCreatureAnimation * getAnimation(const CCreature * creature); std::shared_ptr<CCreatureAnimation> getAnimation(const CCreature * creature);
/// returns animation speed of specific group, taking in mind game setting (in frames per second) /// returns animation speed of specific group, taking in mind game setting (in frames per second)
float getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t groupID); float getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t groupID);

View File

@ -23,7 +23,6 @@
#include "../lib/CRandomGenerator.h" #include "../lib/CRandomGenerator.h"
class SDLImageLoader; class SDLImageLoader;
class CompImageLoader;
typedef std::map <size_t, std::vector <JsonNode> > source_map; typedef std::map <size_t, std::vector <JsonNode> > source_map;
typedef std::map<size_t, IImage* > image_map; typedef std::map<size_t, IImage* > image_map;
@ -79,9 +78,9 @@ public:
public: public:
//Load image from def file //Load image from def file
SDLImage(CDefFile *data, size_t frame, size_t group=0, bool compressed=false); SDLImage(CDefFile *data, size_t frame, size_t group=0);
//Load from bitmap file //Load from bitmap file
SDLImage(std::string filename, bool compressed=false); SDLImage(std::string filename);
SDLImage(const JsonNode & conf); SDLImage(const JsonNode & conf);
//Create using existing surface, extraRef will increase refcount on SDL_Surface //Create using existing surface, extraRef will increase refcount on SDL_Surface
@ -107,65 +106,6 @@ public:
friend class SDLImageLoader; friend class SDLImageLoader;
}; };
/*
* RLE-compressed image data for 8-bit images with alpha-channel, currently far from finished
* primary purpose is not high compression ratio but fast drawing.
* Consist of repeatable segments with format similar to H3 def compression:
* 1st byte:
* if (byte == 0xff)
* raw data, opaque and semi-transparent data always in separate blocks
* else
* RLE-compressed image data with this color
* 2nd byte = size of segment
* raw data (if any)
*/
class CompImage : public IImage
{
//x,y - margins, w,h - sprite size
Rect sprite;
//total size including borders
Point fullSize;
//RLE-d data
ui8 * surf;
//array of offsets for each line
ui32 * line;
//palette
SDL_Color *palette;
//Used internally to blit one block of data
template<int bpp, int dir>
void BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const;
void BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const;
public:
//Load image from def file
CompImage(const CDefFile *data, size_t frame, size_t group=0);
//TODO: load image from SDL_Surface
CompImage(SDL_Surface * surf);
~CompImage();
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
std::shared_ptr<IImage> scaleFast(float scale) const override;
void exportBitmap(const boost::filesystem::path & path) const override;
void playerColored(PlayerColor player) override;
void setFlagColor(PlayerColor player) override;
int width() const override;
int height() const override;
void horizontalFlip() override;
void verticalFlip() override;
void shiftPalette(int from, int howMany) override;
void setBorderPallete(const BorderPallete & borderPallete) override;
friend class CompImageLoader;
};
class SDLImageLoader class SDLImageLoader
{ {
SDLImage * image; SDLImage * image;
@ -184,30 +124,6 @@ public:
~SDLImageLoader(); ~SDLImageLoader();
}; };
class CompImageLoader
{
CompImage * image;
ui8 *position;
ui8 *entry;
ui32 currentLine;
inline ui8 typeOf(ui8 color);
inline void NewEntry(ui8 color, size_t size);
inline void NewEntry(const ui8 * &data, size_t size);
public:
//load size raw pixels from data
inline void Load(size_t size, const ui8 * data);
//set size pixels to color
inline void Load(size_t size, ui8 color=0);
inline void EndLine();
//init image with these sizes and palette
inline void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal);
CompImageLoader(CompImage * Img);
~CompImageLoader();
};
// Extremely simple file cache. TODO: smarter, more general solution // Extremely simple file cache. TODO: smarter, more general solution
class CFileCache class CFileCache
{ {
@ -576,7 +492,7 @@ SDLImageLoader::SDLImageLoader(SDLImage * Img):
void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal) void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
{ {
//Init image //Init image
image->surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SpriteSize.x, SpriteSize.y, 8, 0, 0, 0, 0); image->surf = SDL_CreateRGBSurface(0, SpriteSize.x, SpriteSize.y, 8, 0, 0, 0, 0);
image->margins = Margins; image->margins = Margins;
image->fullSize = FullSize; image->fullSize = FullSize;
@ -621,182 +537,6 @@ SDLImageLoader::~SDLImageLoader()
//TODO: RLE if compressed and bpp>1 //TODO: RLE if compressed and bpp>1
} }
////////////////////////////////////////////////////////////////////////////////
CompImageLoader::CompImageLoader(CompImage * Img):
image(Img),
position(nullptr),
entry(nullptr),
currentLine(0)
{
}
void CompImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
{
image->sprite = Rect(Margins, SpriteSize);
image->fullSize = FullSize;
if (SpriteSize.x && SpriteSize.y)
{
image->palette = new SDL_Color[256];
memcpy((void*)image->palette, (void*)pal, 256*sizeof(SDL_Color));
//Allocate enought space for worst possible case, c-style malloc used due to resizing after load
image->surf = (ui8*)malloc(SpriteSize.x*SpriteSize.y*3);
image->line = new ui32[SpriteSize.y+1];
image->line[0] = 0;
position = image->surf;
}
}
inline void CompImageLoader::NewEntry(ui8 color, size_t size)
{
assert(color != 0xff);
assert(size && size<256);
entry = position;
entry[0] = color;
entry[1] = size;
position +=2;
}
inline void CompImageLoader::NewEntry(const ui8 * &data, size_t size)
{
assert(size && size<256);
entry = position;
entry[0] = 0xff;
entry[1] = size;
position +=2;
memcpy(position, data, size);
position+=size;
data+=size;
}
inline ui8 CompImageLoader::typeOf(ui8 color)
{
if (color == 0)
return 0;
if (image->palette[color].a != 255)
return 1;
return 2;
}
inline void CompImageLoader::Load(size_t size, const ui8 * data)
{
while (size)
{
//Try to compress data
while(true)
{
ui8 color = data[0];
if (color != 0xff)
{
size_t runLength = 1;
while (runLength < size && color == data[runLength])
runLength++;
if (runLength > 1 && runLength < 255)//Row of one color found - use RLE
{
Load(runLength, color);
data += runLength;
size -= runLength;
if (!size)
return;
}
else
break;
}
else
break;
}
//Select length for new raw entry
size_t runLength = 1;
ui8 color = data[0];
ui8 type = typeOf(color);
ui8 color2;
ui8 type2;
if (size > 1)
{
do
{
color2 = data[runLength];
type2 = typeOf(color2);
runLength++;
}
//While we have data of this type and different colors
while ((runLength < size) && (type == type2) && ( (color2 != 0xff) || (color2 != color)));
}
size -= runLength;
//add data to last entry
if (entry && entry[0] == 0xff && type == typeOf(entry[2]))
{
size_t toCopy = std::min<size_t>(runLength, 255 - entry[1]);
runLength -= toCopy;
entry[1] += toCopy;
memcpy(position, data, toCopy);
data+=toCopy;
position+=toCopy;
}
//Create new entries
while (runLength > 255)
{
NewEntry(data, 255);
runLength -= 255;
}
if (runLength)
NewEntry(data, runLength);
}
}
inline void CompImageLoader::Load(size_t size, ui8 color)
{
if (!size)
return;
if (color==0xff)
{
auto tmpbuf = new ui8[size];
memset((void*)tmpbuf, color, size);
Load(size, tmpbuf);
delete [] tmpbuf;
return;
}
//Current entry is RLE with same color as new block
if (entry && entry[0] == color)
{
size_t toCopy = std::min<size_t>(size, 255 - entry[1]);
size -= toCopy;
entry[1] += toCopy;
}
//Create new entries
while (size > 255)
{
NewEntry(color, 255);
size -= 255;
}
if (size)
NewEntry(color, size);
}
void CompImageLoader::EndLine()
{
currentLine++;
image->line[currentLine] = position - image->surf;
entry = nullptr;
}
CompImageLoader::~CompImageLoader()
{
if (!image->surf)
return;
ui8* newPtr = (ui8*)realloc((void*)image->surf, position - image->surf);
if (newPtr)
image->surf = newPtr;
}
/************************************************************************* /*************************************************************************
* Classes for images, support loading from file and drawing on surface * * Classes for images, support loading from file and drawing on surface *
*************************************************************************/ *************************************************************************/
@ -805,7 +545,7 @@ IImage::IImage() = default;
IImage::~IImage() = default; IImage::~IImage() = default;
SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group, bool compressed) SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
: surf(nullptr), : surf(nullptr),
margins(0, 0), margins(0, 0),
fullSize(0, 0) fullSize(0, 0)
@ -857,15 +597,14 @@ SDLImage::SDLImage(const JsonNode & conf)
} }
} }
SDLImage::SDLImage(std::string filename)
SDLImage::SDLImage(std::string filename, bool compressed)
: surf(nullptr), : surf(nullptr),
margins(0, 0), margins(0, 0),
fullSize(0, 0) fullSize(0, 0)
{ {
surf = BitmapHandler::loadBitmap(filename); surf = BitmapHandler::loadBitmap(filename);
if (surf == nullptr) if(surf == nullptr)
{ {
logGlobal->error("Error: failed to load image %s", filename); logGlobal->error("Error: failed to load image %s", filename);
return; return;
@ -875,23 +614,8 @@ SDLImage::SDLImage(std::string filename, bool compressed)
fullSize.x = surf->w; fullSize.x = surf->w;
fullSize.y = surf->h; fullSize.y = surf->h;
} }
if (compressed)
{
SDL_Surface *temp = surf;
// add RLE flag
if (surf->format->palette)
{
CSDL_Ext::setColorKey(temp,temp->format->palette->colors[0]);
}
SDL_SetSurfaceRLE(temp, SDL_RLEACCEL);
// convert surface to enable RLE
surf = SDL_ConvertSurface(temp, temp->format, temp->flags);
SDL_FreeSurface(temp);
}
} }
void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const
{ {
if(!surf) if(!surf)
@ -1042,282 +766,6 @@ SDLImage::~SDLImage()
SDL_FreeSurface(surf); SDL_FreeSurface(surf);
} }
CompImage::CompImage(const CDefFile *data, size_t frame, size_t group):
surf(nullptr),
line(nullptr),
palette(nullptr)
{
CompImageLoader loader(this);
data->loadFrame(frame, group, loader);
}
CompImage::CompImage(SDL_Surface * surf)
{
//TODO
assert(0);
}
void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const
{
Rect dest(posX,posY, width(), height());
draw(where, &dest, src, alpha);
}
void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const
{
int rotation = 0; //TODO
//rotation & 2 = horizontal rotation
//rotation & 4 = vertical rotation
if (!surf)
return;
Rect sourceRect(sprite);
//TODO: rotation and scaling
if (src)
sourceRect = sourceRect & *src;
//Limit source rect to sizes of surface
sourceRect = sourceRect & Rect(0, 0, where->w, where->h);
//Starting point on SDL surface
Point dst(sourceRect.x,sourceRect.y);
if (dest)
{
dst.x += dest->x;
dst.y += dest->y;
}
if (rotation & 2)
dst.y += sourceRect.h;
if (rotation & 4)
dst.x += sourceRect.w;
sourceRect -= sprite.topLeft();
for (int currY = 0; currY <sourceRect.h; currY++)
{
ui8* data = surf + line[currY+sourceRect.y];
ui8 type = *(data++);
ui8 size = *(data++);
int currX = sourceRect.x;
//Skip blocks until starting position reached
while ( currX > size )
{
currX -= size;
if (type == 0xff)
data += size;
type = *(data++);
size = *(data++);
}
//This block will be shown partially - calculate size\position
size -= currX;
if (type == 0xff)
data += currX;
currX = 0;
ui8 bpp = where->format->BytesPerPixel;
//Calculate position for blitting: pixels + Y + X
ui8* blitPos = (ui8*) where->pixels;
if (rotation & 4)
blitPos += (dst.y - currY) * where->pitch;
else
blitPos += (dst.y + currY) * where->pitch;
blitPos += dst.x * bpp;
//Blit blocks that must be fully visible
while (currX + size < sourceRect.w)
{
//blit block, pointers will be modified if needed
BlitBlockWithBpp(bpp, type, size, data, blitPos, alpha, rotation & 2);
currX += size;
type = *(data++);
size = *(data++);
}
//Blit last, semi-visible block
size = sourceRect.w - currX;
BlitBlockWithBpp(bpp, type, size, data, blitPos, alpha, rotation & 2);
}
}
std::shared_ptr<IImage> CompImage::scaleFast(float scale) const
{
//todo: CompImage::scaleFast
logAnim->error("CompImage::scaleFast is not implemented");
return nullptr;
}
#define CASEBPP(x,y) case x: BlitBlock<x,y>(type, size, data, dest, alpha); break
//FIXME: better way to get blitter
void CompImage::BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const
{
assert(bpp>1 && bpp<5);
if (rotated)
switch (bpp)
{
CASEBPP(2,1);
CASEBPP(3,1);
CASEBPP(4,1);
}
else
switch (bpp)
{
CASEBPP(2,1);
CASEBPP(3,1);
CASEBPP(4,1);
}
}
#undef CASEBPP
//Blit one block from RLE-d surface
template<int bpp, int dir>
void CompImage::BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const
{
//Raw data
if (type == 0xff)
{
ui8 color = *data;
if (alpha != 255)//Per-surface alpha is set
{
for (size_t i=0; i<size; i++)
{
SDL_Color col = palette[*(data++)];
col.a = (ui32)col.a*alpha/255;
ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
}
return;
}
if (palette[color].a == 255)
{
//Put row of RGB data
for (size_t i=0; i<size; i++)
ColorPutter<bpp, 1>::PutColor(dest, palette[*(data++)]);
}
else
{
//Put row of RGBA data
for (size_t i=0; i<size; i++)
ColorPutter<bpp, 1>::PutColorAlpha(dest, palette[*(data++)]);
}
}
//RLE-d sequence
else
{
if (alpha != 255 && palette[type].a !=0)//Per-surface alpha is set
{
SDL_Color col = palette[type];
col.a = (int)col.a*(255-alpha)/255;
for (size_t i=0; i<size; i++)
ColorPutter<bpp, 1>::PutColorAlpha(dest, col);
return;
}
switch (palette[type].a)
{
case 0:
{
//Skip row
dest += size*bpp;
break;
}
case 255:
{
//Put RGB row
ColorPutter<bpp, 1>::PutColorRow(dest, palette[type], size);
break;
}
default:
{
//Put RGBA row
for (size_t i=0; i<size; i++)
ColorPutter<bpp, 1>::PutColorAlpha(dest, palette[type]);
break;
}
}
}
}
void CompImage::playerColored(PlayerColor player)
{
SDL_Color *pal = nullptr;
if(player < PlayerColor::PLAYER_LIMIT)
{
pal = graphics->playerColorPalette + 32*player.getNum();
}
else if(player == PlayerColor::NEUTRAL)
{
pal = graphics->neutralColorPalette;
}
else
assert(0);
for(int i=0; i<32; ++i)
{
CSDL_Ext::colorAssign(palette[224+i],pal[i]);
}
}
void CompImage::setFlagColor(PlayerColor player)
{
logAnim->error("CompImage::setFlagColor is not implemented");
}
int CompImage::width() const
{
return fullSize.x;
}
int CompImage::height() const
{
return fullSize.y;
}
CompImage::~CompImage()
{
free(surf);
delete [] line;
delete [] palette;
}
void CompImage::horizontalFlip()
{
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
}
void CompImage::verticalFlip()
{
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
}
void CompImage::shiftPalette(int from, int howMany)
{
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
}
void CompImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
{
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
}
void CompImage::exportBitmap(const boost::filesystem::path & path) const
{
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
}
/*************************************************************************
* CAnimation for animations handling, can load part of file if needed *
*************************************************************************/
std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename) std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
{ {
size_t pos = filename.find(':'); size_t pos = filename.find(':');
@ -1363,17 +811,14 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present
{ {
if(compressed) images[group][frame] = std::make_shared<SDLImage>(defFile.get(), frame, group);
images[group][frame] = std::make_shared<CompImage>(defFile, frame, group);
else
images[group][frame] = std::make_shared<SDLImage>(defFile, frame, group);
return true; return true;
} }
} }
// still here? image is missing // still here? image is missing
printError(frame, group, "LoadFrame"); printError(frame, group, "LoadFrame");
images[group][frame] = std::make_shared<SDLImage>("DEFAULT", compressed); images[group][frame] = std::make_shared<SDLImage>("DEFAULT");
} }
else //load from separate file else //load from separate file
{ {
@ -1507,11 +952,10 @@ void CAnimation::printError(size_t frame, size_t group, std::string type) const
logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame); logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame);
} }
CAnimation::CAnimation(std::string Name, bool Compressed): CAnimation::CAnimation(std::string Name):
name(Name), name(Name),
compressed(Compressed),
preloaded(false), preloaded(false),
defFile(nullptr) defFile()
{ {
size_t dotPos = name.find_last_of('.'); size_t dotPos = name.find_last_of('.');
if ( dotPos!=-1 ) if ( dotPos!=-1 )
@ -1521,7 +965,7 @@ CAnimation::CAnimation(std::string Name, bool Compressed):
ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION); ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION);
if(CResourceHandler::get()->existsResource(resource)) if(CResourceHandler::get()->existsResource(resource))
defFile = new CDefFile(name); defFile = std::make_shared<CDefFile>(name);
init(); init();
@ -1531,21 +975,28 @@ CAnimation::CAnimation(std::string Name, bool Compressed):
CAnimation::CAnimation(): CAnimation::CAnimation():
name(""), name(""),
compressed(false),
preloaded(false), preloaded(false),
defFile(nullptr) defFile()
{ {
init(); init();
} }
CAnimation::~CAnimation() CAnimation::~CAnimation() = default;
{
if(defFile)
delete defFile;
}
void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup) void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup)
{ {
if(!source.count(sourceGroup))
{
logAnim->error("Group %d missing in %s", sourceGroup, name);
return;
}
if(source[sourceGroup].size() <= sourceFrame)
{
logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name);
return;
}
//todo: clone actual loaded Image object //todo: clone actual loaded Image object
JsonNode clone(source[sourceGroup][sourceFrame]); JsonNode clone(source[sourceGroup][sourceFrame]);

View File

@ -68,12 +68,9 @@ private:
//animation file name //animation file name
std::string name; std::string name;
//if true all frames will be stored in compressed (RLE) state
const bool compressed;
bool preloaded; bool preloaded;
CDefFile * defFile; std::shared_ptr<CDefFile> defFile;
//loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded //loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded
bool loadFrame(size_t frame, size_t group); bool loadFrame(size_t frame, size_t group);
@ -93,7 +90,7 @@ private:
std::shared_ptr<IImage> getFromExtraDef(std::string filename); std::shared_ptr<IImage> getFromExtraDef(std::string filename);
public: public:
CAnimation(std::string Name, bool Compressed = false); CAnimation(std::string Name);
CAnimation(); CAnimation();
~CAnimation(); ~CAnimation();

View File

@ -18,8 +18,31 @@
#include "../CMT.h" #include "../CMT.h"
void CCursorHandler::clearBuffer()
{
Uint32 fillColor = SDL_MapRGBA(buffer->format, 0, 0, 0, 0);
CSDL_Ext::fillRect(buffer, nullptr, fillColor);
}
void CCursorHandler::updateBuffer(CIntObject * payload)
{
payload->moveTo(Point(0,0));
payload->showAll(buffer);
needUpdate = true;
}
void CCursorHandler::replaceBuffer(CIntObject * payload)
{
clearBuffer();
updateBuffer(payload);
}
void CCursorHandler::initCursor() void CCursorHandler::initCursor()
{ {
cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40);
SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND);
xpos = ypos = 0; xpos = ypos = 0;
type = ECursor::DEFAULT; type = ECursor::DEFAULT;
dndObject = nullptr; dndObject = nullptr;
@ -34,9 +57,9 @@ void CCursorHandler::initCursor()
currentCursor = cursors.at(int(ECursor::DEFAULT)).get(); currentCursor = cursors.at(int(ECursor::DEFAULT)).get();
help = CSDL_Ext::newSurface(40,40); buffer = CSDL_Ext::newSurface(40,40);
//No blending. Ensure, that we are copying pixels during "screen restore draw"
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE); SDL_SetSurfaceBlendMode(buffer, SDL_BLENDMODE_NONE);
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
changeGraphic(ECursor::ADVENTURE, 0); changeGraphic(ECursor::ADVENTURE, 0);
@ -56,11 +79,17 @@ void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
this->frame = index; this->frame = index;
currentCursor->setFrame(index); currentCursor->setFrame(index);
} }
replaceBuffer(currentCursor);
} }
void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object) void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
{ {
dndObject = std::move(object); dndObject = std::move(object);
if(dndObject)
replaceBuffer(dndObject.get());
else
replaceBuffer(currentCursor);
} }
void CCursorHandler::cursorMove(const int & x, const int & y) void CCursorHandler::cursorMove(const int & x, const int & y)
@ -69,40 +98,6 @@ void CCursorHandler::cursorMove(const int & x, const int & y)
ypos = y; ypos = y;
} }
void CCursorHandler::drawWithScreenRestore()
{
if(!showing) return;
int x = xpos, y = ypos;
shiftPos(x, y);
SDL_Rect temp_rect1 = genRect(40,40,x,y);
SDL_Rect temp_rect2 = genRect(40,40,0,0);
SDL_BlitSurface(screen, &temp_rect1, help, &temp_rect2);
if (dndObject)
{
dndObject->moveTo(Point(x - dndObject->pos.w/2, y - dndObject->pos.h/2));
dndObject->showAll(screen);
}
else
{
currentCursor->moveTo(Point(x,y));
currentCursor->showAll(screen);
}
}
void CCursorHandler::drawRestored()
{
if(!showing)
return;
int x = xpos, y = ypos;
shiftPos(x, y);
SDL_Rect temp_rect = genRect(40, 40, x, y);
SDL_BlitSurface(help, nullptr, screen, &temp_rect);
}
void CCursorHandler::shiftPos( int &x, int &y ) void CCursorHandler::shiftPos( int &x, int &y )
{ {
if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK) if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK)
@ -221,15 +216,54 @@ void CCursorHandler::centerCursor()
void CCursorHandler::render() void CCursorHandler::render()
{ {
drawWithScreenRestore(); if(!showing)
CSDL_Ext::update(screen); return;
drawRestored();
//the must update texture in the main (renderer) thread, but changes to cursor type may come from other threads
updateTexture();
int x = xpos;
int y = ypos;
shiftPos(x, y);
if(dndObject)
{
x -= dndObject->pos.w/2;
y -= dndObject->pos.h/2;
}
SDL_Rect destRect;
destRect.x = x;
destRect.y = y;
destRect.w = 40;
destRect.h = 40;
SDL_RenderCopy(mainRenderer, cursorLayer, nullptr, &destRect);
} }
CCursorHandler::CCursorHandler() = default; void CCursorHandler::updateTexture()
{
if(needUpdate)
{
SDL_UpdateTexture(cursorLayer, nullptr, buffer->pixels, buffer->pitch);
needUpdate = false;
}
}
CCursorHandler::CCursorHandler()
: needUpdate(true),
buffer(nullptr),
cursorLayer(nullptr),
showing(false)
{
}
CCursorHandler::~CCursorHandler() CCursorHandler::~CCursorHandler()
{ {
if(help) if(buffer)
SDL_FreeSurface(help); SDL_FreeSurface(buffer);
if(cursorLayer)
SDL_DestroyTexture(cursorLayer);
} }

View File

@ -8,9 +8,10 @@
* *
*/ */
#pragma once #pragma once
class CIntObject;
class CAnimImage; class CAnimImage;
struct SDL_Surface; struct SDL_Surface;
struct SDL_Texture;
namespace ECursor namespace ECursor
{ {
@ -26,7 +27,10 @@ namespace ECursor
/// handles mouse cursor /// handles mouse cursor
class CCursorHandler final class CCursorHandler final
{ {
SDL_Surface * help; bool needUpdate;
SDL_Texture * cursorLayer;
SDL_Surface * buffer;
CAnimImage * currentCursor; CAnimImage * currentCursor;
std::unique_ptr<CAnimImage> dndObject; //if set, overrides currentCursor std::unique_ptr<CAnimImage> dndObject; //if set, overrides currentCursor
@ -35,10 +39,12 @@ class CCursorHandler final
bool showing; bool showing;
/// Draw cursor preserving original image below cursor void clearBuffer();
void drawWithScreenRestore(); void updateBuffer(CIntObject * payload);
/// Restore original image below cursor void replaceBuffer(CIntObject * payload);
void drawRestored(); void shiftPos( int &x, int &y );
void updateTexture();
public: public:
/// position of cursor /// position of cursor
int xpos, ypos; int xpos, ypos;
@ -63,9 +69,8 @@ public:
void render(); void render();
void shiftPos( int &x, int &y ); void hide() { showing=false; };
void hide() { showing=0; }; void show() { showing=true; };
void show() { showing=1; };
/// change cursor's positions to (x, y) /// change cursor's positions to (x, y)
void cursorMove(const int & x, const int & y); void cursorMove(const int & x, const int & y);

View File

@ -96,10 +96,11 @@ void CGuiHandler::handleElementDeActivate(CIntObject * elem, ui16 activityFlag)
elem->active_m &= ~activityFlag; elem->active_m &= ~activityFlag;
} }
void CGuiHandler::popInt(IShowActivatable *top) void CGuiHandler::popInt(std::shared_ptr<IShowActivatable> top)
{ {
assert(listInt.front() == top); assert(listInt.front() == top);
top->deactivate(); top->deactivate();
disposed.push_back(top);
listInt.pop_front(); listInt.pop_front();
objsToBlit -= top; objsToBlit -= top;
if(!listInt.empty()) if(!listInt.empty())
@ -109,18 +110,10 @@ void CGuiHandler::popInt(IShowActivatable *top)
pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED); pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED);
} }
void CGuiHandler::popIntTotally(IShowActivatable *top) void CGuiHandler::pushInt(std::shared_ptr<IShowActivatable> newInt)
{
assert(listInt.front() == top);
popInt(top);
delete top;
fakeMouseMove();
}
void CGuiHandler::pushInt(IShowActivatable *newInt)
{ {
assert(newInt); assert(newInt);
assert(boost::range::find(listInt, newInt) == listInt.end()); // do not add same object twice assert(!vstd::contains(listInt, 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) //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; screenBuf = screen2;
@ -128,6 +121,7 @@ void CGuiHandler::pushInt(IShowActivatable *newInt)
if(!listInt.empty()) if(!listInt.empty())
listInt.front()->deactivate(); listInt.front()->deactivate();
listInt.push_front(newInt); listInt.push_front(newInt);
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
newInt->activate(); newInt->activate();
objsToBlit.push_back(newInt); objsToBlit.push_back(newInt);
totalRedraw(); totalRedraw();
@ -144,7 +138,7 @@ void CGuiHandler::popInts(int howMany)
for(int i=0; i < howMany; i++) for(int i=0; i < howMany; i++)
{ {
objsToBlit -= listInt.front(); objsToBlit -= listInt.front();
delete listInt.front(); disposed.push_back(listInt.front());
listInt.pop_front(); listInt.pop_front();
} }
@ -158,10 +152,10 @@ void CGuiHandler::popInts(int howMany)
pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED); pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED);
} }
IShowActivatable * CGuiHandler::topInt() std::shared_ptr<IShowActivatable> CGuiHandler::topInt()
{ {
if(listInt.empty()) if(listInt.empty())
return nullptr; return std::shared_ptr<IShowActivatable>();
else else
return listInt.front(); return listInt.front();
} }
@ -234,11 +228,11 @@ void CGuiHandler::handleCurrentEvent()
case SDLK_F9: case SDLK_F9:
//not working yet since CClient::run remain locked after CBattleInterface removal //not working yet since CClient::run remain locked after CBattleInterface removal
if(LOCPLINT->battleInt) // if(LOCPLINT->battleInt)
{ // {
GH.popIntTotally(GH.topInt()); // GH.popInts(1);
vstd::clear_pointer(LOCPLINT->battleInt); // vstd::clear_pointer(LOCPLINT->battleInt);
} // }
break; break;
default: default:
@ -271,7 +265,6 @@ void CGuiHandler::handleCurrentEvent()
} }
else if(current->type == SDL_MOUSEMOTION) else if(current->type == SDL_MOUSEMOTION)
{ {
CCS->curh->cursorMove(current->motion.x, current->motion.y);
handleMouseMotion(); handleMouseMotion();
} }
else if(current->type == SDL_MOUSEBUTTONDOWN) else if(current->type == SDL_MOUSEBUTTONDOWN)
@ -457,15 +450,18 @@ void CGuiHandler::renderFrame()
if(nullptr != curInt) if(nullptr != curInt)
curInt->update(); curInt->update();
if (settings["general"]["showfps"].Bool()) if(settings["general"]["showfps"].Bool())
drawFPSCounter(); drawFPSCounter();
// draw the mouse cursor and update the screen SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch);
CCS->curh->render();
SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr); SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
CCS->curh->render();
SDL_RenderPresent(mainRenderer); SDL_RenderPresent(mainRenderer);
disposed.clear();
} }
mainFPSmng->framerateDelay(); // holds a constant FPS mainFPSmng->framerateDelay(); // holds a constant FPS

View File

@ -58,10 +58,12 @@ class CGuiHandler
{ {
public: public:
CFramerateManager * mainFPSmng; //to keep const framerate CFramerateManager * mainFPSmng; //to keep const framerate
std::list<IShowActivatable *> listInt; //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=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
CGStatusBar * statusbar; CGStatusBar * statusbar;
private: private:
std::vector<std::shared_ptr<IShowActivatable>> disposed;
std::atomic<bool> continueEventHandling; std::atomic<bool> continueEventHandling;
typedef std::list<CIntObject*> CIntObjectList; typedef std::list<CIntObject*> CIntObjectList;
@ -86,7 +88,7 @@ public:
public: public:
//objs to blit //objs to blit
std::vector<IShowable*> objsToBlit; std::vector<std::shared_ptr<IShowActivatable>> objsToBlit;
SDL_Event * current; //current event - can be set to nullptr to stop handling event SDL_Event * current; //current event - can be set to nullptr to stop handling event
IUpdateable *curInt; IUpdateable *curInt;
@ -106,11 +108,19 @@ public:
void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering
void popInt(IShowActivatable *top); //removes given interface from the top and activates next void pushInt(std::shared_ptr<IShowActivatable> newInt); //deactivate old top interface, activates this one and pushes to the top
void popIntTotally(IShowActivatable *top); //deactivates, deletes, removes given interface from the top and activates next template <typename T, typename ... Args>
void pushInt(IShowActivatable *newInt); //deactivate old top interface, activates this one and pushes to the top void pushIntT(Args && ... args)
{
auto newInt = std::make_shared<T>(std::forward<Args>(args)...);
pushInt(newInt);
}
void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
IShowActivatable *topInt(); //returns top interface
void popInt(std::shared_ptr<IShowActivatable> top); //removes given interface from the top and activates next
std::shared_ptr<IShowActivatable> topInt(); //returns top interface
void updateTime(); //handles timeInterested void updateTime(); //handles timeInterested
void handleEvents(); //takes events from queue and calls interested objects void handleEvents(); //takes events from queue and calls interested objects

View File

@ -164,11 +164,6 @@ void CIntObject::printAtLoc(const std::string & text, int x, int y, EFonts font,
graphics->fonts[font]->renderTextLeft(dst, text, kolor, Point(pos.x + x, pos.y + y)); graphics->fonts[font]->renderTextLeft(dst, text, kolor, Point(pos.x + x, pos.y + y));
} }
void CIntObject::printAtRightLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst)
{
graphics->fonts[font]->renderTextRight(dst, text, kolor, Point(pos.x + x, pos.y + y));
}
void CIntObject::printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst) void CIntObject::printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst)
{ {
printAtMiddleLoc(text, Point(x,y), font, kolor, dst); printAtMiddleLoc(text, Point(x,y), font, kolor, dst);
@ -194,11 +189,6 @@ void CIntObject::printAtMiddleWBLoc( const std::string & text, int x, int y, EFo
graphics->fonts[font]->renderTextLinesCenter(dst, CMessage::breakText(text, charpr, font), kolor, Point(pos.x + x, pos.y + y)); graphics->fonts[font]->renderTextLinesCenter(dst, CMessage::breakText(text, charpr, font), kolor, Point(pos.x + x, pos.y + y));
} }
void CIntObject::printToLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst )
{
graphics->fonts[font]->renderTextRight(dst, text, kolor, Point(pos.x + x, pos.y + y));
}
void CIntObject::addUsedEvents(ui16 newActions) void CIntObject::addUsedEvents(ui16 newActions)
{ {
if (active_m) if (active_m)
@ -223,7 +213,7 @@ void CIntObject::disable()
void CIntObject::enable() void CIntObject::enable()
{ {
if(!active_m && parent_m->active) if(!active_m && (!parent_m || parent_m->active))
activate(); activate();
recActions = 255; recActions = 255;
@ -302,11 +292,6 @@ void CIntObject::removeChild(CIntObject * child, bool adjustPosition)
child->pos -= pos; child->pos -= pos;
} }
void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color)
{
CSDL_Ext::drawBorder(sur, r + pos, color);
}
void CIntObject::redraw() void CIntObject::redraw()
{ {
//currently most of calls come from active objects so this check won't affect them //currently most of calls come from active objects so this check won't affect them
@ -375,3 +360,16 @@ void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key)
} }
} }
WindowBase::WindowBase(int used_, Point pos_)
: CIntObject(used_, pos_)
{
}
void WindowBase::close()
{
if(GH.topInt().get() != this)
logGlobal->error("Only top interface must be closed");
GH.popInts(1);
}

View File

@ -183,12 +183,9 @@ public:
/* /*
* Functions that should be used only by specific GUI elements. Don't use them unless you really know why they are here * Functions that should be used only by specific GUI elements. Don't use them unless you really know why they are here
*/ */
//wrappers for CSDL_Ext methods. This versions use coordinates relative to pos
void drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color);
//functions for printing text. Use CLabel where possible instead //functions for printing text. Use CLabel where possible instead
void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
void printAtRightLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
void printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color color, SDL_Surface * dst); void printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color color, SDL_Surface * dst);
void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charsPerLine, SDL_Color color, SDL_Surface * dst); void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charsPerLine, SDL_Color color, SDL_Surface * dst);
@ -211,3 +208,11 @@ public:
CKeyShortcut(std::set<int> Keys); CKeyShortcut(std::set<int> Keys);
virtual void keyPressed(const SDL_KeyboardEvent & key) override; //call-in virtual void keyPressed(const SDL_KeyboardEvent & key) override; //call-in
}; };
class WindowBase : public CIntObject
{
public:
WindowBase(int used_ = 0, Point pos_ = Point());
protected:
void close();
};

View File

@ -39,7 +39,7 @@ void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
{ {
SDL_Surface * ret = SDL_CreateRGBSurface(mod->flags,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); SDL_Surface * ret = SDL_CreateRGBSurface(0,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask);
if (mod->format->palette) if (mod->format->palette)
{ {
assert(ret->format->palette); assert(ret->format->palette);
@ -65,7 +65,7 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
Channels::px<bpp>::b.set((Uint8*)&bMask, 255); Channels::px<bpp>::b.set((Uint8*)&bMask, 255);
Channels::px<bpp>::a.set((Uint8*)&aMask, 255); Channels::px<bpp>::a.set((Uint8*)&aMask, 255);
return SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, bpp * 8, rMask, gMask, bMask, aMask); return SDL_CreateRGBSurface(0, width, height, bpp * 8, rMask, gMask, bMask, aMask);
} }
bool isItIn(const SDL_Rect * rect, int x, int y) bool isItIn(const SDL_Rect * rect, int x, int y)

View File

@ -394,14 +394,14 @@ void CBonusSelection::goBack()
} }
else else
{ {
GH.popIntTotally(this); close();
} }
// TODO: we can actually only pop bonus selection interface for custom campaigns // TODO: we can actually only pop bonus selection interface for custom campaigns
// Though this would require clearing CLobbyScreen::bonusSel pointer when poping this interface // Though this would require clearing CLobbyScreen::bonusSel pointer when poping this interface
/* /*
else else
{ {
GH.popIntTotally(this); close();
CSH->state = EClientState::LOBBY; CSH->state = EClientState::LOBBY;
} }
*/ */
@ -420,7 +420,7 @@ void CBonusSelection::startMap()
const CCampaignScenario & scenario = getCampaign()->camp->scenarios[CSH->campaignMap]; const CCampaignScenario & scenario = getCampaign()->camp->scenarios[CSH->campaignMap];
if(scenario.prolog.hasPrologEpilog) if(scenario.prolog.hasPrologEpilog)
{ {
GH.pushInt(new CPrologEpilogVideo(scenario.prolog, exitCb)); GH.pushIntT<CPrologEpilogVideo>(scenario.prolog, exitCb);
} }
else else
{ {
@ -430,7 +430,7 @@ void CBonusSelection::startMap()
if(LOCPLINT) // we're currently ingame, so ask for starting new map and end game if(LOCPLINT) // we're currently ingame, so ask for starting new map and end game
{ {
GH.popInt(this); close();
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]() LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]()
{ {
showPrologVideo(); showPrologVideo();
@ -444,7 +444,7 @@ void CBonusSelection::startMap()
void CBonusSelection::restartMap() void CBonusSelection::restartMap()
{ {
GH.popInt(this); close();
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]() LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [=]()
{ {
CSH->startCampaignScenario(); CSH->startCampaignScenario();

View File

@ -88,7 +88,11 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
buttonStart->assignedKeys.insert(SDLK_RETURN); buttonStart->assignedKeys.insert(SDLK_RETURN);
buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&](){CSH->sendClientDisconnecting(); GH.popIntTotally(this);}, SDLK_ESCAPE); buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&]()
{
CSH->sendClientDisconnecting();
close();
}, SDLK_ESCAPE);
} }
CLobbyScreen::~CLobbyScreen() CLobbyScreen::~CLobbyScreen()
@ -138,7 +142,7 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
} }
catch(ExceptionNoTemplate & e) catch(ExceptionNoTemplate & e)
{ {
GH.pushInt(CInfoWindow::create(CGI->generaltexth->allTexts[751])); CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1));
} }
catch(...) catch(...)
{ {

View File

@ -31,5 +31,5 @@ public:
const CMapInfo * getMapInfo() override; const CMapInfo * getMapInfo() override;
const StartInfo * getStartInfo() override; const StartInfo * getStartInfo() override;
CBonusSelection * bonusSel; std::shared_ptr<CBonusSelection> bonusSel;
}; };

View File

@ -80,7 +80,7 @@ void CSavingScreen::saveGame()
Settings lastSave = settings.write["general"]["lastSave"]; Settings lastSave = settings.write["general"]["lastSave"];
lastSave->String() = path; lastSave->String() = path;
LOCPLINT->cb->save(path); LOCPLINT->cb->save(path);
GH.popIntTotally(this); close();
}; };
if(CResourceHandler::get("local")->existsResource(ResourceID(path, EResType::CLIENT_SAVEGAME))) if(CResourceHandler::get("local")->existsResource(ResourceID(path, EResType::CLIENT_SAVEGAME)))

View File

@ -39,7 +39,7 @@ CScenarioInfoScreen::CScenarioInfoScreen()
card->changeSelection(); card->changeSelection();
card->iconDifficulty->setSelected(getCurrentDifficulty()); card->iconDifficulty->setSelected(getCurrentDifficulty());
buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE);
} }
CScenarioInfoScreen::~CScenarioInfoScreen() CScenarioInfoScreen::~CScenarioInfoScreen()

View File

@ -12,7 +12,7 @@
#include "CSelectionBase.h" #include "CSelectionBase.h"
/// Scenario information screen shown during the game /// Scenario information screen shown during the game
class CScenarioInfoScreen : public CIntObject, public ISelectionScreenInfo class CScenarioInfoScreen : public WindowBase, public ISelectionScreenInfo
{ {
public: public:
std::shared_ptr<CButton> buttonBack; std::shared_ptr<CButton> buttonBack;

View File

@ -86,7 +86,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type)
} }
pos = background->center(); pos = background->center();
card = std::make_shared<InfoCard>(); card = std::make_shared<InfoCard>();
buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, SDLK_ESCAPE);
} }
void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> tab) void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> tab)
@ -367,7 +367,7 @@ void CFlagBox::recreate()
void CFlagBox::clickRight(tribool down, bool previousState) void CFlagBox::clickRight(tribool down, bool previousState)
{ {
if(down && SEL->getMapInfo()) if(down && SEL->getMapInfo())
GH.pushInt(new CFlagBoxTooltipBox(iconsTeamFlags)); GH.pushIntT<CFlagBoxTooltipBox>(iconsTeamFlags);
} }
CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr<CAnimation> icons) CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr<CAnimation> icons)

View File

@ -422,7 +422,7 @@ void OptionsTab::SelectedBox::clickRight(tribool down, bool previousState)
if(settings.hero == -2 && !SEL->getPlayerInfo(settings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO) if(settings.hero == -2 && !SEL->getPlayerInfo(settings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO)
return; return;
GH.pushInt(new CPlayerOptionTooltipBox(*this)); GH.pushIntT<CPlayerOptionTooltipBox>(*this);
} }
} }

View File

@ -79,8 +79,7 @@ std::shared_ptr<CButton> CCampaignScreen::createExitButton(const JsonNode & butt
if(!button["help"].isNull() && button["help"].Float() > 0) if(!button["help"].isNull() && button["help"].Float() > 0)
help = CGI->generaltexth->zelp[button["help"].Float()]; help = CGI->generaltexth->zelp[button["help"].Float()];
std::function<void()> close = std::bind(&CGuiHandler::popIntTotally, &GH, this); return std::make_shared<CButton>(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, [=](){ close();}, button["hotkey"].Float());
return std::make_shared<CButton>(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, close, button["hotkey"].Float());
} }
CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config) CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config)

View File

@ -60,7 +60,7 @@
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
CMainMenu * CMM = nullptr; std::shared_ptr<CMainMenu> CMM;
ISelectionScreenInfo * SEL; ISelectionScreenInfo * SEL;
static void do_quit() static void do_quit()
@ -176,7 +176,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
case 0: case 0:
return std::bind(CMainMenu::openLobby, ESelectionScreen::newGame, true, nullptr, ELoadMode::NONE); return std::bind(CMainMenu::openLobby, ESelectionScreen::newGame, true, nullptr, ELoadMode::NONE);
case 1: case 1:
return []() { GH.pushInt(new CMultiMode(ESelectionScreen::newGame)); }; return []() { GH.pushIntT<CMultiMode>(ESelectionScreen::newGame); };
case 2: case 2:
return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE); return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE);
case 3: case 3:
@ -191,7 +191,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
case 0: case 0:
return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::SINGLE); return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::SINGLE);
case 1: case 1:
return []() { GH.pushInt(new CMultiMode(ESelectionScreen::loadGame)); }; return []() { GH.pushIntT<CMultiMode>(ESelectionScreen::loadGame); };
case 2: case 2:
return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::CAMPAIGN); return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::CAMPAIGN);
case 3: case 3:
@ -279,8 +279,7 @@ CMainMenu::CMainMenu()
pos.h = screen->h; pos.h = screen->h;
GH.defActionsDef = 63; GH.defActionsDef = 63;
CMM = this; menu = std::make_shared<CMenuScreen>(CMainMenuConfig::get().getConfig()["window"]);
menu = new CMenuScreen(CMainMenuConfig::get().getConfig()["window"]);
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
backgroundAroundMenu = std::make_shared<CFilledTexture>("DIBOXBCK", pos); backgroundAroundMenu = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
} }
@ -288,8 +287,6 @@ CMainMenu::CMainMenu()
CMainMenu::~CMainMenu() CMainMenu::~CMainMenu()
{ {
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim); boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
if(CMM == this)
CMM = nullptr;
if(GH.curInt == this) if(GH.curInt == this)
GH.curInt = nullptr; GH.curInt = nullptr;
@ -297,12 +294,12 @@ CMainMenu::~CMainMenu()
void CMainMenu::update() void CMainMenu::update()
{ {
if(CMM != this) //don't update if you are not a main interface if(CMM != this->shared_from_this()) //don't update if you are not a main interface
return; return;
if(GH.listInt.empty()) if(GH.listInt.empty())
{ {
GH.pushInt(this); GH.pushInt(CMM);
GH.pushInt(menu); GH.pushInt(menu);
menu->switchToTab(0); menu->switchToTab(0);
} }
@ -313,7 +310,7 @@ void CMainMenu::update()
// check for null othervice crash on finishing a campaign // check for null othervice crash on finishing a campaign
// /FIXME: find out why GH.listInt is empty to begin with // /FIXME: find out why GH.listInt is empty to begin with
if(GH.topInt() != nullptr) if(GH.topInt())
GH.topInt()->show(screen); GH.topInt()->show(screen);
} }
@ -323,7 +320,7 @@ void CMainMenu::openLobby(ESelectionScreen screenType, bool host, const std::vec
CSH->screenType = screenType; CSH->screenType = screenType;
CSH->loadMode = loadMode; CSH->loadMode = loadMode;
GH.pushInt(new CSimpleJoinScreen(host)); GH.pushIntT<CSimpleJoinScreen>(host);
} }
void CMainMenu::openCampaignLobby(const std::string & campaignFileName) void CMainMenu::openCampaignLobby(const std::string & campaignFileName)
@ -337,23 +334,23 @@ void CMainMenu::openCampaignLobby(std::shared_ptr<CCampaignState> campaign)
CSH->resetStateForLobby(StartInfo::CAMPAIGN); CSH->resetStateForLobby(StartInfo::CAMPAIGN);
CSH->screenType = ESelectionScreen::campaignList; CSH->screenType = ESelectionScreen::campaignList;
CSH->campaignStateToSend = campaign; CSH->campaignStateToSend = campaign;
GH.pushInt(new CSimpleJoinScreen()); GH.pushIntT<CSimpleJoinScreen>();
} }
void CMainMenu::openCampaignScreen(std::string name) void CMainMenu::openCampaignScreen(std::string name)
{ {
if(vstd::contains(CMainMenuConfig::get().getCampaigns().Struct(), name)) if(vstd::contains(CMainMenuConfig::get().getCampaigns().Struct(), name))
{ {
GH.pushInt(new CCampaignScreen(CMainMenuConfig::get().getCampaigns()[name])); GH.pushIntT<CCampaignScreen>(CMainMenuConfig::get().getCampaigns()[name]);
return; return;
} }
logGlobal->error("Unknown campaign set: %s", name); logGlobal->error("Unknown campaign set: %s", name);
} }
CMainMenu * CMainMenu::create() std::shared_ptr<CMainMenu> CMainMenu::create()
{ {
if(!CMM) if(!CMM)
CMM = new CMainMenu(); CMM = std::shared_ptr<CMainMenu>(new CMainMenu());
GH.terminate_cond->set(false); GH.terminate_cond->set(false);
return CMM; return CMM;
@ -381,19 +378,21 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
buttonHotseat = std::make_shared<CButton>(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this)); buttonHotseat = std::make_shared<CButton>(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), std::bind(&CMultiMode::hostTCP, this)); buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), std::bind(&CMultiMode::hostTCP, this));
buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), std::bind(&CMultiMode::joinTCP, this)); buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), std::bind(&CMultiMode::joinTCP, this));
buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [&]() { GH.popIntTotally(this);}, SDLK_ESCAPE); buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [=](){ close();}, SDLK_ESCAPE);
} }
void CMultiMode::hostTCP() void CMultiMode::hostTCP()
{ {
GH.popIntTotally(this); auto savedScreenType = screenType;
GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, true, ELoadMode::MULTI)); close();
GH.pushIntT<CMultiPlayers>(settings["general"]["playerName"].String(), savedScreenType, true, ELoadMode::MULTI);
} }
void CMultiMode::joinTCP() void CMultiMode::joinTCP()
{ {
GH.popIntTotally(this); auto savedScreenType = screenType;
GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, false, ELoadMode::MULTI)); close();
GH.pushIntT<CMultiPlayers>(settings["general"]["playerName"].String(), savedScreenType, false, ELoadMode::MULTI);
} }
void CMultiMode::onNameChange(std::string newText) void CMultiMode::onNameChange(std::string newText)
@ -420,7 +419,7 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S
} }
buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN); buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN);
buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, std::ref(GH), this), SDLK_ESCAPE); buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, SDLK_ESCAPE);
statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(Rect(7, 381, 348, 18), 0)); //226, 472 statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(Rect(7, 381, 348, 18), 0)); //226, 472
inputNames[0]->setText(firstPlayer, true); inputNames[0]->setText(firstPlayer, true);
@ -497,9 +496,9 @@ void CSimpleJoinScreen::leaveScreen()
textTitle->setText("Closing..."); textTitle->setText("Closing...");
CSH->state = EClientState::CONNECTION_CANCELLED; CSH->state = EClientState::CONNECTION_CANCELLED;
} }
else if(GH.listInt.size() && GH.listInt.front() == this) else if(GH.listInt.size() && GH.listInt.front().get() == this)
{ {
GH.popIntTotally(this); close();
} }
} }
@ -516,9 +515,9 @@ void CSimpleJoinScreen::connectThread(const std::string addr, const ui16 port)
else else
CSH->justConnectToServer(addr, port); CSH->justConnectToServer(addr, port);
if(GH.listInt.size() && GH.listInt.front() == this) if(GH.listInt.size() && GH.listInt.front().get() == this)
{ {
GH.popIntTotally(this); close();
} }
} }

View File

@ -69,7 +69,7 @@ public:
}; };
/// Multiplayer mode /// Multiplayer mode
class CMultiMode : public CIntObject class CMultiMode : public WindowBase
{ {
public: public:
ESelectionScreen screenType; ESelectionScreen screenType;
@ -89,7 +89,7 @@ public:
}; };
/// Hot seat player window /// Hot seat player window
class CMultiPlayers : public CIntObject class CMultiPlayers : public WindowBase
{ {
bool host; bool host;
ELoadMode loadMode; ELoadMode loadMode;
@ -124,14 +124,14 @@ private:
}; };
/// Handles background screen, loads graphics for victory/loss condition and random town or hero selection /// Handles background screen, loads graphics for victory/loss condition and random town or hero selection
class CMainMenu : public CIntObject, public IUpdateable class CMainMenu : public CIntObject, public IUpdateable, public std::enable_shared_from_this<CMainMenu>
{ {
std::shared_ptr<CFilledTexture> backgroundAroundMenu; std::shared_ptr<CFilledTexture> backgroundAroundMenu;
CMainMenu(); //Use CMainMenu::create CMainMenu(); //Use CMainMenu::create
public: public:
CMenuScreen * menu; std::shared_ptr<CMenuScreen> menu;
~CMainMenu(); ~CMainMenu();
void update() override; void update() override;
@ -140,14 +140,14 @@ public:
static void openCampaignLobby(std::shared_ptr<CCampaignState> campaign); static void openCampaignLobby(std::shared_ptr<CCampaignState> campaign);
void openCampaignScreen(std::string name); void openCampaignScreen(std::string name);
static CMainMenu * create(); static std::shared_ptr<CMainMenu> create();
static std::shared_ptr<CPicture> createPicture(const JsonNode & config); static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
}; };
/// Simple window to enter the server's address. /// Simple window to enter the server's address.
class CSimpleJoinScreen : public CIntObject class CSimpleJoinScreen : public WindowBase
{ {
std::shared_ptr<CPicture> background; std::shared_ptr<CPicture> background;
std::shared_ptr<CTextBox> textTitle; std::shared_ptr<CTextBox> textTitle;
@ -179,4 +179,4 @@ public:
void showAll(SDL_Surface * to) override; void showAll(SDL_Surface * to) override;
}; };
extern CMainMenu * CMM; extern std::shared_ptr<CMainMenu> CMM;

View File

@ -58,7 +58,7 @@ void CPrologEpilogVideo::show(SDL_Surface * to)
void CPrologEpilogVideo::clickLeft(tribool down, bool previousState) void CPrologEpilogVideo::clickLeft(tribool down, bool previousState)
{ {
GH.popInt(this); close();
CCS->soundh->stopSound(voiceSoundHandle); CCS->soundh->stopSound(voiceSoundHandle);
exitCb(); exitCb();
} }

View File

@ -1250,21 +1250,16 @@ void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color) CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
: CAdvMapPanel(bg, position), icons(_icons) : CAdvMapPanel(bg, position), icons(_icons)
{ {
fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0; OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
int fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
if (fillerHeight > 0) if(fillerHeight > 0)
{ {
tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color); backgroundFiller = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, pos.h, pos.w, fillerHeight));
} }
else
tmpBackgroundFiller = nullptr;
} }
CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default;
{
if (tmpBackgroundFiller)
SDL_FreeSurface(tmpBackgroundFiller);
}
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset) void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
{ {
@ -1275,13 +1270,6 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOff
const auto & data = iconsData.at(idx); const auto & data = iconsData.at(idx);
currentIcons[idx]->setFrame(data.first + indexOffset); currentIcons[idx]->setFrame(data.first + indexOffset);
} }
if(fillerHeight > 0)
{
if(tmpBackgroundFiller)
SDL_FreeSurface(tmpBackgroundFiller);
tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color);
}
} }
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset) void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
@ -1290,13 +1278,3 @@ void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOf
iconsData.push_back(data); iconsData.push_back(data);
currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y)); currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
} }
void CAdvMapWorldViewPanel::showAll(SDL_Surface * to)
{
if (tmpBackgroundFiller)
{
blitAt(tmpBackgroundFiller, pos.x, pos.y + pos.h, to);
}
CAdvMapPanel::showAll(to);
}

View File

@ -16,6 +16,7 @@ class CArmedInstance;
class CAnimation; class CAnimation;
class CAnimImage; class CAnimImage;
class CShowableAnim; class CShowableAnim;
class CFilledTexture;
class CGGarrison; class CGGarrison;
class CGObjectInstance; class CGObjectInstance;
class CGHeroInstance; class CGHeroInstance;
@ -384,9 +385,8 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
std::vector<std::pair<int, Point>> iconsData; std::vector<std::pair<int, Point>> iconsData;
/// ptrs to child-pictures constructed from iconsData /// ptrs to child-pictures constructed from iconsData
std::vector<std::shared_ptr<CAnimImage>> currentIcons; std::vector<std::shared_ptr<CAnimImage>> currentIcons;
/// temporary surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod) /// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
SDL_Surface * tmpBackgroundFiller; std::shared_ptr<CFilledTexture> backgroundFiller;
int fillerHeight;
std::shared_ptr<CAnimation> icons; std::shared_ptr<CAnimation> icons;
public: public:
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color); CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
@ -395,7 +395,6 @@ public:
void addChildIcon(std::pair<int, Point> data, int indexOffset); void addChildIcon(std::pair<int, Point> data, int indexOffset);
/// recreates all pictures from given def to recolor them according to current player color /// recreates all pictures from given def to recolor them according to current player color
void recolorIcons(const PlayerColor & color, int indexOffset); void recolorIcons(const PlayerColor & color, int indexOffset);
void showAll(SDL_Surface * to) override;
}; };
class CInGameConsole : public CIntObject class CInGameConsole : public CIntObject

View File

@ -126,7 +126,7 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState)
if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH) if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH)
{ {
if(ourArt->artType->id == ArtifactID::SPELLBOOK) if(ourArt->artType->id == ArtifactID::SPELLBOOK)
GH.pushInt(new CSpellWindow(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt)); GH.pushIntT<CSpellWindow>(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt);
} }
if (!down && previousState) if (!down && previousState)
@ -678,14 +678,14 @@ CArtifactsOfHero::~CArtifactsOfHero()
void CArtifactsOfHero::updateParentWindow() void CArtifactsOfHero::updateParentWindow()
{ {
if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt())) if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt().get()))
{ {
if(updateState) if(updateState)
chw->curHero = curHero; chw->curHero = curHero;
else else
chw->update(curHero, true); chw->update(curHero, true);
} }
else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt())) else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt().get()))
{ {
//use our copy of hero to draw window //use our copy of hero to draw window
if(cew->heroInst[0]->id == curHero->id) if(cew->heroInst[0]->id == curHero->id)

View File

@ -161,7 +161,7 @@ bool CGarrisonSlot::viewInfo()
elem->block(true); elem->block(true);
redraw(); redraw();
GH.pushInt(new CStackWindow(myStack, dism, pom, upgr)); GH.pushIntT<CStackWindow>(myStack, dism, pom, upgr);
return true; return true;
} }
@ -170,7 +170,7 @@ bool CGarrisonSlot::viewInfo()
bool CGarrisonSlot::highlightOrDropArtifact() bool CGarrisonSlot::highlightOrDropArtifact()
{ {
bool artSelected = false; bool artSelected = false;
if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt())) //dirty solution if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt().get())) //dirty solution
{ {
const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = chw->getCommonPart(); const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = chw->getCommonPart();
const CArtifactInstance * art = nullptr; const CArtifactInstance * art = nullptr;
@ -241,8 +241,8 @@ bool CGarrisonSlot::split()
int countLeft = selection->myStack ? selection->myStack->count : 0; int countLeft = selection->myStack ? selection->myStack->count : 0;
int countRight = myStack ? myStack->count : 0; int countRight = myStack ? myStack->count : 0;
GH.pushInt(new CSplitWindow(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2), GH.pushIntT<CSplitWindow>(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2),
minLeft, minRight, countLeft, countRight)); minLeft, minRight, countLeft, countRight);
return true; return true;
} }
@ -278,7 +278,7 @@ void CGarrisonSlot::clickRight(tribool down, bool previousState)
{ {
if(creature && down) if(creature && down)
{ {
GH.pushInt(new CStackWindow(myStack, true)); GH.pushIntT<CStackWindow>(myStack, true);
} }
} }

View File

@ -173,7 +173,7 @@ void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
if(screenFormat) if(screenFormat)
bg = CSDL_Ext::newSurface(r.w, r.h); bg = CSDL_Ext::newSurface(r.w, r.h);
else else
bg = SDL_CreateRGBSurface(SDL_SWSURFACE, r.w, r.h, 8, 0, 0, 0, 0); bg = SDL_CreateRGBSurface(0, r.w, r.h, 8, 0, 0, 0, 0);
SDL_FillRect(bg, nullptr, color); SDL_FillRect(bg, nullptr, color);
freeSurf = true; freeSurf = true;
@ -296,7 +296,7 @@ void CAnimImage::playerColored(PlayerColor currPlayer)
} }
CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Delay, size_t Group): CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Delay, size_t Group):
anim(new CAnimation(name, Flags & USE_RLE)), anim(std::make_shared<CAnimation>(name)),
group(Group), group(Group),
frame(0), frame(0),
first(0), first(0),
@ -319,7 +319,6 @@ CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Del
CShowableAnim::~CShowableAnim() CShowableAnim::~CShowableAnim()
{ {
anim->unloadGroup(group); anim->unloadGroup(group);
delete anim;
} }
void CShowableAnim::setAlpha(ui32 alphaValue) void CShowableAnim::setAlpha(ui32 alphaValue)
@ -410,8 +409,8 @@ void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
assert(to); assert(to);
Rect src( xOffset, yOffset, pos.w, pos.h); Rect src( xOffset, yOffset, pos.w, pos.h);
auto img = anim->getImage(frame, group); auto img = anim->getImage(frame, group);
if (img) if(img)
img->draw(to, pos.x-xOffset, pos.y-yOffset, &src, alpha); img->draw(to, pos.x, pos.y, &src, alpha);
} }
void CShowableAnim::rotate(bool on, bool vertical) void CShowableAnim::rotate(bool on, bool vertical)
@ -423,15 +422,11 @@ void CShowableAnim::rotate(bool on, bool vertical)
flags &= ~flag; flags &= ~flag;
} }
CCreatureAnim::CCreatureAnim(int x, int y, std::string name, Rect picPos, ui8 flags, EAnimType type): CCreatureAnim::CCreatureAnim(int x, int y, std::string name, ui8 flags, EAnimType type):
CShowableAnim(x,y,name,flags,4,type) CShowableAnim(x,y,name,flags,4,type)
{ {
xOffset = picPos.x; xOffset = 0;
yOffset = picPos.y; yOffset = 0;
if (picPos.w)
pos.w = picPos.w;
if (picPos.h)
pos.h = picPos.h;
} }
void CCreatureAnim::loopPreview(bool warMachine) void CCreatureAnim::loopPreview(bool warMachine)

View File

@ -105,12 +105,11 @@ public:
BASE=1, //base frame will be blitted before current one BASE=1, //base frame will be blitted before current one
HORIZONTAL_FLIP=2, //TODO: will be displayed rotated HORIZONTAL_FLIP=2, //TODO: will be displayed rotated
VERTICAL_FLIP=4, //TODO: will be displayed rotated VERTICAL_FLIP=4, //TODO: will be displayed rotated
USE_RLE=8, //RLE-d version, support full alpha-channel for 8-bit images
PLAYER_COLORED=16, //TODO: all loaded images will be player-colored PLAYER_COLORED=16, //TODO: all loaded images will be player-colored
PLAY_ONCE=32 //play animation only once and stop at last frame PLAY_ONCE=32 //play animation only once and stop at last frame
}; };
protected: protected:
CAnimation * anim; std::shared_ptr<CAnimation> anim;
size_t group, frame;//current frame size_t group, frame;//current frame
@ -227,7 +226,6 @@ public:
//clear queue and set animation to this sequence //clear queue and set animation to this sequence
void clearAndSet(EAnimType type); void clearAndSet(EAnimType type);
CCreatureAnim(int x, int y, std::string name, Rect picPos, CCreatureAnim(int x, int y, std::string name, ui8 flags = 0, EAnimType = HOLDING);
ui8 flags= USE_RLE, EAnimType = HOLDING );
}; };

View File

@ -457,7 +457,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A
bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg130); bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg130);
else else
bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg120); bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg120);
anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName, Rect()); anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName);
anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON));

View File

@ -59,7 +59,7 @@
#define ADVOPT (conf.go()->ac) #define ADVOPT (conf.go()->ac)
using namespace CSDL_Ext; using namespace CSDL_Ext;
CAdvMapInt *adventureInt; std::shared_ptr<CAdvMapInt> adventureInt;
static void setScrollingCursor(ui8 direction) static void setScrollingCursor(ui8 direction)
{ {
@ -565,7 +565,6 @@ CAdvMapInt::CAdvMapInt():
swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false), swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false),
swipeTargetPosition(int3(-1, -1, -1)) swipeTargetPosition(int3(-1, -1, -1))
{ {
adventureInt = this;
pos.x = pos.y = 0; pos.x = pos.y = 0;
pos.w = screen->w; pos.w = screen->w;
pos.h = screen->h; pos.h = screen->h;
@ -723,7 +722,7 @@ CAdvMapInt::~CAdvMapInt()
void CAdvMapInt::fshowOverview() void CAdvMapInt::fshowOverview()
{ {
GH.pushInt(new CKingdomInterface()); GH.pushIntT<CKingdomInterface>();
} }
void CAdvMapInt::fworldViewBack() void CAdvMapInt::fworldViewBack()
@ -811,17 +810,17 @@ void CAdvMapInt::fshowSpellbok()
centerOn(selection); centerOn(selection);
GH.pushInt(new CSpellWindow(curHero(), LOCPLINT, false)); GH.pushIntT<CSpellWindow>(curHero(), LOCPLINT, false);
} }
void CAdvMapInt::fadventureOPtions() void CAdvMapInt::fadventureOPtions()
{ {
GH.pushInt(new CAdventureOptions()); GH.pushIntT<CAdventureOptions>();
} }
void CAdvMapInt::fsystemOptions() void CAdvMapInt::fsystemOptions()
{ {
GH.pushInt(new CSystemOptionsWindow()); GH.pushIntT<CSystemOptionsWindow>();
} }
void CAdvMapInt::fnextHero() void CAdvMapInt::fnextHero()
@ -1088,7 +1087,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
int scrollSpeed = settings["adventure"]["scrollSpeed"].Float(); int scrollSpeed = settings["adventure"]["scrollSpeed"].Float();
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed) //if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if((animValHitCount % (4 / scrollSpeed)) == 0 if((animValHitCount % (4 / scrollSpeed)) == 0
&& ((GH.topInt() == this) || isCtrlKeyDown())) && ((GH.topInt().get() == this) || isCtrlKeyDown()))
{ {
if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW)) if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
position.x--; position.x--;
@ -1224,7 +1223,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
return; return;
case SDLK_s: case SDLK_s:
if(isActive() && key.type == SDL_KEYUP) if(isActive() && key.type == SDL_KEYUP)
GH.pushInt(new CSavingScreen()); GH.pushIntT<CSavingScreen>();
return; return;
case SDLK_d: case SDLK_d:
{ {
@ -1274,7 +1273,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
} }
case SDLK_ESCAPE: case SDLK_ESCAPE:
{ {
if(isActive() || GH.topInt() != this || !spellBeingCasted || key.state != SDL_PRESSED) if(isActive() || GH.topInt().get() != this || !spellBeingCasted || key.state != SDL_PRESSED)
return; return;
leaveCastingMode(); leaveCastingMode();
@ -1300,7 +1299,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
} }
if(townWithMarket) //if any town has marketplace, open window if(townWithMarket) //if any town has marketplace, open window
GH.pushInt(new CMarketplaceWindow(townWithMarket)); GH.pushIntT<CMarketplaceWindow>(townWithMarket);
else //if not - complain else //if not - complain
LOCPLINT->showInfoDialog("No available marketplace!"); LOCPLINT->showInfoDialog("No available marketplace!");
} }
@ -1957,11 +1956,11 @@ void CAdventureOptions::showScenarioInfo()
{ {
if(LOCPLINT->cb->getStartInfo()->campState) if(LOCPLINT->cb->getStartInfo()->campState)
{ {
GH.pushInt(new CBonusSelection()); GH.pushIntT<CBonusSelection>();
} }
else else
{ {
GH.pushInt(new CScenarioInfoScreen()); GH.pushIntT<CScenarioInfoScreen>();
} }
} }

View File

@ -266,4 +266,4 @@ public:
}; };
extern CAdvMapInt *adventureInt; extern std::shared_ptr<CAdvMapInt> adventureInt;

View File

@ -41,13 +41,12 @@
#include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGTownInstance.h"
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town, const CStructure * Str) CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town, const CStructure * Str)
: CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE), : CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE),
parent(Par), parent(Par),
town(Town), town(Town),
str(Str), str(Str),
stateCounter(80) stateCounter(80)
{ {
recActions = ACTIVATE | DEACTIVATE | DISPOSE | SHARE_POS;
addUsedEvents(LCLICK | RCLICK | HOVER); addUsedEvents(LCLICK | RCLICK | HOVER);
pos.x += str->pos.x; pos.x += str->pos.x;
pos.y += str->pos.y; pos.y += str->pos.y;
@ -131,7 +130,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
else else
{ {
int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN; int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN;
GH.pushInt(new CDwellingInfoBox(parent->pos.x+parent->pos.w/2, parent->pos.y+parent->pos.h/2, town, level)); GH.pushIntT<CDwellingInfoBox>(parent->pos.x+parent->pos.w/2, parent->pos.y+parent->pos.h/2, town, level);
} }
} }
} }
@ -421,7 +420,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState)
{ {
setHighlight(true); setHighlight(true);
owner->garr->selectSlot(nullptr); owner->garr->selectSlot(nullptr);
showAll(screen2); redraw();
} }
//refresh statusbar //refresh statusbar
@ -434,7 +433,7 @@ void CHeroGSlot::clickRight(tribool down, bool previousState)
{ {
if(hero && down) if(hero && down)
{ {
GH.pushInt(new CInfoBoxPopup(Point(pos.x + 175, pos.y + 100), hero)); GH.pushIntT<CInfoBoxPopup>(Point(pos.x + 175, pos.y + 100), hero);
} }
} }
@ -522,17 +521,26 @@ void HeroSlots::swapArmies()
} }
template <class T>
class SORTHELP class SORTHELP
{ {
public: public:
bool operator() (const std::shared_ptr<T> a, const std::shared_ptr<T> b) bool operator() (const CIntObject * a, const CIntObject * b)
{ {
return (*a)<(*b); auto b1 = dynamic_cast<const CBuildingRect *>(a);
auto b2 = dynamic_cast<const CBuildingRect *>(b);
if(!b1 && !b2)
return intptr_t(a) < intptr_t(b);
if(b1 && !b2)
return false;
if(!b1 && b2)
return true;
return (*b1)<(*b2);
} }
}; };
SORTHELP<CBuildingRect> buildSorter; SORTHELP buildSorter;
CCastleBuildings::CCastleBuildings(const CGTownInstance* Town): CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
town(Town), town(Town),
@ -552,8 +560,7 @@ CCastleBuildings::~CCastleBuildings() = default;
void CCastleBuildings::recreate() void CCastleBuildings::recreate()
{ {
selectedBuilding = nullptr; selectedBuilding = nullptr;
//TODO: remove show[all] method and try UPDATE+SHOWALL OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(ACTIVATE+SHARE_POS);
buildings.clear(); buildings.clear();
groups.clear(); groups.clear();
@ -600,7 +607,8 @@ void CCastleBuildings::recreate()
buildings.push_back(std::make_shared<CBuildingRect>(this, town, toAdd)); buildings.push_back(std::make_shared<CBuildingRect>(this, town, toAdd));
} }
boost::sort(buildings, buildSorter);
boost::sort(children, buildSorter); //TODO: create building in blit order
} }
void CCastleBuildings::addBuilding(BuildingID building) void CCastleBuildings::addBuilding(BuildingID building)
@ -632,20 +640,6 @@ void CCastleBuildings::removeBuilding(BuildingID building)
recreate(); recreate();
} }
void CCastleBuildings::show(SDL_Surface * to)
{
CIntObject::show(to);
for(auto str : buildings)
str->show(to);
}
void CCastleBuildings::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
for(auto str : buildings)
str->showAll(to);
}
const CGHeroInstance * CCastleBuildings::getHero() const CGHeroInstance * CCastleBuildings::getHero()
{ {
if(town->visitingHero) if(town->visitingHero)
@ -689,7 +683,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case BuildingID::FORT: case BuildingID::FORT:
case BuildingID::CITADEL: case BuildingID::CITADEL:
case BuildingID::CASTLE: case BuildingID::CASTLE:
GH.pushInt(new CFortScreen(town)); GH.pushIntT<CFortScreen>(town);
break; break;
case BuildingID::VILLAGE_HALL: case BuildingID::VILLAGE_HALL:
@ -700,7 +694,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
break; break;
case BuildingID::MARKETPLACE: case BuildingID::MARKETPLACE:
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero)); GH.pushIntT<CMarketplaceWindow>(town, town->visitingHero);
break; break;
case BuildingID::BLACKSMITH: case BuildingID::BLACKSMITH:
@ -718,7 +712,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case ETownType::DUNGEON://Artifact Merchant case ETownType::DUNGEON://Artifact Merchant
case ETownType::CONFLUX: case ETownType::CONFLUX:
if(town->visitingHero) if(town->visitingHero)
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT)); GH.pushIntT<CMarketplaceWindow>(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT);
else else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s. LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
break; break;
@ -742,14 +736,14 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case ETownType::STRONGHOLD: //Freelancer's Guild case ETownType::STRONGHOLD: //Freelancer's Guild
if(getHero()) if(getHero())
GH.pushInt(new CMarketplaceWindow(town, getHero(), EMarketMode::CREATURE_RESOURCE)); GH.pushIntT<CMarketplaceWindow>(town, getHero(), EMarketMode::CREATURE_RESOURCE);
else else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s. LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
break; break;
case ETownType::CONFLUX: //Magic University case ETownType::CONFLUX: //Magic University
if (getHero()) if (getHero())
GH.pushInt(new CUniversityWindow(getHero(), town)); GH.pushIntT<CUniversityWindow>(getHero(), town);
else else
enterBuilding(building); enterBuilding(building);
break; break;
@ -772,7 +766,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
break; break;
case ETownType::NECROPOLIS: //Skeleton Transformer case ETownType::NECROPOLIS: //Skeleton Transformer
GH.pushInt( new CTransformerWindow(getHero(), town) ); GH.pushIntT<CTransformerWindow>(getHero(), town);
break; break;
case ETownType::DUNGEON: //Portal of Summoning case ETownType::DUNGEON: //Portal of Summoning
@ -810,7 +804,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
int price = CGI->arth->artifacts[artifactID]->price; int price = CGI->arth->artifacts[artifactID]->price;
bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price && !hero->hasArt(artifactID); bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price && !hero->hasArt(artifactID);
CreatureID cre = artifactID.toArtifact()->warMachine; CreatureID cre = artifactID.toArtifact()->warMachine;
GH.pushInt(new CBlacksmithDialog(possible, cre, artifactID, hero->id)); GH.pushIntT<CBlacksmithDialog>(possible, cre, artifactID, hero->id);
} }
void CCastleBuildings::enterBuilding(BuildingID building) void CCastleBuildings::enterBuilding(BuildingID building)
@ -838,20 +832,20 @@ void CCastleBuildings::enterCastleGate()
} }
} }
auto gateIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window auto gateIcon = std::make_shared<CAnimImage>(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window
GH.pushInt(new CObjectListWindow(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], GH.pushIntT<CObjectListWindow>(availableTowns, gateIcon, CGI->generaltexth->jktexts[40],
CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1))); CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1));
} }
void CCastleBuildings::enterDwelling(int level) void CCastleBuildings::enterDwelling(int level)
{ {
assert(level >= 0 && level < town->creatures.size()); assert(level >= 0 && level < town->creatures.size());
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); }; auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); };
GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, -87)); GH.pushIntT<CRecruitmentWindow>(town, level, town, recruitCb, -87);
} }
void CCastleBuildings::enterToTheQuickRecruitmentWindow() void CCastleBuildings::enterToTheQuickRecruitmentWindow()
{ {
GH.pushInt(new QuickRecruitmentWindow(town, pos)); GH.pushIntT<QuickRecruitmentWindow>(town, pos);
} }
void CCastleBuildings::enterFountain(BuildingID building) void CCastleBuildings::enterFountain(BuildingID building)
@ -915,7 +909,7 @@ void CCastleBuildings::enterTownHall()
else else
{ {
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]); LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]);
dynamic_cast<CInfoWindow*>(GH.topInt())->buttons[0]->addCallback(std::bind(&CCastleBuildings::openTownHall, this)); dynamic_cast<CInfoWindow*>(GH.topInt().get())->buttons[0]->addCallback(std::bind(&CCastleBuildings::openTownHall, this));
} }
} }
else else
@ -928,12 +922,12 @@ void CCastleBuildings::openMagesGuild()
{ {
std::string mageGuildBackground; std::string mageGuildBackground;
mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground; mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground;
GH.pushInt(new CMageGuildScreen(LOCPLINT->castleInt,mageGuildBackground)); GH.pushIntT<CMageGuildScreen>(LOCPLINT->castleInt,mageGuildBackground);
} }
void CCastleBuildings::openTownHall() void CCastleBuildings::openTownHall()
{ {
GH.pushInt(new CHallInterface(town)); GH.pushIntT<CHallInterface>(town);
} }
CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact, bool ShowAvailable): CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact, bool ShowAvailable):
@ -1016,7 +1010,7 @@ void CCreaInfo::clickLeft(tribool down, bool previousState)
{ {
LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level);
}; };
GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, offset)); GH.pushIntT<CRecruitmentWindow>(town, level, town, recruitCb, offset);
} }
} }
@ -1036,7 +1030,7 @@ void CCreaInfo::clickRight(tribool down, bool previousState)
if(down) if(down)
{ {
if (showAvailable) if (showAvailable)
GH.pushInt(new CDwellingInfoBox(screen->w/2, screen->h/2, town, level)); GH.pushIntT<CDwellingInfoBox>(screen->w/2, screen->h/2, town, level);
else else
CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->idNumber)); CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->idNumber));
} }
@ -1141,7 +1135,8 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
CCastleInterface::~CCastleInterface() CCastleInterface::~CCastleInterface()
{ {
LOCPLINT->castleInt = nullptr; if(LOCPLINT->castleInt == this)
LOCPLINT->castleInt = nullptr;
} }
void CCastleInterface::updateGarrisons() void CCastleInterface::updateGarrisons()
@ -1170,12 +1165,13 @@ void CCastleInterface::castleTeleport(int where)
void CCastleInterface::townChange() void CCastleInterface::townChange()
{ {
//TODO: do not recreate window
const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()]; const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()];
const CGTownInstance * town = this->town;// "this" is going to be deleted const CGTownInstance * town = this->town;// "this" is going to be deleted
if ( dest == town ) if ( dest == town )
return; return;
close(); close();
GH.pushInt(new CCastleInterface(dest, town)); GH.pushIntT<CCastleInterface>(dest, town);
} }
void CCastleInterface::addBuilding(BuildingID bid) void CCastleInterface::addBuilding(BuildingID bid)
@ -1299,13 +1295,13 @@ void CHallInterface::CBuildingBox::hover(bool on)
void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState) void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState)
{ {
if(previousState && (!down)) if(previousState && (!down))
GH.pushInt(new CBuildWindow(town,building,state,0)); GH.pushIntT<CBuildWindow>(town,building,state,0);
} }
void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState) void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState)
{ {
if(down) if(down)
GH.pushInt(new CBuildWindow(town,building,state,1)); GH.pushIntT<CBuildWindow>(town,building,state,1);
} }
CHallInterface::CHallInterface(const CGTownInstance * Town): CHallInterface::CHallInterface(const CGTownInstance * Town):
@ -1756,7 +1752,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art
animBG->needRefresh = true; animBG->needRefresh = true;
const CCreature * creature = CGI->creh->creatures[creMachineID]; const CCreature * creature = CGI->creh->creatures[creMachineID];
anim = std::make_shared<CCreatureAnim>(64, 50, creature->animDefName, Rect()); anim = std::make_shared<CCreatureAnim>(64, 50, creature->animDefName);
anim->clipRect(113,125,200,150); anim->clipRect(113,125,200,150);
title = std::make_shared<CLabel>(165, 28, FONT_BIG, CENTER, Colors::YELLOW, title = std::make_shared<CLabel>(165, 28, FONT_BIG, CENTER, Colors::YELLOW,

View File

@ -156,9 +156,6 @@ public:
void buildingClicked(BuildingID building); void buildingClicked(BuildingID building);
void addBuilding(BuildingID building); void addBuilding(BuildingID building);
void removeBuilding(BuildingID building);//FIXME: not tested!!! void removeBuilding(BuildingID building);//FIXME: not tested!!!
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
}; };
/// Creature info window /// Creature info window

View File

@ -78,8 +78,8 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState)
owner->update(hero, true); owner->update(hero, true);
#else #else
const CGHeroInstance * buf = hero; const CGHeroInstance * buf = hero;
GH.popIntTotally(parent); GH.popInts(1);
GH.pushInt(new CHeroWindow(buf)); GH.pushIntT<CHeroWindow>(buf);
#endif // 0 #endif // 0
} }
} }
@ -297,16 +297,16 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
//if we have exchange window with this curHero open //if we have exchange window with this curHero open
bool noDismiss=false; bool noDismiss=false;
for(IShowActivatable * isa : GH.listInt) for(auto isa : GH.listInt)
{ {
if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa)) if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa.get()))
{ {
for(int g=0; g < cew->heroInst.size(); ++g) for(int g=0; g < cew->heroInst.size(); ++g)
if(cew->heroInst[g] == curHero) if(cew->heroInst[g] == curHero)
noDismiss = true; noDismiss = true;
} }
if(dynamic_cast<CKingdomInterface*>(isa)) if(dynamic_cast<CKingdomInterface*>(isa.get()))
noDismiss = true; noDismiss = true;
} }
//if player only have one hero and no towns //if player only have one hero and no towns
@ -374,7 +374,7 @@ void CHeroWindow::commanderWindow()
} }
else else
{ {
GH.pushInt(new CStackWindow(curHero->commander, false)); GH.pushIntT<CStackWindow>(curHero->commander, false);
} }
} }

View File

@ -40,8 +40,7 @@ void CQuestLabel::clickLeft(tribool down, bool previousState)
void CQuestLabel::showAll(SDL_Surface * to) void CQuestLabel::showAll(SDL_Surface * to)
{ {
if (active) CMultiLineLabel::showAll (to);
CMultiLineLabel::showAll (to);
} }
CQuestIcon::CQuestIcon (const std::string &defname, int index, int x, int y) : CQuestIcon::CQuestIcon (const std::string &defname, int index, int x, int y) :
@ -204,8 +203,9 @@ void CQuestLog::recreateLabelList()
void CQuestLog::showAll(SDL_Surface * to) void CQuestLog::showAll(SDL_Surface * to)
{ {
CWindowObject::showAll(to); CWindowObject::showAll(to);
if(labels.size() && labels[questIndex]->active) if(questIndex >= 0 && questIndex < labels.size())
{ {
//TODO: use child object to selection rect
Rect rect = Rect::around(labels[questIndex]->pos); Rect rect = Rect::around(labels[questIndex]->pos);
rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics
rect.w += 2; rect.w += 2;

View File

@ -255,7 +255,7 @@ void CSpellWindow::fexitb()
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap) = selectedTab; (myInt->battleInt ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage; (myInt->battleInt ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
GH.popIntTotally(this); close();
} }
void CSpellWindow::fadvSpellsb() void CSpellWindow::fadvSpellsb()
@ -414,13 +414,13 @@ void CSpellWindow::setCurrentPage(int value)
void CSpellWindow::turnPageLeft() void CSpellWindow::turnPageLeft()
{ {
if(settings["video"]["spellbookAnimation"].Bool()) if(settings["video"]["spellbookAnimation"].Bool())
CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen); CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15);
} }
void CSpellWindow::turnPageRight() void CSpellWindow::turnPageRight()
{ {
if(settings["video"]["spellbookAnimation"].Bool()) if(settings["video"]["spellbookAnimation"].Bool())
CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen); CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15);
} }
void CSpellWindow::keyPressed(const SDL_KeyboardEvent & key) void CSpellWindow::keyPressed(const SDL_KeyboardEvent & key)
@ -568,7 +568,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
else //adventure spell else //adventure spell
{ {
const CGHeroInstance * h = owner->myHero; const CGHeroInstance * h = owner->myHero;
GH.popInt(owner); GH.popInts(1);
auto guard = vstd::makeScopeGuard([this]() auto guard = vstd::makeScopeGuard([this]()
{ {

View File

@ -605,22 +605,19 @@ void CTradeWindow::setMode(EMarketMode::EMarketMode Mode)
{ {
const IMarket *m = market; const IMarket *m = market;
const CGHeroInstance *h = hero; const CGHeroInstance *h = hero;
CTradeWindow *nwindow = nullptr;
GH.popIntTotally(this); close();
switch(Mode) switch(Mode)
{ {
case EMarketMode::CREATURE_EXP: case EMarketMode::CREATURE_EXP:
case EMarketMode::ARTIFACT_EXP: case EMarketMode::ARTIFACT_EXP:
nwindow = new CAltarWindow(m, h, Mode); GH.pushIntT<CAltarWindow>(m, h, Mode);
break; break;
default: default:
nwindow = new CMarketplaceWindow(m, h, Mode); GH.pushIntT<CMarketplaceWindow>(m, h, Mode);
break; break;
} }
GH.pushInt(nwindow);
} }
void CTradeWindow::artifactSelected(CHeroArtPlace *slot) void CTradeWindow::artifactSelected(CHeroArtPlace *slot)

View File

@ -34,8 +34,7 @@
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt): CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
CIntObject(getUsedEvents(options_), Point()), WindowBase(getUsedEvents(options_), Point()),
shadow(nullptr),
options(options_), options(options_),
background(createBg(imageName, options & PLAYER_COLORED)) background(createBg(imageName, options & PLAYER_COLORED))
{ {
@ -56,7 +55,7 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt
} }
CWindowObject::CWindowObject(int options_, std::string imageName): CWindowObject::CWindowObject(int options_, std::string imageName):
CIntObject(getUsedEvents(options_), Point()), WindowBase(getUsedEvents(options_), Point()),
options(options_), options(options_),
background(createBg(imageName, options_ & PLAYER_COLORED)) background(createBg(imageName, options_ & PLAYER_COLORED))
{ {
@ -122,10 +121,10 @@ void CWindowObject::setShadow(bool on)
//size of shadow //size of shadow
static const int size = 8; static const int size = 8;
if(on == bool(shadow)) if(on == !shadowParts.empty())
return; return;
shadow.reset(); shadowParts.clear();
//object too small to cast shadow //object too small to cast shadow
if(pos.h <= size || pos.w <= size) if(pos.h <= size || pos.w <= size)
@ -214,15 +213,11 @@ void CWindowObject::setShadow(bool on)
//generate "shadow" object with these 3 pieces in it //generate "shadow" object with these 3 pieces in it
{ {
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
shadow = std::make_shared<CIntObject>();
}
{ shadowParts.push_back(std::make_shared<CPicture>(shadowCorner, shadowPos.x, shadowPos.y));
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255); shadowParts.push_back(std::make_shared<CPicture>(shadowRight, shadowPos.x, shadowStart.y));
shadowParts.push_back(std::make_shared<CPicture>(shadowBottom, shadowStart.x, shadowPos.y));
shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y));
shadow->addChild(new CPicture(shadowRight, shadowPos.x, shadowStart.y));
shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y));
} }
} }
} }
@ -238,11 +233,6 @@ void CWindowObject::showAll(SDL_Surface *to)
CMessage::drawBorder(color, to, pos.w+28, pos.h+29, pos.x-14, pos.y-15); CMessage::drawBorder(color, to, pos.w+28, pos.h+29, pos.x-14, pos.y-15);
} }
void CWindowObject::close()
{
GH.popIntTotally(this);
}
void CWindowObject::clickRight(tribool down, bool previousState) void CWindowObject::clickRight(tribool down, bool previousState)
{ {
close(); close();

View File

@ -11,13 +11,13 @@
#include "../gui/CIntObject.h" #include "../gui/CIntObject.h"
/// Basic class for windows class CWindowObject : public WindowBase
class CWindowObject : public CIntObject
{ {
std::shared_ptr<CPicture> createBg(std::string imageName, bool playerColored); std::shared_ptr<CPicture> createBg(std::string imageName, bool playerColored);
int getUsedEvents(int options); int getUsedEvents(int options);
std::shared_ptr<CIntObject> shadow; std::vector<std::shared_ptr<CPicture>> shadowParts;
void setShadow(bool on); void setShadow(bool on);
int options; int options;
@ -25,8 +25,6 @@ class CWindowObject : public CIntObject
protected: protected:
std::shared_ptr<CPicture> background; std::shared_ptr<CPicture> background;
//Simple function with call to GH.popInt
void close();
//Used only if RCLICK_POPUP was set //Used only if RCLICK_POPUP was set
void clickRight(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override;
//To display border //To display border

View File

@ -96,7 +96,7 @@ void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousSta
void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState) void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState)
{ {
if(down) if(down)
GH.pushInt(new CStackWindow(creature, true)); GH.pushIntT<CStackWindow>(creature, true);
} }
void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to) void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to)
@ -569,8 +569,7 @@ void CSystemOptionsWindow::selectGameRes()
items.push_back(resX + 'x' + resY); items.push_back(resX + 'x' + resY);
} }
GH.pushInt(new CObjectListWindow(items, nullptr, texts["label"].String(), texts["help"].String(), GH.pushIntT<CObjectListWindow>(items, nullptr, texts["label"].String(), texts["help"].String(), std::bind(&CSystemOptionsWindow::setGameRes, this, _1));
std::bind(&CSystemOptionsWindow::setGameRes, this, _1)));
} }
void CSystemOptionsWindow::setGameRes(int index) void CSystemOptionsWindow::setGameRes(int index)
@ -599,7 +598,7 @@ void CSystemOptionsWindow::bquitf()
void CSystemOptionsWindow::breturnf() void CSystemOptionsWindow::breturnf()
{ {
GH.popIntTotally(this); close();
} }
void CSystemOptionsWindow::bmainmenuf() void CSystemOptionsWindow::bmainmenuf()
@ -609,14 +608,14 @@ void CSystemOptionsWindow::bmainmenuf()
void CSystemOptionsWindow::bloadf() void CSystemOptionsWindow::bloadf()
{ {
GH.popIntTotally(this); close();
LOCPLINT->proposeLoadingGame(); LOCPLINT->proposeLoadingGame();
} }
void CSystemOptionsWindow::bsavef() void CSystemOptionsWindow::bsavef()
{ {
GH.popIntTotally(this); close();
GH.pushInt(new CSavingScreen()); GH.pushIntT<CSavingScreen>();
} }
void CSystemOptionsWindow::brestartf() void CSystemOptionsWindow::brestartf()
@ -626,7 +625,7 @@ void CSystemOptionsWindow::brestartf()
void CSystemOptionsWindow::closeAndPushEvent(int eventType, int code) void CSystemOptionsWindow::closeAndPushEvent(int eventType, int code)
{ {
GH.popIntTotally(this); close();
GH.pushSDLEvent(eventType, code); GH.pushSDLEvent(eventType, code);
} }
@ -705,7 +704,7 @@ void CTavernWindow::recruitb()
void CTavernWindow::thievesguildb() void CTavernWindow::thievesguildb()
{ {
GH.pushInt( new CThievesGuildWindow(tavernObj) ); GH.pushIntT<CThievesGuildWindow>(tavernObj);
} }
CTavernWindow::~CTavernWindow() CTavernWindow::~CTavernWindow()
@ -745,9 +744,7 @@ void CTavernWindow::HeroPortrait::clickLeft(tribool down, bool previousState)
void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState) void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState)
{ {
if(h && down) if(h && down)
{ GH.pushIntT<CRClickPopupInt>(std::make_shared<CHeroWindow>(h));
GH.pushInt(new CRClickPopupInt(new CHeroWindow(h), true));
}
} }
CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H) CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H)
@ -990,7 +987,7 @@ CShipyardWindow::CShipyardWindow(const std::vector<si32> & cost, int state, int
std::string boatFilenames[3] = {"AB01_", "AB02_", "AB03_"}; std::string boatFilenames[3] = {"AB01_", "AB02_", "AB03_"};
Point waterCenter = Point(bgWater->pos.x+bgWater->pos.w/2, bgWater->pos.y+bgWater->pos.h/2); Point waterCenter = Point(bgWater->pos.x+bgWater->pos.w/2, bgWater->pos.y+bgWater->pos.h/2);
bgShip = std::make_shared<CAnimImage>(boatFilenames[boatType], 0, 7, 120, 96, CShowableAnim::USE_RLE); bgShip = std::make_shared<CAnimImage>(boatFilenames[boatType], 0, 7, 120, 96, 0);
bgShip->center(waterCenter); bgShip->center(waterCenter);
// Create resource icons and costs. // Create resource icons and costs.
@ -1110,7 +1107,7 @@ void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState)
if(previousState && (!down)) if(previousState && (!down))
{ {
move(); move();
parent->showAll(screen2); parent->redraw();
} }
} }
@ -1152,7 +1149,7 @@ void CTransformerWindow::addAll()
if(elem->left) if(elem->left)
elem->move(); elem->move();
} }
showAll(screen2); redraw();
} }
void CTransformerWindow::updateGarrisons() void CTransformerWindow::updateGarrisons()
@ -1215,10 +1212,7 @@ void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
if(previousState && (!down)) if(previousState && (!down))
{ {
if(state() == 2) if(state() == 2)
{ GH.pushIntT<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000);
auto win = new CUnivConfirmWindow(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000);
GH.pushInt(win);
}
} }
} }
@ -1813,14 +1807,14 @@ void CObjectListWindow::elementSelected()
{ {
std::function<void(int)> toCall = onSelect;//save std::function<void(int)> toCall = onSelect;//save
int where = items[selected].first; //required variables int where = items[selected].first; //required variables
GH.popIntTotally(this);//then destroy window close();//then destroy window
toCall(where);//and send selected object toCall(where);//and send selected object
} }
void CObjectListWindow::exitPressed() void CObjectListWindow::exitPressed()
{ {
std::function<void()> toCall = onExit;//save std::function<void()> toCall = onExit;//save
GH.popIntTotally(this);//then destroy window close();//then destroy window
if(toCall) if(toCall)
toCall(); toCall();
} }

View File

@ -161,7 +161,8 @@ CInfoWindow::CInfoWindow()
void CInfoWindow::close() void CInfoWindow::close()
{ {
GH.popIntTotally(this); WindowBase::close();
if(LOCPLINT) if(LOCPLINT)
LOCPLINT->showingDialog->setn(false); LOCPLINT->showingDialog->setn(false);
} }
@ -181,8 +182,7 @@ void CInfoWindow::showAll(SDL_Surface * to)
void CInfoWindow::showInfoDialog(const std::string &text, const TCompsInfo & components, PlayerColor player) void CInfoWindow::showInfoDialog(const std::string &text, const TCompsInfo & components, PlayerColor player)
{ {
CInfoWindow * window = CInfoWindow::create(text, player, components); GH.pushInt(CInfoWindow::create(text, player, components));
GH.pushInt(window);
} }
void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, PlayerColor player) void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, PlayerColor player)
@ -191,7 +191,7 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c
std::vector<std::pair<std::string,CFunctionList<void()> > > pom; std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0)); pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",0)); pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",0));
CInfoWindow * temp = new CInfoWindow(text, player, components, pom); std::shared_ptr<CInfoWindow> temp = std::make_shared<CInfoWindow>(text, player, components, pom);
temp->buttons[0]->addCallback( onYes ); temp->buttons[0]->addCallback( onYes );
temp->buttons[1]->addCallback( onNo ); temp->buttons[1]->addCallback( onNo );
@ -199,22 +199,11 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c
GH.pushInt(temp); GH.pushInt(temp);
} }
void CInfoWindow::showOkDialog(const std::string & text, const TCompsInfo & components, const std::function<void()> & onOk, PlayerColor player) std::shared_ptr<CInfoWindow> CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components)
{ {
std::vector<std::pair<std::string,CFunctionList<void()> > > pom; std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0)); pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
CInfoWindow * temp = new CInfoWindow(text, player, components, pom); return std::make_shared<CInfoWindow>(text, playerID, components, pom);
temp->buttons[0]->addCallback(onOk);
GH.pushInt(temp);
}
CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components)
{
std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
CInfoWindow * ret = new CInfoWindow(text, playerID, components, pom);
return ret;
} }
std::string CInfoWindow::genText(std::string title, std::string description) std::string CInfoWindow::genText(std::string title, std::string description)
@ -268,7 +257,7 @@ void CInfoPopup::close()
{ {
if(free) if(free)
SDL_FreeSurface(bitmap); SDL_FreeSurface(bitmap);
GH.popIntTotally(this); WindowBase::close();
} }
void CInfoPopup::show(SDL_Surface * to) void CInfoPopup::show(SDL_Surface * to)
@ -307,7 +296,7 @@ void CRClickPopup::clickRight(tribool down, bool previousState)
void CRClickPopup::close() void CRClickPopup::close()
{ {
GH.popIntTotally(this); WindowBase::close();
} }
void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps) void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps)
@ -316,11 +305,11 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom
if(settings["session"]["spectate"].Bool())//TODO: there must be better way to implement this if(settings["session"]["spectate"].Bool())//TODO: there must be better way to implement this
player = PlayerColor(1); player = PlayerColor(1);
CSimpleWindow * temp = new CInfoWindow(txt, player, comps); auto temp = std::make_shared<CInfoWindow>(txt, player, comps);
temp->center(Point(GH.current->motion)); //center on mouse temp->center(Point(GH.current->motion)); //center on mouse
temp->fitToScreen(10); temp->fitToScreen(10);
auto rcpi = new CRClickPopupInt(temp,true);
GH.pushInt(rcpi); GH.pushIntT<CRClickPopupInt>(temp);
} }
void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CComponent> component) void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CComponent> component)
@ -331,14 +320,16 @@ void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CCompo
createAndPush(txt, intComps); createAndPush(txt, intComps);
} }
void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment) void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment)
{ {
CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj auto iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
if(iWin) if(iWin)
{
GH.pushInt(iWin); GH.pushInt(iWin);
}
else else
{ {
if (adventureInt->curHero()) if(adventureInt->curHero())
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero())); CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
else else
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID)); CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
@ -354,31 +345,20 @@ CRClickPopup::~CRClickPopup()
{ {
} }
void CRClickPopupInt::show(SDL_Surface * to) CRClickPopupInt::CRClickPopupInt(std::shared_ptr<CIntObject> our)
{
inner->show(to);
}
CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt )
{ {
CCS->curh->hide(); CCS->curh->hide();
defActions = SHOWALL | UPDATE;
our->recActions = defActions;
inner = our; inner = our;
delInner = deleteInt; addChild(our.get(), false);
} }
CRClickPopupInt::~CRClickPopupInt() CRClickPopupInt::~CRClickPopupInt()
{ {
if(delInner)
delete inner;
CCS->curh->show(); CCS->curh->show();
} }
void CRClickPopupInt::showAll(SDL_Surface * to)
{
inner->showAll(to);
}
Point CInfoBoxPopup::toScreen(Point p) Point CInfoBoxPopup::toScreen(Point p)
{ {
vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100); vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100);
@ -417,7 +397,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
tooltip = std::make_shared<CArmyTooltip>(Point(9, 10), iah); tooltip = std::make_shared<CArmyTooltip>(Point(9, 10), iah);
} }
CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero std::shared_ptr<WindowBase> CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
{ {
if(nullptr == specific) if(nullptr == specific)
specific = adventureInt->selection; specific = adventureInt->selection;
@ -431,13 +411,13 @@ CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance
switch(specific->ID) switch(specific->ID)
{ {
case Obj::HERO: case Obj::HERO:
return new CInfoBoxPopup(position, dynamic_cast<const CGHeroInstance *>(specific)); return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGHeroInstance *>(specific));
case Obj::TOWN: case Obj::TOWN:
return new CInfoBoxPopup(position, dynamic_cast<const CGTownInstance *>(specific)); return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGTownInstance *>(specific));
case Obj::GARRISON: case Obj::GARRISON:
case Obj::GARRISON2: case Obj::GARRISON2:
return new CInfoBoxPopup(position, dynamic_cast<const CGGarrison *>(specific)); return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGGarrison *>(specific));
default: default:
return nullptr; return std::shared_ptr<WindowBase>();
} }
} }

View File

@ -26,11 +26,11 @@ class CSlider;
class CArmyTooltip; class CArmyTooltip;
// Window GUI class // Window GUI class
class CSimpleWindow : public CIntObject class CSimpleWindow : public WindowBase
{ {
public: public:
SDL_Surface * bitmap; //background SDL_Surface * bitmap; //background
virtual void show(SDL_Surface * to) override; void show(SDL_Surface * to) override;
CSimpleWindow():bitmap(nullptr){}; CSimpleWindow():bitmap(nullptr){};
virtual ~CSimpleWindow(); virtual ~CSimpleWindow();
}; };
@ -58,16 +58,15 @@ public:
//use only before the game starts! (showYesNoDialog in LOCPLINT must be used then) //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
static void showInfoDialog( const std::string & text, const TCompsInfo & components, PlayerColor player = PlayerColor(1)); static void showInfoDialog( const std::string & text, const TCompsInfo & components, PlayerColor player = PlayerColor(1));
static void showOkDialog(const std::string & text, const TCompsInfo & components, const std::function<void()> & onOk, PlayerColor player = PlayerColor(1));
static void showYesNoDialog( const std::string & text, const TCompsInfo & components, const CFunctionList<void()> & onYes, const CFunctionList<void()> & onNo, PlayerColor player = PlayerColor(1)); static void showYesNoDialog( const std::string & text, const TCompsInfo & components, const CFunctionList<void()> & onYes, const CFunctionList<void()> & onNo, PlayerColor player = PlayerColor(1));
static CInfoWindow * create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo()); static std::shared_ptr<CInfoWindow> create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo());
/// create text from title and description: {title}\n\n description /// create text from title and description: {title}\n\n description
static std::string genText(std::string title, std::string description); static std::string genText(std::string title, std::string description);
}; };
/// popup displayed on R-click /// popup displayed on R-click
class CRClickPopup : public CIntObject class CRClickPopup : public WindowBase
{ {
public: public:
virtual void close(); virtual void close();
@ -76,7 +75,7 @@ public:
CRClickPopup(); CRClickPopup();
virtual ~CRClickPopup(); virtual ~CRClickPopup();
static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific); static std::shared_ptr<WindowBase> createInfoWin(Point position, const CGObjectInstance * specific);
static void createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo()); static void createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
static void createAndPush(const std::string & txt, std::shared_ptr<CComponent> component); static void createAndPush(const std::string & txt, std::shared_ptr<CComponent> component);
static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT); static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT);
@ -85,13 +84,9 @@ public:
/// popup displayed on R-click /// popup displayed on R-click
class CRClickPopupInt : public CRClickPopup class CRClickPopupInt : public CRClickPopup
{ {
std::shared_ptr<CIntObject> inner;
public: public:
IShowActivatable *inner; CRClickPopupInt(std::shared_ptr<CIntObject> our);
bool delInner;
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
CRClickPopupInt(IShowActivatable *our, bool deleteInt);
virtual ~CRClickPopupInt(); virtual ~CRClickPopupInt();
}; };
@ -123,11 +118,11 @@ public:
/// component selection window /// component selection window
class CSelWindow : public CInfoWindow class CSelWindow : public CInfoWindow
{ //warning - this window deletes its components by closing! {
public: public:
void selectionChange(unsigned to); void selectionChange(unsigned to);
void madeChoice(); //looks for selected component and calls callback void madeChoice(); //looks for selected component and calls callback
CSelWindow(const std::string & text, PlayerColor player, int charperline ,const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID); CSelWindow(const std::string & text, PlayerColor player, int charperline, const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID);
CSelWindow(){};
//notification - this class inherits important destructor from CInfoWindow //notification - this class inherits important destructor from CInfoWindow
}; };