mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Split CIntObjectClasses into multiple smaller files. This should be the last change in files
This commit is contained in:
parent
a69fcdd435
commit
731aedf3a1
@ -39,6 +39,7 @@
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "../lib/logging/CBasicLogConfigurator.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "SDL_syswm.h"
|
||||
|
@ -14,6 +14,7 @@ set(client_SRCS
|
||||
battle/CBattleInterfaceClasses.cpp
|
||||
battle/CCreatureAnimation.cpp
|
||||
|
||||
gui/CAnimation.cpp
|
||||
gui/CCursorHandler.cpp
|
||||
gui/CGuiHandler.cpp
|
||||
gui/CIntObject.cpp
|
||||
@ -22,12 +23,14 @@ set(client_SRCS
|
||||
gui/SDL_Extensions.cpp
|
||||
|
||||
widgets/AdventureMapClasses.cpp
|
||||
widgets/CAnimation.cpp
|
||||
widgets/Buttons.cpp
|
||||
widgets/CArtifactHolder.cpp
|
||||
widgets/CComponent.cpp
|
||||
widgets/CGarrisonInt.cpp
|
||||
widgets/CIntObjectClasses.cpp
|
||||
widgets/Images.cpp
|
||||
widgets/MiscWidgets.cpp
|
||||
widgets/ObjectLists.cpp
|
||||
widgets/TextControls.cpp
|
||||
|
||||
windows/CAdvmapInterface.cpp
|
||||
windows/CCastleInterface.cpp
|
||||
@ -37,6 +40,8 @@ set(client_SRCS
|
||||
windows/CQuestLog.cpp
|
||||
windows/CSpellWindow.cpp
|
||||
windows/CTradeWindow.cpp
|
||||
windows/CWindowObject
|
||||
windows/InfoWindows.cpp
|
||||
windows/GUIClasses.cpp
|
||||
|
||||
CBitmapHandler.cpp
|
||||
@ -54,6 +59,11 @@ set(client_SRCS
|
||||
NetPacksClient.cpp
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
gui/SDL_Pixels.h
|
||||
gui/SDL_Compat.h
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
# OS X specific includes
|
||||
include_directories(${SPARKLE_INCLUDE_DIR})
|
||||
|
@ -11,9 +11,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMessage.h"
|
||||
|
||||
#include "SDL_ttf.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "widgets/CAnimation.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
@ -21,8 +19,11 @@
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "CBitmapHandler.h"
|
||||
#include "widgets/CIntObjectClasses.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
|
||||
#include "widgets/CComponent.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "widgets/Buttons.h"
|
||||
#include "widgets/TextControls.h"
|
||||
|
||||
const int BETWEEN_COMPS_ROWS = 10;
|
||||
const int BEFORE_COMPONENTS = 30;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "CMessage.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "widgets/CComponent.h"
|
||||
#include "windows/CTradeWindow.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "battle/CCreatureAnimation.h"
|
||||
@ -37,8 +38,9 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include <SDL.h>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../lib/CondSh.h"
|
||||
//#include "../lib/CondSh.h"
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/CGameInterface.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "gui/CIntObject.h"
|
||||
#include "../lib/CGameState.h"
|
||||
//#include "../lib/CGameState.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define sprintf_s snprintf
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "gui/CCursorHandler.h"
|
||||
#include "widgets/CAnimation.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
@ -38,8 +37,13 @@
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/CIntObjectClasses.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include "widgets/CComponent.h"
|
||||
#include "widgets/Buttons.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "widgets/ObjectLists.h"
|
||||
#include "widgets/TextControls.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "../lib/mapping/CMapService.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
|
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
//#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/mapping/CMapInfo.h"
|
||||
#include "../lib/rmg/CMapGenerator.h"
|
||||
#include "widgets/CIntObjectClasses.h"
|
||||
#include "windows/CWindowObject.h"
|
||||
|
||||
/*
|
||||
* CPreGame.h, part of VCMI engine
|
||||
@ -17,6 +17,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CMapInfo;
|
||||
class CMusicHandler;
|
||||
class CMapHeader;
|
||||
class CCampaignHeader;
|
||||
@ -31,6 +32,12 @@ class CMapGenOptions;
|
||||
class CRandomMapTab;
|
||||
struct CPackForSelectionScreen;
|
||||
struct PlayerInfo;
|
||||
class CMultiLineLabel;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
class CTabbedInt;
|
||||
class CAdventureMapButton;
|
||||
class CSlider;
|
||||
|
||||
namespace boost{ class thread; class recursive_mutex;}
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "Client.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "CMusicHandler.h"
|
||||
#include "../lib/mapping/CCampaignHandler.h"
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/CondSh.h"
|
||||
#include "../lib/BattleAction.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/int3.h"
|
||||
|
||||
/*
|
||||
* Client.h, part of VCMI engine
|
||||
@ -15,6 +16,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CPack;
|
||||
class CCampaignState;
|
||||
class CBattleCallback;
|
||||
class IGameEventsReceiver;
|
||||
class IBattleEventsReceiver;
|
||||
class CBattleGameInterface;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "../lib/vcmi_endian.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "widgets/CAnimation.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
/*
|
||||
* CBattleAnimations.cpp, part of VCMI engine
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../../lib/BattleHex.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../windows/CCreatureWindow.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
@ -31,6 +30,7 @@
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
|
@ -1,12 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../lib/CCreatureSet.h"
|
||||
//#include "../../lib/CCreatureSet.h"
|
||||
#include "../../lib/ConstTransitivePtr.h" //may be reundant
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
#include "../widgets/CAnimation.h"
|
||||
|
||||
#include "CBattleAnimations.h"
|
||||
|
||||
/*
|
||||
|
@ -14,7 +14,8 @@
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/CCreatureWindow.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
|
||||
@ -22,10 +23,12 @@
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
|
||||
/*
|
||||
* CBattleInterfaceClasses.cpp, part of VCMI engine
|
||||
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
/*
|
||||
* CCreatureAnimation.h, part of VCMI engine
|
||||
|
@ -1222,319 +1222,3 @@ void CAnimation::getAnimInfo()
|
||||
logGlobal->errorStream()<<", "<<anim->images.begin()->second.size()<<" image loaded in group "<< anim->images.begin()->first;
|
||||
}
|
||||
}
|
||||
|
||||
CAnimImage::CAnimImage(std::string name, size_t Frame, size_t Group, int x, int y, ui8 Flags):
|
||||
frame(Frame),
|
||||
group(Group),
|
||||
player(-1),
|
||||
flags(Flags)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
anim = new CAnimation(name);
|
||||
init();
|
||||
}
|
||||
|
||||
CAnimImage::CAnimImage(CAnimation *Anim, size_t Frame, size_t Group, int x, int y, ui8 Flags):
|
||||
anim(Anim),
|
||||
frame(Frame),
|
||||
group(Group),
|
||||
player(-1),
|
||||
flags(Flags)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
init();
|
||||
}
|
||||
|
||||
size_t CAnimImage::size()
|
||||
{
|
||||
return anim->size(group);
|
||||
}
|
||||
|
||||
void CAnimImage::init()
|
||||
{
|
||||
anim->load(frame, group);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->load(0,group);
|
||||
|
||||
IImage *img = anim->getImage(frame, group);
|
||||
if (img)
|
||||
{
|
||||
pos.w = img->width();
|
||||
pos.h = img->height();
|
||||
}
|
||||
}
|
||||
|
||||
CAnimImage::~CAnimImage()
|
||||
{
|
||||
anim->unload(frame, group);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->unload(0,group);
|
||||
delete anim;
|
||||
}
|
||||
|
||||
void CAnimImage::showAll(SDL_Surface * to)
|
||||
{
|
||||
IImage *img;
|
||||
|
||||
if ( flags & CShowableAnim::BASE && frame != 0)
|
||||
if ((img = anim->getImage(0, group)))
|
||||
img->draw(to, pos.x, pos.y);
|
||||
|
||||
if ((img = anim->getImage(frame, group)))
|
||||
img->draw(to, pos.x, pos.y);
|
||||
}
|
||||
|
||||
void CAnimImage::setFrame(size_t Frame, size_t Group)
|
||||
{
|
||||
if (frame == Frame && group==Group)
|
||||
return;
|
||||
if (anim->size(Group) > Frame)
|
||||
{
|
||||
anim->load(Frame, Group);
|
||||
anim->unload(frame, group);
|
||||
frame = Frame;
|
||||
group = Group;
|
||||
IImage *img = anim->getImage(frame, group);
|
||||
if (img)
|
||||
{
|
||||
if (flags & CShowableAnim::PLAYER_COLORED)
|
||||
img->playerColored(player);
|
||||
pos.w = img->width();
|
||||
pos.h = img->height();
|
||||
}
|
||||
}
|
||||
else
|
||||
logGlobal->errorStream() << "Error: accessing unavailable frame " << Group << ":" << Frame << " in CAnimation!";
|
||||
}
|
||||
|
||||
void CAnimImage::playerColored(PlayerColor currPlayer)
|
||||
{
|
||||
player = currPlayer;
|
||||
flags |= CShowableAnim::PLAYER_COLORED;
|
||||
anim->getImage(frame, group)->playerColored(player);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->getImage(0, group)->playerColored(player);
|
||||
}
|
||||
|
||||
CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Delay, size_t Group):
|
||||
anim(name, Flags & USE_RLE),
|
||||
group(Group),
|
||||
frame(0),
|
||||
first(0),
|
||||
frameDelay(Delay),
|
||||
value(0),
|
||||
flags(Flags),
|
||||
xOffset(0),
|
||||
yOffset(0),
|
||||
alpha(255)
|
||||
{
|
||||
anim.loadGroup(group);
|
||||
last = anim.size(group);
|
||||
|
||||
pos.w = anim.getImage(0, group)->width();
|
||||
pos.h = anim.getImage(0, group)->height();
|
||||
pos.x+= x;
|
||||
pos.y+= y;
|
||||
}
|
||||
|
||||
CShowableAnim::~CShowableAnim()
|
||||
{
|
||||
anim.unloadGroup(group);
|
||||
}
|
||||
|
||||
void CShowableAnim::setAlpha(ui32 alphaValue)
|
||||
{
|
||||
alpha = std::min<ui32>(alphaValue, 255);
|
||||
}
|
||||
|
||||
bool CShowableAnim::set(size_t Group, size_t from, size_t to)
|
||||
{
|
||||
size_t max = anim.size(Group);
|
||||
|
||||
if (to < max)
|
||||
max = to;
|
||||
|
||||
if (max < from || max == 0)
|
||||
return false;
|
||||
|
||||
anim.load(Group);
|
||||
anim.unload(group);
|
||||
group = Group;
|
||||
frame = first = from;
|
||||
last = max;
|
||||
value = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShowableAnim::set(size_t Group)
|
||||
{
|
||||
if (anim.size(Group)== 0)
|
||||
return false;
|
||||
if (group != Group)
|
||||
{
|
||||
anim.loadGroup(Group);
|
||||
anim.unloadGroup(group);
|
||||
first = 0;
|
||||
group = Group;
|
||||
last = anim.size(Group);
|
||||
}
|
||||
frame = value = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CShowableAnim::reset()
|
||||
{
|
||||
value = 0;
|
||||
frame = first;
|
||||
|
||||
if (callback)
|
||||
callback();
|
||||
}
|
||||
|
||||
void CShowableAnim::clipRect(int posX, int posY, int width, int height)
|
||||
{
|
||||
xOffset = posX;
|
||||
yOffset = posY;
|
||||
pos.w = width;
|
||||
pos.h = height;
|
||||
}
|
||||
|
||||
void CShowableAnim::show(SDL_Surface * to)
|
||||
{
|
||||
if ( flags & BASE )// && frame != first) // FIXME: results in graphical glytch in Fortress, upgraded hydra's dwelling
|
||||
blitImage(first, group, to);
|
||||
blitImage(frame, group, to);
|
||||
|
||||
if ((flags & PLAY_ONCE) && frame + 1 == last)
|
||||
return;
|
||||
|
||||
if ( ++value == frameDelay )
|
||||
{
|
||||
value = 0;
|
||||
if ( ++frame >= last)
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CShowableAnim::showAll(SDL_Surface * to)
|
||||
{
|
||||
if ( flags & BASE )// && frame != first)
|
||||
blitImage(first, group, to);
|
||||
blitImage(frame, group, to);
|
||||
}
|
||||
|
||||
void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
|
||||
{
|
||||
assert(to);
|
||||
Rect src( xOffset, yOffset, pos.w, pos.h);
|
||||
IImage * img = anim.getImage(frame, group);
|
||||
if (img)
|
||||
img->draw(to, pos.x-xOffset, pos.y-yOffset, &src, alpha);
|
||||
}
|
||||
|
||||
void CShowableAnim::rotate(bool on, bool vertical)
|
||||
{
|
||||
ui8 flag = vertical? VERTICAL_FLIP:HORIZONTAL_FLIP;
|
||||
if (on)
|
||||
flags |= flag;
|
||||
else
|
||||
flags &= ~flag;
|
||||
}
|
||||
|
||||
CCreatureAnim::CCreatureAnim(int x, int y, std::string name, Rect picPos, 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;
|
||||
};
|
||||
|
||||
void CCreatureAnim::loopPreview(bool warMachine)
|
||||
{
|
||||
std::vector<EAnimType> available;
|
||||
|
||||
static const EAnimType creaPreviewList[] = {HOLDING, HITTED, DEFENCE, ATTACK_FRONT, CAST_FRONT};
|
||||
static const EAnimType machPreviewList[] = {HOLDING, MOVING, SHOOT_UP, SHOOT_FRONT, SHOOT_DOWN};
|
||||
auto & previewList = warMachine ? machPreviewList : creaPreviewList;
|
||||
|
||||
for (auto & elem : previewList)
|
||||
if (anim.size(elem))
|
||||
available.push_back(elem);
|
||||
|
||||
size_t rnd = CRandomGenerator::getDefault().nextInt(available.size() * 2 - 1);
|
||||
|
||||
if (rnd >= available.size())
|
||||
{
|
||||
EAnimType type;
|
||||
if ( anim.size(MOVING) == 0 )//no moving animation present
|
||||
type = HOLDING;
|
||||
else
|
||||
type = MOVING;
|
||||
|
||||
//display this anim for ~1 second (time is random, but it looks good)
|
||||
for (size_t i=0; i< 12/anim.size(type) + 1; i++)
|
||||
addLast(type);
|
||||
}
|
||||
else
|
||||
addLast(available[rnd]);
|
||||
}
|
||||
|
||||
void CCreatureAnim::addLast(EAnimType newType)
|
||||
{
|
||||
if (type != MOVING && newType == MOVING)//starting moving - play init sequence
|
||||
{
|
||||
queue.push( MOVE_START );
|
||||
}
|
||||
else if (type == MOVING && newType != MOVING )//previous anim was moving - finish it
|
||||
{
|
||||
queue.push( MOVE_END );
|
||||
}
|
||||
if (newType == TURN_L || newType == TURN_R)
|
||||
queue.push(newType);
|
||||
|
||||
queue.push(newType);
|
||||
}
|
||||
|
||||
void CCreatureAnim::reset()
|
||||
{
|
||||
//if we are in the middle of rotation - set flag
|
||||
if (type == TURN_L && !queue.empty() && queue.front() == TURN_L)
|
||||
rotate(true);
|
||||
if (type == TURN_R && !queue.empty() && queue.front() == TURN_R)
|
||||
rotate(false);
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
EAnimType at = queue.front();
|
||||
queue.pop();
|
||||
if (set(at))
|
||||
return;
|
||||
}
|
||||
if (callback)
|
||||
callback();
|
||||
while (!queue.empty())
|
||||
{
|
||||
EAnimType at = queue.front();
|
||||
queue.pop();
|
||||
if (set(at))
|
||||
return;
|
||||
}
|
||||
set(HOLDING);
|
||||
}
|
||||
|
||||
void CCreatureAnim::startPreview(bool warMachine)
|
||||
{
|
||||
callback = boost::bind(&CCreatureAnim::loopPreview, this, warMachine);
|
||||
}
|
||||
|
||||
void CCreatureAnim::clearAndSet(EAnimType type)
|
||||
{
|
||||
while (!queue.empty())
|
||||
queue.pop();
|
||||
set(type);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "gui/Geometries.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
/*
|
||||
* CAnimation.h, part of VCMI engine
|
||||
@ -219,162 +220,3 @@ public:
|
||||
//total count of frames in group (including not loaded)
|
||||
size_t size(size_t group=0) const;
|
||||
};
|
||||
|
||||
|
||||
/// Class for displaying one image from animation
|
||||
class CAnimImage: public CIntObject
|
||||
{
|
||||
private:
|
||||
CAnimation* anim;
|
||||
//displayed frame/group
|
||||
size_t frame;
|
||||
size_t group;
|
||||
PlayerColor player;
|
||||
ui8 flags;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
CAnimImage(std::string name, size_t Frame, size_t Group=0, int x=0, int y=0, ui8 Flags=0);
|
||||
CAnimImage(CAnimation* anim, size_t Frame, size_t Group=0, int x=0, int y=0, ui8 Flags=0);
|
||||
~CAnimImage();//d-tor
|
||||
|
||||
//size of animation
|
||||
size_t size();
|
||||
|
||||
//change displayed frame on this one
|
||||
void setFrame(size_t Frame, size_t Group=0);
|
||||
|
||||
//makes image player-colored
|
||||
void playerColored(PlayerColor player);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// Base class for displaying animation, used as superclass for different animations
|
||||
class CShowableAnim: public CIntObject
|
||||
{
|
||||
public:
|
||||
enum EFlags
|
||||
{
|
||||
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;
|
||||
|
||||
size_t group, frame;//current frame
|
||||
|
||||
size_t first, last; //animation range
|
||||
|
||||
//TODO: replace with time delay(needed for battles)
|
||||
ui32 frameDelay;//delay in frames of each image
|
||||
ui32 value;//how many times current frame was showed
|
||||
|
||||
ui8 flags;//Flags from EFlags enum
|
||||
|
||||
//blit image with optional rotation, fitting into rect, etc
|
||||
void blitImage(size_t frame, size_t group, SDL_Surface *to);
|
||||
|
||||
//For clipping in rect, offsets of picture coordinates
|
||||
int xOffset, yOffset;
|
||||
|
||||
ui8 alpha;
|
||||
|
||||
public:
|
||||
//called when next animation sequence is required
|
||||
std::function<void()> callback;
|
||||
|
||||
//Set per-surface alpha, 0 = transparent, 255 = opaque
|
||||
void setAlpha(ui32 alphaValue);
|
||||
|
||||
CShowableAnim(int x, int y, std::string name, ui8 flags=0, ui32 Delay=4, size_t Group=0);
|
||||
~CShowableAnim();
|
||||
|
||||
//set animation to group or part of group
|
||||
bool set(size_t Group);
|
||||
bool set(size_t Group, size_t from, size_t to=-1);
|
||||
|
||||
//set rotation flags
|
||||
void rotate(bool on, bool vertical=false);
|
||||
|
||||
//move displayed part of picture (if picture is clipped to rect)
|
||||
void clipRect(int posX, int posY, int width, int height);
|
||||
|
||||
//set frame to first, call callback
|
||||
virtual void reset();
|
||||
|
||||
//show current frame and increase counter
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// Creature-dependend animations like attacking, moving,...
|
||||
class CCreatureAnim: public CShowableAnim
|
||||
{
|
||||
public:
|
||||
|
||||
enum EHeroAnimType
|
||||
{
|
||||
HERO_HOLDING = 0,
|
||||
HERO_IDLE = 1, // idling movement that happens from time to time
|
||||
HERO_DEFEAT = 2, // played when army loses stack or on friendly fire
|
||||
HERO_VICTORY = 3, // when enemy stack killed or huge damage is dealt
|
||||
HERO_CAST_SPELL = 4 // spellcasting
|
||||
};
|
||||
|
||||
enum EAnimType // list of creature animations, numbers were taken from def files
|
||||
{
|
||||
MOVING=0,
|
||||
MOUSEON=1,
|
||||
HOLDING=2,
|
||||
HITTED=3,
|
||||
DEFENCE=4,
|
||||
DEATH=5,
|
||||
//DEATH2=6, //unused?
|
||||
TURN_L=7,
|
||||
TURN_R=8, //same
|
||||
//TURN_L2=9, //identical to previous?
|
||||
//TURN_R2=10,
|
||||
ATTACK_UP=11,
|
||||
ATTACK_FRONT=12,
|
||||
ATTACK_DOWN=13,
|
||||
SHOOT_UP=14,
|
||||
SHOOT_FRONT=15,
|
||||
SHOOT_DOWN=16,
|
||||
CAST_UP=17,
|
||||
CAST_FRONT=18,
|
||||
CAST_DOWN=19,
|
||||
MOVE_START=20,
|
||||
MOVE_END=21,
|
||||
DEAD = 22 // new group, used to show dead stacks. If empty - last frame from "DEATH" will be copied here
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
//queue of animations waiting to be displayed
|
||||
std::queue<EAnimType> queue;
|
||||
|
||||
//this function is used as callback if preview flag was set during construction
|
||||
void loopPreview(bool warMachine);
|
||||
|
||||
public:
|
||||
//change anim to next if queue is not empty, call callback othervice
|
||||
void reset();
|
||||
|
||||
//add sequence to the end of queue
|
||||
void addLast(EAnimType newType);
|
||||
|
||||
void startPreview(bool warMachine);
|
||||
|
||||
//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 );
|
||||
|
||||
};
|
@ -5,9 +5,9 @@
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
#include "CGuiHandler.h"
|
||||
#include "widgets/Images.h"
|
||||
|
||||
#include "../CMT.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
|
||||
/*
|
||||
* CCursorHandler.cpp, part of VCMI engine
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "StdInc.h"
|
||||
#include "CGuiHandler.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "CIntObject.h"
|
||||
#include "CCursorHandler.h"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/CStopWatch.h"
|
||||
//#include "../../lib/CStopWatch.h"
|
||||
#include "Geometries.h"
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SDL_events.h>
|
||||
//#include <SDL_events.h>
|
||||
#include "Geometries.h"
|
||||
#include "../Graphics.h"
|
||||
|
||||
@ -18,6 +18,8 @@ struct SDL_Surface;
|
||||
class CPicture;
|
||||
class CGuiHandler;
|
||||
|
||||
struct SDL_KeyboardEvent;
|
||||
|
||||
using boost::logic::tribool;
|
||||
|
||||
// Defines a activate/deactive method
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include "StdInc.h"
|
||||
#include "Geometries.h"
|
||||
#include "../CMT.h"
|
||||
#include <SDL_events.h>
|
||||
|
||||
Point::Point(const SDL_MouseMotionEvent &a)
|
||||
:x(a.x),y(a.y)
|
||||
{}
|
||||
|
||||
Rect Rect::createCentered( int w, int h )
|
||||
{
|
||||
@ -15,4 +20,4 @@ Rect Rect::around(const Rect &r, int width /*= 1*/) /*creates rect around anothe
|
||||
Rect Rect::centerIn(const Rect &r)
|
||||
{
|
||||
return Rect(r.x + (r.w - w) / 2, r.y + (r.h - h) / 2, w, h);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL_video.h>
|
||||
#include <SDL_events.h>
|
||||
#include "../../lib/int3.h"
|
||||
|
||||
/*
|
||||
@ -21,6 +20,7 @@
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
struct SDL_MouseMotionEvent;
|
||||
|
||||
// A point with x/y coordinate, used mostly for graphic rendering
|
||||
struct Point
|
||||
@ -38,9 +38,7 @@ struct Point
|
||||
Point(const int3 &a)
|
||||
:x(a.x),y(a.y)
|
||||
{}
|
||||
Point(const SDL_MouseMotionEvent &a)
|
||||
:x(a.x),y(a.y)
|
||||
{}
|
||||
Point(const SDL_MouseMotionEvent &a);
|
||||
|
||||
template<typename T>
|
||||
Point operator+(const T &b) const
|
||||
@ -265,4 +263,4 @@ struct Rect : public SDL_Rect
|
||||
ret.h = y2 -ret.y;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -16,10 +16,11 @@
|
||||
#endif
|
||||
|
||||
#include <SDL_video.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <SDL_events.h>
|
||||
#include "../../lib/int3.h"
|
||||
#include "../Graphics.h"
|
||||
//#include "../Graphics.h"
|
||||
#include "Geometries.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
|
||||
//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "StdInc.h"
|
||||
#include "AdventureMapClasses.h"
|
||||
|
||||
#include "CAnimation.h"
|
||||
#include <SDL.h>
|
||||
|
||||
#include "MiscWidgets.h"
|
||||
#include "CComponent.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
@ -13,6 +15,7 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
|
||||
@ -34,7 +37,7 @@
|
||||
#include "../../lib/StringConstants.h"
|
||||
|
||||
/*
|
||||
* CAdventureMapClasses.h, part of VCMI engine
|
||||
* CAdventureMapClasses.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
@ -1205,38 +1208,3 @@ CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDi
|
||||
addUsedEvents(KEYBOARD | TEXTINPUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
CAdventureOptions::CAdventureOptions():
|
||||
CWindowObject(PLAYER_COLORED, "ADVOPTS")
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
exit = new CAdventureMapButton("","",boost::bind(&CAdventureOptions::close, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
|
||||
exit->assignedKeys.insert(SDLK_ESCAPE);
|
||||
|
||||
scenInfo = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 198, "ADVINFO.DEF",SDLK_i);
|
||||
scenInfo->callback += CAdventureOptions::showScenarioInfo;
|
||||
//viewWorld = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
|
||||
|
||||
puzzle = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 81, "ADVPUZ.DEF");
|
||||
puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
|
||||
|
||||
dig = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 139, "ADVDIG.DEF");
|
||||
if(const CGHeroInstance *h = adventureInt->curHero())
|
||||
dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h);
|
||||
else
|
||||
dig->block(true);
|
||||
}
|
||||
|
||||
void CAdventureOptions::showScenarioInfo()
|
||||
{
|
||||
auto campState = LOCPLINT->cb->getStartInfo()->campState;
|
||||
if(campState)
|
||||
{
|
||||
GH.pushInt(new CBonusSelection(campState));
|
||||
}
|
||||
else
|
||||
{
|
||||
GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo()));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CIntObjectClasses.h"
|
||||
#include "ObjectLists.h"
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
class CArmedInstance;
|
||||
class CShowableAnim;
|
||||
@ -8,6 +9,7 @@ class CGGarrison;
|
||||
class CGObjectInstance;
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
class CAdventureMapButton;
|
||||
struct Component;
|
||||
struct InfoAboutArmy;
|
||||
struct InfoAboutHero;
|
||||
@ -339,13 +341,3 @@ public:
|
||||
|
||||
CInGameConsole(); //c-tor
|
||||
};
|
||||
|
||||
/// Adventure options dialogue where you can view the world, dig, play the replay of the last turn,...
|
||||
class CAdventureOptions : public CWindowObject
|
||||
{
|
||||
public:
|
||||
CAdventureMapButton *exit, *viewWorld, *puzzle, *dig, *scenInfo, *replay;
|
||||
|
||||
CAdventureOptions();
|
||||
static void showScenarioInfo();
|
||||
};
|
||||
|
732
client/widgets/Buttons.cpp
Normal file
732
client/widgets/Buttons.cpp
Normal file
@ -0,0 +1,732 @@
|
||||
#include "StdInc.h"
|
||||
#include "Buttons.h"
|
||||
|
||||
#include "Images.h"
|
||||
#include "TextControls.h"
|
||||
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../battle/CBattleInterface.h"
|
||||
#include "../battle/CBattleInterfaceClasses.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
/*
|
||||
* Buttons.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
CButtonBase::CButtonBase()
|
||||
{
|
||||
swappedImages = keepFrame = false;
|
||||
bitmapOffset = 0;
|
||||
state=NORMAL;
|
||||
image = nullptr;
|
||||
overlay = nullptr;
|
||||
}
|
||||
|
||||
CButtonBase::~CButtonBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CButtonBase::update()
|
||||
{
|
||||
if (overlay)
|
||||
{
|
||||
if (state == PRESSED)
|
||||
overlay->moveTo(overlay->pos.centerIn(pos).topLeft() + Point(1,1));
|
||||
else
|
||||
overlay->moveTo(overlay->pos.centerIn(pos).topLeft());
|
||||
}
|
||||
|
||||
int newPos = (int)state + bitmapOffset;
|
||||
if (newPos < 0)
|
||||
newPos = 0;
|
||||
|
||||
if (state == HIGHLIGHTED && image->size() < 4)
|
||||
newPos = image->size()-1;
|
||||
|
||||
if (swappedImages)
|
||||
{
|
||||
if (newPos == 0) newPos = 1;
|
||||
else if (newPos == 1) newPos = 0;
|
||||
}
|
||||
|
||||
if (!keepFrame)
|
||||
image->setFrame(newPos);
|
||||
|
||||
if (active)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CButtonBase::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
addOverlay(new CLabel(pos.w/2, pos.h/2, font, CENTER, color, Text));
|
||||
update();
|
||||
}
|
||||
|
||||
void CButtonBase::addOverlay(CIntObject *newOverlay)
|
||||
{
|
||||
delete overlay;
|
||||
overlay = newOverlay;
|
||||
addChild(newOverlay);
|
||||
overlay->moveTo(overlay->pos.centerIn(pos).topLeft());
|
||||
update();
|
||||
}
|
||||
|
||||
void CButtonBase::setOffset(int newOffset)
|
||||
{
|
||||
if (bitmapOffset == newOffset)
|
||||
return;
|
||||
bitmapOffset = newOffset;
|
||||
update();
|
||||
}
|
||||
|
||||
void CButtonBase::setState(ButtonState newState)
|
||||
{
|
||||
if (state == newState)
|
||||
return;
|
||||
state = newState;
|
||||
update();
|
||||
}
|
||||
|
||||
CButtonBase::ButtonState CButtonBase::getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
bool CButtonBase::isBlocked()
|
||||
{
|
||||
return state == BLOCKED;
|
||||
}
|
||||
|
||||
bool CButtonBase::isHighlighted()
|
||||
{
|
||||
return state == HIGHLIGHTED;
|
||||
}
|
||||
|
||||
void CButtonBase::block(bool on)
|
||||
{
|
||||
setState(on?BLOCKED:NORMAL);
|
||||
}
|
||||
|
||||
CAdventureMapButton::CAdventureMapButton ()
|
||||
{
|
||||
hoverable = actOnDown = borderEnabled = soundDisabled = false;
|
||||
CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
|
||||
}
|
||||
|
||||
CAdventureMapButton::CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName,int key, std::vector<std::string> * add, bool playerColoredButton )
|
||||
{
|
||||
std::map<int,std::string> pom;
|
||||
pom[0] = Name;
|
||||
init(Callback, pom, HelpBox, playerColoredButton, defName, add, x, y, key);
|
||||
}
|
||||
|
||||
CAdventureMapButton::CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, config::ButtonInfo *info, int key/*=0*/ )
|
||||
{
|
||||
std::map<int,std::string> pom;
|
||||
pom[0] = Name;
|
||||
init(Callback, pom, HelpBox, info->playerColoured, info->defName, &info->additionalDefs, info->x, info->y, key);
|
||||
}
|
||||
|
||||
CAdventureMapButton::CAdventureMapButton( const std::pair<std::string, std::string> &help, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key/*=0*/, std::vector<std::string> * add /*= nullptr*/, bool playerColoredButton /*= false */ )
|
||||
{
|
||||
std::map<int,std::string> pom;
|
||||
pom[0] = help.first;
|
||||
init(Callback, pom, help.second, playerColoredButton, defName, add, x, y, key);
|
||||
}
|
||||
|
||||
void CAdventureMapButton::onButtonClicked()
|
||||
{
|
||||
// debug logging to figure out pressed button (and as result - player actions) in case of crash
|
||||
logAnim->traceStream() << "Button clicked at " << pos.x << "x" << pos.y;
|
||||
CIntObject * parent = this->parent;
|
||||
std::string prefix = "Parent is";
|
||||
while (parent)
|
||||
{
|
||||
logAnim->traceStream() << prefix << typeid(*parent).name() << " at " << parent->pos.x << "x" << parent->pos.y;
|
||||
parent = parent->parent;
|
||||
prefix = '\t' + prefix;
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
void CAdventureMapButton::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(isBlocked())
|
||||
return;
|
||||
|
||||
if (down)
|
||||
{
|
||||
if (!soundDisabled)
|
||||
CCS->soundh->playSound(soundBase::button);
|
||||
setState(PRESSED);
|
||||
}
|
||||
else if(hoverable && hovered)
|
||||
setState(HIGHLIGHTED);
|
||||
else
|
||||
setState(NORMAL);
|
||||
|
||||
if (actOnDown && down)
|
||||
{
|
||||
onButtonClicked();
|
||||
}
|
||||
else if (!actOnDown && previousState && (down==false))
|
||||
{
|
||||
onButtonClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void CAdventureMapButton::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down && helpBox.size()) //there is no point to show window with nothing inside...
|
||||
CRClickPopup::createAndPush(helpBox);
|
||||
}
|
||||
|
||||
void CAdventureMapButton::hover (bool on)
|
||||
{
|
||||
if(hoverable)
|
||||
{
|
||||
if(on)
|
||||
setState(HIGHLIGHTED);
|
||||
else
|
||||
setState(NORMAL);
|
||||
}
|
||||
|
||||
if(pressedL && on)
|
||||
setState(PRESSED);
|
||||
|
||||
std::string *name = (vstd::contains(hoverTexts,getState()))
|
||||
? (&hoverTexts[getState()])
|
||||
: (vstd::contains(hoverTexts,0) ? (&hoverTexts[0]) : nullptr);
|
||||
if(name && name->size() && !isBlocked()) //if there is no name, there is nohing to display also
|
||||
{
|
||||
if (LOCPLINT && LOCPLINT->battleInt) //for battle buttons
|
||||
{
|
||||
if(on && LOCPLINT->battleInt->console->alterTxt == "")
|
||||
{
|
||||
LOCPLINT->battleInt->console->alterTxt = *name;
|
||||
LOCPLINT->battleInt->console->whoSetAlter = 1;
|
||||
}
|
||||
else if (LOCPLINT->battleInt->console->alterTxt == *name)
|
||||
{
|
||||
LOCPLINT->battleInt->console->alterTxt = "";
|
||||
LOCPLINT->battleInt->console->whoSetAlter = 0;
|
||||
}
|
||||
}
|
||||
else if(GH.statusbar) //for other buttons
|
||||
{
|
||||
if (on)
|
||||
GH.statusbar->setText(*name);
|
||||
else if ( GH.statusbar->getText()==(*name) )
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAdventureMapButton::init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key)
|
||||
{
|
||||
currentImage = -1;
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
|
||||
callback = Callback;
|
||||
hoverable = actOnDown = borderEnabled = soundDisabled = false;
|
||||
CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton
|
||||
hoverTexts = Name;
|
||||
helpBox=HelpBox;
|
||||
|
||||
if (key != SDLK_UNKNOWN)
|
||||
assignedKeys.insert(key);
|
||||
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
|
||||
if (!defName.empty())
|
||||
imageNames.push_back(defName);
|
||||
if (add)
|
||||
for (auto & elem : *add)
|
||||
imageNames.push_back(elem);
|
||||
setIndex(0, playerColoredButton);
|
||||
}
|
||||
|
||||
void CAdventureMapButton::setIndex(size_t index, bool playerColoredButton)
|
||||
{
|
||||
if (index == currentImage || index>=imageNames.size())
|
||||
return;
|
||||
currentImage = index;
|
||||
setImage(new CAnimation(imageNames[index]), playerColoredButton);
|
||||
}
|
||||
|
||||
void CAdventureMapButton::setImage(CAnimation* anim, bool playerColoredButton, int animFlags)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
delete image;
|
||||
image = new CAnimImage(anim, getState(), 0, 0, 0, animFlags);
|
||||
if (playerColoredButton)
|
||||
image->playerColored(LOCPLINT->playerID);
|
||||
|
||||
pos.w = image->pos.w;
|
||||
pos.h = image->pos.h;
|
||||
}
|
||||
|
||||
void CAdventureMapButton::setPlayerColor(PlayerColor player)
|
||||
{
|
||||
if (image)
|
||||
image->playerColored(player);
|
||||
}
|
||||
|
||||
void CAdventureMapButton::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
if (borderEnabled && borderColor.unused == 0)
|
||||
CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b));
|
||||
#else
|
||||
if (borderEnabled && borderColor.a == 0)
|
||||
CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b));
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
void CHighlightableButton::select(bool on)
|
||||
{
|
||||
selected = on;
|
||||
if (on)
|
||||
{
|
||||
borderEnabled = true;
|
||||
setState(HIGHLIGHTED);
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
borderEnabled = false;
|
||||
setState(NORMAL);
|
||||
callback2();
|
||||
}
|
||||
|
||||
if(hoverTexts.size()>1)
|
||||
{
|
||||
hover(false);
|
||||
hover(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CHighlightableButton::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(isBlocked())
|
||||
return;
|
||||
|
||||
if (down && !(onlyOn && isHighlighted()))
|
||||
{
|
||||
CCS->soundh->playSound(soundBase::button);
|
||||
setState(PRESSED);
|
||||
}
|
||||
|
||||
if(previousState)//mouse up
|
||||
{
|
||||
if(down == false && getState() == PRESSED)
|
||||
select(!selected);
|
||||
else
|
||||
setState(selected?HIGHLIGHTED:NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
CHighlightableButton::CHighlightableButton( const CFunctionList<void()> &onSelect, const CFunctionList<void()> &onDeselect, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key)
|
||||
: onlyOn(false), selected(false), callback2(onDeselect)
|
||||
{
|
||||
init(onSelect,Name,HelpBox,playerColoredButton,defName,add,x,y,key);
|
||||
}
|
||||
|
||||
CHighlightableButton::CHighlightableButton( const std::pair<std::string, std::string> &help, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key/*=0*/, std::vector<std::string> * add /*= nullptr*/, bool playerColoredButton /*= false */ )
|
||||
: onlyOn(false), selected(false) // TODO: callback2(???)
|
||||
{
|
||||
ID = myid;
|
||||
std::map<int,std::string> pom;
|
||||
pom[0] = help.first;
|
||||
init(onSelect, pom, help.second, playerColoredButton, defName, add, x, y, key);
|
||||
}
|
||||
|
||||
CHighlightableButton::CHighlightableButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key/*=0*/, std::vector<std::string> * add /*= nullptr*/, bool playerColoredButton /*= false */ )
|
||||
: onlyOn(false), selected(false) // TODO: callback2(???)
|
||||
{
|
||||
ID = myid;
|
||||
std::map<int,std::string> pom;
|
||||
pom[0] = Name;
|
||||
init(onSelect, pom,HelpBox, playerColoredButton, defName, add, x, y, key);
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::addButton(CHighlightableButton* bt)
|
||||
{
|
||||
if (bt->parent)
|
||||
bt->parent->removeChild(bt);
|
||||
addChild(bt);
|
||||
bt->recActions = defActions;//FIXME: not needed?
|
||||
|
||||
bt->callback += boost::bind(&CHighlightableButtonsGroup::selectionChanged,this,bt->ID);
|
||||
bt->onlyOn = true;
|
||||
buttons.push_back(bt);
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList<void()> &OnSelect, int key)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
CHighlightableButton *bt = new CHighlightableButton(OnSelect, 0, tooltip, HelpBox, false, defName, nullptr, x, y, key);
|
||||
if(musicLike)
|
||||
{
|
||||
bt->setOffset(buttons.size()-3);
|
||||
}
|
||||
bt->ID = uid;
|
||||
bt->callback += boost::bind(&CHighlightableButtonsGroup::selectionChanged,this,bt->ID);
|
||||
bt->onlyOn = true;
|
||||
buttons.push_back(bt);
|
||||
}
|
||||
|
||||
CHighlightableButtonsGroup::CHighlightableButtonsGroup(const CFunctionList<void(int)> &OnChange, bool musicLikeButtons)
|
||||
: onChange(OnChange), musicLike(musicLikeButtons)
|
||||
{}
|
||||
|
||||
CHighlightableButtonsGroup::~CHighlightableButtonsGroup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::select(int id, bool mode)
|
||||
{
|
||||
assert(!buttons.empty());
|
||||
|
||||
CHighlightableButton *bt = buttons.front();
|
||||
if(mode)
|
||||
{
|
||||
for(auto btn : buttons)
|
||||
if (btn->ID == id)
|
||||
bt = btn;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt = buttons[id];
|
||||
}
|
||||
bt->select(true);
|
||||
selectionChanged(bt->ID);
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::selectionChanged(int to)
|
||||
{
|
||||
for(auto & elem : buttons)
|
||||
if(elem->ID!=to && elem->isHighlighted())
|
||||
elem->select(false);
|
||||
onChange(to);
|
||||
if (parent)
|
||||
parent->redraw();
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::show(SDL_Surface * to)
|
||||
{
|
||||
if (musicLike)
|
||||
{
|
||||
for(auto & elem : buttons)
|
||||
if(elem->isHighlighted())
|
||||
elem->show(to);
|
||||
}
|
||||
else
|
||||
CIntObject::show(to);
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::showAll(SDL_Surface * to)
|
||||
{
|
||||
if (musicLike)
|
||||
{
|
||||
for(auto & elem : buttons)
|
||||
if(elem->isHighlighted())
|
||||
elem->showAll(to);
|
||||
}
|
||||
else
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CHighlightableButtonsGroup::block( ui8 on )
|
||||
{
|
||||
for(auto & elem : buttons)
|
||||
{
|
||||
elem->block(on);
|
||||
}
|
||||
}
|
||||
|
||||
void CSlider::sliderClicked()
|
||||
{
|
||||
if(!(active & MOVE))
|
||||
addUsedEvents(MOVE);
|
||||
}
|
||||
|
||||
void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
double v = 0;
|
||||
if(horizontal)
|
||||
{
|
||||
if( std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2+40 || std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2 )
|
||||
return;
|
||||
v = sEvent.x - pos.x - 24;
|
||||
v *= positions;
|
||||
v /= (pos.w - 48);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2+40 || std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2 )
|
||||
return;
|
||||
v = sEvent.y - pos.y - 24;
|
||||
v *= positions;
|
||||
v /= (pos.h - 48);
|
||||
}
|
||||
v += 0.5;
|
||||
if(v!=value)
|
||||
{
|
||||
moveTo(v);
|
||||
redrawSlider();
|
||||
}
|
||||
}
|
||||
|
||||
void CSlider::redrawSlider()
|
||||
{
|
||||
//slider->show(screenBuf);
|
||||
}
|
||||
|
||||
void CSlider::moveLeft()
|
||||
{
|
||||
moveTo(value-1);
|
||||
}
|
||||
|
||||
void CSlider::moveRight()
|
||||
{
|
||||
moveTo(value+1);
|
||||
}
|
||||
|
||||
void CSlider::moveTo(int to)
|
||||
{
|
||||
vstd::amax(to, 0);
|
||||
vstd::amin(to, positions);
|
||||
|
||||
//same, old position?
|
||||
if(value == to)
|
||||
return;
|
||||
|
||||
value = to;
|
||||
if(horizontal)
|
||||
{
|
||||
if(positions)
|
||||
{
|
||||
double part = static_cast<double>(to) / positions;
|
||||
part*=(pos.w-48);
|
||||
int newPos = part + pos.x + 16 - slider->pos.x;
|
||||
slider->moveBy(Point(newPos, 0));
|
||||
}
|
||||
else
|
||||
slider->moveTo(Point(pos.x+16, pos.y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(positions)
|
||||
{
|
||||
double part = static_cast<double>(to) / positions;
|
||||
part*=(pos.h-48);
|
||||
int newPos = part + pos.y + 16 - slider->pos.y;
|
||||
slider->moveBy(Point(0, newPos));
|
||||
}
|
||||
else
|
||||
slider->moveTo(Point(pos.x, pos.y+16));
|
||||
}
|
||||
|
||||
if(moved)
|
||||
moved(to);
|
||||
}
|
||||
|
||||
void CSlider::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(down && !slider->isBlocked())
|
||||
{
|
||||
double pw = 0;
|
||||
double rw = 0;
|
||||
if(horizontal)
|
||||
{
|
||||
pw = GH.current->motion.x-pos.x-25;
|
||||
rw = pw / static_cast<double>(pos.w - 48);
|
||||
}
|
||||
else
|
||||
{
|
||||
pw = GH.current->motion.y-pos.y-24;
|
||||
rw = pw / (pos.h-48);
|
||||
}
|
||||
if(pw < -8 || pw > (horizontal ? pos.w : pos.h) - 40)
|
||||
return;
|
||||
// if (rw>1) return;
|
||||
// if (rw<0) return;
|
||||
slider->clickLeft(true, slider->pressedL);
|
||||
moveTo(rw * positions + 0.5);
|
||||
return;
|
||||
}
|
||||
if(active & MOVE)
|
||||
removeUsedEvents(MOVE);
|
||||
}
|
||||
|
||||
CSlider::~CSlider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CSlider::CSlider(int x, int y, int totalw, std::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, int style):
|
||||
capacity(Capacity),
|
||||
amount(Amount),
|
||||
scrollStep(1),
|
||||
horizontal(Horizontal),
|
||||
moved(Moved)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
setAmount(amount);
|
||||
|
||||
addUsedEvents(LCLICK | KEYBOARD | WHEEL);
|
||||
strongInterest = true;
|
||||
|
||||
|
||||
left = new CAdventureMapButton();
|
||||
right = new CAdventureMapButton();
|
||||
slider = new CAdventureMapButton();
|
||||
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
|
||||
if(horizontal)
|
||||
{
|
||||
left->pos.y = slider->pos.y = right->pos.y = pos.y;
|
||||
left->pos.x = pos.x;
|
||||
right->pos.x = pos.x + totalw - 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
left->pos.x = slider->pos.x = right->pos.x = pos.x;
|
||||
left->pos.y = pos.y;
|
||||
right->pos.y = pos.y + totalw - 16;
|
||||
}
|
||||
|
||||
left->callback = boost::bind(&CSlider::moveLeft,this);
|
||||
right->callback = boost::bind(&CSlider::moveRight,this);
|
||||
slider->callback = boost::bind(&CSlider::sliderClicked,this);
|
||||
left->pos.w = left->pos.h = right->pos.w = right->pos.h = slider->pos.w = slider->pos.h = 16;
|
||||
if(horizontal)
|
||||
{
|
||||
pos.h = 16;
|
||||
pos.w = totalw;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.w = 16;
|
||||
pos.h = totalw;
|
||||
}
|
||||
|
||||
if(style == 0)
|
||||
{
|
||||
std::string name = horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF";
|
||||
//NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...)
|
||||
|
||||
//use source def to create custom animations. Format "name.def:123" will load this frame from def file
|
||||
auto animLeft = new CAnimation();
|
||||
animLeft->setCustom(name + ":0", 0);
|
||||
animLeft->setCustom(name + ":1", 1);
|
||||
left->setImage(animLeft);
|
||||
|
||||
auto animRight = new CAnimation();
|
||||
animRight->setCustom(name + ":2", 0);
|
||||
animRight->setCustom(name + ":3", 1);
|
||||
right->setImage(animRight);
|
||||
|
||||
auto animSlider = new CAnimation();
|
||||
animSlider->setCustom(name + ":4", 0);
|
||||
slider->setImage(animSlider);
|
||||
}
|
||||
else
|
||||
{
|
||||
left->setImage(new CAnimation(horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF"));
|
||||
right->setImage(new CAnimation(horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF"));
|
||||
slider->setImage(new CAnimation("SCNRBSL.DEF"));
|
||||
}
|
||||
slider->actOnDown = true;
|
||||
slider->soundDisabled = true;
|
||||
left->soundDisabled = true;
|
||||
right->soundDisabled = true;
|
||||
|
||||
value = -1;
|
||||
moveTo(Value);
|
||||
}
|
||||
|
||||
void CSlider::block( bool on )
|
||||
{
|
||||
left->block(on);
|
||||
right->block(on);
|
||||
slider->block(on);
|
||||
}
|
||||
|
||||
void CSlider::setAmount( int to )
|
||||
{
|
||||
amount = to;
|
||||
positions = to - capacity;
|
||||
vstd::amax(positions, 0);
|
||||
}
|
||||
|
||||
void CSlider::showAll(SDL_Surface * to)
|
||||
{
|
||||
CSDL_Ext::fillRectBlack(to, &pos);
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CSlider::wheelScrolled(bool down, bool in)
|
||||
{
|
||||
moveTo(value + 3 * (down ? +scrollStep : -scrollStep));
|
||||
}
|
||||
|
||||
void CSlider::keyPressed(const SDL_KeyboardEvent & key)
|
||||
{
|
||||
if(key.state != SDL_PRESSED) return;
|
||||
|
||||
int moveDest = 0;
|
||||
switch(key.keysym.sym)
|
||||
{
|
||||
case SDLK_UP:
|
||||
case SDLK_LEFT:
|
||||
moveDest = value - scrollStep;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
case SDLK_RIGHT:
|
||||
moveDest = value + scrollStep;
|
||||
break;
|
||||
case SDLK_PAGEUP:
|
||||
moveDest = value - capacity + scrollStep;
|
||||
break;
|
||||
case SDLK_PAGEDOWN:
|
||||
moveDest = value + capacity - scrollStep;
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
moveDest = 0;
|
||||
break;
|
||||
case SDLK_END:
|
||||
moveDest = amount - capacity;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
moveTo(moveDest);
|
||||
}
|
||||
|
||||
void CSlider::moveToMax()
|
||||
{
|
||||
moveTo(amount);
|
||||
}
|
175
client/widgets/Buttons.h
Normal file
175
client/widgets/Buttons.h
Normal file
@ -0,0 +1,175 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
namespace config
|
||||
{
|
||||
struct ButtonInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Buttons.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Base class for buttons.
|
||||
class CButtonBase : public CKeyShortcut
|
||||
{
|
||||
public:
|
||||
enum ButtonState
|
||||
{
|
||||
NORMAL=0,
|
||||
PRESSED=1,
|
||||
BLOCKED=2,
|
||||
HIGHLIGHTED=3
|
||||
};
|
||||
private:
|
||||
int bitmapOffset; // base offset of visible bitmap from animation
|
||||
ButtonState state;//current state of button from enum
|
||||
|
||||
public:
|
||||
bool swappedImages,//fix for some buttons: normal and pressed image are swapped
|
||||
keepFrame; // don't change visual representation
|
||||
|
||||
void addOverlay(CIntObject * newOverlay);
|
||||
void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE);
|
||||
|
||||
void update();//to refresh button after image or text change
|
||||
|
||||
void setOffset(int newOffset);
|
||||
void setState(ButtonState newState);
|
||||
ButtonState getState();
|
||||
|
||||
//just to make code clearer
|
||||
void block(bool on);
|
||||
bool isBlocked();
|
||||
bool isHighlighted();
|
||||
|
||||
CAnimImage * image; //image for this button
|
||||
CIntObject * overlay;//object-overlay
|
||||
|
||||
CButtonBase(); //c-tor
|
||||
virtual ~CButtonBase(); //d-tor
|
||||
};
|
||||
|
||||
/// Typical Heroes 3 button which can be inactive or active and can
|
||||
/// hold further information if you right-click it
|
||||
class CAdventureMapButton : public CButtonBase
|
||||
{
|
||||
std::vector<std::string> imageNames;//store list of images that can be used by this button
|
||||
size_t currentImage;
|
||||
|
||||
void onButtonClicked(); // calls callback
|
||||
public:
|
||||
std::map<int, std::string> hoverTexts; //text for statusbar
|
||||
std::string helpBox; //for right-click help
|
||||
CFunctionList<void()> callback;
|
||||
bool actOnDown,//runs when mouse is pressed down over it, not when up
|
||||
hoverable,//if true, button will be highlighted when hovered
|
||||
borderEnabled,
|
||||
soundDisabled;
|
||||
SDL_Color borderColor;
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
|
||||
CAdventureMapButton(); //c-tor
|
||||
CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CAdventureMapButton( const std::pair<std::string, std::string> &help, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, config::ButtonInfo *info, int key=0);//c-tor
|
||||
|
||||
void init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key );
|
||||
|
||||
void setIndex(size_t index, bool playerColoredButton=false);
|
||||
void setImage(CAnimation* anim, bool playerColoredButton=false, int animFlags=0);
|
||||
void setPlayerColor(PlayerColor player);
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// A button which can be selected/deselected
|
||||
class CHighlightableButton
|
||||
: public CAdventureMapButton
|
||||
{
|
||||
public:
|
||||
CHighlightableButton(const CFunctionList<void()> &onSelect, const CFunctionList<void()> &onDeselect, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key=0);
|
||||
CHighlightableButton(const std::pair<std::string, std::string> &help, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CHighlightableButton(const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
bool onlyOn;//button can not be de-selected
|
||||
bool selected;//state of highlightable button
|
||||
int ID; //for identification
|
||||
CFunctionList<void()> callback2; //when de-selecting
|
||||
void select(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
};
|
||||
|
||||
/// A group of buttons where one button can be selected
|
||||
class CHighlightableButtonsGroup : public CIntObject
|
||||
{
|
||||
public:
|
||||
CFunctionList<void(int)> onChange; //called when changing selected button with new button's id
|
||||
std::vector<CHighlightableButton*> buttons;
|
||||
bool musicLike; //determines the behaviour of this group
|
||||
|
||||
//void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid);
|
||||
void addButton(CHighlightableButton* bt);//add existing button, it'll be deleted by CHighlightableButtonsGroup destructor
|
||||
void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList<void()> &OnSelect=0, int key=0); //creates new button
|
||||
CHighlightableButtonsGroup(const CFunctionList<void(int)> & OnChange, bool musicLikeButtons = false);
|
||||
~CHighlightableButtonsGroup();
|
||||
void select(int id, bool mode); //mode==0: id is serial; mode==1: id is unique button id
|
||||
void selectionChanged(int to);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void block(ui8 on);
|
||||
};
|
||||
|
||||
/// A typical slider which can be orientated horizontally/vertically.
|
||||
class CSlider : public CIntObject
|
||||
{
|
||||
public:
|
||||
CAdventureMapButton *left, *right, *slider; //if vertical then left=up
|
||||
int capacity;//how many elements can be active at same time (e.g. hero list = 5)
|
||||
int amount; //total amount of elements (e.g. hero list = 0-8)
|
||||
int positions; //number of highest position (0 if there is only one)
|
||||
int value; //first active element
|
||||
int scrollStep; // how many elements will be scrolled via one click, default = 1
|
||||
bool horizontal;
|
||||
bool wheelScrolling;
|
||||
bool keyScrolling;
|
||||
|
||||
std::function<void(int)> moved;
|
||||
|
||||
void redrawSlider();
|
||||
void sliderClicked();
|
||||
void moveLeft();
|
||||
void moveRight();
|
||||
void moveTo(int to);
|
||||
void block(bool on);
|
||||
void setAmount(int to);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void wheelScrolled(bool down, bool in);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
CSlider(int x, int y, int totalw, std::function<void(int)> Moved, int Capacity, int Amount,
|
||||
int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
|
||||
~CSlider();
|
||||
void moveToMax();
|
||||
};
|
@ -4,7 +4,9 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "CAnimation.h"
|
||||
#include "Buttons.h"
|
||||
#include "CComponent.h"
|
||||
|
||||
#include "../windows/CHeroWindow.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CComponent.h"
|
||||
//#include "CComponent.h"
|
||||
#include "MiscWidgets.h"
|
||||
|
||||
/*
|
||||
* CArtifactHolder.h, part of VCMI engine
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "CAnimation.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
|
||||
#include "../../lib/CArtHandler.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CIntObjectClasses.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
/*
|
||||
* CComponent.h, part of VCMI engine
|
||||
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
struct Component;
|
||||
class CAnimImage;
|
||||
|
||||
/// common popup window component
|
||||
class CComponent : public virtual CIntObject
|
||||
@ -109,16 +110,3 @@ public:
|
||||
/// onSelect - optional function that will be called every time on selection change
|
||||
CComponentBox(std::vector<CSelectableComponent *> components, Rect position, std::function<void(int newID)> onSelect = nullptr);
|
||||
};
|
||||
|
||||
/// Can interact on left and right mouse clicks
|
||||
class LRClickableAreaWTextComp: public LRClickableAreaWText
|
||||
{
|
||||
public:
|
||||
int baseType;
|
||||
int bonusValue, type;
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
|
||||
LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
|
||||
CComponent * createComponent() const;
|
||||
};
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "CAnimation.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/CCreatureWindow.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
|
||||
@ -17,6 +18,16 @@
|
||||
|
||||
#include "../../lib/CGameState.h"
|
||||
|
||||
/*
|
||||
* CGarrisonInt.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
void CGarrisonSlot::setHighlight(bool on)
|
||||
{
|
||||
if (on)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CIntObjectClasses.h"
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
/*
|
||||
* CGarrisonInt.h, part of VCMI engine
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,560 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
/*
|
||||
* CPicture.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
// Window GUI class
|
||||
class CSimpleWindow : public CIntObject
|
||||
{
|
||||
public:
|
||||
SDL_Surface * bitmap; //background
|
||||
virtual void show(SDL_Surface * to);
|
||||
CSimpleWindow():bitmap(nullptr){}; //c-tor
|
||||
virtual ~CSimpleWindow(); //d-tor
|
||||
};
|
||||
|
||||
// Image class
|
||||
class CPicture : public CIntObject
|
||||
{
|
||||
void setSurface(SDL_Surface *to);
|
||||
public:
|
||||
SDL_Surface * bg;
|
||||
Rect * srcRect; //if nullptr then whole surface will be used
|
||||
bool freeSurf; //whether surface will be freed upon CPicture destruction
|
||||
bool needRefresh;//Surface needs to be displayed each frame
|
||||
|
||||
operator SDL_Surface*()
|
||||
{
|
||||
return bg;
|
||||
}
|
||||
|
||||
CPicture(const Rect & r, const SDL_Color & color, bool screenFormat = false); //rect filled with given color
|
||||
CPicture(const Rect & r, ui32 color, bool screenFormat = false); //rect filled with given color
|
||||
CPicture(SDL_Surface * BG, int x = 0, int y=0, bool Free = true); //wrap existing SDL_Surface
|
||||
CPicture(const std::string &bmpname, int x=0, int y=0);
|
||||
CPicture(SDL_Surface *BG, const Rect &SrcRext, int x = 0, int y = 0, bool free = false); //wrap subrect of given surface
|
||||
~CPicture();
|
||||
void init();
|
||||
|
||||
//set alpha value for whole surface. Note: may be messed up if surface is shared
|
||||
// 0=transparent, 255=opaque
|
||||
void setAlpha(int value);
|
||||
|
||||
void scaleTo(Point size);
|
||||
void createSimpleRect(const Rect &r, bool screenFormat, ui32 color);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void convertToScreenBPP();
|
||||
void colorizeAndConvert(PlayerColor player);
|
||||
void colorize(PlayerColor player);
|
||||
};
|
||||
|
||||
/// area filled with specific texture
|
||||
class CFilledTexture : CIntObject
|
||||
{
|
||||
SDL_Surface * texture;
|
||||
|
||||
public:
|
||||
CFilledTexture(std::string imageName, Rect position);
|
||||
~CFilledTexture();
|
||||
void showAll(SDL_Surface *to);
|
||||
};
|
||||
|
||||
namespace config{struct ButtonInfo;}
|
||||
|
||||
/// Base class for buttons.
|
||||
class CButtonBase : public CKeyShortcut
|
||||
{
|
||||
public:
|
||||
enum ButtonState
|
||||
{
|
||||
NORMAL=0,
|
||||
PRESSED=1,
|
||||
BLOCKED=2,
|
||||
HIGHLIGHTED=3
|
||||
};
|
||||
private:
|
||||
int bitmapOffset; // base offset of visible bitmap from animation
|
||||
ButtonState state;//current state of button from enum
|
||||
|
||||
public:
|
||||
bool swappedImages,//fix for some buttons: normal and pressed image are swapped
|
||||
keepFrame; // don't change visual representation
|
||||
|
||||
void addOverlay(CIntObject * newOverlay);
|
||||
void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE);
|
||||
|
||||
void update();//to refresh button after image or text change
|
||||
|
||||
void setOffset(int newOffset);
|
||||
void setState(ButtonState newState);
|
||||
ButtonState getState();
|
||||
|
||||
//just to make code clearer
|
||||
void block(bool on);
|
||||
bool isBlocked();
|
||||
bool isHighlighted();
|
||||
|
||||
CAnimImage * image; //image for this button
|
||||
CIntObject * overlay;//object-overlay
|
||||
|
||||
CButtonBase(); //c-tor
|
||||
virtual ~CButtonBase(); //d-tor
|
||||
};
|
||||
|
||||
/// Typical Heroes 3 button which can be inactive or active and can
|
||||
/// hold further information if you right-click it
|
||||
class CAdventureMapButton : public CButtonBase
|
||||
{
|
||||
std::vector<std::string> imageNames;//store list of images that can be used by this button
|
||||
size_t currentImage;
|
||||
|
||||
void onButtonClicked(); // calls callback
|
||||
public:
|
||||
std::map<int, std::string> hoverTexts; //text for statusbar
|
||||
std::string helpBox; //for right-click help
|
||||
CFunctionList<void()> callback;
|
||||
bool actOnDown,//runs when mouse is pressed down over it, not when up
|
||||
hoverable,//if true, button will be highlighted when hovered
|
||||
borderEnabled,
|
||||
soundDisabled;
|
||||
SDL_Color borderColor;
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
|
||||
CAdventureMapButton(); //c-tor
|
||||
CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CAdventureMapButton( const std::pair<std::string, std::string> &help, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, config::ButtonInfo *info, int key=0);//c-tor
|
||||
|
||||
void init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key );
|
||||
|
||||
void setIndex(size_t index, bool playerColoredButton=false);
|
||||
void setImage(CAnimation* anim, bool playerColoredButton=false, int animFlags=0);
|
||||
void setPlayerColor(PlayerColor player);
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// A button which can be selected/deselected
|
||||
class CHighlightableButton
|
||||
: public CAdventureMapButton
|
||||
{
|
||||
public:
|
||||
CHighlightableButton(const CFunctionList<void()> &onSelect, const CFunctionList<void()> &onDeselect, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key=0);
|
||||
CHighlightableButton(const std::pair<std::string, std::string> &help, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
CHighlightableButton(const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector<std::string> * add = nullptr, bool playerColoredButton = false );//c-tor
|
||||
bool onlyOn;//button can not be de-selected
|
||||
bool selected;//state of highlightable button
|
||||
int ID; //for identification
|
||||
CFunctionList<void()> callback2; //when de-selecting
|
||||
void select(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
};
|
||||
|
||||
/// A group of buttons where one button can be selected
|
||||
class CHighlightableButtonsGroup : public CIntObject
|
||||
{
|
||||
public:
|
||||
CFunctionList<void(int)> onChange; //called when changing selected button with new button's id
|
||||
std::vector<CHighlightableButton*> buttons;
|
||||
bool musicLike; //determines the behaviour of this group
|
||||
|
||||
//void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid);
|
||||
void addButton(CHighlightableButton* bt);//add existing button, it'll be deleted by CHighlightableButtonsGroup destructor
|
||||
void addButton(const std::map<int,std::string> &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList<void()> &OnSelect=0, int key=0); //creates new button
|
||||
CHighlightableButtonsGroup(const CFunctionList<void(int)> & OnChange, bool musicLikeButtons = false);
|
||||
~CHighlightableButtonsGroup();
|
||||
void select(int id, bool mode); //mode==0: id is serial; mode==1: id is unique button id
|
||||
void selectionChanged(int to);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void block(ui8 on);
|
||||
};
|
||||
|
||||
/// A typical slider which can be orientated horizontally/vertically.
|
||||
class CSlider : public CIntObject
|
||||
{
|
||||
public:
|
||||
CAdventureMapButton *left, *right, *slider; //if vertical then left=up
|
||||
int capacity;//how many elements can be active at same time (e.g. hero list = 5)
|
||||
int amount; //total amount of elements (e.g. hero list = 0-8)
|
||||
int positions; //number of highest position (0 if there is only one)
|
||||
int value; //first active element
|
||||
int scrollStep; // how many elements will be scrolled via one click, default = 1
|
||||
bool horizontal;
|
||||
bool wheelScrolling;
|
||||
bool keyScrolling;
|
||||
|
||||
std::function<void(int)> moved;
|
||||
|
||||
void redrawSlider();
|
||||
void sliderClicked();
|
||||
void moveLeft();
|
||||
void moveRight();
|
||||
void moveTo(int to);
|
||||
void block(bool on);
|
||||
void setAmount(int to);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void wheelScrolled(bool down, bool in);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
CSlider(int x, int y, int totalw, std::function<void(int)> Moved, int Capacity, int Amount,
|
||||
int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
|
||||
~CSlider();
|
||||
void moveToMax();
|
||||
};
|
||||
|
||||
/// Used as base for Tabs and List classes
|
||||
class CObjectList : public CIntObject
|
||||
{
|
||||
public:
|
||||
typedef std::function<CIntObject* (size_t)> CreateFunc;
|
||||
typedef std::function<void(CIntObject *)> DestroyFunc;
|
||||
|
||||
private:
|
||||
CreateFunc createObject;
|
||||
DestroyFunc destroyObject;
|
||||
|
||||
protected:
|
||||
//Internal methods for safe creation of items (Children capturing and activation/deactivation if needed)
|
||||
void deleteItem(CIntObject* item);
|
||||
CIntObject* createItem(size_t index);
|
||||
|
||||
CObjectList(CreateFunc create, DestroyFunc destroy = DestroyFunc());//Protected constructor
|
||||
};
|
||||
|
||||
/// Window element with multiple tabs
|
||||
class CTabbedInt : public CObjectList
|
||||
{
|
||||
private:
|
||||
CIntObject * activeTab;
|
||||
size_t activeID;
|
||||
|
||||
public:
|
||||
//CreateFunc, DestroyFunc - see CObjectList
|
||||
//Pos - position of object, all tabs will be moved to this position
|
||||
//ActiveID - ID of initially active tab
|
||||
CTabbedInt(CreateFunc create, DestroyFunc destroy = DestroyFunc(), Point position=Point(), size_t ActiveID=0);
|
||||
|
||||
void setActive(size_t which);
|
||||
//recreate active tab
|
||||
void reset();
|
||||
|
||||
//return currently active item
|
||||
CIntObject * getItem();
|
||||
};
|
||||
|
||||
/// List of IntObjects with optional slider
|
||||
class CListBox : public CObjectList
|
||||
{
|
||||
private:
|
||||
std::list< CIntObject* > items;
|
||||
size_t first;
|
||||
size_t totalSize;
|
||||
|
||||
Point itemOffset;
|
||||
CSlider * slider;
|
||||
|
||||
void updatePositions();
|
||||
public:
|
||||
//CreateFunc, DestroyFunc - see CObjectList
|
||||
//Pos - position of first item
|
||||
//ItemOffset - distance between items in the list
|
||||
//VisibleSize - maximal number of displayable at once items
|
||||
//TotalSize
|
||||
//Slider - slider style, bit field: 1 = present(disabled), 2=horisontal(vertical), 4=blue(brown)
|
||||
//SliderPos - position of slider, if present
|
||||
CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
|
||||
size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() );
|
||||
|
||||
//recreate all visible items
|
||||
void reset();
|
||||
|
||||
//change or get total amount of items in the list
|
||||
void resize(size_t newSize);
|
||||
size_t size();
|
||||
|
||||
//return item with index which or null if not present
|
||||
CIntObject * getItem(size_t which);
|
||||
|
||||
//return currently active items
|
||||
const std::list< CIntObject * > & getItems();
|
||||
|
||||
//get index of this item. -1 if not found
|
||||
size_t getIndexOf(CIntObject * item);
|
||||
|
||||
//scroll list to make item which visible
|
||||
void scrollTo(size_t which);
|
||||
|
||||
//scroll list to specified position
|
||||
void moveToPos(size_t which);
|
||||
void moveToNext();
|
||||
void moveToPrev();
|
||||
|
||||
size_t getPos();
|
||||
};
|
||||
|
||||
/// Small helper class to manage group of similar labels
|
||||
class CLabelGroup : public CIntObject
|
||||
{
|
||||
std::list<CLabel*> labels;
|
||||
EFonts font;
|
||||
EAlignment align;
|
||||
SDL_Color color;
|
||||
public:
|
||||
CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE);
|
||||
void add(int x=0, int y=0, const std::string &text = "");
|
||||
};
|
||||
|
||||
/// Base class for all text-related widgets.
|
||||
/// Controls text blitting-related options
|
||||
class CTextContainer : public virtual CIntObject
|
||||
{
|
||||
protected:
|
||||
/// returns size of border, for left- or right-aligned text
|
||||
virtual Point getBorderSize() = 0;
|
||||
/// do actual blitting of line. Text "what" will be placed at "where" and aligned according to alignment
|
||||
void blitLine(SDL_Surface * to, Rect where, std::string what);
|
||||
|
||||
CTextContainer(EAlignment alignment, EFonts font, SDL_Color color);
|
||||
|
||||
public:
|
||||
EAlignment alignment;
|
||||
EFonts font;
|
||||
SDL_Color color; // default font color. Can be overridden by placing "{}" into the string
|
||||
};
|
||||
|
||||
/// Label which shows text
|
||||
class CLabel : public CTextContainer
|
||||
{
|
||||
protected:
|
||||
Point getBorderSize() override;
|
||||
virtual std::string visibleText();
|
||||
|
||||
CPicture *bg;
|
||||
public:
|
||||
|
||||
std::string text;
|
||||
bool autoRedraw; //whether control will redraw itself on setTxt
|
||||
|
||||
std::string getText();
|
||||
virtual void setText(const std::string &Txt);
|
||||
|
||||
CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT,
|
||||
const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
void showAll(SDL_Surface * to); //shows statusbar (with current text)
|
||||
};
|
||||
|
||||
/// Multi-line label that can display multiple lines of text
|
||||
/// If text is too big to fit into requested area remaining part will not be visible
|
||||
class CMultiLineLabel : public CLabel
|
||||
{
|
||||
// text to blit, split into lines that are no longer than widget width
|
||||
std::vector<std::string> lines;
|
||||
|
||||
// area of text that actually will be printed, default is widget size
|
||||
Rect visibleSize;
|
||||
|
||||
void splitText(const std::string &Txt);
|
||||
Rect getTextLocation();
|
||||
public:
|
||||
// total size of text, x = longest line of text, y = total height of lines
|
||||
Point textSize;
|
||||
|
||||
CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
|
||||
void setText(const std::string &Txt);
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
void setVisibleSize(Rect visibleSize);
|
||||
// scrolls text visible in widget. Positive value will move text up
|
||||
void scrollTextTo(int distance);
|
||||
void scrollTextBy(int distance);
|
||||
};
|
||||
|
||||
/// a multi-line label that tries to fit text with given available width and height;
|
||||
/// if not possible, it creates a slider for scrolling text
|
||||
class CTextBox : public CIntObject
|
||||
{
|
||||
int sliderStyle;
|
||||
public:
|
||||
CMultiLineLabel * label;
|
||||
CSlider *slider;
|
||||
|
||||
CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE);
|
||||
|
||||
void resize(Point newSize);
|
||||
void setText(const std::string &Txt);
|
||||
void sliderMoved(int to);
|
||||
};
|
||||
|
||||
/// Status bar which is shown at the bottom of the in-game screens
|
||||
class CGStatusBar : public CLabel
|
||||
{
|
||||
bool textLock; //Used for blocking changes to the text
|
||||
void init();
|
||||
|
||||
CGStatusBar *oldStatusBar;
|
||||
protected:
|
||||
Point getBorderSize() override;
|
||||
|
||||
public:
|
||||
|
||||
void clear();//clears statusbar and refreshes
|
||||
void setText(const std::string & Text) override; //prints text and refreshes statusbar
|
||||
|
||||
void show(SDL_Surface * to); //shows statusbar (with current text)
|
||||
|
||||
CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar
|
||||
CGStatusBar(int x, int y, std::string name, int maxw=-1);
|
||||
~CGStatusBar();
|
||||
|
||||
void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called
|
||||
};
|
||||
|
||||
/// UIElement which can get input focus
|
||||
class CFocusable : public virtual CIntObject
|
||||
{
|
||||
protected:
|
||||
virtual void focusGot(){};
|
||||
virtual void focusLost(){};
|
||||
public:
|
||||
bool focus; //only one focusable control can have focus at one moment
|
||||
|
||||
void giveFocus(); //captures focus
|
||||
void moveFocus(); //moves focus to next active control (may be used for tab switching)
|
||||
|
||||
static std::list<CFocusable*> focusables; //all existing objs
|
||||
static CFocusable *inputWithFocus; //who has focus now
|
||||
CFocusable();
|
||||
~CFocusable();
|
||||
};
|
||||
|
||||
/// Text input box where players can enter text
|
||||
class CTextInput : public CLabel, public CFocusable
|
||||
{
|
||||
std::string newText;
|
||||
protected:
|
||||
std::string visibleText() override;
|
||||
|
||||
void focusGot() override;
|
||||
void focusLost() override;
|
||||
public:
|
||||
CFunctionList<void(const std::string &)> cb;
|
||||
CFunctionList<void(std::string &, const std::string &)> filters;
|
||||
void setText(const std::string &nText, bool callCb = false);
|
||||
|
||||
CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB);
|
||||
CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB);
|
||||
CTextInput(const Rect &Pos, SDL_Surface *srf = nullptr);
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
bool captureThisEvent(const SDL_KeyboardEvent & key) override;
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
void textInputed(const SDL_TextInputEvent & event) override;
|
||||
void textEdited(const SDL_TextEditingEvent & event) override;
|
||||
|
||||
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
//Filter that will block all characters not allowed in filenames
|
||||
static void filenameFilter(std::string &text, const std::string & oldText);
|
||||
//Filter that will allow only input of numbers in range min-max (min-max are allowed)
|
||||
//min-max should be set via something like boost::bind
|
||||
static void numberFilter(std::string &text, const std::string & oldText, int minValue, int maxValue);
|
||||
};
|
||||
|
||||
/// Shows a text by moving the mouse cursor over the object
|
||||
class CHoverableArea: public virtual CIntObject
|
||||
{
|
||||
public:
|
||||
std::string hoverText;
|
||||
|
||||
virtual void hover (bool on);
|
||||
|
||||
CHoverableArea();
|
||||
virtual ~CHoverableArea();
|
||||
};
|
||||
|
||||
/// Can interact on left and right mouse clicks, plus it shows a text when by hovering over it
|
||||
class LRClickableAreaWText: public CHoverableArea
|
||||
{
|
||||
public:
|
||||
std::string text;
|
||||
|
||||
LRClickableAreaWText();
|
||||
LRClickableAreaWText(const Rect &Pos, const std::string &HoverText = "", const std::string &ClickText = "");
|
||||
virtual ~LRClickableAreaWText();
|
||||
void init();
|
||||
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
};
|
||||
|
||||
/// Basic class for windows
|
||||
class CWindowObject : public CIntObject
|
||||
{
|
||||
CPicture * createBg(std::string imageName, bool playerColored);
|
||||
int getUsedEvents(int options);
|
||||
|
||||
CIntObject *shadow;
|
||||
void setShadow(bool on);
|
||||
|
||||
int options;
|
||||
|
||||
protected:
|
||||
CPicture * background;
|
||||
|
||||
//Simple function with call to GH.popInt
|
||||
void close();
|
||||
//Used only if RCLICK_POPUP was set
|
||||
void clickRight(tribool down, bool previousState);
|
||||
//To display border
|
||||
void showAll(SDL_Surface *to);
|
||||
//change or set background image
|
||||
void setBackground(std::string filename);
|
||||
void updateShadow();
|
||||
public:
|
||||
enum EOptions
|
||||
{
|
||||
PLAYER_COLORED=1, //background will be player-colored
|
||||
RCLICK_POPUP=2, // window will behave as right-click popup
|
||||
BORDERED=4, // window will have border if current resolution is bigger than size of window
|
||||
SHADOW_DISABLED=8 //this window won't display any shadow
|
||||
};
|
||||
|
||||
/*
|
||||
* options - EOpions enum
|
||||
* imageName - name for background image, can be empty
|
||||
* centerAt - position of window center. Default - center of the screen
|
||||
*/
|
||||
CWindowObject(int options, std::string imageName, Point centerAt);
|
||||
CWindowObject(int options, std::string imageName = "");
|
||||
~CWindowObject();
|
||||
};
|
533
client/widgets/Images.cpp
Normal file
533
client/widgets/Images.cpp
Normal file
@ -0,0 +1,533 @@
|
||||
#include "StdInc.h"
|
||||
#include "Images.h"
|
||||
|
||||
#include "MiscWidgets.h"
|
||||
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "../battle/CBattleInterface.h"
|
||||
#include "../battle/CBattleInterfaceClasses.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* Images.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
|
||||
{
|
||||
init();
|
||||
bg = BG;
|
||||
freeSurf = Free;
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
pos.w = BG->w;
|
||||
pos.h = BG->h;
|
||||
}
|
||||
|
||||
CPicture::CPicture( const std::string &bmpname, int x, int y )
|
||||
{
|
||||
init();
|
||||
bg = BitmapHandler::loadBitmap(bmpname);
|
||||
freeSurf = true;;
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
if(bg)
|
||||
{
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.w = pos.h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPicture::CPicture(const Rect &r, const SDL_Color &color, bool screenFormat /*= false*/)
|
||||
{
|
||||
init();
|
||||
createSimpleRect(r, screenFormat, SDL_MapRGB(bg->format, color.r, color.g,color.b));
|
||||
}
|
||||
|
||||
CPicture::CPicture(const Rect &r, ui32 color, bool screenFormat /*= false*/)
|
||||
{
|
||||
init();
|
||||
createSimpleRect(r, screenFormat, color);
|
||||
}
|
||||
|
||||
CPicture::CPicture(SDL_Surface *BG, const Rect &SrcRect, int x /*= 0*/, int y /*= 0*/, bool free /*= false*/)
|
||||
{
|
||||
needRefresh = false;
|
||||
srcRect = new Rect(SrcRect);
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
pos.w = srcRect->w;
|
||||
pos.h = srcRect->h;
|
||||
bg = BG;
|
||||
freeSurf = free;
|
||||
}
|
||||
|
||||
void CPicture::setSurface(SDL_Surface *to)
|
||||
{
|
||||
bg = to;
|
||||
if (srcRect)
|
||||
{
|
||||
pos.w = srcRect->w;
|
||||
pos.h = srcRect->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
}
|
||||
|
||||
CPicture::~CPicture()
|
||||
{
|
||||
if(freeSurf)
|
||||
SDL_FreeSurface(bg);
|
||||
delete srcRect;
|
||||
}
|
||||
|
||||
void CPicture::init()
|
||||
{
|
||||
needRefresh = false;
|
||||
srcRect = nullptr;
|
||||
}
|
||||
|
||||
void CPicture::show(SDL_Surface * to)
|
||||
{
|
||||
if (needRefresh)
|
||||
showAll(to);
|
||||
}
|
||||
|
||||
void CPicture::showAll(SDL_Surface * to)
|
||||
{
|
||||
if(bg)
|
||||
{
|
||||
if(srcRect)
|
||||
{
|
||||
SDL_Rect srcRectCpy = *srcRect;
|
||||
SDL_Rect dstRect = srcRectCpy;
|
||||
dstRect.x = pos.x;
|
||||
dstRect.y = pos.y;
|
||||
|
||||
CSDL_Ext::blitSurface(bg, &srcRectCpy, to, &dstRect);
|
||||
}
|
||||
else
|
||||
blitAt(bg, pos, to);
|
||||
}
|
||||
}
|
||||
|
||||
void CPicture::convertToScreenBPP()
|
||||
{
|
||||
SDL_Surface *hlp = bg;
|
||||
bg = SDL_ConvertSurface(hlp,screen->format,0);
|
||||
CSDL_Ext::setDefaultColorKey(bg);
|
||||
SDL_FreeSurface(hlp);
|
||||
}
|
||||
|
||||
void CPicture::setAlpha(int value)
|
||||
{
|
||||
#ifdef VCMI_SDL1
|
||||
SDL_SetAlpha(bg, SDL_SRCALPHA, value);
|
||||
#else
|
||||
SDL_SetSurfaceAlphaMod(bg,value);
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
void CPicture::scaleTo(Point size)
|
||||
{
|
||||
SDL_Surface * scaled = CSDL_Ext::scaleSurface(bg, size.x, size.y);
|
||||
|
||||
if(freeSurf)
|
||||
SDL_FreeSurface(bg);
|
||||
|
||||
setSurface(scaled);
|
||||
freeSurf = false;
|
||||
}
|
||||
|
||||
void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
|
||||
{
|
||||
pos += r;
|
||||
pos.w = r.w;
|
||||
pos.h = r.h;
|
||||
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);
|
||||
|
||||
SDL_FillRect(bg, nullptr, color);
|
||||
freeSurf = true;
|
||||
}
|
||||
|
||||
void CPicture::colorizeAndConvert(PlayerColor player)
|
||||
{
|
||||
assert(bg);
|
||||
colorize(player);
|
||||
convertToScreenBPP();
|
||||
}
|
||||
|
||||
void CPicture::colorize(PlayerColor player)
|
||||
{
|
||||
assert(bg);
|
||||
graphics->blueToPlayersAdv(bg, player);
|
||||
}
|
||||
|
||||
CFilledTexture::CFilledTexture(std::string imageName, Rect position):
|
||||
CIntObject(0, position.topLeft()),
|
||||
texture(BitmapHandler::loadBitmap(imageName))
|
||||
{
|
||||
pos.w = position.w;
|
||||
pos.h = position.h;
|
||||
}
|
||||
|
||||
CFilledTexture::~CFilledTexture()
|
||||
{
|
||||
SDL_FreeSurface(texture);
|
||||
}
|
||||
|
||||
void CFilledTexture::showAll(SDL_Surface *to)
|
||||
{
|
||||
CSDL_Ext::CClipRectGuard guard(to, pos);
|
||||
CSDL_Ext::fillTexture(to, texture);
|
||||
}
|
||||
|
||||
CAnimImage::CAnimImage(std::string name, size_t Frame, size_t Group, int x, int y, ui8 Flags):
|
||||
frame(Frame),
|
||||
group(Group),
|
||||
player(-1),
|
||||
flags(Flags)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
anim = new CAnimation(name);
|
||||
init();
|
||||
}
|
||||
|
||||
CAnimImage::CAnimImage(CAnimation *Anim, size_t Frame, size_t Group, int x, int y, ui8 Flags):
|
||||
anim(Anim),
|
||||
frame(Frame),
|
||||
group(Group),
|
||||
player(-1),
|
||||
flags(Flags)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
init();
|
||||
}
|
||||
|
||||
size_t CAnimImage::size()
|
||||
{
|
||||
return anim->size(group);
|
||||
}
|
||||
|
||||
void CAnimImage::init()
|
||||
{
|
||||
anim->load(frame, group);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->load(0,group);
|
||||
|
||||
IImage *img = anim->getImage(frame, group);
|
||||
if (img)
|
||||
{
|
||||
pos.w = img->width();
|
||||
pos.h = img->height();
|
||||
}
|
||||
}
|
||||
|
||||
CAnimImage::~CAnimImage()
|
||||
{
|
||||
anim->unload(frame, group);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->unload(0,group);
|
||||
delete anim;
|
||||
}
|
||||
|
||||
void CAnimImage::showAll(SDL_Surface * to)
|
||||
{
|
||||
IImage *img;
|
||||
|
||||
if ( flags & CShowableAnim::BASE && frame != 0)
|
||||
if ((img = anim->getImage(0, group)))
|
||||
img->draw(to, pos.x, pos.y);
|
||||
|
||||
if ((img = anim->getImage(frame, group)))
|
||||
img->draw(to, pos.x, pos.y);
|
||||
}
|
||||
|
||||
void CAnimImage::setFrame(size_t Frame, size_t Group)
|
||||
{
|
||||
if (frame == Frame && group==Group)
|
||||
return;
|
||||
if (anim->size(Group) > Frame)
|
||||
{
|
||||
anim->load(Frame, Group);
|
||||
anim->unload(frame, group);
|
||||
frame = Frame;
|
||||
group = Group;
|
||||
IImage *img = anim->getImage(frame, group);
|
||||
if (img)
|
||||
{
|
||||
if (flags & CShowableAnim::PLAYER_COLORED)
|
||||
img->playerColored(player);
|
||||
pos.w = img->width();
|
||||
pos.h = img->height();
|
||||
}
|
||||
}
|
||||
else
|
||||
logGlobal->errorStream() << "Error: accessing unavailable frame " << Group << ":" << Frame << " in CAnimation!";
|
||||
}
|
||||
|
||||
void CAnimImage::playerColored(PlayerColor currPlayer)
|
||||
{
|
||||
player = currPlayer;
|
||||
flags |= CShowableAnim::PLAYER_COLORED;
|
||||
anim->getImage(frame, group)->playerColored(player);
|
||||
if (flags & CShowableAnim::BASE)
|
||||
anim->getImage(0, group)->playerColored(player);
|
||||
}
|
||||
|
||||
CShowableAnim::CShowableAnim(int x, int y, std::string name, ui8 Flags, ui32 Delay, size_t Group):
|
||||
anim(new CAnimation(name, Flags & USE_RLE)),
|
||||
group(Group),
|
||||
frame(0),
|
||||
first(0),
|
||||
frameDelay(Delay),
|
||||
value(0),
|
||||
flags(Flags),
|
||||
xOffset(0),
|
||||
yOffset(0),
|
||||
alpha(255)
|
||||
{
|
||||
anim->loadGroup(group);
|
||||
last = anim->size(group);
|
||||
|
||||
pos.w = anim->getImage(0, group)->width();
|
||||
pos.h = anim->getImage(0, group)->height();
|
||||
pos.x+= x;
|
||||
pos.y+= y;
|
||||
}
|
||||
|
||||
CShowableAnim::~CShowableAnim()
|
||||
{
|
||||
anim->unloadGroup(group);
|
||||
delete anim;
|
||||
}
|
||||
|
||||
void CShowableAnim::setAlpha(ui32 alphaValue)
|
||||
{
|
||||
alpha = std::min<ui32>(alphaValue, 255);
|
||||
}
|
||||
|
||||
bool CShowableAnim::set(size_t Group, size_t from, size_t to)
|
||||
{
|
||||
size_t max = anim->size(Group);
|
||||
|
||||
if (to < max)
|
||||
max = to;
|
||||
|
||||
if (max < from || max == 0)
|
||||
return false;
|
||||
|
||||
anim->load(Group);
|
||||
anim->unload(group);
|
||||
group = Group;
|
||||
frame = first = from;
|
||||
last = max;
|
||||
value = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShowableAnim::set(size_t Group)
|
||||
{
|
||||
if (anim->size(Group)== 0)
|
||||
return false;
|
||||
if (group != Group)
|
||||
{
|
||||
anim->loadGroup(Group);
|
||||
anim->unloadGroup(group);
|
||||
first = 0;
|
||||
group = Group;
|
||||
last = anim->size(Group);
|
||||
}
|
||||
frame = value = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CShowableAnim::reset()
|
||||
{
|
||||
value = 0;
|
||||
frame = first;
|
||||
|
||||
if (callback)
|
||||
callback();
|
||||
}
|
||||
|
||||
void CShowableAnim::clipRect(int posX, int posY, int width, int height)
|
||||
{
|
||||
xOffset = posX;
|
||||
yOffset = posY;
|
||||
pos.w = width;
|
||||
pos.h = height;
|
||||
}
|
||||
|
||||
void CShowableAnim::show(SDL_Surface * to)
|
||||
{
|
||||
if ( flags & BASE )// && frame != first) // FIXME: results in graphical glytch in Fortress, upgraded hydra's dwelling
|
||||
blitImage(first, group, to);
|
||||
blitImage(frame, group, to);
|
||||
|
||||
if ((flags & PLAY_ONCE) && frame + 1 == last)
|
||||
return;
|
||||
|
||||
if ( ++value == frameDelay )
|
||||
{
|
||||
value = 0;
|
||||
if ( ++frame >= last)
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CShowableAnim::showAll(SDL_Surface * to)
|
||||
{
|
||||
if ( flags & BASE )// && frame != first)
|
||||
blitImage(first, group, to);
|
||||
blitImage(frame, group, to);
|
||||
}
|
||||
|
||||
void CShowableAnim::blitImage(size_t frame, size_t group, SDL_Surface *to)
|
||||
{
|
||||
assert(to);
|
||||
Rect src( xOffset, yOffset, pos.w, pos.h);
|
||||
IImage * img = anim->getImage(frame, group);
|
||||
if (img)
|
||||
img->draw(to, pos.x-xOffset, pos.y-yOffset, &src, alpha);
|
||||
}
|
||||
|
||||
void CShowableAnim::rotate(bool on, bool vertical)
|
||||
{
|
||||
ui8 flag = vertical? VERTICAL_FLIP:HORIZONTAL_FLIP;
|
||||
if (on)
|
||||
flags |= flag;
|
||||
else
|
||||
flags &= ~flag;
|
||||
}
|
||||
|
||||
CCreatureAnim::CCreatureAnim(int x, int y, std::string name, Rect picPos, 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;
|
||||
};
|
||||
|
||||
void CCreatureAnim::loopPreview(bool warMachine)
|
||||
{
|
||||
std::vector<EAnimType> available;
|
||||
|
||||
static const EAnimType creaPreviewList[] = {HOLDING, HITTED, DEFENCE, ATTACK_FRONT, CAST_FRONT};
|
||||
static const EAnimType machPreviewList[] = {HOLDING, MOVING, SHOOT_UP, SHOOT_FRONT, SHOOT_DOWN};
|
||||
auto & previewList = warMachine ? machPreviewList : creaPreviewList;
|
||||
|
||||
for (auto & elem : previewList)
|
||||
if (anim->size(elem))
|
||||
available.push_back(elem);
|
||||
|
||||
size_t rnd = CRandomGenerator::getDefault().nextInt(available.size() * 2 - 1);
|
||||
|
||||
if (rnd >= available.size())
|
||||
{
|
||||
EAnimType type;
|
||||
if ( anim->size(MOVING) == 0 )//no moving animation present
|
||||
type = HOLDING;
|
||||
else
|
||||
type = MOVING;
|
||||
|
||||
//display this anim for ~1 second (time is random, but it looks good)
|
||||
for (size_t i=0; i< 12/anim->size(type) + 1; i++)
|
||||
addLast(type);
|
||||
}
|
||||
else
|
||||
addLast(available[rnd]);
|
||||
}
|
||||
|
||||
void CCreatureAnim::addLast(EAnimType newType)
|
||||
{
|
||||
if (type != MOVING && newType == MOVING)//starting moving - play init sequence
|
||||
{
|
||||
queue.push( MOVE_START );
|
||||
}
|
||||
else if (type == MOVING && newType != MOVING )//previous anim was moving - finish it
|
||||
{
|
||||
queue.push( MOVE_END );
|
||||
}
|
||||
if (newType == TURN_L || newType == TURN_R)
|
||||
queue.push(newType);
|
||||
|
||||
queue.push(newType);
|
||||
}
|
||||
|
||||
void CCreatureAnim::reset()
|
||||
{
|
||||
//if we are in the middle of rotation - set flag
|
||||
if (type == TURN_L && !queue.empty() && queue.front() == TURN_L)
|
||||
rotate(true);
|
||||
if (type == TURN_R && !queue.empty() && queue.front() == TURN_R)
|
||||
rotate(false);
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
EAnimType at = queue.front();
|
||||
queue.pop();
|
||||
if (set(at))
|
||||
return;
|
||||
}
|
||||
if (callback)
|
||||
callback();
|
||||
while (!queue.empty())
|
||||
{
|
||||
EAnimType at = queue.front();
|
||||
queue.pop();
|
||||
if (set(at))
|
||||
return;
|
||||
}
|
||||
set(HOLDING);
|
||||
}
|
||||
|
||||
void CCreatureAnim::startPreview(bool warMachine)
|
||||
{
|
||||
callback = boost::bind(&CCreatureAnim::loopPreview, this, warMachine);
|
||||
}
|
||||
|
||||
void CCreatureAnim::clearAndSet(EAnimType type)
|
||||
{
|
||||
while (!queue.empty())
|
||||
queue.pop();
|
||||
set(type);
|
||||
}
|
226
client/widgets/Images.h
Normal file
226
client/widgets/Images.h
Normal file
@ -0,0 +1,226 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
/*
|
||||
* Images.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
// Image class
|
||||
class CPicture : public CIntObject
|
||||
{
|
||||
void setSurface(SDL_Surface *to);
|
||||
public:
|
||||
SDL_Surface * bg;
|
||||
Rect * srcRect; //if nullptr then whole surface will be used
|
||||
bool freeSurf; //whether surface will be freed upon CPicture destruction
|
||||
bool needRefresh;//Surface needs to be displayed each frame
|
||||
|
||||
operator SDL_Surface*()
|
||||
{
|
||||
return bg;
|
||||
}
|
||||
|
||||
CPicture(const Rect & r, const SDL_Color & color, bool screenFormat = false); //rect filled with given color
|
||||
CPicture(const Rect & r, ui32 color, bool screenFormat = false); //rect filled with given color
|
||||
CPicture(SDL_Surface * BG, int x = 0, int y=0, bool Free = true); //wrap existing SDL_Surface
|
||||
CPicture(const std::string &bmpname, int x=0, int y=0);
|
||||
CPicture(SDL_Surface *BG, const Rect &SrcRext, int x = 0, int y = 0, bool free = false); //wrap subrect of given surface
|
||||
~CPicture();
|
||||
void init();
|
||||
|
||||
//set alpha value for whole surface. Note: may be messed up if surface is shared
|
||||
// 0=transparent, 255=opaque
|
||||
void setAlpha(int value);
|
||||
|
||||
void scaleTo(Point size);
|
||||
void createSimpleRect(const Rect &r, bool screenFormat, ui32 color);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void convertToScreenBPP();
|
||||
void colorizeAndConvert(PlayerColor player);
|
||||
void colorize(PlayerColor player);
|
||||
};
|
||||
|
||||
/// area filled with specific texture
|
||||
class CFilledTexture : CIntObject
|
||||
{
|
||||
SDL_Surface * texture;
|
||||
|
||||
public:
|
||||
CFilledTexture(std::string imageName, Rect position);
|
||||
~CFilledTexture();
|
||||
void showAll(SDL_Surface *to);
|
||||
};
|
||||
|
||||
/// Class for displaying one image from animation
|
||||
class CAnimImage: public CIntObject
|
||||
{
|
||||
private:
|
||||
CAnimation* anim;
|
||||
//displayed frame/group
|
||||
size_t frame;
|
||||
size_t group;
|
||||
PlayerColor player;
|
||||
ui8 flags;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
CAnimImage(std::string name, size_t Frame, size_t Group=0, int x=0, int y=0, ui8 Flags=0);
|
||||
CAnimImage(CAnimation* anim, size_t Frame, size_t Group=0, int x=0, int y=0, ui8 Flags=0);
|
||||
~CAnimImage();//d-tor
|
||||
|
||||
//size of animation
|
||||
size_t size();
|
||||
|
||||
//change displayed frame on this one
|
||||
void setFrame(size_t Frame, size_t Group=0);
|
||||
|
||||
//makes image player-colored
|
||||
void playerColored(PlayerColor player);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// Base class for displaying animation, used as superclass for different animations
|
||||
class CShowableAnim: public CIntObject
|
||||
{
|
||||
public:
|
||||
enum EFlags
|
||||
{
|
||||
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;
|
||||
|
||||
size_t group, frame;//current frame
|
||||
|
||||
size_t first, last; //animation range
|
||||
|
||||
//TODO: replace with time delay(needed for battles)
|
||||
ui32 frameDelay;//delay in frames of each image
|
||||
ui32 value;//how many times current frame was showed
|
||||
|
||||
ui8 flags;//Flags from EFlags enum
|
||||
|
||||
//blit image with optional rotation, fitting into rect, etc
|
||||
void blitImage(size_t frame, size_t group, SDL_Surface *to);
|
||||
|
||||
//For clipping in rect, offsets of picture coordinates
|
||||
int xOffset, yOffset;
|
||||
|
||||
ui8 alpha;
|
||||
|
||||
public:
|
||||
//called when next animation sequence is required
|
||||
std::function<void()> callback;
|
||||
|
||||
//Set per-surface alpha, 0 = transparent, 255 = opaque
|
||||
void setAlpha(ui32 alphaValue);
|
||||
|
||||
CShowableAnim(int x, int y, std::string name, ui8 flags=0, ui32 Delay=4, size_t Group=0);
|
||||
~CShowableAnim();
|
||||
|
||||
//set animation to group or part of group
|
||||
bool set(size_t Group);
|
||||
bool set(size_t Group, size_t from, size_t to=-1);
|
||||
|
||||
//set rotation flags
|
||||
void rotate(bool on, bool vertical=false);
|
||||
|
||||
//move displayed part of picture (if picture is clipped to rect)
|
||||
void clipRect(int posX, int posY, int width, int height);
|
||||
|
||||
//set frame to first, call callback
|
||||
virtual void reset();
|
||||
|
||||
//show current frame and increase counter
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
/// Creature-dependend animations like attacking, moving,...
|
||||
class CCreatureAnim: public CShowableAnim
|
||||
{
|
||||
public:
|
||||
|
||||
enum EHeroAnimType
|
||||
{
|
||||
HERO_HOLDING = 0,
|
||||
HERO_IDLE = 1, // idling movement that happens from time to time
|
||||
HERO_DEFEAT = 2, // played when army loses stack or on friendly fire
|
||||
HERO_VICTORY = 3, // when enemy stack killed or huge damage is dealt
|
||||
HERO_CAST_SPELL = 4 // spellcasting
|
||||
};
|
||||
|
||||
enum EAnimType // list of creature animations, numbers were taken from def files
|
||||
{
|
||||
MOVING=0,
|
||||
MOUSEON=1,
|
||||
HOLDING=2,
|
||||
HITTED=3,
|
||||
DEFENCE=4,
|
||||
DEATH=5,
|
||||
//DEATH2=6, //unused?
|
||||
TURN_L=7,
|
||||
TURN_R=8, //same
|
||||
//TURN_L2=9, //identical to previous?
|
||||
//TURN_R2=10,
|
||||
ATTACK_UP=11,
|
||||
ATTACK_FRONT=12,
|
||||
ATTACK_DOWN=13,
|
||||
SHOOT_UP=14,
|
||||
SHOOT_FRONT=15,
|
||||
SHOOT_DOWN=16,
|
||||
CAST_UP=17,
|
||||
CAST_FRONT=18,
|
||||
CAST_DOWN=19,
|
||||
MOVE_START=20,
|
||||
MOVE_END=21,
|
||||
DEAD = 22 // new group, used to show dead stacks. If empty - last frame from "DEATH" will be copied here
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
//queue of animations waiting to be displayed
|
||||
std::queue<EAnimType> queue;
|
||||
|
||||
//this function is used as callback if preview flag was set during construction
|
||||
void loopPreview(bool warMachine);
|
||||
|
||||
public:
|
||||
//change anim to next if queue is not empty, call callback othervice
|
||||
void reset();
|
||||
|
||||
//add sequence to the end of queue
|
||||
void addLast(EAnimType newType);
|
||||
|
||||
void startPreview(bool warMachine);
|
||||
|
||||
//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 );
|
||||
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
#include "StdInc.h"
|
||||
#include "MiscWidgets.h"
|
||||
|
||||
#include "CComponent.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
@ -10,12 +12,15 @@
|
||||
#include "../CGameInfo.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../windows/CCastleInterface.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
|
||||
/*
|
||||
* MiscWidgets.cpp, part of VCMI engine
|
||||
@ -27,408 +32,58 @@
|
||||
*
|
||||
*/
|
||||
|
||||
void CSelWindow::selectionChange(unsigned to)
|
||||
void CHoverableArea::hover (bool on)
|
||||
{
|
||||
for (unsigned i=0;i<components.size();i++)
|
||||
{
|
||||
CSelectableComponent * pom = dynamic_cast<CSelectableComponent*>(components[i]);
|
||||
if (!pom)
|
||||
continue;
|
||||
pom->select(i==to);
|
||||
}
|
||||
redraw();
|
||||
if (on)
|
||||
GH.statusbar->setText(hoverText);
|
||||
else if (GH.statusbar->getText()==hoverText)
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
||||
CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector<CSelectableComponent*> &comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID)
|
||||
CHoverableArea::CHoverableArea()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
ID = askID;
|
||||
for(int i=0;i<Buttons.size();i++)
|
||||
{
|
||||
buttons.push_back(new CAdventureMapButton("","",Buttons[i].second,0,0,Buttons[i].first));
|
||||
if(!i && askID.getNum() >= 0)
|
||||
buttons.back()->callback += boost::bind(&CSelWindow::madeChoice,this);
|
||||
buttons[i]->callback += boost::bind(&CInfoWindow::close,this); //each button will close the window apart from call-defined actions
|
||||
}
|
||||
|
||||
text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
|
||||
|
||||
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
|
||||
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
|
||||
|
||||
if(buttons.size() > 1 && askID.getNum() >= 0) //cancel button functionality
|
||||
buttons.back()->callback += boost::bind(&CCallback::selectionMade,LOCPLINT->cb.get(),0,askID);
|
||||
|
||||
for(int i=0;i<comps.size();i++)
|
||||
{
|
||||
comps[i]->recActions = 255;
|
||||
addChild(comps[i]);
|
||||
components.push_back(comps[i]);
|
||||
comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,this,i);
|
||||
if(i<9)
|
||||
comps[i]->assignedKeys.insert(SDLK_1+i);
|
||||
}
|
||||
CMessage::drawIWindow(this, Text, player);
|
||||
addUsedEvents(HOVER);
|
||||
}
|
||||
|
||||
void CSelWindow::madeChoice()
|
||||
CHoverableArea::~CHoverableArea()
|
||||
{
|
||||
if(ID.getNum() < 0)
|
||||
return;
|
||||
int ret = -1;
|
||||
for (int i=0;i<components.size();i++)
|
||||
{
|
||||
if(dynamic_cast<CSelectableComponent*>(components[i])->selected)
|
||||
{
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
LOCPLINT->cb->selectionMade(ret+1,ID);
|
||||
}
|
||||
|
||||
CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps)
|
||||
void LRClickableAreaWText::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
type |= BLOCK_ADV_HOTKEYS;
|
||||
ID = QueryID(-1);
|
||||
for(auto & Button : Buttons)
|
||||
if(!down && previousState && !text.empty())
|
||||
{
|
||||
CAdventureMapButton *button = new CAdventureMapButton("","",boost::bind(&CInfoWindow::close,this),0,0,Button.first);
|
||||
button->borderColor = Colors::METALLIC_GOLD;
|
||||
button->borderEnabled = true;
|
||||
button->callback.add(Button.second); //each button will close the window apart from call-defined actions
|
||||
buttons.push_back(button);
|
||||
}
|
||||
|
||||
text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
|
||||
if(!text->slider)
|
||||
{
|
||||
text->resize(text->label->textSize);
|
||||
}
|
||||
|
||||
if(buttons.size())
|
||||
{
|
||||
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
|
||||
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
|
||||
}
|
||||
|
||||
for(auto & comp : comps)
|
||||
{
|
||||
comp->recActions = 0xff;
|
||||
addChild(comp);
|
||||
comp->recActions &= ~(SHOWALL | UPDATE);
|
||||
components.push_back(comp);
|
||||
}
|
||||
setDelComps(delComps);
|
||||
CMessage::drawIWindow(this,Text,player);
|
||||
}
|
||||
|
||||
CInfoWindow::CInfoWindow()
|
||||
{
|
||||
ID = QueryID(-1);
|
||||
setDelComps(false);
|
||||
text = nullptr;
|
||||
}
|
||||
|
||||
void CInfoWindow::close()
|
||||
{
|
||||
GH.popIntTotally(this);
|
||||
if(LOCPLINT)
|
||||
LOCPLINT->showingDialog->setn(false);
|
||||
}
|
||||
|
||||
void CInfoWindow::show(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::show(to);
|
||||
}
|
||||
|
||||
CInfoWindow::~CInfoWindow()
|
||||
{
|
||||
if(!delComps)
|
||||
{
|
||||
for (auto & elem : components)
|
||||
removeChild(elem);
|
||||
LOCPLINT->showInfoDialog(text);
|
||||
}
|
||||
}
|
||||
|
||||
void CInfoWindow::showAll(SDL_Surface * to)
|
||||
void LRClickableAreaWText::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
CSimpleWindow::show(to);
|
||||
CIntObject::showAll(to);
|
||||
if (!text.empty())
|
||||
adventureInt->handleRightClick(text, down);
|
||||
}
|
||||
|
||||
void CInfoWindow::showInfoDialog(const std::string &text, const std::vector<CComponent *> *components, bool DelComps, PlayerColor player)
|
||||
LRClickableAreaWText::LRClickableAreaWText()
|
||||
{
|
||||
CInfoWindow * window = CInfoWindow::create(text, player, components, DelComps);
|
||||
GH.pushInt(window);
|
||||
init();
|
||||
}
|
||||
|
||||
void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps, PlayerColor player)
|
||||
LRClickableAreaWText::LRClickableAreaWText(const Rect &Pos, const std::string &HoverText /*= ""*/, const std::string &ClickText /*= ""*/)
|
||||
{
|
||||
assert(!LOCPLINT || LOCPLINT->showingDialog->get());
|
||||
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 ? *components : std::vector<CComponent*>(), pom, DelComps);
|
||||
for(auto & elem : onYes.funcs)
|
||||
temp->buttons[0]->callback += elem;
|
||||
for(auto & elem : onNo.funcs)
|
||||
temp->buttons[1]->callback += elem;
|
||||
|
||||
GH.pushInt(temp);
|
||||
init();
|
||||
pos = Pos + pos;
|
||||
hoverText = HoverText;
|
||||
text = ClickText;
|
||||
}
|
||||
|
||||
void CInfoWindow::showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps, PlayerColor player)
|
||||
{
|
||||
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, delComps);
|
||||
temp->buttons[0]->callback += onOk;
|
||||
|
||||
GH.pushInt(temp);
|
||||
}
|
||||
|
||||
CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID /*= 1*/, const std::vector<CComponent*> *components /*= nullptr*/, bool DelComps)
|
||||
{
|
||||
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 ? *components : std::vector<CComponent*>(), pom, DelComps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CInfoWindow::genText(std::string title, std::string description)
|
||||
{
|
||||
return std::string("{") + title + "}" + "\n\n" + description;
|
||||
}
|
||||
|
||||
void CInfoWindow::setDelComps(bool DelComps)
|
||||
{
|
||||
delComps = DelComps;
|
||||
for(CComponent *comp : components)
|
||||
{
|
||||
if(delComps)
|
||||
comp->recActions |= DISPOSE;
|
||||
else
|
||||
comp->recActions &= ~DISPOSE;
|
||||
}
|
||||
}
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free)
|
||||
:free(Free),bitmap(Bitmap)
|
||||
{
|
||||
init(x, y);
|
||||
}
|
||||
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free/*=false*/)
|
||||
: free(Free),bitmap(Bitmap)
|
||||
{
|
||||
switch(alignment)
|
||||
{
|
||||
case BOTTOMRIGHT:
|
||||
init(p.x - Bitmap->w, p.y - Bitmap->h);
|
||||
break;
|
||||
case CENTER:
|
||||
init(p.x - Bitmap->w/2, p.y - Bitmap->h/2);
|
||||
break;
|
||||
case TOPLEFT:
|
||||
init(p.x, p.y);
|
||||
break;
|
||||
default:
|
||||
assert(0); //not implemented
|
||||
}
|
||||
}
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free)
|
||||
{
|
||||
CCS->curh->hide();
|
||||
|
||||
free=Free;
|
||||
bitmap=Bitmap;
|
||||
|
||||
if(bitmap)
|
||||
{
|
||||
pos.x = screen->w/2 - bitmap->w/2;
|
||||
pos.y = screen->h/2 - bitmap->h/2;
|
||||
pos.h = bitmap->h;
|
||||
pos.w = bitmap->w;
|
||||
}
|
||||
}
|
||||
|
||||
void CInfoPopup::close()
|
||||
{
|
||||
if(free)
|
||||
SDL_FreeSurface(bitmap);
|
||||
GH.popIntTotally(this);
|
||||
}
|
||||
|
||||
void CInfoPopup::show(SDL_Surface * to)
|
||||
{
|
||||
blitAt(bitmap,pos.x,pos.y,to);
|
||||
}
|
||||
|
||||
CInfoPopup::~CInfoPopup()
|
||||
{
|
||||
CCS->curh->show();
|
||||
}
|
||||
|
||||
void CInfoPopup::init(int x, int y)
|
||||
{
|
||||
CCS->curh->hide();
|
||||
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
pos.h = bitmap->h;
|
||||
pos.w = bitmap->w;
|
||||
|
||||
// Put the window back on screen if necessary
|
||||
vstd::amax(pos.x, 0);
|
||||
vstd::amax(pos.y, 0);
|
||||
vstd::amin(pos.x, screen->w - bitmap->w);
|
||||
vstd::amin(pos.y, screen->h - bitmap->h);
|
||||
}
|
||||
|
||||
|
||||
void CRClickPopup::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down)
|
||||
return;
|
||||
close();
|
||||
}
|
||||
|
||||
void CRClickPopup::close()
|
||||
{
|
||||
GH.popIntTotally(this);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps)
|
||||
{
|
||||
PlayerColor player = LOCPLINT ? LOCPLINT->playerID : PlayerColor(1); //if no player, then use blue
|
||||
|
||||
CSimpleWindow * temp = new 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);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const std::string &txt, CComponent * component)
|
||||
{
|
||||
CInfoWindow::TCompsInfo intComps;
|
||||
intComps.push_back(component);
|
||||
|
||||
createAndPush(txt, intComps);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/)
|
||||
{
|
||||
CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
|
||||
if(iWin)
|
||||
GH.pushInt(iWin);
|
||||
else
|
||||
{
|
||||
if (adventureInt->curHero())
|
||||
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
|
||||
else
|
||||
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
|
||||
}
|
||||
}
|
||||
|
||||
CRClickPopup::CRClickPopup()
|
||||
{
|
||||
addUsedEvents(RCLICK);
|
||||
}
|
||||
|
||||
CRClickPopup::~CRClickPopup()
|
||||
LRClickableAreaWText::~LRClickableAreaWText()
|
||||
{
|
||||
}
|
||||
|
||||
void CRClickPopupInt::show(SDL_Surface * to)
|
||||
void LRClickableAreaWText::init()
|
||||
{
|
||||
inner->show(to);
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
||||
}
|
||||
|
||||
CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt )
|
||||
{
|
||||
CCS->curh->hide();
|
||||
inner = our;
|
||||
delInner = deleteInt;
|
||||
}
|
||||
|
||||
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);
|
||||
vstd::abetween(p.y, adventureInt->terrain.pos.y + 100, adventureInt->terrain.pos.y + adventureInt->terrain.pos.h - 100);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutTown iah;
|
||||
LOCPLINT->cb->getTownInfo(town, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CTownTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutHero iah;
|
||||
LOCPLINT->cb->getHeroInfo(hero, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CHeroTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutTown iah;
|
||||
LOCPLINT->cb->getTownInfo(garr, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CArmyTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
|
||||
{
|
||||
if(!specific)
|
||||
specific = adventureInt->selection;
|
||||
|
||||
assert(specific);
|
||||
|
||||
switch(specific->ID)
|
||||
{
|
||||
case Obj::HERO:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGHeroInstance *>(specific));
|
||||
case Obj::TOWN:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGTownInstance *>(specific));
|
||||
case Obj::GARRISON:
|
||||
case Obj::GARRISON2:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGGarrison *>(specific));
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if((!down) && previousState)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CComponent.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
/*
|
||||
* MiscWidgets.h, part of VCMI engine
|
||||
@ -19,105 +19,33 @@ class CSelectableComponent;
|
||||
class InfoAboutArmy;
|
||||
class CArmedInstance;
|
||||
class IBonusBearer;
|
||||
class CAnimImage;
|
||||
|
||||
/// text + comp. + ok button
|
||||
class CInfoWindow : public CSimpleWindow
|
||||
{ //window able to delete its components when closed
|
||||
bool delComps; //whether comps will be deleted
|
||||
|
||||
public:
|
||||
typedef std::vector<std::pair<std::string,CFunctionList<void()> > > TButtonsInfo;
|
||||
typedef std::vector<CComponent*> TCompsInfo;
|
||||
QueryID ID; //for identification
|
||||
CTextBox *text;
|
||||
std::vector<CAdventureMapButton *> buttons;
|
||||
std::vector<CComponent*> components;
|
||||
CSlider *slider;
|
||||
|
||||
void setDelComps(bool DelComps);
|
||||
virtual void close();
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void sliderMoved(int to);
|
||||
|
||||
CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); //c-tor
|
||||
CInfoWindow(); //c-tor
|
||||
~CInfoWindow(); //d-tor
|
||||
|
||||
//use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
|
||||
static void showInfoDialog( const std::string & text, const std::vector<CComponent*> *components, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showYesNoDialog( const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector<CComponent*> *components = nullptr, bool DelComps = false);
|
||||
|
||||
/// 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
|
||||
/// Shows a text by moving the mouse cursor over the object
|
||||
class CHoverableArea: public virtual CIntObject
|
||||
{
|
||||
public:
|
||||
virtual void close();
|
||||
void clickRight(tribool down, bool previousState);
|
||||
std::string hoverText;
|
||||
|
||||
CRClickPopup();
|
||||
virtual ~CRClickPopup(); //d-tor
|
||||
virtual void hover (bool on);
|
||||
|
||||
static CIntObject* 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, CComponent * component);
|
||||
static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
|
||||
CHoverableArea();
|
||||
virtual ~CHoverableArea();
|
||||
};
|
||||
|
||||
/// popup displayed on R-click
|
||||
class CRClickPopupInt : public CRClickPopup
|
||||
/// Can interact on left and right mouse clicks, plus it shows a text when by hovering over it
|
||||
class LRClickableAreaWText: public CHoverableArea
|
||||
{
|
||||
public:
|
||||
IShowActivatable *inner;
|
||||
bool delInner;
|
||||
std::string text;
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
CRClickPopupInt(IShowActivatable *our, bool deleteInt); //c-tor
|
||||
virtual ~CRClickPopupInt(); //d-tor
|
||||
};
|
||||
LRClickableAreaWText();
|
||||
LRClickableAreaWText(const Rect &Pos, const std::string &HoverText = "", const std::string &ClickText = "");
|
||||
virtual ~LRClickableAreaWText();
|
||||
void init();
|
||||
|
||||
class CInfoPopup : public CRClickPopup
|
||||
{
|
||||
public:
|
||||
bool free; //TODO: comment me
|
||||
SDL_Surface * bitmap; //popup background
|
||||
void close();
|
||||
void show(SDL_Surface * to);
|
||||
CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap = nullptr, bool Free = false); //default c-tor
|
||||
|
||||
void init(int x, int y);
|
||||
~CInfoPopup(); //d-tor
|
||||
};
|
||||
|
||||
/// popup on adventure map for town\hero objects
|
||||
class CInfoBoxPopup : public CWindowObject
|
||||
{
|
||||
Point toScreen(Point pos);
|
||||
public:
|
||||
CInfoBoxPopup(Point position, const CGTownInstance * town);
|
||||
CInfoBoxPopup(Point position, const CGHeroInstance * hero);
|
||||
CInfoBoxPopup(Point position, const CGGarrison * garr);
|
||||
};
|
||||
|
||||
/// 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<CSelectableComponent*> &comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID); //c-tor
|
||||
CSelWindow(){}; //c-tor
|
||||
//notification - this class inherits important destructor from CInfoWindow
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
};
|
||||
|
||||
/// base class for hero/town/garrison tooltips
|
||||
@ -173,18 +101,6 @@ public:
|
||||
~CMinorResDataBar(); //d-tor
|
||||
};
|
||||
|
||||
class MoraleLuckBox : public LRClickableAreaWTextComp
|
||||
{
|
||||
CAnimImage *image;
|
||||
public:
|
||||
bool morale; //true if morale, false if luck
|
||||
bool small;
|
||||
|
||||
void set(const IBonusBearer *node);
|
||||
|
||||
MoraleLuckBox(bool Morale, const Rect &r, bool Small=false);
|
||||
};
|
||||
|
||||
/// Opens hero window by left-clicking on it
|
||||
class CHeroArea: public CIntObject
|
||||
{
|
||||
@ -198,6 +114,19 @@ public:
|
||||
void hover(bool on);
|
||||
};
|
||||
|
||||
/// Can interact on left and right mouse clicks
|
||||
class LRClickableAreaWTextComp: public LRClickableAreaWText
|
||||
{
|
||||
public:
|
||||
int baseType;
|
||||
int bonusValue, type;
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
|
||||
LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
|
||||
CComponent * createComponent() const;
|
||||
};
|
||||
|
||||
/// Opens town screen by left-clicking on it
|
||||
class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
|
||||
{
|
||||
@ -207,3 +136,15 @@ public:
|
||||
void clickRight(tribool down, bool previousState);
|
||||
LRClickableAreaOpenTown();
|
||||
};
|
||||
|
||||
class MoraleLuckBox : public LRClickableAreaWTextComp
|
||||
{
|
||||
CAnimImage *image;
|
||||
public:
|
||||
bool morale; //true if morale, false if luck
|
||||
bool small;
|
||||
|
||||
void set(const IBonusBearer *node);
|
||||
|
||||
MoraleLuckBox(bool Morale, const Rect &r, bool Small=false);
|
||||
};
|
||||
|
234
client/widgets/ObjectLists.cpp
Normal file
234
client/widgets/ObjectLists.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
#include "StdInc.h"
|
||||
#include "ObjectLists.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "Buttons.h"
|
||||
|
||||
/*
|
||||
* ObjectLists.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static void intDeleter(CIntObject* object)
|
||||
{
|
||||
delete object;
|
||||
}
|
||||
|
||||
CObjectList::CObjectList(CreateFunc create, DestroyFunc destroy):
|
||||
createObject(create),
|
||||
destroyObject(destroy)
|
||||
{
|
||||
if (!destroyObject)
|
||||
destroyObject = intDeleter;
|
||||
}
|
||||
|
||||
void CObjectList::deleteItem(CIntObject* item)
|
||||
{
|
||||
if (!item)
|
||||
return;
|
||||
removeChild(item);
|
||||
destroyObject(item);
|
||||
}
|
||||
|
||||
CIntObject* CObjectList::createItem(size_t index)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
CIntObject * item = createObject(index);
|
||||
if (item == nullptr)
|
||||
item = new CIntObject();
|
||||
|
||||
item->recActions = defActions;
|
||||
|
||||
addChild(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
CTabbedInt::CTabbedInt(CreateFunc create, DestroyFunc destroy, Point position, size_t ActiveID):
|
||||
CObjectList(create, destroy),
|
||||
activeTab(nullptr),
|
||||
activeID(ActiveID)
|
||||
{
|
||||
pos += position;
|
||||
reset();
|
||||
}
|
||||
|
||||
void CTabbedInt::setActive(size_t which)
|
||||
{
|
||||
if (which != activeID)
|
||||
{
|
||||
activeID = which;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CTabbedInt::reset()
|
||||
{
|
||||
deleteItem(activeTab);
|
||||
activeTab = createItem(activeID);
|
||||
activeTab->moveTo(pos.topLeft());
|
||||
|
||||
if (active)
|
||||
redraw();
|
||||
}
|
||||
|
||||
CIntObject * CTabbedInt::getItem()
|
||||
{
|
||||
return activeTab;
|
||||
}
|
||||
|
||||
CListBox::CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
|
||||
size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos):
|
||||
CObjectList(create, destroy),
|
||||
first(InitialPos),
|
||||
totalSize(TotalSize),
|
||||
itemOffset(ItemOffset),
|
||||
slider(nullptr)
|
||||
{
|
||||
pos += Pos;
|
||||
items.resize(VisibleSize, nullptr);
|
||||
|
||||
if (Slider & 1)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
slider = new CSlider(SliderPos.x, SliderPos.y, SliderPos.w, boost::bind(&CListBox::moveToPos, this, _1),
|
||||
VisibleSize, TotalSize, InitialPos, Slider & 2, Slider & 4);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
// Used to move active items after changing list position
|
||||
void CListBox::updatePositions()
|
||||
{
|
||||
Point itemPos = pos.topLeft();
|
||||
for (auto & elem : items)
|
||||
{
|
||||
(elem)->moveTo(itemPos);
|
||||
itemPos += itemOffset;
|
||||
}
|
||||
if (active)
|
||||
{
|
||||
redraw();
|
||||
if (slider)
|
||||
slider->moveTo(first);
|
||||
}
|
||||
}
|
||||
|
||||
void CListBox::reset()
|
||||
{
|
||||
size_t current = first;
|
||||
for (auto & elem : items)
|
||||
{
|
||||
deleteItem(elem);
|
||||
elem = createItem(current++);
|
||||
}
|
||||
updatePositions();
|
||||
}
|
||||
|
||||
void CListBox::resize(size_t newSize)
|
||||
{
|
||||
totalSize = newSize;
|
||||
if (slider)
|
||||
slider->setAmount(totalSize);
|
||||
reset();
|
||||
}
|
||||
|
||||
size_t CListBox::size()
|
||||
{
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
CIntObject * CListBox::getItem(size_t which)
|
||||
{
|
||||
if (which < first || which > first + items.size() || which > totalSize)
|
||||
return nullptr;
|
||||
|
||||
size_t i=first;
|
||||
for (auto iter = items.begin(); iter != items.end(); iter++, i++)
|
||||
if( i == which)
|
||||
return *iter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t CListBox::getIndexOf(CIntObject *item)
|
||||
{
|
||||
size_t i=first;
|
||||
for (auto iter = items.begin(); iter != items.end(); iter++, i++)
|
||||
if(*iter == item)
|
||||
return i;
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
void CListBox::scrollTo(size_t which)
|
||||
{
|
||||
//scroll up
|
||||
if (first > which)
|
||||
moveToPos(which);
|
||||
//scroll down
|
||||
else if (first + items.size() <= which && which < totalSize)
|
||||
moveToPos(which - items.size() + 1);
|
||||
}
|
||||
|
||||
void CListBox::moveToPos(size_t which)
|
||||
{
|
||||
//Calculate new position
|
||||
size_t maxPossible;
|
||||
if (totalSize > items.size())
|
||||
maxPossible = totalSize - items.size();
|
||||
else
|
||||
maxPossible = 0;
|
||||
|
||||
size_t newPos = std::min(which, maxPossible);
|
||||
|
||||
//If move distance is 1 (most of calls from Slider) - use faster shifts instead of resetting all items
|
||||
if (first - newPos == 1)
|
||||
moveToPrev();
|
||||
else if (newPos - first == 1)
|
||||
moveToNext();
|
||||
else if (newPos != first)
|
||||
{
|
||||
first = newPos;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CListBox::moveToNext()
|
||||
{
|
||||
//Remove front item and insert new one to end
|
||||
if (first + items.size() < totalSize)
|
||||
{
|
||||
first++;
|
||||
deleteItem(items.front());
|
||||
items.pop_front();
|
||||
items.push_back(createItem(first+items.size()));
|
||||
updatePositions();
|
||||
}
|
||||
}
|
||||
|
||||
void CListBox::moveToPrev()
|
||||
{
|
||||
//Remove last item and insert new one at start
|
||||
if (first)
|
||||
{
|
||||
first--;
|
||||
deleteItem(items.back());
|
||||
items.pop_back();
|
||||
items.push_front(createItem(first));
|
||||
updatePositions();
|
||||
}
|
||||
}
|
||||
|
||||
size_t CListBox::getPos()
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
const std::list<CIntObject *> &CListBox::getItems()
|
||||
{
|
||||
return items;
|
||||
}
|
111
client/widgets/ObjectLists.h
Normal file
111
client/widgets/ObjectLists.h
Normal file
@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CSlider;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
/*
|
||||
* ObjectLists.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Used as base for Tabs and List classes
|
||||
class CObjectList : public CIntObject
|
||||
{
|
||||
public:
|
||||
typedef std::function<CIntObject* (size_t)> CreateFunc;
|
||||
typedef std::function<void(CIntObject *)> DestroyFunc;
|
||||
|
||||
private:
|
||||
CreateFunc createObject;
|
||||
DestroyFunc destroyObject;
|
||||
|
||||
protected:
|
||||
//Internal methods for safe creation of items (Children capturing and activation/deactivation if needed)
|
||||
void deleteItem(CIntObject* item);
|
||||
CIntObject* createItem(size_t index);
|
||||
|
||||
CObjectList(CreateFunc create, DestroyFunc destroy = DestroyFunc());//Protected constructor
|
||||
};
|
||||
|
||||
/// Window element with multiple tabs
|
||||
class CTabbedInt : public CObjectList
|
||||
{
|
||||
private:
|
||||
CIntObject * activeTab;
|
||||
size_t activeID;
|
||||
|
||||
public:
|
||||
//CreateFunc, DestroyFunc - see CObjectList
|
||||
//Pos - position of object, all tabs will be moved to this position
|
||||
//ActiveID - ID of initially active tab
|
||||
CTabbedInt(CreateFunc create, DestroyFunc destroy = DestroyFunc(), Point position=Point(), size_t ActiveID=0);
|
||||
|
||||
void setActive(size_t which);
|
||||
//recreate active tab
|
||||
void reset();
|
||||
|
||||
//return currently active item
|
||||
CIntObject * getItem();
|
||||
};
|
||||
|
||||
/// List of IntObjects with optional slider
|
||||
class CListBox : public CObjectList
|
||||
{
|
||||
private:
|
||||
std::list< CIntObject* > items;
|
||||
size_t first;
|
||||
size_t totalSize;
|
||||
|
||||
Point itemOffset;
|
||||
CSlider * slider;
|
||||
|
||||
void updatePositions();
|
||||
public:
|
||||
//CreateFunc, DestroyFunc - see CObjectList
|
||||
//Pos - position of first item
|
||||
//ItemOffset - distance between items in the list
|
||||
//VisibleSize - maximal number of displayable at once items
|
||||
//TotalSize
|
||||
//Slider - slider style, bit field: 1 = present(disabled), 2=horisontal(vertical), 4=blue(brown)
|
||||
//SliderPos - position of slider, if present
|
||||
CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
|
||||
size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() );
|
||||
|
||||
//recreate all visible items
|
||||
void reset();
|
||||
|
||||
//change or get total amount of items in the list
|
||||
void resize(size_t newSize);
|
||||
size_t size();
|
||||
|
||||
//return item with index which or null if not present
|
||||
CIntObject * getItem(size_t which);
|
||||
|
||||
//return currently active items
|
||||
const std::list< CIntObject * > & getItems();
|
||||
|
||||
//get index of this item. -1 if not found
|
||||
size_t getIndexOf(CIntObject * item);
|
||||
|
||||
//scroll list to make item which visible
|
||||
void scrollTo(size_t which);
|
||||
|
||||
//scroll list to specified position
|
||||
void moveToPos(size_t which);
|
||||
void moveToNext();
|
||||
void moveToPrev();
|
||||
|
||||
size_t getPos();
|
||||
};
|
642
client/widgets/TextControls.cpp
Normal file
642
client/widgets/TextControls.cpp
Normal file
@ -0,0 +1,642 @@
|
||||
#include "StdInc.h"
|
||||
#include "TextControls.h"
|
||||
|
||||
#include "Buttons.h"
|
||||
#include "Images.h"
|
||||
|
||||
#include "../CMessage.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
|
||||
|
||||
/*
|
||||
* TextControls.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
std::string CLabel::visibleText()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
void CLabel::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
|
||||
if(!visibleText().empty())
|
||||
blitLine(to, pos, visibleText());
|
||||
|
||||
}
|
||||
|
||||
CLabel::CLabel(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, const SDL_Color &Color /*= Colors::WHITE*/, const std::string &Text /*= ""*/)
|
||||
:CTextContainer(Align, Font, Color), text(Text)
|
||||
{
|
||||
type |= REDRAW_PARENT;
|
||||
autoRedraw = true;
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
pos.w = pos.h = 0;
|
||||
bg = nullptr;
|
||||
|
||||
if (alignment == TOPLEFT) // causes issues for MIDDLE
|
||||
{
|
||||
pos.w = graphics->fonts[font]->getStringWidth(visibleText().c_str());
|
||||
pos.h = graphics->fonts[font]->getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
Point CLabel::getBorderSize()
|
||||
{
|
||||
return Point(0, 0);
|
||||
}
|
||||
|
||||
std::string CLabel::getText()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
void CLabel::setText(const std::string &Txt)
|
||||
{
|
||||
text = Txt;
|
||||
if(autoRedraw)
|
||||
{
|
||||
if(bg || !parent)
|
||||
redraw();
|
||||
else
|
||||
parent->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
CMultiLineLabel::CMultiLineLabel(Rect position, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text):
|
||||
CLabel(position.x, position.y, Font, Align, Color, Text),
|
||||
visibleSize(0, 0, position.w, position.h)
|
||||
{
|
||||
pos.w = position.w;
|
||||
pos.h = position.h;
|
||||
splitText(Text);
|
||||
}
|
||||
|
||||
void CMultiLineLabel::setVisibleSize(Rect visibleSize)
|
||||
{
|
||||
this->visibleSize = visibleSize;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CMultiLineLabel::scrollTextBy(int distance)
|
||||
{
|
||||
scrollTextTo(visibleSize.y + distance);
|
||||
}
|
||||
|
||||
void CMultiLineLabel::scrollTextTo(int distance)
|
||||
{
|
||||
Rect size = visibleSize;
|
||||
size.y = distance;
|
||||
setVisibleSize(size);
|
||||
}
|
||||
|
||||
void CMultiLineLabel::setText(const std::string &Txt)
|
||||
{
|
||||
splitText(Txt);
|
||||
CLabel::setText(Txt);
|
||||
}
|
||||
|
||||
void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what)
|
||||
{
|
||||
const IFont * f = graphics->fonts[font];
|
||||
Point where = destRect.topLeft();
|
||||
|
||||
// input is rect in which given text should be placed
|
||||
// calculate proper position for top-left corner of the text
|
||||
if (alignment == TOPLEFT)
|
||||
{
|
||||
where.x += getBorderSize().x;
|
||||
where.y += getBorderSize().y;
|
||||
}
|
||||
|
||||
if (alignment == CENTER)
|
||||
{
|
||||
where.x += (int(destRect.w) - int(f->getStringWidth(what))) / 2;
|
||||
where.y += (int(destRect.h) - int(f->getLineHeight())) / 2;
|
||||
}
|
||||
|
||||
if (alignment == BOTTOMRIGHT)
|
||||
{
|
||||
where.x += getBorderSize().x + destRect.w - f->getStringWidth(what);
|
||||
where.y += getBorderSize().y + destRect.h - f->getLineHeight();
|
||||
}
|
||||
|
||||
size_t begin = 0;
|
||||
std::string delimeters = "{}";
|
||||
size_t currDelimeter = 0;
|
||||
|
||||
do
|
||||
{
|
||||
size_t end = what.find_first_of(delimeters[currDelimeter % 2], begin);
|
||||
if (begin != end)
|
||||
{
|
||||
std::string toPrint = what.substr(begin, end - begin);
|
||||
|
||||
if (currDelimeter % 2) // Enclosed in {} text - set to yellow
|
||||
f->renderTextLeft(to, toPrint, Colors::YELLOW, where);
|
||||
else // Non-enclosed text, use default color
|
||||
f->renderTextLeft(to, toPrint, color, where);
|
||||
begin = end;
|
||||
|
||||
where.x += f->getStringWidth(toPrint);
|
||||
}
|
||||
currDelimeter++;
|
||||
}
|
||||
while (begin++ != std::string::npos);
|
||||
}
|
||||
|
||||
CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color color):
|
||||
alignment(alignment),
|
||||
font(font),
|
||||
color(color)
|
||||
{}
|
||||
|
||||
void CMultiLineLabel::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
|
||||
const IFont * f = graphics->fonts[font];
|
||||
|
||||
// calculate which lines should be visible
|
||||
int totalLines = lines.size();
|
||||
int beginLine = visibleSize.y;
|
||||
int endLine = getTextLocation().h + visibleSize.y;
|
||||
|
||||
if (beginLine < 0)
|
||||
beginLine = 0;
|
||||
else
|
||||
beginLine /= f->getLineHeight();
|
||||
|
||||
if (endLine < 0)
|
||||
endLine = 0;
|
||||
else
|
||||
endLine /= f->getLineHeight();
|
||||
endLine++;
|
||||
|
||||
// and where they should be displayed
|
||||
Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * f->getLineHeight());
|
||||
Point lineSize = Point(getTextLocation().w, f->getLineHeight());
|
||||
|
||||
CSDL_Ext::CClipRectGuard guard(to, getTextLocation()); // to properly trim text that is too big to fit
|
||||
|
||||
for (int i = beginLine; i < std::min(totalLines, endLine); i++)
|
||||
{
|
||||
if (!lines[i].empty()) //non-empty line
|
||||
blitLine(to, Rect(lineStart, lineSize), lines[i]);
|
||||
|
||||
lineStart.y += f->getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void CMultiLineLabel::splitText(const std::string &Txt)
|
||||
{
|
||||
lines.clear();
|
||||
|
||||
const IFont * f = graphics->fonts[font];
|
||||
int lineHeight = f->getLineHeight();
|
||||
|
||||
lines = CMessage::breakText(Txt, pos.w, font);
|
||||
|
||||
textSize.y = lineHeight * lines.size();
|
||||
textSize.x = 0;
|
||||
for(const std::string &line : lines)
|
||||
vstd::amax( textSize.x, f->getStringWidth(line.c_str()));
|
||||
redraw();
|
||||
}
|
||||
|
||||
Rect CMultiLineLabel::getTextLocation()
|
||||
{
|
||||
// this method is needed for vertical alignment alignment of text
|
||||
// when height of available text is smaller than height of widget
|
||||
// in this case - we should add proper offset to display text at required position
|
||||
if (pos.h <= textSize.y)
|
||||
return pos;
|
||||
|
||||
Point textSize(pos.w, graphics->fonts[font]->getLineHeight() * lines.size());
|
||||
Point textOffset(pos.w - textSize.x, pos.h - textSize.y);
|
||||
|
||||
switch(alignment)
|
||||
{
|
||||
case TOPLEFT: return Rect(pos.topLeft(), textSize);
|
||||
case CENTER: return Rect(pos.topLeft() + textOffset / 2, textSize);
|
||||
case BOTTOMRIGHT: return Rect(pos.topLeft() + textOffset, textSize);
|
||||
}
|
||||
assert(0);
|
||||
return Rect();
|
||||
}
|
||||
|
||||
CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color &Color):
|
||||
font(Font), align(Align), color(Color)
|
||||
{}
|
||||
|
||||
void CLabelGroup::add(int x, int y, const std::string &text)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CLabel(x, y, font, align, color, text);
|
||||
}
|
||||
|
||||
CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= TOPLEFT*/, const SDL_Color &Color /*= Colors::WHITE*/):
|
||||
sliderStyle(SliderStyle),
|
||||
slider(nullptr)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
label = new CMultiLineLabel(rect, Font, Align, Color);
|
||||
|
||||
type |= REDRAW_PARENT;
|
||||
pos.x += rect.x;
|
||||
pos.y += rect.y;
|
||||
pos.h = rect.h;
|
||||
pos.w = rect.w;
|
||||
|
||||
assert(pos.w >= 40); //we need some space
|
||||
setText(Text);
|
||||
}
|
||||
|
||||
void CTextBox::sliderMoved(int to)
|
||||
{
|
||||
label->scrollTextTo(to);
|
||||
}
|
||||
|
||||
void CTextBox::resize(Point newSize)
|
||||
{
|
||||
pos.w = newSize.x;
|
||||
pos.h = newSize.y;
|
||||
label->pos.w = pos.w;
|
||||
label->pos.h = pos.h;
|
||||
if (slider)
|
||||
vstd::clear_pointer(slider); // will be recreated if needed later
|
||||
|
||||
setText(label->getText()); // force refresh
|
||||
}
|
||||
|
||||
void CTextBox::setText(const std::string &text)
|
||||
{
|
||||
label->setText(text);
|
||||
if (label->textSize.y <= label->pos.h && slider)
|
||||
{
|
||||
// slider is no longer needed
|
||||
vstd::clear_pointer(slider);
|
||||
label->pos.w = pos.w;
|
||||
label->setText(text);
|
||||
}
|
||||
else if (label->textSize.y > label->pos.h && !slider)
|
||||
{
|
||||
// create slider and update widget
|
||||
label->pos.w = pos.w - 32;
|
||||
label->setText(text);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
slider = new CSlider(pos.w - 32, 0, pos.h, boost::bind(&CTextBox::sliderMoved, this, _1),
|
||||
label->pos.h, label->textSize.y, 0, false, sliderStyle);
|
||||
slider->scrollStep = graphics->fonts[label->font]->getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void CGStatusBar::setText(const std::string & Text)
|
||||
{
|
||||
if(!textLock)
|
||||
CLabel::setText(Text);
|
||||
}
|
||||
|
||||
void CGStatusBar::clear()
|
||||
{
|
||||
setText("");
|
||||
}
|
||||
|
||||
CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= CENTER*/, const SDL_Color &Color /*= Colors::WHITE*/)
|
||||
: CLabel(BG->pos.x, BG->pos.y, Font, Align, Color, "")
|
||||
{
|
||||
init();
|
||||
bg = BG;
|
||||
addChild(bg);
|
||||
pos = bg->pos;
|
||||
getBorderSize();
|
||||
textLock = false;
|
||||
}
|
||||
|
||||
CGStatusBar::CGStatusBar(int x, int y, std::string name/*="ADROLLVR.bmp"*/, int maxw/*=-1*/)
|
||||
: CLabel(x, y, FONT_SMALL, CENTER)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
init();
|
||||
bg = new CPicture(name);
|
||||
pos = bg->pos;
|
||||
if((unsigned int)maxw < pos.w)
|
||||
{
|
||||
vstd::amin(pos.w, maxw);
|
||||
bg->srcRect = new Rect(0, 0, maxw, pos.h);
|
||||
}
|
||||
textLock = false;
|
||||
}
|
||||
|
||||
CGStatusBar::~CGStatusBar()
|
||||
{
|
||||
GH.statusbar = oldStatusBar;
|
||||
}
|
||||
|
||||
void CGStatusBar::show(SDL_Surface * to)
|
||||
{
|
||||
showAll(to);
|
||||
}
|
||||
|
||||
void CGStatusBar::init()
|
||||
{
|
||||
oldStatusBar = GH.statusbar;
|
||||
GH.statusbar = this;
|
||||
}
|
||||
|
||||
Point CGStatusBar::getBorderSize()
|
||||
{
|
||||
//Width of borders where text should not be printed
|
||||
static const Point borderSize(5,1);
|
||||
|
||||
switch(alignment)
|
||||
{
|
||||
case TOPLEFT: return Point(borderSize.x, borderSize.y);
|
||||
case CENTER: return Point(pos.w/2, pos.h/2);
|
||||
case BOTTOMRIGHT: return Point(pos.w - borderSize.x, pos.h - borderSize.y);
|
||||
}
|
||||
assert(0);
|
||||
return Point();
|
||||
}
|
||||
|
||||
void CGStatusBar::lock(bool shouldLock)
|
||||
{
|
||||
textLock = shouldLock;
|
||||
}
|
||||
|
||||
CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB):
|
||||
CLabel(Pos.x, Pos.y, font, CENTER),
|
||||
cb(CB)
|
||||
{
|
||||
type |= REDRAW_PARENT;
|
||||
focus = false;
|
||||
pos.h = Pos.h;
|
||||
pos.w = Pos.w;
|
||||
captureAllKeys = true;
|
||||
bg = nullptr;
|
||||
addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
|
||||
giveFocus();
|
||||
}
|
||||
|
||||
CTextInput::CTextInput( const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB )
|
||||
:cb(CB)
|
||||
{
|
||||
focus = false;
|
||||
pos += Pos;
|
||||
captureAllKeys = true;
|
||||
OBJ_CONSTRUCTION;
|
||||
bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
|
||||
addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
|
||||
giveFocus();
|
||||
}
|
||||
|
||||
CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
|
||||
{
|
||||
focus = false;
|
||||
pos += Pos;
|
||||
captureAllKeys = true;
|
||||
OBJ_CONSTRUCTION;
|
||||
bg = new CPicture(Pos, 0, true);
|
||||
Rect hlp = Pos;
|
||||
if(srf)
|
||||
CSDL_Ext::blitSurface(srf, &hlp, *bg, nullptr);
|
||||
else
|
||||
SDL_FillRect(*bg, nullptr, 0);
|
||||
pos.w = bg->pos.w;
|
||||
pos.h = bg->pos.h;
|
||||
bg->pos = pos;
|
||||
addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
|
||||
giveFocus();
|
||||
}
|
||||
|
||||
void CTextInput::focusGot()
|
||||
{
|
||||
CSDL_Ext::startTextInput(&pos);
|
||||
}
|
||||
|
||||
void CTextInput::focusLost()
|
||||
{
|
||||
CSDL_Ext::stopTextInput();
|
||||
}
|
||||
|
||||
|
||||
std::string CTextInput::visibleText()
|
||||
{
|
||||
return focus ? text + newText + "_" : text;
|
||||
}
|
||||
|
||||
void CTextInput::clickLeft( tribool down, bool previousState )
|
||||
{
|
||||
if(down && !focus)
|
||||
giveFocus();
|
||||
}
|
||||
|
||||
void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
|
||||
{
|
||||
|
||||
if(!focus || key.state != SDL_PRESSED)
|
||||
return;
|
||||
|
||||
if(key.keysym.sym == SDLK_TAB)
|
||||
{
|
||||
moveFocus();
|
||||
GH.breakEventHandling();
|
||||
return;
|
||||
}
|
||||
|
||||
bool redrawNeeded = false;
|
||||
#ifdef VCMI_SDL1
|
||||
std::string oldText = text;
|
||||
#endif // 0
|
||||
switch(key.keysym.sym)
|
||||
{
|
||||
case SDLK_DELETE: // have index > ' ' so it won't be filtered out by default section
|
||||
return;
|
||||
case SDLK_BACKSPACE:
|
||||
if(!newText.empty())
|
||||
{
|
||||
Unicode::trimRight(newText);
|
||||
redrawNeeded = true;
|
||||
}
|
||||
else if(!text.empty())
|
||||
{
|
||||
Unicode::trimRight(text);
|
||||
redrawNeeded = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef VCMI_SDL1
|
||||
if (key.keysym.unicode < ' ')
|
||||
return;
|
||||
else
|
||||
{
|
||||
text += key.keysym.unicode; //TODO 16-/>8
|
||||
redrawNeeded = true;
|
||||
}
|
||||
#endif // 0
|
||||
break;
|
||||
}
|
||||
#ifdef VCMI_SDL1
|
||||
filters(text, oldText);
|
||||
#endif // 0
|
||||
if (redrawNeeded)
|
||||
{
|
||||
redraw();
|
||||
cb(text);
|
||||
}
|
||||
}
|
||||
|
||||
void CTextInput::setText( const std::string &nText, bool callCb )
|
||||
{
|
||||
CLabel::setText(nText);
|
||||
if(callCb)
|
||||
cb(text);
|
||||
}
|
||||
|
||||
bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
|
||||
{
|
||||
if(key.keysym.sym == SDLK_RETURN || key.keysym.sym == SDLK_KP_ENTER)
|
||||
return false;
|
||||
|
||||
#ifdef VCMI_SDL1
|
||||
//this should allow all non-printable keys to go through (for example arrows)
|
||||
if (key.keysym.unicode < ' ')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
void CTextInput::textInputed(const SDL_TextInputEvent & event)
|
||||
{
|
||||
if(!focus)
|
||||
return;
|
||||
std::string oldText = text;
|
||||
|
||||
text += event.text;
|
||||
|
||||
filters(text,oldText);
|
||||
if (text != oldText)
|
||||
{
|
||||
redraw();
|
||||
cb(text);
|
||||
}
|
||||
newText = "";
|
||||
}
|
||||
|
||||
void CTextInput::textEdited(const SDL_TextEditingEvent & event)
|
||||
{
|
||||
if(!focus)
|
||||
return;
|
||||
|
||||
newText = event.text;
|
||||
redraw();
|
||||
cb(text+newText);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void CTextInput::filenameFilter(std::string & text, const std::string &)
|
||||
{
|
||||
static const std::string forbiddenChars = "<>:\"/\\|?*\r\n"; //if we are entering a filename, some special characters won't be allowed
|
||||
size_t pos;
|
||||
while ((pos = text.find_first_of(forbiddenChars)) != std::string::npos)
|
||||
text.erase(pos, 1);
|
||||
}
|
||||
|
||||
void CTextInput::numberFilter(std::string & text, const std::string & oldText, int minValue, int maxValue)
|
||||
{
|
||||
assert(minValue < maxValue);
|
||||
|
||||
if (text.empty())
|
||||
text = "0";
|
||||
|
||||
size_t pos = 0;
|
||||
if (text[0] == '-') //allow '-' sign as first symbol only
|
||||
pos++;
|
||||
|
||||
while (pos < text.size())
|
||||
{
|
||||
if (text[pos] < '0' || text[pos] > '9')
|
||||
{
|
||||
text = oldText;
|
||||
return; //new text is not number.
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
try
|
||||
{
|
||||
int value = boost::lexical_cast<int>(text);
|
||||
if (value < minValue)
|
||||
text = boost::lexical_cast<std::string>(minValue);
|
||||
else if (value > maxValue)
|
||||
text = boost::lexical_cast<std::string>(maxValue);
|
||||
}
|
||||
catch(boost::bad_lexical_cast &)
|
||||
{
|
||||
//Should never happen. Unless I missed some cases
|
||||
logGlobal->warnStream() << "Warning: failed to convert "<< text << " to number!";
|
||||
text = oldText;
|
||||
}
|
||||
}
|
||||
|
||||
CFocusable::CFocusable()
|
||||
{
|
||||
focusables.push_back(this);
|
||||
}
|
||||
|
||||
CFocusable::~CFocusable()
|
||||
{
|
||||
if(inputWithFocus == this)
|
||||
{
|
||||
focusLost();
|
||||
inputWithFocus = nullptr;
|
||||
}
|
||||
|
||||
focusables -= this;
|
||||
}
|
||||
void CFocusable::giveFocus()
|
||||
{
|
||||
if(inputWithFocus)
|
||||
{
|
||||
inputWithFocus->focus = false;
|
||||
inputWithFocus->focusLost();
|
||||
inputWithFocus->redraw();
|
||||
}
|
||||
|
||||
focus = true;
|
||||
inputWithFocus = this;
|
||||
focusGot();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CFocusable::moveFocus()
|
||||
{
|
||||
auto i = vstd::find(focusables, this),
|
||||
ourIt = i;
|
||||
for(i++; i != ourIt; i++)
|
||||
{
|
||||
if(i == focusables.end())
|
||||
i = focusables.begin();
|
||||
|
||||
if((*i)->active)
|
||||
{
|
||||
(*i)->giveFocus();
|
||||
break;;
|
||||
}
|
||||
}
|
||||
}
|
189
client/widgets/TextControls.h
Normal file
189
client/widgets/TextControls.h
Normal file
@ -0,0 +1,189 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
/*
|
||||
* TextControls.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CSlider;
|
||||
|
||||
/// Base class for all text-related widgets.
|
||||
/// Controls text blitting-related options
|
||||
class CTextContainer : public virtual CIntObject
|
||||
{
|
||||
protected:
|
||||
/// returns size of border, for left- or right-aligned text
|
||||
virtual Point getBorderSize() = 0;
|
||||
/// do actual blitting of line. Text "what" will be placed at "where" and aligned according to alignment
|
||||
void blitLine(SDL_Surface * to, Rect where, std::string what);
|
||||
|
||||
CTextContainer(EAlignment alignment, EFonts font, SDL_Color color);
|
||||
|
||||
public:
|
||||
EAlignment alignment;
|
||||
EFonts font;
|
||||
SDL_Color color; // default font color. Can be overridden by placing "{}" into the string
|
||||
};
|
||||
|
||||
/// Label which shows text
|
||||
class CLabel : public CTextContainer
|
||||
{
|
||||
protected:
|
||||
Point getBorderSize() override;
|
||||
virtual std::string visibleText();
|
||||
|
||||
CPicture *bg;
|
||||
public:
|
||||
|
||||
std::string text;
|
||||
bool autoRedraw; //whether control will redraw itself on setTxt
|
||||
|
||||
std::string getText();
|
||||
virtual void setText(const std::string &Txt);
|
||||
|
||||
CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT,
|
||||
const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
void showAll(SDL_Surface * to); //shows statusbar (with current text)
|
||||
};
|
||||
|
||||
/// Small helper class to manage group of similar labels
|
||||
class CLabelGroup : public CIntObject
|
||||
{
|
||||
std::list<CLabel*> labels;
|
||||
EFonts font;
|
||||
EAlignment align;
|
||||
SDL_Color color;
|
||||
public:
|
||||
CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE);
|
||||
void add(int x=0, int y=0, const std::string &text = "");
|
||||
};
|
||||
|
||||
/// Multi-line label that can display multiple lines of text
|
||||
/// If text is too big to fit into requested area remaining part will not be visible
|
||||
class CMultiLineLabel : public CLabel
|
||||
{
|
||||
// text to blit, split into lines that are no longer than widget width
|
||||
std::vector<std::string> lines;
|
||||
|
||||
// area of text that actually will be printed, default is widget size
|
||||
Rect visibleSize;
|
||||
|
||||
void splitText(const std::string &Txt);
|
||||
Rect getTextLocation();
|
||||
public:
|
||||
// total size of text, x = longest line of text, y = total height of lines
|
||||
Point textSize;
|
||||
|
||||
CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
|
||||
void setText(const std::string &Txt);
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
void setVisibleSize(Rect visibleSize);
|
||||
// scrolls text visible in widget. Positive value will move text up
|
||||
void scrollTextTo(int distance);
|
||||
void scrollTextBy(int distance);
|
||||
};
|
||||
|
||||
/// a multi-line label that tries to fit text with given available width and height;
|
||||
/// if not possible, it creates a slider for scrolling text
|
||||
class CTextBox : public CIntObject
|
||||
{
|
||||
int sliderStyle;
|
||||
public:
|
||||
CMultiLineLabel * label;
|
||||
CSlider *slider;
|
||||
|
||||
CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE);
|
||||
|
||||
void resize(Point newSize);
|
||||
void setText(const std::string &Txt);
|
||||
void sliderMoved(int to);
|
||||
};
|
||||
|
||||
/// Status bar which is shown at the bottom of the in-game screens
|
||||
class CGStatusBar : public CLabel
|
||||
{
|
||||
bool textLock; //Used for blocking changes to the text
|
||||
void init();
|
||||
|
||||
CGStatusBar *oldStatusBar;
|
||||
protected:
|
||||
Point getBorderSize() override;
|
||||
|
||||
public:
|
||||
|
||||
void clear();//clears statusbar and refreshes
|
||||
void setText(const std::string & Text) override; //prints text and refreshes statusbar
|
||||
|
||||
void show(SDL_Surface * to); //shows statusbar (with current text)
|
||||
|
||||
CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar
|
||||
CGStatusBar(int x, int y, std::string name, int maxw=-1);
|
||||
~CGStatusBar();
|
||||
|
||||
void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called
|
||||
};
|
||||
|
||||
/// UIElement which can get input focus
|
||||
class CFocusable : public virtual CIntObject
|
||||
{
|
||||
protected:
|
||||
virtual void focusGot(){};
|
||||
virtual void focusLost(){};
|
||||
public:
|
||||
bool focus; //only one focusable control can have focus at one moment
|
||||
|
||||
void giveFocus(); //captures focus
|
||||
void moveFocus(); //moves focus to next active control (may be used for tab switching)
|
||||
|
||||
static std::list<CFocusable*> focusables; //all existing objs
|
||||
static CFocusable *inputWithFocus; //who has focus now
|
||||
CFocusable();
|
||||
~CFocusable();
|
||||
};
|
||||
|
||||
/// Text input box where players can enter text
|
||||
class CTextInput : public CLabel, public CFocusable
|
||||
{
|
||||
std::string newText;
|
||||
protected:
|
||||
std::string visibleText() override;
|
||||
|
||||
void focusGot() override;
|
||||
void focusLost() override;
|
||||
public:
|
||||
CFunctionList<void(const std::string &)> cb;
|
||||
CFunctionList<void(std::string &, const std::string &)> filters;
|
||||
void setText(const std::string &nText, bool callCb = false);
|
||||
|
||||
CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB);
|
||||
CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB);
|
||||
CTextInput(const Rect &Pos, SDL_Surface *srf = nullptr);
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
bool captureThisEvent(const SDL_KeyboardEvent & key) override;
|
||||
|
||||
#ifndef VCMI_SDL1
|
||||
void textInputed(const SDL_TextInputEvent & event) override;
|
||||
void textEdited(const SDL_TextEditingEvent & event) override;
|
||||
|
||||
|
||||
#endif // VCMI_SDL1
|
||||
|
||||
//Filter that will block all characters not allowed in filenames
|
||||
static void filenameFilter(std::string &text, const std::string & oldText);
|
||||
//Filter that will allow only input of numbers in range min-max (min-max are allowed)
|
||||
//min-max should be set via something like boost::bind
|
||||
static void numberFilter(std::string &text, const std::string & oldText, int minValue, int maxValue);
|
||||
};
|
@ -21,8 +21,8 @@
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@ -1530,3 +1530,38 @@ void CAdvMapInt::adjustActiveness(bool aiTurnStart)
|
||||
if(wasActive)
|
||||
activate();
|
||||
}
|
||||
|
||||
CAdventureOptions::CAdventureOptions():
|
||||
CWindowObject(PLAYER_COLORED, "ADVOPTS")
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
exit = new CAdventureMapButton("","",boost::bind(&CAdventureOptions::close, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
|
||||
exit->assignedKeys.insert(SDLK_ESCAPE);
|
||||
|
||||
scenInfo = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 198, "ADVINFO.DEF",SDLK_i);
|
||||
scenInfo->callback += CAdventureOptions::showScenarioInfo;
|
||||
//viewWorld = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
|
||||
|
||||
puzzle = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 81, "ADVPUZ.DEF");
|
||||
puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
|
||||
|
||||
dig = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 139, "ADVDIG.DEF");
|
||||
if(const CGHeroInstance *h = adventureInt->curHero())
|
||||
dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h);
|
||||
else
|
||||
dig->block(true);
|
||||
}
|
||||
|
||||
void CAdventureOptions::showScenarioInfo()
|
||||
{
|
||||
auto campState = LOCPLINT->cb->getStartInfo()->campState;
|
||||
if(campState)
|
||||
{
|
||||
GH.pushInt(new CBonusSelection(campState));
|
||||
}
|
||||
else
|
||||
{
|
||||
GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo()));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
||||
class CDefHandler;
|
||||
class CCallback;
|
||||
@ -24,6 +28,16 @@ class IShipyard;
|
||||
*
|
||||
*/
|
||||
|
||||
/// Adventure options dialogue where you can view the world, dig, play the replay of the last turn,...
|
||||
class CAdventureOptions : public CWindowObject
|
||||
{
|
||||
public:
|
||||
CAdventureMapButton *exit, *viewWorld, *puzzle, *dig, *scenInfo, *replay;
|
||||
|
||||
CAdventureOptions();
|
||||
static void showScenarioInfo();
|
||||
};
|
||||
|
||||
/// Holds information about which tiles of the terrain are shown/not shown at the screen
|
||||
class CTerrainRect
|
||||
: public CIntObject
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CArtHandler.h"
|
||||
@ -30,6 +30,7 @@
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
class CAdventureMapButton;
|
||||
class CBuilding;
|
||||
|
@ -3,9 +3,12 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/ObjectLists.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
@ -14,6 +17,7 @@
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
|
||||
using namespace CSDL_Ext;
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "../../lib/HeroBonus.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
/*
|
||||
* CCreatureWindow.h, part of VCMI engine
|
||||
@ -18,7 +19,8 @@ class CCommanderInstance;
|
||||
class CStackInstance;
|
||||
class CStack;
|
||||
struct UpgradeInfo;
|
||||
class LRClickableAreaWTextComp;
|
||||
class CTabbedInt;
|
||||
class CAdventureMapButton;
|
||||
|
||||
class CClickableObject : public LRClickableAreaWText
|
||||
{
|
||||
|
@ -17,9 +17,8 @@
|
||||
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
|
@ -25,6 +25,9 @@ class LRClickableAreaWText;
|
||||
class LRClickableAreaWTextComp;
|
||||
class CArtifactsOfHero;
|
||||
class MoraleLuckBox;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
class CGStatusBar;
|
||||
|
||||
/// Button which switches hero selection
|
||||
class CHeroSwitcher : public CIntObject
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include "../CMT.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/MiscObjects.h"
|
||||
|
||||
/*
|
||||
* CKingdomInterface.cpp, part of VCMI engine
|
||||
|
@ -15,6 +15,9 @@ class LRClickableAreaOpenTown;
|
||||
class CComponent;
|
||||
class CHeroArea;
|
||||
class MoraleLuckBox;
|
||||
class CListBox;
|
||||
class CTabbedInt;
|
||||
class CGStatusBar;
|
||||
|
||||
/*
|
||||
* CKingdomInterface.h, part of VCMI engine
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CArtHandler.h"
|
||||
|
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
/*
|
||||
* CQuestLog.h, part of VCMI engine
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "GUIClasses.h"
|
||||
#include "InfoWindows.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../CDefHandler.h"
|
||||
@ -14,9 +15,11 @@
|
||||
#include "../Graphics.h"
|
||||
|
||||
#include "../battle/CBattleInterface.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@ -26,6 +29,8 @@
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
/*
|
||||
* CSpellWindow.cpp, part of VCMI engine
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/CIntObjectClasses.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
/*
|
||||
* CSpellWindow.h, part of VCMI engine
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
@ -17,7 +17,10 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/CGMarket.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/CArtifactHolder.h"
|
||||
#include "CWindowObject.h"
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
/*
|
||||
* CTradeWindow.h, part of VCMI engine
|
||||
@ -13,6 +15,8 @@
|
||||
*/
|
||||
|
||||
class IMarket;
|
||||
class CSlider;
|
||||
class CTextBox;
|
||||
|
||||
class CTradeWindow : public CWindowObject, public CWindowWithArtifacts //base for markets and altar of sacrifice
|
||||
{
|
||||
|
242
client/windows/CWindowObject.cpp
Normal file
242
client/windows/CWindowObject.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
#include "StdInc.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "../battle/CBattleInterface.h"
|
||||
#include "../battle/CBattleInterfaceClasses.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
|
||||
|
||||
/*
|
||||
* CWindowObject.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
|
||||
CIntObject(getUsedEvents(options_), Point()),
|
||||
shadow(nullptr),
|
||||
options(options_),
|
||||
background(createBg(imageName, options & PLAYER_COLORED))
|
||||
{
|
||||
assert(parent == nullptr); //Safe to remove, but windows should not have parent
|
||||
|
||||
if (options & RCLICK_POPUP)
|
||||
CCS->curh->hide();
|
||||
|
||||
if (background)
|
||||
pos = background->center(centerAt);
|
||||
else
|
||||
center(centerAt);
|
||||
|
||||
if (!(options & SHADOW_DISABLED))
|
||||
setShadow(true);
|
||||
}
|
||||
|
||||
CWindowObject::CWindowObject(int options_, std::string imageName):
|
||||
CIntObject(getUsedEvents(options_), Point()),
|
||||
shadow(nullptr),
|
||||
options(options_),
|
||||
background(createBg(imageName, options & PLAYER_COLORED))
|
||||
{
|
||||
assert(parent == nullptr); //Safe to remove, but windows should not have parent
|
||||
|
||||
if (options & RCLICK_POPUP)
|
||||
CCS->curh->hide();
|
||||
|
||||
if (background)
|
||||
pos = background->center();
|
||||
else
|
||||
center(Point(screen->w/2, screen->h/2));
|
||||
|
||||
if (!(options & SHADOW_DISABLED))
|
||||
setShadow(true);
|
||||
}
|
||||
|
||||
CWindowObject::~CWindowObject()
|
||||
{
|
||||
setShadow(false);
|
||||
}
|
||||
|
||||
CPicture * CWindowObject::createBg(std::string imageName, bool playerColored)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
if (imageName.empty())
|
||||
return nullptr;
|
||||
|
||||
auto image = new CPicture(imageName);
|
||||
if (playerColored)
|
||||
image->colorize(LOCPLINT->playerID);
|
||||
return image;
|
||||
}
|
||||
|
||||
void CWindowObject::setBackground(std::string filename)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
delete background;
|
||||
background = createBg(filename, options & PLAYER_COLORED);
|
||||
|
||||
if (background)
|
||||
pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y));
|
||||
|
||||
updateShadow();
|
||||
}
|
||||
|
||||
int CWindowObject::getUsedEvents(int options)
|
||||
{
|
||||
if (options & RCLICK_POPUP)
|
||||
return RCLICK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CWindowObject::updateShadow()
|
||||
{
|
||||
setShadow(false);
|
||||
if (!(options & SHADOW_DISABLED))
|
||||
setShadow(true);
|
||||
}
|
||||
|
||||
void CWindowObject::setShadow(bool on)
|
||||
{
|
||||
//size of shadow
|
||||
static const int size = 8;
|
||||
|
||||
if (on == bool(shadow))
|
||||
return;
|
||||
|
||||
vstd::clear_pointer(shadow);
|
||||
|
||||
//object too small to cast shadow
|
||||
if (pos.h <= size || pos.w <= size)
|
||||
return;
|
||||
|
||||
if (on)
|
||||
{
|
||||
|
||||
//helper to set last row
|
||||
auto blitAlphaRow = [](SDL_Surface *surf, size_t row)
|
||||
{
|
||||
Uint8 * ptr = (Uint8*)surf->pixels + surf->pitch * (row);
|
||||
|
||||
for (size_t i=0; i< surf->w; i++)
|
||||
{
|
||||
Channels::px<4>::a.set(ptr, 128);
|
||||
ptr+=4;
|
||||
}
|
||||
};
|
||||
|
||||
// helper to set last column
|
||||
auto blitAlphaCol = [](SDL_Surface *surf, size_t col)
|
||||
{
|
||||
Uint8 * ptr = (Uint8*)surf->pixels + 4 * (col);
|
||||
|
||||
for (size_t i=0; i< surf->h; i++)
|
||||
{
|
||||
Channels::px<4>::a.set(ptr, 128);
|
||||
ptr+= surf->pitch;
|
||||
}
|
||||
};
|
||||
|
||||
static SDL_Surface * shadowCornerTempl = nullptr;
|
||||
static SDL_Surface * shadowBottomTempl = nullptr;
|
||||
static SDL_Surface * shadowRightTempl = nullptr;
|
||||
|
||||
//one-time initialization
|
||||
if (!shadowCornerTempl)
|
||||
{
|
||||
//create "template" surfaces
|
||||
shadowCornerTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, size);
|
||||
shadowBottomTempl = CSDL_Ext::createSurfaceWithBpp<4>(1, size);
|
||||
shadowRightTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, 1);
|
||||
|
||||
Uint32 shadowColor = SDL_MapRGBA(shadowCornerTempl->format, 0, 0, 0, 192);
|
||||
|
||||
//fill with shadow body color
|
||||
SDL_FillRect(shadowCornerTempl, nullptr, shadowColor);
|
||||
SDL_FillRect(shadowBottomTempl, nullptr, shadowColor);
|
||||
SDL_FillRect(shadowRightTempl, nullptr, shadowColor);
|
||||
|
||||
//fill last row and column with more transparent color
|
||||
blitAlphaCol(shadowRightTempl , size-1);
|
||||
blitAlphaCol(shadowCornerTempl, size-1);
|
||||
blitAlphaRow(shadowBottomTempl, size-1);
|
||||
blitAlphaRow(shadowCornerTempl, size-1);
|
||||
}
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
//FIXME: do something with this points
|
||||
Point shadowStart;
|
||||
if (options & BORDERED)
|
||||
shadowStart = Point(size - 14, size - 14);
|
||||
else
|
||||
shadowStart = Point(size, size);
|
||||
|
||||
Point shadowPos;
|
||||
if (options & BORDERED)
|
||||
shadowPos = Point(pos.w + 14, pos.h + 14);
|
||||
else
|
||||
shadowPos = Point(pos.w, pos.h);
|
||||
|
||||
Point fullsize;
|
||||
if (options & BORDERED)
|
||||
fullsize = Point(pos.w + 28, pos.h + 29);
|
||||
else
|
||||
fullsize = Point(pos.w, pos.h);
|
||||
|
||||
//create base 8x8 piece of shadow
|
||||
SDL_Surface * shadowCorner = CSDL_Ext::copySurface(shadowCornerTempl);
|
||||
SDL_Surface * shadowBottom = CSDL_Ext::scaleSurfaceFast(shadowBottomTempl, fullsize.x - size, size);
|
||||
SDL_Surface * shadowRight = CSDL_Ext::scaleSurfaceFast(shadowRightTempl, size, fullsize.y - size);
|
||||
|
||||
blitAlphaCol(shadowBottom, 0);
|
||||
blitAlphaRow(shadowRight, 0);
|
||||
|
||||
//generate "shadow" object with these 3 pieces in it
|
||||
shadow = new CIntObject;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void CWindowObject::showAll(SDL_Surface *to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
if ((options & BORDERED) && (pos.h != to->h || pos.w != to->w))
|
||||
CMessage::drawBorder(LOCPLINT ? LOCPLINT->playerID : PlayerColor(1), 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();
|
||||
CCS->curh->show();
|
||||
}
|
65
client/windows/CWindowObject.h
Normal file
65
client/windows/CWindowObject.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
//#include "../gui/SDL_Extensions.h"
|
||||
|
||||
//#include "../../lib/FunctionList.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
|
||||
/*
|
||||
* CWindowObject.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Basic class for windows
|
||||
class CWindowObject : public CIntObject
|
||||
{
|
||||
CPicture * createBg(std::string imageName, bool playerColored);
|
||||
int getUsedEvents(int options);
|
||||
|
||||
CIntObject *shadow;
|
||||
void setShadow(bool on);
|
||||
|
||||
int options;
|
||||
|
||||
protected:
|
||||
CPicture * background;
|
||||
|
||||
//Simple function with call to GH.popInt
|
||||
void close();
|
||||
//Used only if RCLICK_POPUP was set
|
||||
void clickRight(tribool down, bool previousState);
|
||||
//To display border
|
||||
void showAll(SDL_Surface *to);
|
||||
//change or set background image
|
||||
void setBackground(std::string filename);
|
||||
void updateShadow();
|
||||
public:
|
||||
enum EOptions
|
||||
{
|
||||
PLAYER_COLORED=1, //background will be player-colored
|
||||
RCLICK_POPUP=2, // window will behave as right-click popup
|
||||
BORDERED=4, // window will have border if current resolution is bigger than size of window
|
||||
SHADOW_DISABLED=8 //this window won't display any shadow
|
||||
};
|
||||
|
||||
/*
|
||||
* options - EOpions enum
|
||||
* imageName - name for background image, can be empty
|
||||
* centerAt - position of window center. Default - center of the screen
|
||||
*/
|
||||
CWindowObject(int options, std::string imageName, Point centerAt);
|
||||
CWindowObject(int options, std::string imageName = "");
|
||||
~CWindowObject();
|
||||
};
|
@ -26,8 +26,9 @@
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../widgets/CArtifactHolder.h"
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
#include "../widgets/CAnimation.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
/*
|
||||
* GUIClasses.h, part of VCMI engine
|
||||
@ -23,8 +24,14 @@ class CCreaturePic;
|
||||
class MoraleLuckBox;
|
||||
class CHeroArea;
|
||||
class CMinorResDataBar;
|
||||
|
||||
class CSlider;
|
||||
class CComponentBox;
|
||||
class CTextInput;
|
||||
class CListBox;
|
||||
class CLabelGroup;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
class CGStatusBar;
|
||||
|
||||
/// Recruitment window where you can recruit creatures
|
||||
class CRecruitmentWindow : public CWindowObject
|
||||
|
456
client/windows/InfoWindows.cpp
Normal file
456
client/windows/InfoWindows.cpp
Normal file
@ -0,0 +1,456 @@
|
||||
#include "StdInc.h"
|
||||
#include "InfoWindows.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
|
||||
#include "../battle/CBattleInterface.h"
|
||||
#include "../battle/CBattleInterfaceClasses.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
#include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/MiscObjects.h"
|
||||
|
||||
/*
|
||||
* InfoWindows.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
void CSimpleWindow::show(SDL_Surface * to)
|
||||
{
|
||||
if(bitmap)
|
||||
blitAt(bitmap,pos.x,pos.y,to);
|
||||
}
|
||||
CSimpleWindow::~CSimpleWindow()
|
||||
{
|
||||
if (bitmap)
|
||||
{
|
||||
SDL_FreeSurface(bitmap);
|
||||
bitmap=nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CSelWindow::selectionChange(unsigned to)
|
||||
{
|
||||
for (unsigned i=0;i<components.size();i++)
|
||||
{
|
||||
CSelectableComponent * pom = dynamic_cast<CSelectableComponent*>(components[i]);
|
||||
if (!pom)
|
||||
continue;
|
||||
pom->select(i==to);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector<CSelectableComponent*> &comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
ID = askID;
|
||||
for(int i=0;i<Buttons.size();i++)
|
||||
{
|
||||
buttons.push_back(new CAdventureMapButton("","",Buttons[i].second,0,0,Buttons[i].first));
|
||||
if(!i && askID.getNum() >= 0)
|
||||
buttons.back()->callback += boost::bind(&CSelWindow::madeChoice,this);
|
||||
buttons[i]->callback += boost::bind(&CInfoWindow::close,this); //each button will close the window apart from call-defined actions
|
||||
}
|
||||
|
||||
text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
|
||||
|
||||
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
|
||||
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
|
||||
|
||||
if(buttons.size() > 1 && askID.getNum() >= 0) //cancel button functionality
|
||||
buttons.back()->callback += boost::bind(&CCallback::selectionMade,LOCPLINT->cb.get(),0,askID);
|
||||
|
||||
for(int i=0;i<comps.size();i++)
|
||||
{
|
||||
comps[i]->recActions = 255;
|
||||
addChild(comps[i]);
|
||||
components.push_back(comps[i]);
|
||||
comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,this,i);
|
||||
if(i<9)
|
||||
comps[i]->assignedKeys.insert(SDLK_1+i);
|
||||
}
|
||||
CMessage::drawIWindow(this, Text, player);
|
||||
}
|
||||
|
||||
void CSelWindow::madeChoice()
|
||||
{
|
||||
if(ID.getNum() < 0)
|
||||
return;
|
||||
int ret = -1;
|
||||
for (int i=0;i<components.size();i++)
|
||||
{
|
||||
if(dynamic_cast<CSelectableComponent*>(components[i])->selected)
|
||||
{
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
LOCPLINT->cb->selectionMade(ret+1,ID);
|
||||
}
|
||||
|
||||
CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
type |= BLOCK_ADV_HOTKEYS;
|
||||
ID = QueryID(-1);
|
||||
for(auto & Button : Buttons)
|
||||
{
|
||||
CAdventureMapButton *button = new CAdventureMapButton("","",boost::bind(&CInfoWindow::close,this),0,0,Button.first);
|
||||
button->borderColor = Colors::METALLIC_GOLD;
|
||||
button->borderEnabled = true;
|
||||
button->callback.add(Button.second); //each button will close the window apart from call-defined actions
|
||||
buttons.push_back(button);
|
||||
}
|
||||
|
||||
text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
|
||||
if(!text->slider)
|
||||
{
|
||||
text->resize(text->label->textSize);
|
||||
}
|
||||
|
||||
if(buttons.size())
|
||||
{
|
||||
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
|
||||
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
|
||||
}
|
||||
|
||||
for(auto & comp : comps)
|
||||
{
|
||||
comp->recActions = 0xff;
|
||||
addChild(comp);
|
||||
comp->recActions &= ~(SHOWALL | UPDATE);
|
||||
components.push_back(comp);
|
||||
}
|
||||
setDelComps(delComps);
|
||||
CMessage::drawIWindow(this,Text,player);
|
||||
}
|
||||
|
||||
CInfoWindow::CInfoWindow()
|
||||
{
|
||||
ID = QueryID(-1);
|
||||
setDelComps(false);
|
||||
text = nullptr;
|
||||
}
|
||||
|
||||
void CInfoWindow::close()
|
||||
{
|
||||
GH.popIntTotally(this);
|
||||
if(LOCPLINT)
|
||||
LOCPLINT->showingDialog->setn(false);
|
||||
}
|
||||
|
||||
void CInfoWindow::show(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::show(to);
|
||||
}
|
||||
|
||||
CInfoWindow::~CInfoWindow()
|
||||
{
|
||||
if(!delComps)
|
||||
{
|
||||
for (auto & elem : components)
|
||||
removeChild(elem);
|
||||
}
|
||||
}
|
||||
|
||||
void CInfoWindow::showAll(SDL_Surface * to)
|
||||
{
|
||||
CSimpleWindow::show(to);
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CInfoWindow::showInfoDialog(const std::string &text, const std::vector<CComponent *> *components, bool DelComps, PlayerColor player)
|
||||
{
|
||||
CInfoWindow * window = CInfoWindow::create(text, player, components, DelComps);
|
||||
GH.pushInt(window);
|
||||
}
|
||||
|
||||
void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps, PlayerColor player)
|
||||
{
|
||||
assert(!LOCPLINT || LOCPLINT->showingDialog->get());
|
||||
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 ? *components : std::vector<CComponent*>(), pom, DelComps);
|
||||
for(auto & elem : onYes.funcs)
|
||||
temp->buttons[0]->callback += elem;
|
||||
for(auto & elem : onNo.funcs)
|
||||
temp->buttons[1]->callback += elem;
|
||||
|
||||
GH.pushInt(temp);
|
||||
}
|
||||
|
||||
void CInfoWindow::showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps, PlayerColor player)
|
||||
{
|
||||
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, delComps);
|
||||
temp->buttons[0]->callback += onOk;
|
||||
|
||||
GH.pushInt(temp);
|
||||
}
|
||||
|
||||
CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID /*= 1*/, const std::vector<CComponent*> *components /*= nullptr*/, bool DelComps)
|
||||
{
|
||||
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 ? *components : std::vector<CComponent*>(), pom, DelComps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CInfoWindow::genText(std::string title, std::string description)
|
||||
{
|
||||
return std::string("{") + title + "}" + "\n\n" + description;
|
||||
}
|
||||
|
||||
void CInfoWindow::setDelComps(bool DelComps)
|
||||
{
|
||||
delComps = DelComps;
|
||||
for(CComponent *comp : components)
|
||||
{
|
||||
if(delComps)
|
||||
comp->recActions |= DISPOSE;
|
||||
else
|
||||
comp->recActions &= ~DISPOSE;
|
||||
}
|
||||
}
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free)
|
||||
:free(Free),bitmap(Bitmap)
|
||||
{
|
||||
init(x, y);
|
||||
}
|
||||
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free/*=false*/)
|
||||
: free(Free),bitmap(Bitmap)
|
||||
{
|
||||
switch(alignment)
|
||||
{
|
||||
case BOTTOMRIGHT:
|
||||
init(p.x - Bitmap->w, p.y - Bitmap->h);
|
||||
break;
|
||||
case CENTER:
|
||||
init(p.x - Bitmap->w/2, p.y - Bitmap->h/2);
|
||||
break;
|
||||
case TOPLEFT:
|
||||
init(p.x, p.y);
|
||||
break;
|
||||
default:
|
||||
assert(0); //not implemented
|
||||
}
|
||||
}
|
||||
|
||||
CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free)
|
||||
{
|
||||
CCS->curh->hide();
|
||||
|
||||
free=Free;
|
||||
bitmap=Bitmap;
|
||||
|
||||
if(bitmap)
|
||||
{
|
||||
pos.x = screen->w/2 - bitmap->w/2;
|
||||
pos.y = screen->h/2 - bitmap->h/2;
|
||||
pos.h = bitmap->h;
|
||||
pos.w = bitmap->w;
|
||||
}
|
||||
}
|
||||
|
||||
void CInfoPopup::close()
|
||||
{
|
||||
if(free)
|
||||
SDL_FreeSurface(bitmap);
|
||||
GH.popIntTotally(this);
|
||||
}
|
||||
|
||||
void CInfoPopup::show(SDL_Surface * to)
|
||||
{
|
||||
blitAt(bitmap,pos.x,pos.y,to);
|
||||
}
|
||||
|
||||
CInfoPopup::~CInfoPopup()
|
||||
{
|
||||
CCS->curh->show();
|
||||
}
|
||||
|
||||
void CInfoPopup::init(int x, int y)
|
||||
{
|
||||
CCS->curh->hide();
|
||||
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
pos.h = bitmap->h;
|
||||
pos.w = bitmap->w;
|
||||
|
||||
// Put the window back on screen if necessary
|
||||
vstd::amax(pos.x, 0);
|
||||
vstd::amax(pos.y, 0);
|
||||
vstd::amin(pos.x, screen->w - bitmap->w);
|
||||
vstd::amin(pos.y, screen->h - bitmap->h);
|
||||
}
|
||||
|
||||
|
||||
void CRClickPopup::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down)
|
||||
return;
|
||||
close();
|
||||
}
|
||||
|
||||
void CRClickPopup::close()
|
||||
{
|
||||
GH.popIntTotally(this);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps)
|
||||
{
|
||||
PlayerColor player = LOCPLINT ? LOCPLINT->playerID : PlayerColor(1); //if no player, then use blue
|
||||
|
||||
CSimpleWindow * temp = new 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);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const std::string &txt, CComponent * component)
|
||||
{
|
||||
CInfoWindow::TCompsInfo intComps;
|
||||
intComps.push_back(component);
|
||||
|
||||
createAndPush(txt, intComps);
|
||||
}
|
||||
|
||||
void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/)
|
||||
{
|
||||
CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
|
||||
if(iWin)
|
||||
GH.pushInt(iWin);
|
||||
else
|
||||
{
|
||||
if (adventureInt->curHero())
|
||||
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
|
||||
else
|
||||
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
|
||||
}
|
||||
}
|
||||
|
||||
CRClickPopup::CRClickPopup()
|
||||
{
|
||||
addUsedEvents(RCLICK);
|
||||
}
|
||||
|
||||
CRClickPopup::~CRClickPopup()
|
||||
{
|
||||
}
|
||||
|
||||
void CRClickPopupInt::show(SDL_Surface * to)
|
||||
{
|
||||
inner->show(to);
|
||||
}
|
||||
|
||||
CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt )
|
||||
{
|
||||
CCS->curh->hide();
|
||||
inner = our;
|
||||
delInner = deleteInt;
|
||||
}
|
||||
|
||||
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);
|
||||
vstd::abetween(p.y, adventureInt->terrain.pos.y + 100, adventureInt->terrain.pos.y + adventureInt->terrain.pos.h - 100);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutTown iah;
|
||||
LOCPLINT->cb->getTownInfo(town, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CTownTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutHero iah;
|
||||
LOCPLINT->cb->getHeroInfo(hero, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CHeroTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr):
|
||||
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutTown iah;
|
||||
LOCPLINT->cb->getTownInfo(garr, iah);
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CArmyTooltip(Point(9, 10), iah);
|
||||
}
|
||||
|
||||
CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
|
||||
{
|
||||
if(!specific)
|
||||
specific = adventureInt->selection;
|
||||
|
||||
assert(specific);
|
||||
|
||||
switch(specific->ID)
|
||||
{
|
||||
case Obj::HERO:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGHeroInstance *>(specific));
|
||||
case Obj::TOWN:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGTownInstance *>(specific));
|
||||
case Obj::GARRISON:
|
||||
case Obj::GARRISON2:
|
||||
return new CInfoBoxPopup(position, dynamic_cast<const CGGarrison *>(specific));
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
137
client/windows/InfoWindows.h
Normal file
137
client/windows/InfoWindows.h
Normal file
@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include "CWindowObject.h"
|
||||
//#include "../gui/SDL_Extensions.h"
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct Rect;
|
||||
class CAnimImage;
|
||||
class CLabel;
|
||||
class CAnimation;
|
||||
class CDefHandler;
|
||||
class CComponent;
|
||||
class CSelectableComponent;
|
||||
class CGGarrison;
|
||||
class CTextBox;
|
||||
class CAdventureMapButton;
|
||||
class CSlider;
|
||||
|
||||
/*
|
||||
* InfoWindows.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
// Window GUI class
|
||||
class CSimpleWindow : public CIntObject
|
||||
{
|
||||
public:
|
||||
SDL_Surface * bitmap; //background
|
||||
virtual void show(SDL_Surface * to);
|
||||
CSimpleWindow():bitmap(nullptr){}; //c-tor
|
||||
virtual ~CSimpleWindow(); //d-tor
|
||||
};
|
||||
|
||||
/// text + comp. + ok button
|
||||
class CInfoWindow : public CSimpleWindow
|
||||
{ //window able to delete its components when closed
|
||||
bool delComps; //whether comps will be deleted
|
||||
|
||||
public:
|
||||
typedef std::vector<std::pair<std::string,CFunctionList<void()> > > TButtonsInfo;
|
||||
typedef std::vector<CComponent*> TCompsInfo;
|
||||
QueryID ID; //for identification
|
||||
CTextBox *text;
|
||||
std::vector<CAdventureMapButton *> buttons;
|
||||
std::vector<CComponent*> components;
|
||||
CSlider *slider;
|
||||
|
||||
void setDelComps(bool DelComps);
|
||||
virtual void close();
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void sliderMoved(int to);
|
||||
|
||||
CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); //c-tor
|
||||
CInfoWindow(); //c-tor
|
||||
~CInfoWindow(); //d-tor
|
||||
|
||||
//use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
|
||||
static void showInfoDialog( const std::string & text, const std::vector<CComponent*> *components, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const boost::function<void()> & onOk, bool delComps = true, PlayerColor player = PlayerColor(1));
|
||||
static void showYesNoDialog( const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1));
|
||||
static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector<CComponent*> *components = nullptr, bool DelComps = false);
|
||||
|
||||
/// 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
|
||||
{
|
||||
public:
|
||||
virtual void close();
|
||||
void clickRight(tribool down, bool previousState);
|
||||
|
||||
CRClickPopup();
|
||||
virtual ~CRClickPopup(); //d-tor
|
||||
|
||||
static CIntObject* 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, CComponent * component);
|
||||
static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
|
||||
};
|
||||
|
||||
/// popup displayed on R-click
|
||||
class CRClickPopupInt : public CRClickPopup
|
||||
{
|
||||
public:
|
||||
IShowActivatable *inner;
|
||||
bool delInner;
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
CRClickPopupInt(IShowActivatable *our, bool deleteInt); //c-tor
|
||||
virtual ~CRClickPopupInt(); //d-tor
|
||||
};
|
||||
|
||||
class CInfoPopup : public CRClickPopup
|
||||
{
|
||||
public:
|
||||
bool free; //TODO: comment me
|
||||
SDL_Surface * bitmap; //popup background
|
||||
void close();
|
||||
void show(SDL_Surface * to);
|
||||
CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap = nullptr, bool Free = false); //default c-tor
|
||||
|
||||
void init(int x, int y);
|
||||
~CInfoPopup(); //d-tor
|
||||
};
|
||||
|
||||
/// popup on adventure map for town\hero objects
|
||||
class CInfoBoxPopup : public CWindowObject
|
||||
{
|
||||
Point toScreen(Point pos);
|
||||
public:
|
||||
CInfoBoxPopup(Point position, const CGTownInstance * town);
|
||||
CInfoBoxPopup(Point position, const CGHeroInstance * hero);
|
||||
CInfoBoxPopup(Point position, const CGGarrison * garr);
|
||||
};
|
||||
|
||||
/// 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<CSelectableComponent*> &comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID); //c-tor
|
||||
CSelWindow(){}; //c-tor
|
||||
//notification - this class inherits important destructor from CInfoWindow
|
||||
};
|
Loading…
Reference in New Issue
Block a user