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;
}
int CBattleCallback::battleMakeAction(BattleAction* action)
int CBattleCallback::battleMakeAction(const BattleAction * action)
{
assert(action->actionType == EActionType::HERO_SPELL);
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 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
virtual int battleMakeAction(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 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
};
class IGameActionCallback
@ -88,7 +88,7 @@ protected:
public:
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
friend class CCallback;

View File

@ -57,7 +57,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
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;
for (int i=0; i<height; i++)
@ -89,7 +89,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
int gmask = 0x00ff00;
int rmask = 0xff0000;
#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;
for (int i=0; i<height; i++)

View File

@ -118,32 +118,13 @@ static void mainLoop();
void init()
{
CStopWatch tmh, pomtime;
CStopWatch tmh;
loadDLLClasses();
const_cast<CGameInfo*>(CGI)->setFromLib();
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()
@ -466,8 +447,10 @@ int main(int argc, char * argv[])
playIntro();
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255);
SDL_RenderClear(mainRenderer);
SDL_RenderPresent(mainRenderer);
}
SDL_RenderPresent(mainRenderer);
#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
{
@ -480,6 +463,27 @@ int main(int argc, char * argv[])
}
#endif // ANDROID
#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());
session["autoSkip"].Bool() = vm.count("autoSkip");
@ -500,7 +504,7 @@ int main(int argc, char * argv[])
}
else
{
GH.curInt = CMainMenu::create();
GH.curInt = CMainMenu::create().get();
}
if(!settings["session"]["headless"].Bool())
@ -786,9 +790,9 @@ void processCommand(const std::string &message)
}
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);
else
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)
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);
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)
@ -1080,47 +1072,85 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
}
bool bufOnScreen = (screenBuf == screen);
bool realFullscreen = settings["video"]["realFullscreen"].Bool();
cleanupRenderer();
bool realFullscreen = settings["video"]["realFullscreen"].Bool();
#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(nullptr == mainWindow)
{
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");
#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);
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
{
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
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))
{
SDL_RenderSetLogicalSize(mainRenderer, w, h);
@ -1270,7 +1300,7 @@ static void handleEvent(SDL_Event & ev)
};
if(epilogue.hasPrologEpilog)
{
GH.pushInt(new CPrologEpilogVideo(epilogue, finisher));
GH.pushIntT<CPrologEpilogVideo>(epilogue, finisher);
}
else
{
@ -1306,6 +1336,13 @@ static void handleEvent(SDL_Event & ev)
}
return;
}
//preprocessing
if(ev.type == SDL_MOUSEMOTION)
{
CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
}
{
boost::unique_lock<boost::mutex> lock(eventsM);
events.push(ev);
@ -1349,6 +1386,19 @@ void handleQuit(bool ask)
if(!settings["session"]["headless"].Bool())
{
cleanupRenderer();
if(nullptr != mainRenderer)
{
SDL_DestroyRenderer(mainRenderer);
mainRenderer = nullptr;
}
if(nullptr != mainWindow)
{
SDL_DestroyWindow(mainWindow);
mainWindow = nullptr;
}
SDL_Quit();
}

View File

@ -97,7 +97,7 @@ void CMessage::dispose()
SDL_Surface * CMessage::drawDialogBox(int w, int h, PlayerColor playerColor)
{
//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 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 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)
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);
/// split text in lines

View File

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

View File

@ -82,7 +82,7 @@ public:
std::shared_ptr<CCallback> cb; //to communicate with engine
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 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, 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 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 stopMovement();

View File

@ -494,12 +494,12 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
{
if(CMM)
{
GH.curInt = CMM;
GH.curInt = CMM.get();
CMM->enable();
}
else
{
GH.curInt = CMainMenu::create();
GH.curInt = CMainMenu::create().get();
}
}
}
@ -566,7 +566,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
else
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));
while(!mi || mapInfo->fileURI != CSH->mi->fileURI)
{

View File

@ -396,7 +396,7 @@ void CVideoPlayer::close()
}
// 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
// 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())
{
if(stopOnKey && keyDown())
return false;
SDL_RenderCopy(mainRenderer, texture, NULL, &pos);
SDL_RenderCopy(mainRenderer, texture, nullptr, &pos);
SDL_RenderPresent(mainRenderer);
// Wait 3 frames
@ -423,10 +422,10 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
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);
bool ret = playVideo(x, y, dst, stopOnKey);
bool ret = playVideo(x, y, stopOnKey);
close();
return ret;
}

View File

@ -31,7 +31,7 @@ public:
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 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;
}
@ -111,7 +111,7 @@ class CVideoPlayer : public IMainVideoPlayer
int refreshCount;
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);
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
// 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:
bool wait() override {return false;};

View File

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

View File

@ -35,7 +35,7 @@ bool LobbyClientConnected::applyOnLobbyHandler(CServerHandler * handler)
{
handler->c->connectionID = clientId;
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;
return true;
}
@ -60,7 +60,7 @@ bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler)
void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
{
GH.popIntTotally(lobby);
GH.popInts(1);
}
void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
@ -114,7 +114,7 @@ bool LobbyStartGame::applyOnLobbyHandler(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)
@ -128,7 +128,7 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler *
{
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);
}

View File

@ -207,7 +207,7 @@ bool CDefenceAnimation::init()
if (!rangedAttack && getMyAnimType() != CCreatureAnim::DEFENCE)
{
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;

View File

@ -39,7 +39,7 @@ public:
class CBattleStackAnimation : public CBattleAnimation
{
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
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);

View File

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

View File

@ -34,10 +34,10 @@ SDL_Color AnimationControls::getNoBorder()
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);
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)

View File

@ -25,7 +25,7 @@ namespace AnimationControls
SDL_Color getNoBorder();
/// 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)
float getCreatureAnimationSpeed(const CCreature * creature, const CCreatureAnimation * anim, size_t groupID);

