mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Split CIntObjectClasses into multiple smaller files. This should be the last change in files
This commit is contained in:
		| @@ -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 | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user