View File

@ -23,7 +23,6 @@
#include "../lib/CRandomGenerator.h"
class SDLImageLoader;
class CompImageLoader;
typedef std::map <size_t, std::vector <JsonNode> > source_map;
typedef std::map<size_t, IImage* > image_map;
@ -79,9 +78,9 @@ public:
public:
//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
SDLImage(std::string filename, bool compressed=false);
SDLImage(std::string filename);
SDLImage(const JsonNode & conf);
//Create using existing surface, extraRef will increase refcount on SDL_Surface
@ -107,65 +106,6 @@ public:
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
{
SDLImage * image;
@ -184,30 +124,6 @@ public:
~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
class CFileCache
{
@ -576,7 +492,7 @@ SDLImageLoader::SDLImageLoader(SDLImage * Img):
void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
{
//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->fullSize = FullSize;
@ -621,182 +537,6 @@ SDLImageLoader::~SDLImageLoader()
//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 *
*************************************************************************/
@ -805,7 +545,7 @@ 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),
margins(0, 0),
fullSize(0, 0)
@ -857,15 +597,14 @@ SDLImage::SDLImage(const JsonNode & conf)
}
}
SDLImage::SDLImage(std::string filename, bool compressed)
SDLImage::SDLImage(std::string filename)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0)
{
surf = BitmapHandler::loadBitmap(filename);
if (surf == nullptr)
if(surf == nullptr)
{
logGlobal->error("Error: failed to load image %s", filename);
return;
@ -875,23 +614,8 @@ SDLImage::SDLImage(std::string filename, bool compressed)
fullSize.x = surf->w;
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
{
if(!surf)
@ -1042,282 +766,6 @@ SDLImage::~SDLImage()
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)
{
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(compressed)
images[group][frame] = std::make_shared<CompImage>(defFile, frame, group);
else
images[group][frame] = std::make_shared<SDLImage>(defFile, frame, group);
images[group][frame] = std::make_shared<SDLImage>(defFile.get(), frame, group);
return true;
}
}
// still here? image is missing
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
{
@ -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);
}
CAnimation::CAnimation(std::string Name, bool Compressed):
CAnimation::CAnimation(std::string Name):
name(Name),
compressed(Compressed),
preloaded(false),
defFile(nullptr)
defFile()
{
size_t dotPos = name.find_last_of('.');
if ( dotPos!=-1 )
@ -1521,7 +965,7 @@ CAnimation::CAnimation(std::string Name, bool Compressed):
ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION);
if(CResourceHandler::get()->existsResource(resource))
defFile = new CDefFile(name);
defFile = std::make_shared<CDefFile>(name);
init();
@ -1531,21 +975,28 @@ CAnimation::CAnimation(std::string Name, bool Compressed):
CAnimation::CAnimation():
name(""),
compressed(false),
preloaded(false),
defFile(nullptr)
defFile()
{
init();
}
CAnimation::~CAnimation()
{
if(defFile)
delete defFile;
}
CAnimation::~CAnimation() = default;
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
JsonNode clone(source[sourceGroup][sourceFrame]);

View File

@ -68,12 +68,9 @@ private:
//animation file name
std::string name;
//if true all frames will be stored in compressed (RLE) state
const bool compressed;
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
bool loadFrame(size_t frame, size_t group);
@ -93,7 +90,7 @@ private:
std::shared_ptr<IImage> getFromExtraDef(std::string filename);
public:
CAnimation(std::string Name, bool Compressed = false);
CAnimation(std::string Name);
CAnimation();
~CAnimation();

View File

@ -18,8 +18,31 @@
#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()
{
cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40);
SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND);
xpos = ypos = 0;
type = ECursor::DEFAULT;
dndObject = nullptr;
@ -34,9 +57,9 @@ void CCursorHandler::initCursor()
currentCursor = cursors.at(int(ECursor::DEFAULT)).get();
help = CSDL_Ext::newSurface(40,40);
//No blending. Ensure, that we are copying pixels during "screen restore draw"
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
buffer = CSDL_Ext::newSurface(40,40);
SDL_SetSurfaceBlendMode(buffer, SDL_BLENDMODE_NONE);
SDL_ShowCursor(SDL_DISABLE);
changeGraphic(ECursor::ADVENTURE, 0);
@ -56,11 +79,17 @@ void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
this->frame = index;
currentCursor->setFrame(index);
}
replaceBuffer(currentCursor);
}
void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
{
dndObject = std::move(object);
if(dndObject)
replaceBuffer(dndObject.get());
else
replaceBuffer(currentCursor);
}
void CCursorHandler::cursorMove(const int & x, const int & y)
@ -69,40 +98,6 @@ void CCursorHandler::cursorMove(const int & x, const int & 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 )
{
if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK)
@ -221,15 +216,54 @@ void CCursorHandler::centerCursor()
void CCursorHandler::render()
{
drawWithScreenRestore();
CSDL_Ext::update(screen);
drawRestored();
if(!showing)
return;
//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()
{
if(help)
SDL_FreeSurface(help);
if(buffer)
SDL_FreeSurface(buffer);
if(cursorLayer)
SDL_DestroyTexture(cursorLayer);
}

View File

@ -8,9 +8,10 @@
*
*/
#pragma once
class CIntObject;
class CAnimImage;
struct SDL_Surface;
struct SDL_Texture;
namespace ECursor
{
@ -26,7 +27,10 @@ namespace ECursor
/// handles mouse cursor
class CCursorHandler final
{
SDL_Surface * help;
bool needUpdate;
SDL_Texture * cursorLayer;
SDL_Surface * buffer;
CAnimImage * currentCursor;
std::unique_ptr<CAnimImage> dndObject; //if set, overrides currentCursor
@ -35,10 +39,12 @@ class CCursorHandler final
bool showing;
/// Draw cursor preserving original image below cursor
void drawWithScreenRestore();
/// Restore original image below cursor
void drawRestored();
void clearBuffer();
void updateBuffer(CIntObject * payload);
void replaceBuffer(CIntObject * payload);
void shiftPos( int &x, int &y );
void updateTexture();
public:
/// position of cursor
int xpos, ypos;
@ -63,9 +69,8 @@ public:
void render();
void shiftPos( int &x, int &y );
void hide() { showing=0; };
void show() { showing=1; };
void hide() { showing=false; };
void show() { showing=true; };
/// change cursor's positions to (x, 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;
}
void CGuiHandler::popInt(IShowActivatable *top)
void CGuiHandler::popInt(std::shared_ptr<IShowActivatable> top)
{
assert(listInt.front() == top);
top->deactivate();
disposed.push_back(top);
listInt.pop_front();
objsToBlit -= top;
if(!listInt.empty())
@ -109,18 +110,10 @@ void CGuiHandler::popInt(IShowActivatable *top)
pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED);
}
void CGuiHandler::popIntTotally(IShowActivatable *top)
{
assert(listInt.front() == top);
popInt(top);
delete top;
fakeMouseMove();
}
void CGuiHandler::pushInt(IShowActivatable *newInt)
void CGuiHandler::pushInt(std::shared_ptr<IShowActivatable> 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)
screenBuf = screen2;
@ -128,6 +121,7 @@ void CGuiHandler::pushInt(IShowActivatable *newInt)
if(!listInt.empty())
listInt.front()->deactivate();
listInt.push_front(newInt);
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
newInt->activate();
objsToBlit.push_back(newInt);
totalRedraw();
@ -144,7 +138,7 @@ void CGuiHandler::popInts(int howMany)
for(int i=0; i < howMany; i++)
{
objsToBlit -= listInt.front();
delete listInt.front();
disposed.push_back(listInt.front());
listInt.pop_front();
}
@ -158,10 +152,10 @@ void CGuiHandler::popInts(int howMany)
pushSDLEvent(SDL_USEREVENT, EUserEvent::INTERFACE_CHANGED);
}
IShowActivatable * CGuiHandler::topInt()
std::shared_ptr<IShowActivatable> CGuiHandler::topInt()
{
if(listInt.empty())
return nullptr;
return std::shared_ptr<IShowActivatable>();
else
return listInt.front();
}
@ -234,11 +228,11 @@ void CGuiHandler::handleCurrentEvent()
case SDLK_F9:
//not working yet since CClient::run remain locked after CBattleInterface removal
if(LOCPLINT->battleInt)
{
GH.popIntTotally(GH.topInt());
vstd::clear_pointer(LOCPLINT->battleInt);
}
// if(LOCPLINT->battleInt)
// {
// GH.popInts(1);
// vstd::clear_pointer(LOCPLINT->battleInt);
// }
break;
default:
@ -271,7 +265,6 @@ void CGuiHandler::handleCurrentEvent()
}
else if(current->type == SDL_MOUSEMOTION)
{
CCS->curh->cursorMove(current->motion.x, current->motion.y);
handleMouseMotion();
}
else if(current->type == SDL_MOUSEBUTTONDOWN)
@ -457,15 +450,18 @@ void CGuiHandler::renderFrame()
if(nullptr != curInt)
curInt->update();
if (settings["general"]["showfps"].Bool())
if(settings["general"]["showfps"].Bool())
drawFPSCounter();
// draw the mouse cursor and update the screen
CCS->curh->render();
SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch);
SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
CCS->curh->render();
SDL_RenderPresent(mainRenderer);
disposed.clear();
}
mainFPSmng->framerateDelay(); // holds a constant FPS

View File

@ -58,10 +58,12 @@ class CGuiHandler
{
public:
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;
private:
std::vector<std::shared_ptr<IShowActivatable>> disposed;
std::atomic<bool> continueEventHandling;
typedef std::list<CIntObject*> CIntObjectList;
@ -86,7 +88,7 @@ public:
public:
//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
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 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 popIntTotally(IShowActivatable *top); //deactivates, deletes, removes given interface from the top and activates next
void pushInt(IShowActivatable *newInt); //deactivate old top interface, activates this one and pushes to the top
void pushInt(std::shared_ptr<IShowActivatable> newInt); //deactivate old top interface, activates this one and pushes to the top
template <typename T, typename ... Args>
void pushIntT(Args && ... args)
{
auto newInt = std::make_shared<T>(std::forward<Args>(args)...);
pushInt(newInt);
}
void 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 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));
}
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)
{
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));
}
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)
{
if (active_m)
@ -223,7 +213,7 @@ void CIntObject::disable()
void CIntObject::enable()
{
if(!active_m && parent_m->active)
if(!active_m && (!parent_m || parent_m->active))
activate();
recActions = 255;
@ -302,11 +292,6 @@ void CIntObject::removeChild(CIntObject * child, bool adjustPosition)
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()
{
//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
*/
//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
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, 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);
@ -211,3 +208,11 @@ public:
CKeyShortcut(std::set<int> Keys);
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 * 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)
{
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>::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)

View File

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

View File

@ -88,7 +88,11 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
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()
@ -138,7 +142,7 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
}
catch(ExceptionNoTemplate & e)
{
GH.pushInt(CInfoWindow::create(CGI->generaltexth->allTexts[751]));
CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1));
}
catch(...)
{

View File

@ -31,5 +31,5 @@ public:
const CMapInfo * getMapInfo() 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"];
lastSave->String() = path;
LOCPLINT->cb->save(path);
GH.popIntTotally(this);
close();
};
if(CResourceHandler::get("local")->existsResource(ResourceID(path, EResType::CLIENT_SAVEGAME)))

View File

@ -39,7 +39,7 @@ CScenarioInfoScreen::CScenarioInfoScreen()
card->changeSelection();
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()

View File

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

View File

@ -86,7 +86,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type)
}
pos = background->center();
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)
@ -367,7 +367,7 @@ void CFlagBox::recreate()
void CFlagBox::clickRight(tribool down, bool previousState)
{
if(down && SEL->getMapInfo())
GH.pushInt(new CFlagBoxTooltipBox(iconsTeamFlags));
GH.pushIntT<CFlagBoxTooltipBox>(iconsTeamFlags);
}
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)
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)
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)

View File

@ -60,7 +60,7 @@
namespace fs = boost::filesystem;
CMainMenu * CMM = nullptr;
std::shared_ptr<CMainMenu> CMM;
ISelectionScreenInfo * SEL;
static void do_quit()
@ -176,7 +176,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
case 0:
return std::bind(CMainMenu::openLobby, ESelectionScreen::newGame, true, nullptr, ELoadMode::NONE);
case 1:
return []() { GH.pushInt(new CMultiMode(ESelectionScreen::newGame)); };
return []() { GH.pushIntT<CMultiMode>(ESelectionScreen::newGame); };
case 2:
return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE);
case 3:
@ -191,7 +191,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
case 0:
return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::SINGLE);
case 1:
return []() { GH.pushInt(new CMultiMode(ESelectionScreen::loadGame)); };
return []() { GH.pushIntT<CMultiMode>(ESelectionScreen::loadGame); };
case 2:
return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::CAMPAIGN);
case 3:
@ -279,8 +279,7 @@ CMainMenu::CMainMenu()
pos.h = screen->h;
GH.defActionsDef = 63;
CMM = this;
menu = new CMenuScreen(CMainMenuConfig::get().getConfig()["window"]);
menu = std::make_shared<CMenuScreen>(CMainMenuConfig::get().getConfig()["window"]);
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
backgroundAroundMenu = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
}
@ -288,8 +287,6 @@ CMainMenu::CMainMenu()
CMainMenu::~CMainMenu()
{
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
if(CMM == this)
CMM = nullptr;
if(GH.curInt == this)
GH.curInt = nullptr;
@ -297,12 +294,12 @@ CMainMenu::~CMainMenu()
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;
if(GH.listInt.empty())
{
GH.pushInt(this);
GH.pushInt(CMM);
GH.pushInt(menu);
menu->switchToTab(0);
}
@ -313,7 +310,7 @@ void CMainMenu::update()
// check for null othervice crash on finishing a campaign
// /FIXME: find out why GH.listInt is empty to begin with
if(GH.topInt() != nullptr)
if(GH.topInt())
GH.topInt()->show(screen);
}
@ -323,7 +320,7 @@ void CMainMenu::openLobby(ESelectionScreen screenType, bool host, const std::vec
CSH->screenType = screenType;
CSH->loadMode = loadMode;
GH.pushInt(new CSimpleJoinScreen(host));
GH.pushIntT<CSimpleJoinScreen>(host);
}
void CMainMenu::openCampaignLobby(const std::string & campaignFileName)
@ -337,23 +334,23 @@ void CMainMenu::openCampaignLobby(std::shared_ptr<CCampaignState> campaign)
CSH->resetStateForLobby(StartInfo::CAMPAIGN);
CSH->screenType = ESelectionScreen::campaignList;
CSH->campaignStateToSend = campaign;
GH.pushInt(new CSimpleJoinScreen());
GH.pushIntT<CSimpleJoinScreen>();
}
void CMainMenu::openCampaignScreen(std::string 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;
}
logGlobal->error("Unknown campaign set: %s", name);
}
CMainMenu * CMainMenu::create()
std::shared_ptr<CMainMenu> CMainMenu::create()
{
if(!CMM)
CMM = new CMainMenu();
CMM = std::shared_ptr<CMainMenu>(new CMainMenu());
GH.terminate_cond->set(false);
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));
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));
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()
{
GH.popIntTotally(this);
GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, true, ELoadMode::MULTI));
auto savedScreenType = screenType;
close();
GH.pushIntT<CMultiPlayers>(settings["general"]["playerName"].String(), savedScreenType, true, ELoadMode::MULTI);
}
void CMultiMode::joinTCP()
{
GH.popIntTotally(this);
GH.pushInt(new CMultiPlayers(settings["general"]["playerName"].String(), screenType, false, ELoadMode::MULTI));
auto savedScreenType = screenType;
close();
GH.pushIntT<CMultiPlayers>(settings["general"]["playerName"].String(), savedScreenType, false, ELoadMode::MULTI);
}
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);
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
inputNames[0]->setText(firstPlayer, true);
@ -497,9 +496,9 @@ void CSimpleJoinScreen::leaveScreen()
textTitle->setText("Closing...");
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
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
class CMultiMode : public CIntObject
class CMultiMode : public WindowBase
{
public:
ESelectionScreen screenType;
@ -89,7 +89,7 @@ public:
};
/// Hot seat player window
class CMultiPlayers : public CIntObject
class CMultiPlayers : public WindowBase
{
bool host;
ELoadMode loadMode;
@ -124,14 +124,14 @@ private:
};
/// 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;
CMainMenu(); //Use CMainMenu::create
public:
CMenuScreen * menu;
std::shared_ptr<CMenuScreen> menu;
~CMainMenu();
void update() override;
@ -140,14 +140,14 @@ public:
static void openCampaignLobby(std::shared_ptr<CCampaignState> campaign);
void openCampaignScreen(std::string name);
static CMainMenu * create();
static std::shared_ptr<CMainMenu> create();
static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
};
/// Simple window to enter the server's address.
class CSimpleJoinScreen : public CIntObject
class CSimpleJoinScreen : public WindowBase
{
std::shared_ptr<CPicture> background;
std::shared_ptr<CTextBox> textTitle;
@ -179,4 +179,4 @@ public:
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)
{
GH.popInt(this);
close();
CCS->soundh->stopSound(voiceSoundHandle);
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)
: 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()
{
if (tmpBackgroundFiller)
SDL_FreeSurface(tmpBackgroundFiller);
}
CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default;
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);
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)
@ -1290,13 +1278,3 @@ void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOf
iconsData.push_back(data);
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 CAnimImage;
class CShowableAnim;
class CFilledTexture;
class CGGarrison;
class CGObjectInstance;
class CGHeroInstance;
@ -384,9 +385,8 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
std::vector<std::pair<int, Point>> iconsData;
/// ptrs to child-pictures constructed from iconsData
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)
SDL_Surface * tmpBackgroundFiller;
int fillerHeight;
/// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
std::shared_ptr<CFilledTexture> backgroundFiller;
std::shared_ptr<CAnimation> icons;
public:
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);
/// recreates all pictures from given def to recolor them according to current player color
void recolorIcons(const PlayerColor & color, int indexOffset);
void showAll(SDL_Surface * to) override;
};
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->artType->id == ArtifactID::SPELLBOOK)
GH.pushInt(new CSpellWindow(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt));
GH.pushIntT<CSpellWindow>(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt);
}
if (!down && previousState)
@ -678,14 +678,14 @@ CArtifactsOfHero::~CArtifactsOfHero()
void CArtifactsOfHero::updateParentWindow()
{
if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt()))
if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt().get()))
{
if(updateState)
chw->curHero = curHero;
else
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
if(cew->heroInst[0]->id == curHero->id)

View File

@ -161,7 +161,7 @@ bool CGarrisonSlot::viewInfo()
elem->block(true);
redraw();
GH.pushInt(new CStackWindow(myStack, dism, pom, upgr));
GH.pushIntT<CStackWindow>(myStack, dism, pom, upgr);
return true;
}
@ -170,7 +170,7 @@ bool CGarrisonSlot::viewInfo()
bool CGarrisonSlot::highlightOrDropArtifact()
{
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 CArtifactInstance * art = nullptr;
@ -241,8 +241,8 @@ bool CGarrisonSlot::split()
int countLeft = selection->myStack ? selection->myStack->count : 0;
int countRight = myStack ? myStack->count : 0;
GH.pushInt(new CSplitWindow(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2),
minLeft, minRight, countLeft, countRight));
GH.pushIntT<CSplitWindow>(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2),
minLeft, minRight, countLeft, countRight);
return true;
}
@ -278,7 +278,7 @@ void CGarrisonSlot::clickRight(tribool down, bool previousState)
{
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)
bg = CSDL_Ext::newSurface(r.w, r.h);
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);
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):
anim(new CAnimation(name, Flags & USE_RLE)),
anim(std::make_shared<CAnimation>(name)),
group(Group),
frame(0),
first(0),
@ -319,7 +319,6 @@ CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Del
CShowableAnim::~CShowableAnim()
{
anim->unloadGroup(group);
delete anim;
}
void CShowableAnim::setAlpha(ui32 alphaValue)
@ -410,8 +409,8 @@ void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
assert(to);
Rect src( xOffset, yOffset, pos.w, pos.h);
auto img = anim->getImage(frame, group);
if (img)
img->draw(to, pos.x-xOffset, pos.y-yOffset, &src, alpha);
if(img)
img->draw(to, pos.x, pos.y, &src, alpha);
}
void CShowableAnim::rotate(bool on, bool vertical)
@ -423,15 +422,11 @@ void CShowableAnim::rotate(bool on, bool vertical)
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)
{
xOffset = picPos.x;
yOffset = picPos.y;
if (picPos.w)
pos.w = picPos.w;
if (picPos.h)
pos.h = picPos.h;
xOffset = 0;
yOffset = 0;
}
void CCreatureAnim::loopPreview(bool warMachine)

View File

@ -105,12 +105,11 @@ public:
BASE=1, //base frame will be blitted before current one
HORIZONTAL_FLIP=2, //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
PLAY_ONCE=32 //play animation only once and stop at last frame
};
protected:
CAnimation * anim;
std::shared_ptr<CAnimation> anim;
size_t group, frame;//current frame
@ -227,7 +226,6 @@ public:
//clear queue and set animation to this sequence
void clearAndSet(EAnimType type);
CCreatureAnim(int x, int y, std::string name, Rect picPos,
ui8 flags= USE_RLE, EAnimType = HOLDING );
CCreatureAnim(int x, int y, std::string name, ui8 flags = 0, 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);
else
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->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON));

View File

@ -59,7 +59,7 @@
#define ADVOPT (conf.go()->ac)
using namespace CSDL_Ext;
CAdvMapInt *adventureInt;
std::shared_ptr<CAdvMapInt> adventureInt;
static void setScrollingCursor(ui8 direction)
{
@ -565,7 +565,6 @@ CAdvMapInt::CAdvMapInt():
swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false),
swipeTargetPosition(int3(-1, -1, -1))
{
adventureInt = this;
pos.x = pos.y = 0;
pos.w = screen->w;
pos.h = screen->h;
@ -723,7 +722,7 @@ CAdvMapInt::~CAdvMapInt()
void CAdvMapInt::fshowOverview()
{
GH.pushInt(new CKingdomInterface());
GH.pushIntT<CKingdomInterface>();
}
void CAdvMapInt::fworldViewBack()
@ -811,17 +810,17 @@ void CAdvMapInt::fshowSpellbok()
centerOn(selection);
GH.pushInt(new CSpellWindow(curHero(), LOCPLINT, false));
GH.pushIntT<CSpellWindow>(curHero(), LOCPLINT, false);
}
void CAdvMapInt::fadventureOPtions()
{
GH.pushInt(new CAdventureOptions());
GH.pushIntT<CAdventureOptions>();
}
void CAdvMapInt::fsystemOptions()
{
GH.pushInt(new CSystemOptionsWindow());
GH.pushIntT<CSystemOptionsWindow>();
}
void CAdvMapInt::fnextHero()
@ -1088,7 +1087,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
int scrollSpeed = settings["adventure"]["scrollSpeed"].Float();
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if((animValHitCount % (4 / scrollSpeed)) == 0
&& ((GH.topInt() == this) || isCtrlKeyDown()))
&& ((GH.topInt().get() == this) || isCtrlKeyDown()))
{
if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
position.x--;
@ -1224,7 +1223,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
return;
case SDLK_s:
if(isActive() && key.type == SDL_KEYUP)
GH.pushInt(new CSavingScreen());
GH.pushIntT<CSavingScreen>();
return;
case SDLK_d:
{
@ -1274,7 +1273,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
}
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;
leaveCastingMode();
@ -1300,7 +1299,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
}
if(townWithMarket) //if any town has marketplace, open window
GH.pushInt(new CMarketplaceWindow(townWithMarket));
GH.pushIntT<CMarketplaceWindow>(townWithMarket);
else //if not - complain
LOCPLINT->showInfoDialog("No available marketplace!");
}
@ -1957,11 +1956,11 @@ void CAdventureOptions::showScenarioInfo()
{
if(LOCPLINT->cb->getStartInfo()->campState)
{
GH.pushInt(new CBonusSelection());
GH.pushIntT<CBonusSelection>();
}
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"
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),
town(Town),
str(Str),
stateCounter(80)
{
recActions = ACTIVATE | DEACTIVATE | DISPOSE | SHARE_POS;
addUsedEvents(LCLICK | RCLICK | HOVER);
pos.x += str->pos.x;
pos.y += str->pos.y;
@ -131,7 +130,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
else
{
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);
owner->garr->selectSlot(nullptr);
showAll(screen2);
redraw();
}
//refresh statusbar
@ -434,7 +433,7 @@ void CHeroGSlot::clickRight(tribool down, bool previousState)
{
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
{
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):
town(Town),
@ -552,8 +560,7 @@ CCastleBuildings::~CCastleBuildings() = default;
void CCastleBuildings::recreate()
{
selectedBuilding = nullptr;
//TODO: remove show[all] method and try UPDATE+SHOWALL
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(ACTIVATE+SHARE_POS);
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
buildings.clear();
groups.clear();
@ -600,7 +607,8 @@ void CCastleBuildings::recreate()
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)
@ -632,20 +640,6 @@ void CCastleBuildings::removeBuilding(BuildingID building)
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()
{
if(town->visitingHero)
@ -689,7 +683,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case BuildingID::FORT:
case BuildingID::CITADEL:
case BuildingID::CASTLE:
GH.pushInt(new CFortScreen(town));
GH.pushIntT<CFortScreen>(town);
break;
case BuildingID::VILLAGE_HALL:
@ -700,7 +694,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
break;
case BuildingID::MARKETPLACE:
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero));
GH.pushIntT<CMarketplaceWindow>(town, town->visitingHero);
break;
case BuildingID::BLACKSMITH:
@ -718,7 +712,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case ETownType::DUNGEON://Artifact Merchant
case ETownType::CONFLUX:
if(town->visitingHero)
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT));
GH.pushIntT<CMarketplaceWindow>(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT);
else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
break;
@ -742,14 +736,14 @@ void CCastleBuildings::buildingClicked(BuildingID building)
case ETownType::STRONGHOLD: //Freelancer's Guild
if(getHero())
GH.pushInt(new CMarketplaceWindow(town, getHero(), EMarketMode::CREATURE_RESOURCE));
GH.pushIntT<CMarketplaceWindow>(town, getHero(), EMarketMode::CREATURE_RESOURCE);
else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
break;
case ETownType::CONFLUX: //Magic University
if (getHero())
GH.pushInt(new CUniversityWindow(getHero(), town));
GH.pushIntT<CUniversityWindow>(getHero(), town);
else
enterBuilding(building);
break;
@ -772,7 +766,7 @@ void CCastleBuildings::buildingClicked(BuildingID building)
break;
case ETownType::NECROPOLIS: //Skeleton Transformer
GH.pushInt( new CTransformerWindow(getHero(), town) );
GH.pushIntT<CTransformerWindow>(getHero(), town);
break;
case ETownType::DUNGEON: //Portal of Summoning
@ -810,7 +804,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
int price = CGI->arth->artifacts[artifactID]->price;
bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price && !hero->hasArt(artifactID);
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)
@ -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
GH.pushInt(new CObjectListWindow(availableTowns, gateIcon, CGI->generaltexth->jktexts[40],
CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1)));
GH.pushIntT<CObjectListWindow>(availableTowns, gateIcon, CGI->generaltexth->jktexts[40],
CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1));
}
void CCastleBuildings::enterDwelling(int level)
{
assert(level >= 0 && level < town->creatures.size());
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()
{
GH.pushInt(new QuickRecruitmentWindow(town, pos));
GH.pushIntT<QuickRecruitmentWindow>(town, pos);
}
void CCastleBuildings::enterFountain(BuildingID building)
@ -915,7 +909,7 @@ void CCastleBuildings::enterTownHall()
else
{
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
@ -928,12 +922,12 @@ void CCastleBuildings::openMagesGuild()
{
std::string mageGuildBackground;
mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground;
GH.pushInt(new CMageGuildScreen(LOCPLINT->castleInt,mageGuildBackground));
GH.pushIntT<CMageGuildScreen>(LOCPLINT->castleInt,mageGuildBackground);
}
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):
@ -1016,7 +1010,7 @@ void CCreaInfo::clickLeft(tribool down, bool previousState)
{
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 (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
CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->idNumber));
}
@ -1141,7 +1135,8 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
CCastleInterface::~CCastleInterface()
{
LOCPLINT->castleInt = nullptr;
if(LOCPLINT->castleInt == this)
LOCPLINT->castleInt = nullptr;
}
void CCastleInterface::updateGarrisons()
@ -1170,12 +1165,13 @@ void CCastleInterface::castleTeleport(int where)
void CCastleInterface::townChange()
{
//TODO: do not recreate window
const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()];
const CGTownInstance * town = this->town;// "this" is going to be deleted
if ( dest == town )
return;
close();
GH.pushInt(new CCastleInterface(dest, town));
GH.pushIntT<CCastleInterface>(dest, town);
}
void CCastleInterface::addBuilding(BuildingID bid)
@ -1299,13 +1295,13 @@ void CHallInterface::CBuildingBox::hover(bool on)
void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState)
{
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)
{
if(down)
GH.pushInt(new CBuildWindow(town,building,state,1));
GH.pushIntT<CBuildWindow>(town,building,state,1);
}
CHallInterface::CHallInterface(const CGTownInstance * Town):
@ -1756,7 +1752,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art
animBG->needRefresh = true;
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);
title = std::make_shared<CLabel>(165, 28, FONT_BIG, CENTER, Colors::YELLOW,

View File

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

View File

@ -78,8 +78,8 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState)
owner->update(hero, true);
#else
const CGHeroInstance * buf = hero;
GH.popIntTotally(parent);
GH.pushInt(new CHeroWindow(buf));
GH.popInts(1);
GH.pushIntT<CHeroWindow>(buf);
#endif // 0
}
}
@ -297,16 +297,16 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
//if we have exchange window with this curHero open
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)
if(cew->heroInst[g] == curHero)
noDismiss = true;
}
if(dynamic_cast<CKingdomInterface*>(isa))
if(dynamic_cast<CKingdomInterface*>(isa.get()))
noDismiss = true;
}
//if player only have one hero and no towns
@ -374,7 +374,7 @@ void CHeroWindow::commanderWindow()
}
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)
{
if (active)
CMultiLineLabel::showAll (to);
CMultiLineLabel::showAll (to);
}
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)
{
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.x -= 2; // Adjustment needed as we want selection box on top of border in graphics
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.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
GH.popIntTotally(this);
close();
}
void CSpellWindow::fadvSpellsb()
@ -414,13 +414,13 @@ void CSpellWindow::setCurrentPage(int value)
void CSpellWindow::turnPageLeft()
{
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()
{
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)
@ -568,7 +568,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
else //adventure spell
{
const CGHeroInstance * h = owner->myHero;
GH.popInt(owner);
GH.popInts(1);
auto guard = vstd::makeScopeGuard([this]()
{

View File

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

View File

@ -34,8 +34,7 @@
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
CIntObject(getUsedEvents(options_), Point()),
shadow(nullptr),
WindowBase(getUsedEvents(options_), Point()),
options(options_),
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):
CIntObject(getUsedEvents(options_), Point()),
WindowBase(getUsedEvents(options_), Point()),
options(options_),
background(createBg(imageName, options_ & PLAYER_COLORED))
{
@ -122,10 +121,10 @@ void CWindowObject::setShadow(bool on)
//size of shadow
static const int size = 8;
if(on == bool(shadow))
if(on == !shadowParts.empty())
return;
shadow.reset();
shadowParts.clear();
//object too small to cast shadow
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
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
shadow = std::make_shared<CIntObject>();
}
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255);
shadowParts.push_back(std::make_shared<CPicture>(shadowCorner, shadowPos.x, shadowPos.y));
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);
}
void CWindowObject::close()
{
GH.popIntTotally(this);
}
void CWindowObject::clickRight(tribool down, bool previousState)
{
close();

View File

@ -11,13 +11,13 @@
#include "../gui/CIntObject.h"
/// Basic class for windows
class CWindowObject : public CIntObject
class CWindowObject : public WindowBase
{
std::shared_ptr<CPicture> createBg(std::string imageName, bool playerColored);
int getUsedEvents(int options);
std::shared_ptr<CIntObject> shadow;
std::vector<std::shared_ptr<CPicture>> shadowParts;
void setShadow(bool on);
int options;
@ -25,8 +25,6 @@ class CWindowObject : public CIntObject
protected:
std::shared_ptr<CPicture> background;
//Simple function with call to GH.popInt
void close();
//Used only if RCLICK_POPUP was set
void clickRight(tribool down, bool previousState) override;
//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)
{
if(down)
GH.pushInt(new CStackWindow(creature, true));
GH.pushIntT<CStackWindow>(creature, true);
}
void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to)
@ -569,8 +569,7 @@ void CSystemOptionsWindow::selectGameRes()
items.push_back(resX + 'x' + resY);
}
GH.pushInt(new CObjectListWindow(items, nullptr, texts["label"].String(), texts["help"].String(),
std::bind(&CSystemOptionsWindow::setGameRes, this, _1)));
GH.pushIntT<CObjectListWindow>(items, nullptr, texts["label"].String(), texts["help"].String(), std::bind(&CSystemOptionsWindow::setGameRes, this, _1));
}
void CSystemOptionsWindow::setGameRes(int index)
@ -599,7 +598,7 @@ void CSystemOptionsWindow::bquitf()
void CSystemOptionsWindow::breturnf()
{
GH.popIntTotally(this);
close();
}
void CSystemOptionsWindow::bmainmenuf()
@ -609,14 +608,14 @@ void CSystemOptionsWindow::bmainmenuf()
void CSystemOptionsWindow::bloadf()
{
GH.popIntTotally(this);
close();
LOCPLINT->proposeLoadingGame();
}
void CSystemOptionsWindow::bsavef()
{
GH.popIntTotally(this);
GH.pushInt(new CSavingScreen());
close();
GH.pushIntT<CSavingScreen>();
}
void CSystemOptionsWindow::brestartf()
@ -626,7 +625,7 @@ void CSystemOptionsWindow::brestartf()
void CSystemOptionsWindow::closeAndPushEvent(int eventType, int code)
{
GH.popIntTotally(this);
close();
GH.pushSDLEvent(eventType, code);
}
@ -705,7 +704,7 @@ void CTavernWindow::recruitb()
void CTavernWindow::thievesguildb()
{
GH.pushInt( new CThievesGuildWindow(tavernObj) );
GH.pushIntT<CThievesGuildWindow>(tavernObj);
}
CTavernWindow::~CTavernWindow()
@ -745,9 +744,7 @@ void CTavernWindow::HeroPortrait::clickLeft(tribool down, bool previousState)
void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState)
{
if(h && down)
{
GH.pushInt(new CRClickPopupInt(new CHeroWindow(h), true));
}
GH.pushIntT<CRClickPopupInt>(std::make_shared<CHeroWindow>(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_"};
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);
// Create resource icons and costs.
@ -1110,7 +1107,7 @@ void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState)
if(previousState && (!down))
{
move();
parent->showAll(screen2);
parent->redraw();
}
}
@ -1152,7 +1149,7 @@ void CTransformerWindow::addAll()
if(elem->left)
elem->move();
}
showAll(screen2);
redraw();
}
void CTransformerWindow::updateGarrisons()
@ -1215,10 +1212,7 @@ void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
if(previousState && (!down))
{
if(state() == 2)
{
auto win = new CUnivConfirmWindow(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000);
GH.pushInt(win);
}
GH.pushIntT<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(Res::GOLD) >= 2000);
}
}
@ -1813,14 +1807,14 @@ void CObjectListWindow::elementSelected()
{
std::function<void(int)> toCall = onSelect;//save
int where = items[selected].first; //required variables
GH.popIntTotally(this);//then destroy window
close();//then destroy window
toCall(where);//and send selected object
}
void CObjectListWindow::exitPressed()
{
std::function<void()> toCall = onExit;//save
GH.popIntTotally(this);//then destroy window
close();//then destroy window
if(toCall)
toCall();
}

View File

@ -161,7 +161,8 @@ CInfoWindow::CInfoWindow()
void CInfoWindow::close()
{
GH.popIntTotally(this);
WindowBase::close();
if(LOCPLINT)
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)
{
CInfoWindow * window = CInfoWindow::create(text, player, components);
GH.pushInt(window);
GH.pushInt(CInfoWindow::create(text, player, components));
}
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;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.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[1]->addCallback( onNo );
@ -199,22 +199,11 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & c
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;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
CInfoWindow * temp = new CInfoWindow(text, player, 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;
return std::make_shared<CInfoWindow>(text, playerID, components, pom);
}
std::string CInfoWindow::genText(std::string title, std::string description)
@ -268,7 +257,7 @@ void CInfoPopup::close()
{
if(free)
SDL_FreeSurface(bitmap);
GH.popIntTotally(this);
WindowBase::close();
}
void CInfoPopup::show(SDL_Surface * to)
@ -307,7 +296,7 @@ void CRClickPopup::clickRight(tribool down, bool previousState)
void CRClickPopup::close()
{
GH.popIntTotally(this);
WindowBase::close();
}
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
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->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)
@ -331,14 +320,16 @@ void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CCompo
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)
{
GH.pushInt(iWin);
}
else
{
if (adventureInt->curHero())
if(adventureInt->curHero())
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
else
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
@ -354,31 +345,20 @@ CRClickPopup::~CRClickPopup()
{
}
void CRClickPopupInt::show(SDL_Surface * to)
{
inner->show(to);
}
CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt )
CRClickPopupInt::CRClickPopupInt(std::shared_ptr<CIntObject> our)
{
CCS->curh->hide();
defActions = SHOWALL | UPDATE;
our->recActions = defActions;
inner = our;
delInner = deleteInt;
addChild(our.get(), false);
}
CRClickPopupInt::~CRClickPopupInt()
{
if(delInner)
delete inner;
CCS->curh->show();
}
void CRClickPopupInt::showAll(SDL_Surface * to)
{
inner->showAll(to);
}
Point CInfoBoxPopup::toScreen(Point p)
{
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);
}
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)
specific = adventureInt->selection;
@ -431,13 +411,13 @@ CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance
switch(specific->ID)
{
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:
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::GARRISON2:
return new CInfoBoxPopup(position, dynamic_cast<const CGGarrison *>(specific));
return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGGarrison *>(specific));
default:
return nullptr;
return std::shared_ptr<WindowBase>();
}
}

View File

@ -26,11 +26,11 @@ class CSlider;
class CArmyTooltip;
// Window GUI class
class CSimpleWindow : public CIntObject
class CSimpleWindow : public WindowBase
{
public:
SDL_Surface * bitmap; //background
virtual void show(SDL_Surface * to) override;
void show(SDL_Surface * to) override;
CSimpleWindow():bitmap(nullptr){};
virtual ~CSimpleWindow();
};
@ -58,16 +58,15 @@ public:
//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 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 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
static std::string genText(std::string title, std::string description);
};
/// popup displayed on R-click
class CRClickPopup : public CIntObject
class CRClickPopup : public WindowBase
{
public:
virtual void close();
@ -76,7 +75,7 @@ public:
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, std::shared_ptr<CComponent> component);
static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT);
@ -85,13 +84,9 @@ public:
/// popup displayed on R-click
class CRClickPopupInt : public CRClickPopup
{
std::shared_ptr<CIntObject> inner;
public:
IShowActivatable *inner;
bool delInner;
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
CRClickPopupInt(IShowActivatable *our, bool deleteInt);
CRClickPopupInt(std::shared_ptr<CIntObject> our);
virtual ~CRClickPopupInt();
};
@ -123,11 +118,11 @@ public:
/// component selection window
class CSelWindow : public CInfoWindow
{ //warning - this window deletes its components by closing!
{
public:
void selectionChange(unsigned to);
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(){};
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);
//notification - this class inherits important destructor from CInfoWindow
};