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

Merge pull request #1535 from IvanSavenko/client_files_layout_rearrangement

Reorganize client source files
This commit is contained in:
Ivan Savenko 2023-02-02 12:20:54 +02:00 committed by GitHub
commit 5f046f25a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
123 changed files with 5606 additions and 4925 deletions

View File

@ -11,7 +11,6 @@
#include "CCallback.h"
#include "lib/CCreatureHandler.h"
#include "client/CGameInfo.h"
#include "lib/CGameState.h"
#include "client/CPlayerInterface.h"
#include "client/Client.h"
@ -21,7 +20,6 @@
#include "lib/CGeneralTextHandler.h"
#include "lib/CHeroHandler.h"
#include "lib/NetPacks.h"
#include "client/mapHandler.h"
#include "lib/CArtHandler.h"
#include "lib/GameConstants.h"
#include "lib/CPlayerState.h"

View File

@ -11,48 +11,43 @@
//
#include "StdInc.h"
#include <boost/program_options.hpp>
#include "gui/SDL_Extensions.h"
#include "CGameInfo.h"
#include "mapHandler.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/FileStream.h"
#include "mainmenu/CMainMenu.h"
#include "lobby/CSelectionBase.h"
#include "windows/CCastleInterface.h"
#include "../lib/CConsoleHandler.h"
#include "gui/CursorHandler.h"
#include "../lib/CGameState.h"
#include "../CCallback.h"
#include "CPlayerInterface.h"
#include "windows/CAdvmapInterface.h"
#include "../lib/CBuildingHandler.h"
#include "CVideoHandler.h"
#include "CMusicHandler.h"
#include "Client.h"
#include "gui/CGuiHandler.h"
#include "CServerHandler.h"
#include "gui/NotificationHandler.h"
#include "ClientCommandManager.h"
#include "windows/CMessage.h"
#include "renderSDL/SDL_Extensions.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/FileStream.h"
#include "../lib/CConsoleHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CBuildingHandler.h"
#include "../CCallback.h"
#include "../lib/CHeroHandler.h"
#include "../lib/spells/CSpellHandler.h"
#include "CMusicHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "Graphics.h"
#include "Client.h"
#include "../lib/serializer/BinaryDeserializer.h"
#include "../lib/serializer/BinarySerializer.h"
#include "../lib/VCMIDirs.h"
#include "../lib/NetPacks.h"
#include "CMessage.h"
#include "../lib/CModHandler.h"
#include "../lib/CTownHandler.h"
#include "gui/CGuiHandler.h"
#include "../lib/logging/CBasicLogConfigurator.h"
#include "../lib/CPlayerState.h"
#include "gui/CAnimation.h"
#include "../lib/serializer/Connection.h"
#include "CServerHandler.h"
#include "gui/NotificationHandler.h"
#include "ClientCommandManager.h"
#include <boost/asio.hpp>
#include <boost/program_options.hpp>
#include "mainmenu/CPrologEpilogVideo.h"
#include <vstd/StringUtils.h>

View File

@ -1,173 +1,215 @@
set(client_SRCS
StdInc.cpp
../CCallback.cpp
StdInc.cpp
../CCallback.cpp
battle/BattleActionsController.cpp
battle/BattleAnimationClasses.cpp
battle/BattleEffectsController.cpp
battle/BattleFieldController.cpp
battle/BattleInterfaceClasses.cpp
battle/BattleInterface.cpp
battle/BattleObstacleController.cpp
battle/BattleProjectileController.cpp
battle/BattleRenderer.cpp
battle/BattleSiegeController.cpp
battle/BattleStacksController.cpp
battle/BattleWindow.cpp
battle/CreatureAnimation.cpp
adventureMap/CAdvMapPanel.cpp
adventureMap/CAdvMapInt.cpp
adventureMap/CAdventureOptions.cpp
adventureMap/CInGameConsole.cpp
adventureMap/CInfoBar.cpp
adventureMap/CList.cpp
adventureMap/CMinimap.cpp
adventureMap/CResDataBar.cpp
adventureMap/CTerrainRect.cpp
adventureMap/mapHandler.cpp
gui/CAnimation.cpp
gui/Canvas.cpp
gui/CursorHandler.cpp
gui/CGuiHandler.cpp
gui/CIntObject.cpp
gui/ColorFilter.cpp
gui/Fonts.cpp
gui/SDL_Extensions.cpp
gui/NotificationHandler.cpp
gui/InterfaceObjectConfigurable.cpp
battle/BattleActionsController.cpp
battle/BattleAnimationClasses.cpp
battle/BattleEffectsController.cpp
battle/BattleFieldController.cpp
battle/BattleInterface.cpp
battle/BattleInterfaceClasses.cpp
battle/BattleObstacleController.cpp
battle/BattleProjectileController.cpp
battle/BattleRenderer.cpp
battle/BattleSiegeController.cpp
battle/BattleStacksController.cpp
battle/BattleWindow.cpp
battle/CreatureAnimation.cpp
widgets/AdventureMapClasses.cpp
widgets/Buttons.cpp
widgets/CArtifactHolder.cpp
widgets/CComponent.cpp
widgets/CGarrisonInt.cpp
widgets/Images.cpp
widgets/MiscWidgets.cpp
widgets/ObjectLists.cpp
widgets/TextControls.cpp
gui/CGuiHandler.cpp
gui/CIntObject.cpp
gui/CursorHandler.cpp
gui/InterfaceObjectConfigurable.cpp
gui/NotificationHandler.cpp
windows/CAdvmapInterface.cpp
windows/CCastleInterface.cpp
windows/CCreatureWindow.cpp
windows/CreaturePurchaseCard.cpp
windows/CHeroWindow.cpp
windows/CKingdomInterface.cpp
windows/CQuestLog.cpp
windows/CSpellWindow.cpp
windows/CTradeWindow.cpp
windows/CWindowObject.cpp
windows/GUIClasses.cpp
windows/InfoWindows.cpp
windows/QuickRecruitmentWindow.cpp
lobby/CBonusSelection.cpp
lobby/CCampaignInfoScreen.cpp
lobby/CLobbyScreen.cpp
lobby/CSavingScreen.cpp
lobby/CScenarioInfoScreen.cpp
lobby/CSelectionBase.cpp
lobby/OptionsTab.cpp
lobby/RandomMapTab.cpp
lobby/SelectionTab.cpp
mainmenu/CMainMenu.cpp
mainmenu/CCampaignScreen.cpp
mainmenu/CreditsScreen.cpp
mainmenu/CPrologEpilogVideo.cpp
mainmenu/CCampaignScreen.cpp
mainmenu/CMainMenu.cpp
mainmenu/CPrologEpilogVideo.cpp
mainmenu/CreditsScreen.cpp
lobby/CBonusSelection.cpp
lobby/CSelectionBase.cpp
lobby/CLobbyScreen.cpp
lobby/CSavingScreen.cpp
lobby/CScenarioInfoScreen.cpp
lobby/CCampaignInfoScreen.cpp
lobby/OptionsTab.cpp
lobby/RandomMapTab.cpp
lobby/SelectionTab.cpp
render/CAnimation.cpp
render/CBitmapHandler.cpp
render/CDefFile.cpp
render/CFadeAnimation.cpp
render/Canvas.cpp
render/ColorFilter.cpp
render/Graphics.cpp
render/IFont.cpp
CBitmapHandler.cpp
CreatureCostBox.cpp
CGameInfo.cpp
Client.cpp
CMessage.cpp
CMT.cpp
CMusicHandler.cpp
CPlayerInterface.cpp
CVideoHandler.cpp
CServerHandler.cpp
Graphics.cpp
mapHandler.cpp
NetPacksClient.cpp
NetPacksLobbyClient.cpp
SDLRWwrapper.cpp
ClientCommandManager.cpp
renderSDL/CBitmapFont.cpp
renderSDL/CBitmapHanFont.cpp
renderSDL/CTrueTypeFont.cpp
renderSDL/CursorHardware.cpp
renderSDL/CursorSoftware.cpp
renderSDL/SDLImage.cpp
renderSDL/SDLImageLoader.cpp
renderSDL/SDLRWwrapper.cpp
renderSDL/SDL_Extensions.cpp
widgets/Buttons.cpp
widgets/CArtifactHolder.cpp
widgets/CComponent.cpp
widgets/CGarrisonInt.cpp
widgets/CreatureCostBox.cpp
widgets/Images.cpp
widgets/MiscWidgets.cpp
widgets/ObjectLists.cpp
widgets/TextControls.cpp
windows/CCastleInterface.cpp
windows/CCreatureWindow.cpp
windows/CHeroWindow.cpp
windows/CKingdomInterface.cpp
windows/CMessage.cpp
windows/CQuestLog.cpp
windows/CSpellWindow.cpp
windows/CTradeWindow.cpp
windows/CWindowObject.cpp
windows/CreaturePurchaseCard.cpp
windows/GUIClasses.cpp
windows/InfoWindows.cpp
windows/QuickRecruitmentWindow.cpp
CGameInfo.cpp
CMT.cpp
CMusicHandler.cpp
CPlayerInterface.cpp
CServerHandler.cpp
CVideoHandler.cpp
Client.cpp
ClientCommandManager.cpp
NetPacksClient.cpp
NetPacksLobbyClient.cpp
)
set(client_HEADERS
StdInc.h
StdInc.h
battle/BattleActionsController.h
battle/BattleAnimationClasses.h
battle/BattleEffectsController.h
battle/BattleFieldController.h
battle/BattleInterfaceClasses.h
battle/BattleInterface.h
battle/BattleObstacleController.h
battle/BattleProjectileController.h
battle/BattleRenderer.h
battle/BattleSiegeController.h
battle/BattleStacksController.h
battle/BattleWindow.h
battle/CreatureAnimation.h
battle/BattleConstants.h
adventureMap/CAdvMapPanel.h
adventureMap/CAdvMapInt.h
adventureMap/CAdventureOptions.h
adventureMap/CInGameConsole.h
adventureMap/CInfoBar.h
adventureMap/CList.h
adventureMap/CMinimap.h
adventureMap/CResDataBar.h
adventureMap/CTerrainRect.h
adventureMap/mapHandler.h
gui/CAnimation.h
gui/Canvas.h
gui/CursorHandler.h
gui/CGuiHandler.h
gui/ColorFilter.h
gui/CIntObject.h
gui/Fonts.h
gui/TextAlignment.h
gui/SDL_Extensions.h
gui/SDL_PixelAccess.h
gui/NotificationHandler.h
gui/InterfaceObjectConfigurable.h
battle/BattleActionsController.h
battle/BattleAnimationClasses.h
battle/BattleConstants.h
battle/BattleEffectsController.h
battle/BattleFieldController.h
battle/BattleInterface.h
battle/BattleInterfaceClasses.h
battle/BattleObstacleController.h
battle/BattleProjectileController.h
battle/BattleRenderer.h
battle/BattleSiegeController.h
battle/BattleStacksController.h
battle/BattleWindow.h
battle/CreatureAnimation.h
widgets/AdventureMapClasses.h
widgets/Buttons.h
widgets/CArtifactHolder.h
widgets/CComponent.h
widgets/CGarrisonInt.h
widgets/Images.h
widgets/MiscWidgets.h
widgets/ObjectLists.h
widgets/TextControls.h
windows/CAdvmapInterface.h
windows/CCastleInterface.h
windows/CCreatureWindow.h
windows/CreaturePurchaseCard.h
windows/CHeroWindow.h
windows/CKingdomInterface.h
windows/CQuestLog.h
windows/CSpellWindow.h
windows/CTradeWindow.h
windows/CWindowObject.h
windows/GUIClasses.h
windows/InfoWindows.h
windows/QuickRecruitmentWindow.h
gui/CGuiHandler.h
gui/CIntObject.h
gui/CursorHandler.h
gui/InterfaceObjectConfigurable.h
gui/NotificationHandler.h
gui/TextAlignment.h
mainmenu/CMainMenu.h
mainmenu/CCampaignScreen.h
mainmenu/CreditsScreen.h
mainmenu/CPrologEpilogVideo.h
lobby/CBonusSelection.h
lobby/CCampaignInfoScreen.h
lobby/CLobbyScreen.h
lobby/CSavingScreen.h
lobby/CScenarioInfoScreen.h
lobby/CSelectionBase.h
lobby/OptionsTab.h
lobby/RandomMapTab.h
lobby/SelectionTab.h
lobby/CBonusSelection.h
lobby/CSelectionBase.h
lobby/CLobbyScreen.h
lobby/CSavingScreen.h
lobby/CScenarioInfoScreen.h
lobby/CCampaignInfoScreen.h
lobby/OptionsTab.h
lobby/RandomMapTab.h
lobby/SelectionTab.h
mainmenu/CCampaignScreen.h
mainmenu/CMainMenu.h
mainmenu/CPrologEpilogVideo.h
mainmenu/CreditsScreen.h
CBitmapHandler.h
CreatureCostBox.h
CGameInfo.h
Client.h
CMessage.h
CMT.h
CMusicHandler.h
CPlayerInterface.h
CVideoHandler.h
CServerHandler.h
Graphics.h
mapHandler.h
resource.h
SDLRWwrapper.h
ClientCommandManager.h
render/CAnimation.h
render/CBitmapHandler.h
render/CDefFile.h
render/CFadeAnimation.h
render/Canvas.h
render/ColorFilter.h
render/Graphics.h
render/ICursor.h
render/IFont.h
render/IImage.h
render/IImageLoader.h
renderSDL/CBitmapFont.h
renderSDL/CBitmapHanFont.h
renderSDL/CTrueTypeFont.h
renderSDL/CursorHardware.h
renderSDL/CursorSoftware.h
renderSDL/SDLImage.h
renderSDL/SDLImageLoader.h
renderSDL/SDLRWwrapper.h
renderSDL/SDL_Extensions.h
renderSDL/SDL_PixelAccess.h
widgets/Buttons.h
widgets/CArtifactHolder.h
widgets/CComponent.h
widgets/CGarrisonInt.h
widgets/CreatureCostBox.h
widgets/Images.h
widgets/MiscWidgets.h
widgets/ObjectLists.h
widgets/TextControls.h
windows/CCastleInterface.h
windows/CCreatureWindow.h
windows/CHeroWindow.h
windows/CKingdomInterface.h
windows/CMessage.h
windows/CQuestLog.h
windows/CSpellWindow.h
windows/CTradeWindow.h
windows/CWindowObject.h
windows/CreaturePurchaseCard.h
windows/GUIClasses.h
windows/InfoWindows.h
windows/QuickRecruitmentWindow.h
CGameInfo.h
CMT.h
CMusicHandler.h
CPlayerInterface.h
CServerHandler.h
CVideoHandler.h
Client.h
ClientCommandManager.h
resource.h
)
if(APPLE_IOS)

View File

@ -13,7 +13,8 @@
#include "CMusicHandler.h"
#include "CGameInfo.h"
#include "SDLRWwrapper.h"
#include "renderSDL/SDLRWwrapper.h"
#include "../lib/JsonNode.h"
#include "../lib/GameConstants.h"
#include "../lib/filesystem/Filesystem.h"
@ -22,6 +23,7 @@
#include "../lib/VCMIDirs.h"
#include "../lib/TerrainHandler.h"
#define VCMI_SOUND_NAME(x)
#define VCMI_SOUND_FILE(y) #y,

View File

@ -11,7 +11,8 @@
#include <vcmi/Artifact.h>
#include "windows/CAdvmapInterface.h"
#include "adventureMap/CAdvMapInt.h"
#include "adventureMap/mapHandler.h"
#include "battle/BattleInterface.h"
#include "battle/BattleEffectsController.h"
#include "battle/BattleFieldController.h"
@ -25,15 +26,15 @@
#include "windows/CHeroWindow.h"
#include "windows/CCreatureWindow.h"
#include "windows/CQuestLog.h"
#include "CMessage.h"
#include "CPlayerInterface.h"
#include "gui/SDL_Extensions.h"
#include "widgets/CComponent.h"
#include "widgets/Buttons.h"
#include "windows/CTradeWindow.h"
#include "windows/CSpellWindow.h"
#include "../lib/CConfigHandler.h"
#include "Graphics.h"
#include "windows/GUIClasses.h"
#include "render/CAnimation.h"
#include "render/IImage.h"
#include "../lib/CArtHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CHeroHandler.h"
@ -51,13 +52,11 @@
#include "../lib/NetPacks.h"//todo: remove
#include "../lib/mapping/CMap.h"
#include "../lib/VCMIDirs.h"
#include "mapHandler.h"
#include "../lib/CStopWatch.h"
#include "../lib/StartInfo.h"
#include "../lib/CPlayerState.h"
#include "../lib/GameConstants.h"
#include "gui/CGuiHandler.h"
#include "gui/CAnimation.h"
#include "windows/InfoWindows.h"
#include "../lib/UnlockGuard.h"
#include "../lib/CPathfinder.h"
@ -67,6 +66,7 @@
// FIXME: only needed for CGameState::mutex
#include "../lib/CGameState.h"
#include "gui/NotificationHandler.h"
#include "adventureMap/CInGameConsole.h"
#include <SDL_events.h>

View File

@ -11,7 +11,7 @@
#include "CVideoHandler.h"
#include "gui/CGuiHandler.h"
#include "gui/SDL_Extensions.h"
#include "renderSDL/SDL_Extensions.h"
#include "CPlayerInterface.h"
#include "../lib/filesystem/Filesystem.h"

View File

@ -13,6 +13,8 @@
#include "CMusicHandler.h"
#include "../lib/mapping/CCampaignHandler.h"
#include "../CCallback.h"
#include "adventureMap/CAdvMapInt.h"
#include "adventureMap/mapHandler.h"
#include "../lib/CConsoleHandler.h"
#include "CGameInfo.h"
#include "../lib/CGameState.h"
@ -35,7 +37,6 @@
#include "../lib/mapping/CMap.h"
#include "../lib/mapping/CMapService.h"
#include "../lib/JsonNode.h"
#include "mapHandler.h"
#include "../lib/CConfigHandler.h"
#include "mainmenu/CMainMenu.h"
#include "mainmenu/CCampaignScreen.h"
@ -46,7 +47,6 @@
#include "gui/CGuiHandler.h"
#include "CServerHandler.h"
#include "../lib/ScriptHandler.h"
#include "windows/CAdvmapInterface.h"
#include <vcmi/events/EventBus.h>
#ifdef VCMI_ANDROID

View File

@ -12,6 +12,8 @@
#include "ClientCommandManager.h"
#include "Client.h"
#include "adventureMap/CInGameConsole.h"
#include "adventureMap/CAdvMapInt.h"
#include "CPlayerInterface.h"
#include "CServerHandler.h"
#include "gui/CGuiHandler.h"
@ -20,14 +22,14 @@
#include "../lib/CGameState.h"
#include "../lib/CPlayerState.h"
#include "../lib/StringConstants.h"
#include "gui/CAnimation.h"
#include "windows/CAdvmapInterface.h"
#include "windows/CCastleInterface.h"
#include "render/CAnimation.h"
#include "../CCallback.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CHeroHandler.h"
#include "../lib/CModHandler.h"
#include "../lib/VCMIDirs.h"
#include "CMT.h"
#ifdef SCRIPTING_ENABLED
#include "../lib/ScriptHandler.h"

View File

@ -10,12 +10,21 @@
#include "StdInc.h"
#include "../lib/NetPacks.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/FileInfo.h"
#include "../CCallback.h"
#include "Client.h"
#include "CPlayerInterface.h"
#include "CGameInfo.h"
#include "windows/GUIClasses.h"
#include "adventureMap/mapHandler.h"
#include "adventureMap/CInGameConsole.h"
#include "battle/BattleInterface.h"
#include "gui/CGuiHandler.h"
#include "widgets/MiscWidgets.h"
#include "CMT.h"
#include "CServerHandler.h"
#include "../CCallback.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/FileInfo.h"
#include "../lib/serializer/Connection.h"
#include "../lib/serializer/BinarySerializer.h"
#include "../lib/CGeneralTextHandler.h"
@ -26,22 +35,13 @@
#include "../lib/spells/CSpellHandler.h"
#include "../lib/CSoundBase.h"
#include "../lib/StartInfo.h"
#include "mapHandler.h"
#include "windows/GUIClasses.h"
#include "../lib/CConfigHandler.h"
#include "gui/SDL_Extensions.h"
#include "battle/BattleInterface.h"
#include "../lib/mapping/CCampaignHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CStack.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/GameConstants.h"
#include "../lib/CPlayerState.h"
#include "gui/CGuiHandler.h"
#include "widgets/MiscWidgets.h"
#include "widgets/AdventureMapClasses.h"
#include "CMT.h"
#include "CServerHandler.h"
// TODO: as Tow suggested these template should all be part of CClient
// This will require rework spectator interface properly though

View File

@ -1,5 +1,5 @@
/*
* CAdvmapInterface.cpp, part of VCMI engine
* CAdvMapInt.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
@ -8,58 +8,44 @@
*
*/
#include "StdInc.h"
#include "CAdvmapInterface.h"
#include "CAdvMapInt.h"
#include "CCastleInterface.h"
#include "CHeroWindow.h"
#include "CKingdomInterface.h"
#include "CSpellWindow.h"
#include "CTradeWindow.h"
#include "GUIClasses.h"
#include "InfoWindows.h"
#include "CAdvMapPanel.h"
#include "CAdventureOptions.h"
#include "CInGameConsole.h"
#include "mapHandler.h"
#include "../CBitmapHandler.h"
#include "../windows/CKingdomInterface.h"
#include "../windows/CSpellWindow.h"
#include "../windows/CTradeWindow.h"
#include "../windows/GUIClasses.h"
#include "../windows/InfoWindows.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../mainmenu/CMainMenu.h"
#include "../lobby/CSelectionBase.h"
#include "../lobby/CCampaignInfoScreen.h"
#include "../lobby/CSavingScreen.h"
#include "../lobby/CScenarioInfoScreen.h"
#include "../Graphics.h"
#include "../mapHandler.h"
#include "../gui/CAnimation.h"
#include "../render/CAnimation.h"
#include "../gui/CursorHandler.h"
#include "../render/IImage.h"
#include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/TextControls.h"
#include "../widgets/Buttons.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGameState.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CSoundBase.h"
#include "../../lib/spells/CSpellHandler.h"
#include "../../lib/CTownHandler.h"
#include "../../lib/JsonNode.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/CPathfinder.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/UnlockGuard.h"
#include "../../lib/VCMI_Lib.h"
#include "../../lib/StartInfo.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/TerrainHandler.h"
#include <SDL_surface.h>
#include <SDL_events.h>
#define ADVOPT (conf.go()->ac)
using namespace CSDL_Ext;
std::shared_ptr<CAdvMapInt> adventureInt;
@ -89,467 +75,6 @@ static void setScrollingCursor(ui8 direction)
CCS->curh->set(Cursor::Map::SCROLL_SOUTH);
}
CTerrainRect::CTerrainRect()
: fadeSurface(nullptr),
lastRedrawStatus(EMapAnimRedrawStatus::OK),
fadeAnim(std::make_shared<CFadeAnimation>()),
curHoveredTile(-1,-1,-1),
currentPath(nullptr)
{
tilesw=(ADVOPT.advmapW+31)/32;
tilesh=(ADVOPT.advmapH+31)/32;
pos.x=ADVOPT.advmapX;
pos.y=ADVOPT.advmapY;
pos.w=ADVOPT.advmapW;
pos.h=ADVOPT.advmapH;
moveX = moveY = 0;
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
}
CTerrainRect::~CTerrainRect()
{
if(fadeSurface)
SDL_FreeSurface(fadeSurface);
}
void CTerrainRect::deactivate()
{
CIntObject::deactivate();
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
}
void CTerrainRect::clickLeft(tribool down, bool previousState)
{
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if(indeterminate(down))
return;
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(adventureInt->swipeEnabled)
{
if(handleSwipeStateChange((bool)down == true))
{
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
}
}
else
{
#endif
if(down == false)
return;
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
}
#endif
int3 mp = whichTileIsIt();
if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
return;
adventureInt->tileLClicked(mp);
}
void CTerrainRect::clickRight(tribool down, bool previousState)
{
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(adventureInt->swipeEnabled && isSwiping)
return;
#endif
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
int3 mp = whichTileIsIt();
if(CGI->mh->map->isInTheMap(mp) && down)
adventureInt->tileRClicked(mp);
}
void CTerrainRect::clickMiddle(tribool down, bool previousState)
{
handleSwipeStateChange((bool)down == true);
}
void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
{
handleHover(sEvent);
if(!adventureInt->swipeEnabled)
return;
handleSwipeMove(sEvent);
}
void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
{
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(sEvent.state == 0 || GH.multifinger) // any "button" is enough on mobile
#else
if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
#endif
{
return;
}
if(!isSwiping)
{
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
if(abs(sEvent.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
abs(sEvent.y - swipeInitialRealPos.y) > SwipeTouchSlop)
{
isSwiping = true;
}
}
if(isSwiping)
{
adventureInt->swipeTargetPosition.x =
swipeInitialMapPos.x + static_cast<si32>(swipeInitialRealPos.x - sEvent.x) / 32;
adventureInt->swipeTargetPosition.y =
swipeInitialMapPos.y + static_cast<si32>(swipeInitialRealPos.y - sEvent.y) / 32;
adventureInt->swipeMovementRequested = true;
}
}
bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
{
if(btnPressed)
{
swipeInitialRealPos = int3(GH.getCursorPosition().x, GH.getCursorPosition().y, 0);
swipeInitialMapPos = int3(adventureInt->position);
return true;
}
else if(isSwiping) // only accept this touch if it wasn't a swipe
{
isSwiping = false;
return true;
}
return false;
}
void CTerrainRect::handleHover(const SDL_MouseMotionEvent &sEvent)
{
int3 tHovered = whichTileIsIt(sEvent.x, sEvent.y);
int3 pom = adventureInt->verifyPos(tHovered);
if(tHovered != pom) //tile outside the map
{
CCS->curh->set(Cursor::Map::POINTER);
return;
}
if (pom != curHoveredTile)
{
curHoveredTile = pom;
adventureInt->tileHovered(pom);
}
}
void CTerrainRect::hover(bool on)
{
if (!on)
{
adventureInt->statusbar->clear();
CCS->curh->set(Cursor::Map::POINTER);
}
//Hoverable::hover(on);
}
void CTerrainRect::showPath(const Rect & extRect, SDL_Surface * to)
{
const static int pns[9][9] = {
{16, 17, 18, 7, -1, 19, 6, 5, -1},
{ 8, 9, 18, 7, -1, 19, 6, -1, 20},
{ 8, 1, 10, 7, -1, 19, -1, 21, 20},
{24, 17, 18, 15, -1, -1, 6, 5, 4},
{-1, -1, -1, -1, -1, -1, -1, -1, -1},
{ 8, 1, 2, -1, -1, 11, 22, 21, 20},
{24, 17, -1, 23, -1, 3, 14, 5, 4},
{24, -1, 2, 23, -1, 3, 22, 13, 4},
{-1, 1, 2, 23, -1, 3, 22, 21, 12}
}; //table of magic values TODO meaning, change variable name
for (int i = 0; i < -1 + (int)currentPath->nodes.size(); ++i)
{
const int3 &curPos = currentPath->nodes[i].coord, &nextPos = currentPath->nodes[i+1].coord;
if(curPos.z != adventureInt->position.z)
continue;
int pn=-1;//number of picture
if (i==0) //last tile
{
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
if (x<0 || y<0 || x>pos.w || y>pos.h)
continue;
pn=0;
}
else
{
const int3 &prevPos = currentPath->nodes[i-1].coord;
std::vector<CGPathNode> & cv = currentPath->nodes;
/* Vector directions
* 0 1 2
* \ | /
* 3 - 4 - 5
* / | \
* 6 7 8
*For example:
* |
* |__\
* /
* is id1=7, id2=5 (pns[7][5])
*/
bool pathContinuous = curPos.areNeighbours(nextPos) && curPos.areNeighbours(prevPos);
if(pathContinuous && cv[i].action != CGPathNode::EMBARK && cv[i].action != CGPathNode::DISEMBARK)
{
int id1=(curPos.x-nextPos.x+1)+3*(curPos.y-nextPos.y+1); //Direction of entering vector
int id2=(cv[i-1].coord.x-curPos.x+1)+3*(cv[i-1].coord.y-curPos.y+1); //Direction of exiting vector
pn=pns[id1][id2];
}
else //path discontinuity or sea/land transition (eg. when moving through Subterranean Gate or Boat)
{
pn = 0;
}
}
if (currentPath->nodes[i].turns)
pn+=25;
if (pn>=0)
{
const auto arrow = graphics->heroMoveArrows->getImage(pn);
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
if (x< -32 || y< -32 || x>pos.w || y>pos.h)
continue;
int hvx = (x + arrow->width()) - (pos.x + pos.w),
hvy = (y + arrow->height()) - (pos.y + pos.h);
Rect prevClip;
CSDL_Ext::getClipRect(to, prevClip);
CSDL_Ext::setClipRect(to, extRect); //preventing blitting outside of that rect
if(ADVOPT.smoothMove) //version for smooth hero move, with pos shifts
{
if (hvx<0 && hvy<0)
{
arrow->draw(to, x + moveX, y + moveY);
}
else if(hvx<0)
{
Rect srcRect = genRect(arrow->height() - hvy, arrow->width(), 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
else if (hvy<0)
{
Rect srcRect = genRect(arrow->height(), arrow->width() - hvx, 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
else
{
Rect srcRect = genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
}
else //standard version
{
if (hvx<0 && hvy<0)
{
arrow->draw(to, x, y);
}
else if(hvx<0)
{
Rect srcRect = genRect(arrow->height() - hvy, arrow->width(), 0, 0);
arrow->draw(to, x, y, &srcRect);
}
else if (hvy<0)
{
Rect srcRect = genRect(arrow->height(), arrow->width() - hvx, 0, 0);
arrow->draw(to, x, y, &srcRect);
}
else
{
Rect srcRect = genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
arrow->draw(to, x, y, &srcRect);
}
}
CSDL_Ext::setClipRect(to, prevClip);
}
} //for (int i=0;i<currentPath->nodes.size()-1;i++)
}
void CTerrainRect::show(SDL_Surface * to)
{
if (adventureInt->mode == EAdvMapMode::NORMAL)
{
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
info.otherheroAnim = true;
info.anim = adventureInt->anim;
info.heroAnim = adventureInt->heroAnim;
if (ADVOPT.smoothMove)
info.movement = int3(moveX, moveY, 0);
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
if (fadeAnim->isFading())
{
Rect r(pos);
fadeAnim->update();
fadeAnim->draw(to, r.topLeft());
}
if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
{
showPath(pos, to);
}
}
}
void CTerrainRect::showAll(SDL_Surface * to)
{
// world view map is static and doesn't need redraw every frame
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
{
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
info.scaled = true;
info.scale = adventureInt->worldViewScale;
adventureInt->worldViewOptions.adjustDrawingInfo(info);
CGI->mh->drawTerrainRectNew(to, &info);
}
}
void CTerrainRect::showAnim(SDL_Surface * to)
{
if (fadeAnim->isFading())
show(to);
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
}
int3 CTerrainRect::whichTileIsIt(const int x, const int y)
{
int3 ret;
ret.x = adventureInt->position.x + ((x-CGI->mh->offsetX-pos.x)/32);
ret.y = adventureInt->position.y + ((y-CGI->mh->offsetY-pos.y)/32);
ret.z = adventureInt->position.z;
return ret;
}
int3 CTerrainRect::whichTileIsIt()
{
return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
}
int3 CTerrainRect::tileCountOnScreen()
{
switch (adventureInt->mode)
{
default:
logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
return int3();
case EAdvMapMode::NORMAL:
return int3(tilesw, tilesh, 1);
case EAdvMapMode::WORLD_VIEW:
return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
}
}
void CTerrainRect::fadeFromCurrentView()
{
if (!ADVOPT.screenFading)
return;
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if (!fadeSurface)
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
}
bool CTerrainRect::needsAnimUpdate()
{
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
}
void CResDataBar::clickRight(tribool down, bool previousState)
{
}
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
{
pos.x += x;
pos.y += y;
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(defname, 0, 0);
background->colorize(LOCPLINT->playerID);
pos.w = background->pos.w;
pos.h = background->pos.h;
txtpos.resize(8);
for (int i = 0; i < 8 ; i++)
{
txtpos[i].first = pos.x + offx + resdist*i;
txtpos[i].second = pos.y + offy;
}
txtpos[7].first = txtpos[6].first + datedist;
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
addUsedEvents(RCLICK);
}
CResDataBar::CResDataBar()
{
pos.x += ADVOPT.resdatabarX;
pos.y += ADVOPT.resdatabarY;
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
background->colorize(LOCPLINT->playerID);
pos.w = background->pos.w;
pos.h = background->pos.h;
txtpos.resize(8);
for (int i = 0; i < 8 ; i++)
{
txtpos[i].first = pos.x + ADVOPT.resOffsetX + ADVOPT.resDist*i;
txtpos[i].second = pos.y + ADVOPT.resOffsetY;
}
txtpos[7].first = txtpos[6].first + ADVOPT.resDateDist;
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
}
CResDataBar::~CResDataBar() = default;
void CResDataBar::draw(SDL_Surface * to)
{
//TODO: all this should be labels, but they require proper text update on change
for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
{
std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, Point(txtpos[i].first,txtpos[i].second));
}
std::vector<std::string> temp;
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::MONTH)));
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK)));
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK)));
graphics->fonts[FONT_SMALL]->renderTextLeft(to, processStr(datetext,temp), Colors::WHITE, Point(txtpos[7].first,txtpos[7].second));
}
void CResDataBar::show(SDL_Surface * to)
{
}
void CResDataBar::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
draw(to);
}
CAdvMapInt::CAdvMapInt():
mode(EAdvMapMode::NORMAL),
worldViewScale(0.0f), //actual init later in changeMode
@ -1091,7 +616,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
int scrollSpeed = static_cast<int>(settings["adventure"]["scrollSpeed"].Float());
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if((animValHitCount % (4 / scrollSpeed)) == 0
&& ((GH.topInt().get() == this) || isCtrlKeyDown()))
&& ((GH.topInt().get() == this) || CSDL_Ext::isCtrlKeyDown()))
{
if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
position.x--;
@ -1455,7 +980,7 @@ void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
// adventure map scrolling with mouse
// currently disabled in world view mode (as it is in OH3), but should work correctly if mode check is removed
// don't scroll if there is no window in focus - these events don't seem to correspond to the actual mouse movement
if(!isCtrlKeyDown() && isActive() && sEvent.windowID != 0 && mode == EAdvMapMode::NORMAL)
if(!CSDL_Ext::isCtrlKeyDown() && isActive() && sEvent.windowID != 0 && mode == EAdvMapMode::NORMAL)
{
if(sEvent.x<15)
{
@ -1965,42 +1490,6 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale)
}
}
CAdventureOptions::CAdventureOptions()
: CWindowObject(PLAYER_COLORED, "ADVOPTS")
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
exit->assignedKeys.insert(SDLK_ESCAPE);
scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
scenInfo->addCallback(CAdventureOptions::showScenarioInfo);
puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
if(const CGHeroInstance *h = adventureInt->curHero())
dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
else
dig->block(true);
}
void CAdventureOptions::showScenarioInfo()
{
if(LOCPLINT->cb->getStartInfo()->campState)
{
GH.pushIntT<CCampaignInfoScreen>();
}
else
{
GH.pushIntT<CScenarioInfoScreen>();
}
}
CAdvMapInt::WorldViewOptions::WorldViewOptions()
{
clear();
@ -2019,3 +1508,4 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
info.additionalIcons = &iconPositions;
}

View File

@ -1,5 +1,5 @@
/*
* CAdvmapInterface.h, part of VCMI engine
* CAdvMapInt.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
@ -9,119 +9,45 @@
*/
#pragma once
#include "../widgets/AdventureMapClasses.h"
#include "CWindowObject.h"
#include "../gui/CIntObject.h"
#include "../widgets/TextControls.h"
#include "../widgets/Buttons.h"
#include "../../lib/int3.h"
#include "../../lib/GameConstants.h"
#include "../../lib/spells/ViewSpellInt.h"
#include "CTerrainRect.h"
#include "CResDataBar.h"
#include "CList.h"
#include "CInfoBar.h"
#include "CMinimap.h"
VCMI_LIB_NAMESPACE_BEGIN
struct CGPath;
struct CGPathNode;
class CGObjectInstance;
class CGHeroInstance;
class CGTownInstance;
class CSpell;
class CArmedInstance;
class IShipyard;
struct CGPathNode;
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END
class CCallback;
class CAdvMapInt;
class CHeroWindow;
enum class EMapAnimRedrawStatus;
class CFadeAnimation;
class CButton;
class IImage;
class CAnimImage;
class CGStatusBar;
class CAdvMapPanel;
class CAdvMapWorldViewPanel;
class CAnimation;
struct MapDrawingInfo;
/*****************************/
enum class EAdvMapMode
{
NORMAL,
WORLD_VIEW
};
/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
class CAdventureOptions : public CWindowObject
{
public:
std::shared_ptr<CButton> exit;
std::shared_ptr<CButton> viewWorld;
std::shared_ptr<CButton> puzzle;
std::shared_ptr<CButton> dig;
std::shared_ptr<CButton> scenInfo;
/*std::shared_ptr<CButton> replay*/
CAdventureOptions();
static void showScenarioInfo();
};
/// Holds information about which tiles of the terrain are shown/not shown at the screen
class CTerrainRect : public CIntObject
{
SDL_Surface * fadeSurface;
EMapAnimRedrawStatus lastRedrawStatus;
std::shared_ptr<CFadeAnimation> fadeAnim;
int3 swipeInitialMapPos;
int3 swipeInitialRealPos;
bool isSwiping;
static constexpr float SwipeTouchSlop = 16.0f;
void handleHover(const SDL_MouseMotionEvent & sEvent);
void handleSwipeMove(const SDL_MouseMotionEvent & sEvent);
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
bool handleSwipeStateChange(bool btnPressed);
public:
int tilesw, tilesh; //width and height of terrain to blit in tiles
int3 curHoveredTile;
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
CGPath * currentPath;
CTerrainRect();
virtual ~CTerrainRect();
void deactivate() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void clickMiddle(tribool down, bool previousState) override;
void hover(bool on) override;
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
void showAnim(SDL_Surface * to);
void showPath(const Rect &extRect, SDL_Surface * to);
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos
/// @returns number of visible tiles on screen respecting current map scaling
int3 tileCountOnScreen();
/// animates view by caching current surface and crossfading it with normal screen
void fadeFromCurrentView();
bool needsAnimUpdate();
};
/// Resources bar which shows information about how many gold, crystals,... you have
/// Current date is displayed too
class CResDataBar : public CIntObject
{
public:
std::shared_ptr<CPicture> background;
std::vector<std::pair<int,int> > txtpos;
std::string datetext;
void clickRight(tribool down, bool previousState) override;
CResDataBar();
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
~CResDataBar();
void draw(SDL_Surface * to);
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
};
/// That's a huge class which handles general adventure map actions and
/// shows the right menu(questlog, spellbook, end turn,..) from where you
/// can get to the towns and heroes.

View File

@ -0,0 +1,96 @@
/*
* CAdvMapPanel.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
*
*/
#include "StdInc.h"
#include "CAdvMapPanel.h"
#include "../widgets/Buttons.h"
#include "../widgets/Images.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
#include "../gui/CGuiHandler.h"
CAdvMapPanel::CAdvMapPanel(std::shared_ptr<IImage> bg, Point position)
: CIntObject()
, background(bg)
{
defActions = 255;
recActions = 255;
pos.x += position.x;
pos.y += position.y;
if (bg)
{
pos.w = bg->width();
pos.h = bg->height();
}
}
void CAdvMapPanel::addChildColorableButton(std::shared_ptr<CButton> button)
{
colorableButtons.push_back(button);
addChildToPanel(button, ACTIVATE | DEACTIVATE);
}
void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
{
for(auto & button : colorableButtons)
{
button->setPlayerColor(clr);
}
}
void CAdvMapPanel::showAll(SDL_Surface * to)
{
if(background)
background->draw(to, pos.x, pos.y);
CIntObject::showAll(to);
}
void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
{
otherObjects.push_back(obj);
obj->recActions |= actions | SHOWALL;
obj->recActions &= ~DISPOSE;
addChild(obj.get(), false);
}
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color)
: CAdvMapPanel(bg, position), icons(_icons)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
int fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
if(fillerHeight > 0)
{
backgroundFiller = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, pos.h, pos.w, fillerHeight));
}
}
CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default;
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
{
assert(iconsData.size() == currentIcons.size());
for(size_t idx = 0; idx < iconsData.size(); idx++)
{
const auto & data = iconsData.at(idx);
currentIcons[idx]->setFrame(data.first + indexOffset);
}
}
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
iconsData.push_back(data);
currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
}

View File

@ -0,0 +1,60 @@
/*
* CAdvMapPanel.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
VCMI_LIB_NAMESPACE_BEGIN
class PlayerColor;
VCMI_LIB_NAMESPACE_END
class CAnimation;
class CAnimImage;
class CFilledTexture;
class CButton;
class IImage;
/// simple panel that contains other displayable elements; used to separate groups of controls
class CAdvMapPanel : public CIntObject
{
std::vector<std::shared_ptr<CButton>> colorableButtons;
std::vector<std::shared_ptr<CIntObject>> otherObjects;
/// the surface passed to this obj will be freed in dtor
std::shared_ptr<IImage> background;
public:
CAdvMapPanel(std::shared_ptr<IImage> bg, Point position);
void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
void addChildColorableButton(std::shared_ptr<CButton> button);
/// recolors all buttons to given player color
void setPlayerColor(const PlayerColor & clr);
void showAll(SDL_Surface * to) override;
};
/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
class CAdvMapWorldViewPanel : public CAdvMapPanel
{
/// data that allows reconstruction of panel info icons
std::vector<std::pair<int, Point>> iconsData;
/// ptrs to child-pictures constructed from iconsData
std::vector<std::shared_ptr<CAnimImage>> currentIcons;
/// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
std::shared_ptr<CFilledTexture> backgroundFiller;
std::shared_ptr<CAnimation> icons;
public:
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
virtual ~CAdvMapWorldViewPanel();
void addChildIcon(std::pair<int, Point> data, int indexOffset);
/// recreates all pictures from given def to recolor them according to current player color
void recolorIcons(const PlayerColor & color, int indexOffset);
};

View File

@ -0,0 +1,61 @@
/*
* CAdventureOptions.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
*
*/
#include "StdInc.h"
#include "CAdventureOptions.h"
#include "CAdvMapInt.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../lobby/CCampaignInfoScreen.h"
#include "../lobby/CScenarioInfoScreen.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/Buttons.h"
#include "../../CCallback.h"
#include "../../lib/StartInfo.h"
CAdventureOptions::CAdventureOptions()
: CWindowObject(PLAYER_COLORED, "ADVOPTS")
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
exit->assignedKeys.insert(SDLK_ESCAPE);
scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
scenInfo->addCallback(CAdventureOptions::showScenarioInfo);
puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
if(const CGHeroInstance *h = adventureInt->curHero())
dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
else
dig->block(true);
}
void CAdventureOptions::showScenarioInfo()
{
if(LOCPLINT->cb->getStartInfo()->campState)
{
GH.pushIntT<CCampaignInfoScreen>();
}
else
{
GH.pushIntT<CScenarioInfoScreen>();
}
}

View File

@ -0,0 +1,30 @@
/*
* CAdventureOptions.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
*
*/
#pragma once
#include "../windows/CWindowObject.h"
class CButton;
/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
class CAdventureOptions : public CWindowObject
{
public:
std::shared_ptr<CButton> exit;
std::shared_ptr<CButton> viewWorld;
std::shared_ptr<CButton> puzzle;
std::shared_ptr<CButton> dig;
std::shared_ptr<CButton> scenInfo;
/*std::shared_ptr<CButton> replay*/
CAdventureOptions();
static void showScenarioInfo();
};

View File

@ -0,0 +1,261 @@
/*
* CInGameConsole.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
*
*/
#include "StdInc.h"
#include "CInGameConsole.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../ClientCommandManager.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/mapObjects/CArmedInstance.h"
#include <SDL_timer.h>
#include <SDL_events.h>
CInGameConsole::CInGameConsole()
: CIntObject(KEYBOARD | TEXTINPUT),
prevEntDisp(-1),
defaultTimeout(10000),
maxDisplayedTexts(10)
{
}
void CInGameConsole::show(SDL_Surface * to)
{
int number = 0;
std::vector<std::list< std::pair< std::string, uint32_t > >::iterator> toDel;
boost::unique_lock<boost::mutex> lock(texts_mx);
for(auto it = texts.begin(); it != texts.end(); ++it, ++number)
{
Point leftBottomCorner(0, pos.h);
graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN,
Point(leftBottomCorner.x + 50, leftBottomCorner.y - (int)texts.size() * 20 - 80 + number*20));
if((int)(SDL_GetTicks() - it->second) > defaultTimeout)
{
toDel.push_back(it);
}
}
for(auto & elem : toDel)
{
texts.erase(elem);
}
}
void CInGameConsole::print(const std::string &txt)
{
boost::unique_lock<boost::mutex> lock(texts_mx);
int lineLen = conf.go()->ac.outputLineLength;
if(txt.size() < lineLen)
{
texts.push_back(std::make_pair(txt, SDL_GetTicks()));
if(texts.size() > maxDisplayedTexts)
{
texts.pop_front();
}
}
else
{
assert(lineLen);
for(int g=0; g<txt.size() / lineLen + 1; ++g)
{
std::string part = txt.substr(g * lineLen, lineLen);
if(part.size() == 0)
break;
texts.push_back(std::make_pair(part, SDL_GetTicks()));
if(texts.size() > maxDisplayedTexts)
{
texts.pop_front();
}
}
}
}
void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
{
if(key.type != SDL_KEYDOWN) return;
if(!captureAllKeys && key.keysym.sym != SDLK_TAB) return; //because user is not entering any text
switch(key.keysym.sym)
{
case SDLK_TAB:
case SDLK_ESCAPE:
{
if(captureAllKeys)
{
endEnteringText(false);
}
else if(SDLK_TAB == key.keysym.sym)
{
startEnteringText();
}
break;
}
case SDLK_RETURN: //enter key
{
if(!enteredText.empty() && captureAllKeys)
{
bool anyTextExceptCaret = enteredText.size() > 1;
endEnteringText(anyTextExceptCaret);
if(anyTextExceptCaret)
{
CCS->soundh->playSound("CHAT");
}
}
break;
}
case SDLK_BACKSPACE:
{
if(enteredText.size() > 1)
{
Unicode::trimRight(enteredText,2);
enteredText += '_';
refreshEnteredText();
}
break;
}
case SDLK_UP: //up arrow
{
if(previouslyEntered.size() == 0)
break;
if(prevEntDisp == -1)
{
prevEntDisp = static_cast<int>(previouslyEntered.size() - 1);
enteredText = previouslyEntered[prevEntDisp] + "_";
refreshEnteredText();
}
else if( prevEntDisp > 0)
{
--prevEntDisp;
enteredText = previouslyEntered[prevEntDisp] + "_";
refreshEnteredText();
}
break;
}
case SDLK_DOWN: //down arrow
{
if(prevEntDisp != -1 && prevEntDisp+1 < previouslyEntered.size())
{
++prevEntDisp;
enteredText = previouslyEntered[prevEntDisp] + "_";
refreshEnteredText();
}
else if(prevEntDisp+1 == previouslyEntered.size()) //useful feature
{
prevEntDisp = -1;
enteredText = "_";
refreshEnteredText();
}
break;
}
default:
{
break;
}
}
}
void CInGameConsole::textInputed(const SDL_TextInputEvent & event)
{
if(!captureAllKeys || enteredText.size() == 0)
return;
enteredText.resize(enteredText.size()-1);
enteredText += event.text;
enteredText += "_";
refreshEnteredText();
}
void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
{
//do nothing here
}
void CInGameConsole::startEnteringText()
{
if (!active)
return;
if (captureAllKeys)
return;
assert(GH.statusbar);
assert(currentStatusBar.expired());//effectively, nullptr check
currentStatusBar = GH.statusbar;
captureAllKeys = true;
enteredText = "_";
GH.statusbar->setEnteringMode(true);
GH.statusbar->setEnteredText(enteredText);
}
void CInGameConsole::endEnteringText(bool processEnteredText)
{
captureAllKeys = false;
prevEntDisp = -1;
if(processEnteredText)
{
std::string txt = enteredText.substr(0, enteredText.size()-1);
previouslyEntered.push_back(txt);
if(txt.at(0) == '/')
{
//some commands like gosolo don't work when executed from GUI thread
auto threadFunction = [=]()
{
ClientCommandManager commandController;
commandController.processCommand(txt.substr(1), true);
};
boost::thread clientCommandThread(threadFunction);
clientCommandThread.detach();
}
else
LOCPLINT->cb->sendMessage(txt, LOCPLINT->getSelection());
}
enteredText.clear();
auto statusbar = currentStatusBar.lock();
assert(statusbar);
if (statusbar)
statusbar->setEnteringMode(false);
currentStatusBar.reset();
}
void CInGameConsole::refreshEnteredText()
{
auto statusbar = currentStatusBar.lock();
assert(statusbar);
if (statusbar)
statusbar->setEnteredText(enteredText);
}

View File

@ -0,0 +1,39 @@
/*
* CInGameConsole.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
class CInGameConsole : public CIntObject
{
private:
std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add>
boost::mutex texts_mx; // protects texts
std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work
int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1
int defaultTimeout; //timeout for new texts (in ms)
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
std::weak_ptr<IStatusBar> currentStatusBar;
public:
std::string enteredText;
void show(SDL_Surface * to) override;
void print(const std::string &txt);
void keyPressed (const SDL_KeyboardEvent & key) override; //call-in
void textInputed(const SDL_TextInputEvent & event) override;
void textEdited(const SDL_TextEditingEvent & event) override;
void startEnteringText();
void endEnteringText(bool processEnteredText);
void refreshEnteredText();
CInGameConsole();
};

View File

@ -0,0 +1,323 @@
/*
* CInfoBar.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
*
*/
#include "StdInc.h"
#include "CInfoBar.h"
#include "CAdvMapInt.h"
#include "../widgets/CComponent.h"
#include "../widgets/Images.h"
#include "../widgets/TextControls.h"
#include "../widgets/MiscWidgets.h"
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
CInfoBar::CVisibleInfo::CVisibleInfo()
: CIntObject(0, Point(8, 12))
{
}
void CInfoBar::CVisibleInfo::show(SDL_Surface * to)
{
CIntObject::show(to);
for(auto object : forceRefresh)
object->showAll(to);
}
CInfoBar::EmptyVisibleInfo::EmptyVisibleInfo()
{
}
CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATHR");
heroTooltip = std::make_shared<CHeroTooltip>(Point(0,0), hero);
}
CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATCS");
townTooltip = std::make_shared<CTownTooltip>(Point(0,0), town);
}
CInfoBar::VisibleDateInfo::VisibleDateInfo()
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
animation = std::make_shared<CShowableAnim>(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE, 180);// H3 uses around 175-180 ms per frame
std::string labelText;
if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info
labelText = CGI->generaltexth->allTexts[63] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK));
else
labelText = CGI->generaltexth->allTexts[64] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK));
label = std::make_shared<CLabel>(95, 31, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, labelText);
forceRefresh.push_back(label);
}
std::string CInfoBar::VisibleDateInfo::getNewDayName()
{
if(LOCPLINT->cb->getDate(Date::DAY) == 1)
return "NEWDAY";
if(LOCPLINT->cb->getDate(Date::DAY) != 1)
return "NEWDAY";
switch(LOCPLINT->cb->getDate(Date::WEEK))
{
case 1:
return "NEWWEEK1";
case 2:
return "NEWWEEK2";
case 3:
return "NEWWEEK3";
case 4:
return "NEWWEEK4";
default:
return "";
}
}
CInfoBar::VisibleEnemyTurnInfo::VisibleEnemyTurnInfo(PlayerColor player)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATNX");
banner = std::make_shared<CAnimImage>("CREST58", player.getNum(), 0, 20, 51);
sand = std::make_shared<CShowableAnim>(99, 51, "HOURSAND", 0, 100); // H3 uses around 100 ms per frame
glass = std::make_shared<CShowableAnim>(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 1000); // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
}
CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
//get amount of halls of each level
std::vector<int> halls(4, 0);
for(auto town : LOCPLINT->towns)
{
int hallLevel = town->hallLevel();
//negative value means no village hall, unlikely but possible
if(hallLevel >= 0)
halls.at(hallLevel)++;
}
std::vector<PlayerColor> allies, enemies;
//generate list of allies and enemies
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
{
if(LOCPLINT->cb->getPlayerStatus(PlayerColor(i), false) == EPlayerStatus::INGAME)
{
if(LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES)
allies.push_back(PlayerColor(i));
else
enemies.push_back(PlayerColor(i));
}
}
//generate widgets
background = std::make_shared<CPicture>("ADSTATIN");
allyLabel = std::make_shared<CLabel>(10, 106, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
enemyLabel = std::make_shared<CLabel>(10, 136, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4;
for(PlayerColor & player : allies)
{
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 102);
posx += image->pos.w;
flags.push_back(image);
}
posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4;
for(PlayerColor & player : enemies)
{
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 132);
posx += image->pos.w;
flags.push_back(image);
}
for(size_t i=0; i<halls.size(); i++)
{
hallIcons.push_back(std::make_shared<CAnimImage>("itmtl", i, 0, 6 + 42 * (int)i , 11));
if(halls[i])
hallLabels.push_back(std::make_shared<CLabel>( 26 + 42 * (int)i, 64, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, boost::lexical_cast<std::string>(halls[i])));
}
}
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDisplay, std::string message)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
comp = std::make_shared<CComponent>(compToDisplay);
comp->moveTo(Point(pos.x+47, pos.y+50));
text = std::make_shared<CTextBox>(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
}
void CInfoBar::playNewDaySound()
{
if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week
CCS->soundh->playSound(soundBase::newDay);
else if(LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month
CCS->soundh->playSound(soundBase::newWeek);
else if(LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month
CCS->soundh->playSound(soundBase::newMonth);
else
CCS->soundh->playSound(soundBase::newDay);
}
void CInfoBar::reset()
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
state = EMPTY;
visibleInfo = std::make_shared<EmptyVisibleInfo>();
}
void CInfoBar::showSelection()
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
if(adventureInt->selection)
{
if(auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
{
showHeroSelection(hero);
return;
}
else if(auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection))
{
showTownSelection(town);
return;
}
}
showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
}
void CInfoBar::tick()
{
removeUsedEvents(TIME);
if(GH.topInt() == adventureInt)
showSelection();
}
void CInfoBar::clickLeft(tribool down, bool previousState)
{
if(down)
{
if(state == HERO || state == TOWN)
showGameStatus();
else if(state == GAME)
showDate();
else
showSelection();
}
}
void CInfoBar::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->allTexts[109], down);
}
void CInfoBar::hover(bool on)
{
if(on)
GH.statusbar->write(CGI->generaltexth->zelp[292].first);
else
GH.statusbar->clear();
}
CInfoBar::CInfoBar(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
state(EMPTY)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
pos.w = position.w;
pos.h = position.h;
reset();
}
void CInfoBar::showDate()
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
playNewDaySound();
state = DATE;
visibleInfo = std::make_shared<VisibleDateInfo>();
setTimer(3000); // confirmed to match H3
redraw();
}
void CInfoBar::showComponent(const Component & comp, std::string message)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
state = COMPONENT;
visibleInfo = std::make_shared<VisibleComponentInfo>(comp, message);
setTimer(3000);
redraw();
}
void CInfoBar::startEnemyTurn(PlayerColor color)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
state = AITURN;
visibleInfo = std::make_shared<VisibleEnemyTurnInfo>(color);
redraw();
}
void CInfoBar::showHeroSelection(const CGHeroInstance * hero)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
if(!hero)
{
reset();
}
else
{
state = HERO;
visibleInfo = std::make_shared<VisibleHeroInfo>(hero);
}
redraw();
}
void CInfoBar::showTownSelection(const CGTownInstance * town)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
if(!town)
{
reset();
}
else
{
state = TOWN;
visibleInfo = std::make_shared<VisibleTownInfo>(town);
}
redraw();
}
void CInfoBar::showGameStatus()
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
state = GAME;
visibleInfo = std::make_shared<VisibleGameStatusInfo>();
setTimer(3000);
redraw();
}

View File

@ -0,0 +1,146 @@
/*
* CInfoBar.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
VCMI_LIB_NAMESPACE_BEGIN
class CGHeroInstance;
class CGTownInstance;
struct Component;
class PlayerColor;
VCMI_LIB_NAMESPACE_END
class CAnimImage;
class CShowableAnim;
class CComponent;
class CHeroTooltip;
class CTownTooltip;
class CLabel;
class CTextBox;
/// Info box which shows next week/day information, hold the current date
class CInfoBar : public CIntObject
{
//all visible information located in one object - for ease of replacing
class CVisibleInfo : public CIntObject
{
public:
void show(SDL_Surface * to) override;
protected:
std::shared_ptr<CPicture> background;
std::list<std::shared_ptr<CIntObject>> forceRefresh;
CVisibleInfo();
};
class EmptyVisibleInfo : public CVisibleInfo
{
public:
EmptyVisibleInfo();
};
class VisibleHeroInfo : public CVisibleInfo
{
std::shared_ptr<CHeroTooltip> heroTooltip;
public:
VisibleHeroInfo(const CGHeroInstance * hero);
};
class VisibleTownInfo : public CVisibleInfo
{
std::shared_ptr<CTownTooltip> townTooltip;
public:
VisibleTownInfo(const CGTownInstance * town);
};
class VisibleDateInfo : public CVisibleInfo
{
std::shared_ptr<CShowableAnim> animation;
std::shared_ptr<CLabel> label;
std::string getNewDayName();
public:
VisibleDateInfo();
};
class VisibleEnemyTurnInfo : public CVisibleInfo
{
std::shared_ptr<CAnimImage> banner;
std::shared_ptr<CShowableAnim> glass;
std::shared_ptr<CShowableAnim> sand;
public:
VisibleEnemyTurnInfo(PlayerColor player);
};
class VisibleGameStatusInfo : public CVisibleInfo
{
std::shared_ptr<CLabel> allyLabel;
std::shared_ptr<CLabel> enemyLabel;
std::vector<std::shared_ptr<CAnimImage>> flags;
std::vector<std::shared_ptr<CAnimImage>> hallIcons;
std::vector<std::shared_ptr<CLabel>> hallLabels;
public:
VisibleGameStatusInfo();
};
class VisibleComponentInfo : public CVisibleInfo
{
std::shared_ptr<CComponent> comp;
std::shared_ptr<CTextBox> text;
public:
VisibleComponentInfo(const Component & compToDisplay, std::string message);
};
enum EState
{
EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT
};
std::shared_ptr<CVisibleInfo> visibleInfo;
EState state;
//removes all information about current state, deactivates timer (if any)
void reset();
void tick() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover(bool on) override;
void playNewDaySound();
public:
CInfoBar(const Rect & pos);
/// show new day/week animation
void showDate();
/// show component for 3 seconds. Used to display picked up resources
void showComponent(const Component & comp, std::string message);
/// print enemy turn progress
void startEnemyTurn(PlayerColor color);
/// reset to default view - selected object
void showSelection();
/// show hero\town information
void showHeroSelection(const CGHeroInstance * hero);
void showTownSelection(const CGTownInstance * town);
/// for 3 seconds shows amount of town halls and players status
void showGameStatus();
};

View File

@ -0,0 +1,339 @@
/*
* CList.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
*
*/
#include "StdInc.h"
#include "CList.h"
#include "CAdvMapInt.h"
#include "../widgets/Images.h"
#include "../widgets/Buttons.h"
#include "../windows/InfoWindows.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CModHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
CList::CListItem::CListItem(CList * Parent)
: CIntObject(LCLICK | RCLICK | HOVER),
parent(Parent),
selection()
{
defActions = 255-DISPOSE;
}
CList::CListItem::~CListItem()
{
}
void CList::CListItem::clickRight(tribool down, bool previousState)
{
if (down == true)
showTooltip();
}
void CList::CListItem::clickLeft(tribool down, bool previousState)
{
if(down == true)
{
//second click on already selected item
if(parent->selected == this->shared_from_this())
{
open();
}
else
{
//first click - switch selection
parent->select(this->shared_from_this());
}
}
}
void CList::CListItem::hover(bool on)
{
if (on)
GH.statusbar->write(getHoverText());
else
GH.statusbar->clear();
}
void CList::CListItem::onSelect(bool on)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
selection.reset();
if(on)
selection = genSelection();
select(on);
GH.totalRedraw();
}
CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create)
: CIntObject(0, position),
size(Size),
selected(nullptr)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
scrollUp = std::make_shared<CButton>(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]);
scrollDown = std::make_shared<CButton>(Point(0, scrollUp->pos.h + 32*(int)size), btnDown, CGI->generaltexth->zelp[helpDown]);
listBox = std::make_shared<CListBox>(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
//assign callback only after list was created
scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
scrollUp->addCallback(std::bind(&CList::update, this));
scrollDown->addCallback(std::bind(&CList::update, this));
update();
}
void CList::update()
{
bool onTop = listBox->getPos() == 0;
bool onBottom = listBox->getPos() + size >= listBox->size();
scrollUp->block(onTop);
scrollDown->block(onBottom);
}
void CList::select(std::shared_ptr<CListItem> which)
{
if(selected == which)
return;
if(selected)
selected->onSelect(false);
selected = which;
if(which)
{
which->onSelect(true);
onSelect();
}
}
int CList::getSelectedIndex()
{
return static_cast<int>(listBox->getIndexOf(selected));
}
void CList::selectIndex(int which)
{
if(which < 0)
{
if(selected)
select(nullptr);
}
else
{
listBox->scrollTo(which);
update();
select(std::dynamic_pointer_cast<CListItem>(listBox->getItem(which)));
}
}
void CList::selectNext()
{
int index = getSelectedIndex() + 1;
if(index >= listBox->size())
index = 0;
selectIndex(index);
}
void CList::selectPrev()
{
int index = getSelectedIndex();
if(index <= 0)
selectIndex(0);
else
selectIndex(index-1);
}
CHeroList::CEmptyHeroItem::CEmptyHeroItem()
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1, 0);
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
pos.w = mana->pos.w + mana->pos.x - pos.x;
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
}
CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
: CListItem(parent),
hero(Hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
portrait = std::make_shared<CAnimImage>("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
pos.w = mana->pos.w + mana->pos.x - pos.x;
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
update();
}
void CHeroList::CHeroItem::update()
{
movement->setFrame(std::min<size_t>(movement->size()-1, hero->movement / 100));
mana->setFrame(std::min<size_t>(mana->size()-1, hero->mana / 5));
redraw();
}
std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
{
return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1, 0);
}
void CHeroList::CHeroItem::select(bool on)
{
if(on && adventureInt->selection != hero)
adventureInt->select(hero);
}
void CHeroList::CHeroItem::open()
{
LOCPLINT->openHeroWindow(hero);
}
void CHeroList::CHeroItem::showTooltip()
{
CRClickPopup::createAndPush(hero, GH.getCursorPosition());
}
std::string CHeroList::CHeroItem::getHoverText()
{
return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->getNameTranslated() % hero->type->heroClass->getNameTranslated());
}
std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
{
if (LOCPLINT->wanderingHeroes.size() > index)
return std::make_shared<CHeroItem>(this, LOCPLINT->wanderingHeroes[index]);
return std::make_shared<CEmptyHeroItem>();
}
CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->wanderingHeroes.size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
{
}
void CHeroList::select(const CGHeroInstance * hero)
{
selectIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
}
void CHeroList::update(const CGHeroInstance * hero)
{
//this hero is already present, update its status
for(auto & elem : listBox->getItems())
{
auto item = std::dynamic_pointer_cast<CHeroItem>(elem);
if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
{
item->update();
return;
}
}
//simplest solution for now: reset list and restore selection
listBox->resize(LOCPLINT->wanderingHeroes.size());
if (adventureInt->selection)
{
auto selectedHero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
if (selectedHero)
select(selectedHero);
}
CList::update();
}
std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
{
if (LOCPLINT->towns.size() > index)
return std::make_shared<CTownItem>(this, LOCPLINT->towns[index]);
return std::make_shared<CAnimImage>("ITPA", 0);
}
CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
CListItem(parent),
town(Town)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
picture = std::make_shared<CAnimImage>("ITPA", 0);
pos = picture->pos;
update();
}
std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
{
return std::make_shared<CAnimImage>("ITPA", 1);
}
void CTownList::CTownItem::update()
{
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN];
picture->setFrame(iconIndex + 2);
redraw();
}
void CTownList::CTownItem::select(bool on)
{
if (on && adventureInt->selection != town)
adventureInt->select(town);
}
void CTownList::CTownItem::open()
{
LOCPLINT->openTownWindow(town);
}
void CTownList::CTownItem::showTooltip()
{
CRClickPopup::createAndPush(town, GH.getCursorPosition());
}
std::string CTownList::CTownItem::getHoverText()
{
return town->getObjectName();
}
CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->towns.size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
{
}
void CTownList::select(const CGTownInstance * town)
{
selectIndex(vstd::find_pos(LOCPLINT->towns, town));
}
void CTownList::update(const CGTownInstance *)
{
//simplest solution for now: reset list and restore selection
listBox->resize(LOCPLINT->towns.size());
if (adventureInt->selection)
{
auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
if (town)
select(town);
}
CList::update();
}

176
client/adventureMap/CList.h Normal file
View File

@ -0,0 +1,176 @@
/*
* CList.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../widgets/ObjectLists.h"
#include "../../lib/FunctionList.h"
VCMI_LIB_NAMESPACE_BEGIN
class CGHeroInstance;
class CGTownInstance;
VCMI_LIB_NAMESPACE_END
class CButton;
/// Base UI Element for hero\town lists
class CList : public CIntObject
{
protected:
class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
{
CList * parent;
std::shared_ptr<CIntObject> selection;
public:
CListItem(CList * parent);
~CListItem();
void clickRight(tribool down, bool previousState) override;
void clickLeft(tribool down, bool previousState) override;
void hover(bool on) override;
void onSelect(bool on);
/// create object with selection rectangle
virtual std::shared_ptr<CIntObject> genSelection()=0;
/// reaction on item selection (e.g. enable selection border)
/// NOTE: item may be deleted in selected state
virtual void select(bool on)=0;
/// open item (town or hero screen)
virtual void open()=0;
/// show right-click tooltip
virtual void showTooltip()=0;
/// get hover text for status bar
virtual std::string getHoverText()=0;
};
std::shared_ptr<CListBox> listBox;
const size_t size;
/**
* @brief CList - protected constructor
* @param size - maximal amount of visible at once items
* @param position - cordinates
* @param btnUp - path to image to use as top button
* @param btnDown - path to image to use as bottom button
* @param listAmount - amount of items in the list
* @param helpUp - index in zelp.txt for button help tooltip
* @param helpDown - index in zelp.txt for button help tooltip
* @param create - function for creating items in listbox
* @param destroy - function for deleting items in listbox
*/
CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create);
//for selection\deselection
std::shared_ptr<CListItem> selected;
void select(std::shared_ptr<CListItem> which);
friend class CListItem;
std::shared_ptr<CButton> scrollUp;
std::shared_ptr<CButton> scrollDown;
/// should be called when list is invalidated
void update();
public:
/// functions that will be called when selection changes
CFunctionList<void()> onSelect;
/// return index of currently selected element
int getSelectedIndex();
/// set of methods to switch selection
void selectIndex(int which);
void selectNext();
void selectPrev();
};
/// List of heroes which is shown at the right of the adventure map screen
class CHeroList : public CList
{
/// Empty hero item used as placeholder for unused entries in list
class CEmptyHeroItem : public CIntObject
{
std::shared_ptr<CAnimImage> movement;
std::shared_ptr<CAnimImage> mana;
std::shared_ptr<CPicture> portrait;
public:
CEmptyHeroItem();
};
class CHeroItem : public CListItem
{
std::shared_ptr<CAnimImage> movement;
std::shared_ptr<CAnimImage> mana;
std::shared_ptr<CAnimImage> portrait;
public:
const CGHeroInstance * const hero;
CHeroItem(CHeroList * parent, const CGHeroInstance * hero);
std::shared_ptr<CIntObject> genSelection() override;
void update();
void select(bool on) override;
void open() override;
void showTooltip() override;
std::string getHoverText() override;
};
std::shared_ptr<CIntObject> createHeroItem(size_t index);
public:
/**
* @brief CHeroList
* @param size, position, btnUp, btnDown @see CList::CList
*/
CHeroList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific hero and scroll if needed
void select(const CGHeroInstance * hero = nullptr);
/// Update hero. Will add or remove it from the list if needed
void update(const CGHeroInstance * hero = nullptr);
};
/// List of towns which is shown at the right of the adventure map screen or in the town screen
class CTownList : public CList
{
class CTownItem : public CListItem
{
std::shared_ptr<CAnimImage> picture;
public:
const CGTownInstance * const town;
CTownItem(CTownList *parent, const CGTownInstance * town);
std::shared_ptr<CIntObject> genSelection() override;
void update();
void select(bool on) override;
void open() override;
void showTooltip() override;
std::string getHoverText() override;
};
std::shared_ptr<CIntObject> createTownItem(size_t index);
public:
/**
* @brief CTownList
* @param size, position, btnUp, btnDown @see CList::CList
*/
CTownList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific town and scroll if needed
void select(const CGTownInstance * town = nullptr);
/// Update town. Will add or remove it from the list if needed
void update(const CGTownInstance * town = nullptr);
};

View File

@ -0,0 +1,317 @@
/*
* CMinimap.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
*
*/
#include "StdInc.h"
#include "CMinimap.h"
#include "CAdvMapInt.h"
#include "../widgets/Images.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../renderSDL/SDL_PixelAccess.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/TerrainHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapping/CMapDefines.h"
#include <SDL_surface.h>
const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
{
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
// if tile is not visible it will be black on minimap
if(!tile)
return Colors::BLACK;
// if object at tile is owned - it will be colored as its owner
for (const CGObjectInstance *obj : tile->blockingObjects)
{
//heroes will be blitted later
switch (obj->ID)
{
case Obj::HERO:
case Obj::PRISON:
continue;
}
PlayerColor player = obj->getOwner();
if(player == PlayerColor::NEUTRAL)
return *graphics->neutralColor;
else
if (player < PlayerColor::PLAYER_LIMIT)
return graphics->playerColors[player.getNum()];
}
// else - use terrain color (blocked version or normal)
const auto & colorPair = parent->colors.find(tile->terType->getId())->second;
if (tile->blocked && (!tile->visitable))
return colorPair.second;
else
return colorPair.first;
}
void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
x = static_cast<int>(toX + stepX * tile.x);
y = static_cast<int>(toY + stepY * tile.y);
}
void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY)
{
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin, yBegin, xEnd, yEnd;
tileToPixels (tile, xBegin, yBegin, toX, toY);
tileToPixels (int3 (tile.x + 1, tile.y + 1, tile.z), xEnd, yEnd, toX, toY);
for (int y=yBegin; y<yEnd; y++)
{
uint8_t *ptr = (uint8_t*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
}
void CMinimapInstance::refreshTile(const int3 &tile)
{
blitTileWithColor(getTileColor(int3(tile.x, tile.y, level)), tile, minimap, 0, 0);
}
void CMinimapInstance::drawScaled(int level)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
//size of one map tile on our minimap
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
double currY = 0;
for (int y=0; y<mapSizes.y; y++, currY += stepY)
{
double currX = 0;
for (int x=0; x<mapSizes.x; x++, currX += stepX)
{
const SDL_Color &color = getTileColor(int3(x,y,level));
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin = static_cast<int>(currX);
int yBegin = static_cast<int>(currY);
int xEnd = static_cast<int>(currX + stepX);
int yEnd = static_cast<int>(currY + stepY);
for (int y=yBegin; y<yEnd; y++)
{
uint8_t *ptr = (uint8_t*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
}
}
}
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
parent(Parent),
minimap(CSDL_Ext::createSurfaceWithBpp<4>(parent->pos.w, parent->pos.h)),
level(Level)
{
pos.w = parent->pos.w;
pos.h = parent->pos.h;
drawScaled(level);
}
CMinimapInstance::~CMinimapInstance()
{
SDL_FreeSurface(minimap);
}
void CMinimapInstance::showAll(SDL_Surface * to)
{
blitAtLoc(minimap, 0, 0, to);
//draw heroes
std::vector <const CGHeroInstance *> heroes = LOCPLINT->cb->getHeroesInfo(false); //TODO: do we really need separate function for drawing heroes?
for(auto & hero : heroes)
{
int3 position = hero->visitablePos();
if(position.z == level)
{
const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()];
blitTileWithColor(color, position, to, pos.x, pos.y);
}
}
}
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
{
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > ret;
for(const auto & terrain : CGI->terrainTypeHandler->objects)
{
SDL_Color normal = CSDL_Ext::toSDL(terrain->minimapUnblocked);
SDL_Color blocked = CSDL_Ext::toSDL(terrain->minimapBlocked);
ret[terrain->getId()] = std::make_pair(normal, blocked);
}
return ret;
}
CMinimap::CMinimap(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
level(0),
colors(loadColors())
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
pos.w = position.w;
pos.h = position.h;
aiShield = std::make_shared<CPicture>("AIShield");
aiShield->disable();
}
int3 CMinimap::translateMousePosition()
{
// 0 = top-left corner, 1 = bottom-right corner
double dx = double(GH.getCursorPosition().x - pos.x) / pos.w;
double dy = double(GH.getCursorPosition().y - pos.y) / pos.h;
int3 mapSizes = LOCPLINT->cb->getMapSize();
int3 tile ((si32)(mapSizes.x * dx), (si32)(mapSizes.y * dy), level);
return tile;
}
void CMinimap::moveAdvMapSelection()
{
int3 newLocation = translateMousePosition();
adventureInt->centerOn(newLocation);
if (!(adventureInt->active & GENERAL))
GH.totalRedraw(); //redraw this as well as inactive adventure map
else
redraw();//redraw only this
}
void CMinimap::clickLeft(tribool down, bool previousState)
{
if(down)
moveAdvMapSelection();
}
void CMinimap::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[291].second, down);
}
void CMinimap::hover(bool on)
{
if(on)
GH.statusbar->write(CGI->generaltexth->zelp[291].first);
else
GH.statusbar->clear();
}
void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent)
{
if(mouseState(EIntObjMouseBtnType::LEFT))
moveAdvMapSelection();
}
void CMinimap::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
if(minimap)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
//draw radar
Rect oldClip;
Rect radar =
{
si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
ui16(tileCountOnScreen.x * pos.w / mapSizes.x),
ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
};
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
{
// adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
radar.x = std::min<int>(std::max(pos.x, radar.x), pos.x + pos.w - radar.w);
radar.y = std::min<int>(std::max(pos.y, radar.y), pos.y + pos.h - radar.h);
if(radar.x < pos.x && radar.y < pos.y)
return; // whole map is visible at once, no point in redrawing border
}
CSDL_Ext::getClipRect(to, oldClip);
CSDL_Ext::setClipRect(to, pos);
CSDL_Ext::drawDashedBorder(to, radar, Colors::PURPLE);
CSDL_Ext::setClipRect(to, oldClip);
}
}
void CMinimap::update()
{
if(aiShield->recActions & UPDATE) //AI turn is going on. There is no need to update minimap
return;
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
minimap = std::make_shared<CMinimapInstance>(this, level);
redraw();
}
void CMinimap::setLevel(int newLevel)
{
level = newLevel;
update();
}
void CMinimap::setAIRadar(bool on)
{
if(on)
{
aiShield->enable();
minimap.reset();
}
else
{
aiShield->disable();
update();
}
// this my happen during AI turn when this interface is inactive
// force redraw in order to properly update interface
GH.totalRedraw();
}
void CMinimap::hideTile(const int3 &pos)
{
if(minimap)
minimap->refreshTile(pos);
}
void CMinimap::showTile(const int3 &pos)
{
if(minimap)
minimap->refreshTile(pos);
}

View File

@ -0,0 +1,77 @@
/*
* CMinimap.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../../lib/GameConstants.h"
struct SDL_Color;
class CMinimap;
class CMinimapInstance : public CIntObject
{
CMinimap * parent;
SDL_Surface * minimap;
int level;
//get color of selected tile on minimap
const SDL_Color & getTileColor(const int3 & pos);
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
//draw minimap already scaled.
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
void drawScaled(int level);
public:
CMinimapInstance(CMinimap * parent, int level);
~CMinimapInstance();
void showAll(SDL_Surface * to) override;
void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
void refreshTile(const int3 & pos);
};
/// Minimap which is displayed at the right upper corner of adventure map
class CMinimap : public CIntObject
{
protected:
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
std::shared_ptr<CMinimapInstance> minimap;
int level;
//to initialize colors
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > loadColors();
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover (bool on) override;
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
void moveAdvMapSelection();
public:
// terrainID -> (normal color, blocked color)
const std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > colors;
CMinimap(const Rect & position);
//should be called to invalidate whole map - different player or level
int3 translateMousePosition();
void update();
void setLevel(int level);
void setAIRadar(bool on);
void showAll(SDL_Surface * to) override;
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
};

View File

@ -0,0 +1,105 @@
/*
* CResDataBar.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
*
*/
#include "StdInc.h"
#include "CResDataBar.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/Images.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"
#define ADVOPT (conf.go()->ac)
void CResDataBar::clickRight(tribool down, bool previousState)
{
}
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
{
pos.x += x;
pos.y += y;
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(defname, 0, 0);
background->colorize(LOCPLINT->playerID);
pos.w = background->pos.w;
pos.h = background->pos.h;
txtpos.resize(8);
for (int i = 0; i < 8 ; i++)
{
txtpos[i].first = pos.x + offx + resdist*i;
txtpos[i].second = pos.y + offy;
}
txtpos[7].first = txtpos[6].first + datedist;
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
addUsedEvents(RCLICK);
}
CResDataBar::CResDataBar()
{
pos.x += ADVOPT.resdatabarX;
pos.y += ADVOPT.resdatabarY;
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
background->colorize(LOCPLINT->playerID);
pos.w = background->pos.w;
pos.h = background->pos.h;
txtpos.resize(8);
for (int i = 0; i < 8 ; i++)
{
txtpos[i].first = pos.x + ADVOPT.resOffsetX + ADVOPT.resDist*i;
txtpos[i].second = pos.y + ADVOPT.resOffsetY;
}
txtpos[7].first = txtpos[6].first + ADVOPT.resDateDist;
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
}
CResDataBar::~CResDataBar() = default;
void CResDataBar::draw(SDL_Surface * to)
{
//TODO: all this should be labels, but they require proper text update on change
for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
{
std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, Point(txtpos[i].first,txtpos[i].second));
}
std::vector<std::string> temp;
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::MONTH)));
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK)));
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK)));
graphics->fonts[FONT_SMALL]->renderTextLeft(to, CSDL_Ext::processStr(datetext,temp), Colors::WHITE, Point(txtpos[7].first,txtpos[7].second));
}
void CResDataBar::show(SDL_Surface * to)
{
}
void CResDataBar::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
draw(to);
}

View File

@ -0,0 +1,33 @@
/*
* CResDataBar.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
/// Resources bar which shows information about how many gold, crystals,... you have
/// Current date is displayed too
class CResDataBar : public CIntObject
{
public:
std::shared_ptr<CPicture> background;
std::vector<std::pair<int,int> > txtpos;
std::string datetext;
void clickRight(tribool down, bool previousState) override;
CResDataBar();
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
~CResDataBar();
void draw(SDL_Surface * to);
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
};

View File

@ -0,0 +1,414 @@
/*
* CTerrainRect.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
*
*/
#include "StdInc.h"
#include "CTerrainRect.h"
#include "mapHandler.h"
#include "CAdvMapInt.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../render/CAnimation.h"
#include "../render/CFadeAnimation.h"
#include "../render/IImage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../widgets/TextControls.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/CPathfinder.h"
#include <SDL_events.h>
#define ADVOPT (conf.go()->ac)
CTerrainRect::CTerrainRect()
: fadeSurface(nullptr),
lastRedrawStatus(EMapAnimRedrawStatus::OK),
fadeAnim(std::make_shared<CFadeAnimation>()),
curHoveredTile(-1,-1,-1),
currentPath(nullptr)
{
tilesw=(ADVOPT.advmapW+31)/32;
tilesh=(ADVOPT.advmapH+31)/32;
pos.x=ADVOPT.advmapX;
pos.y=ADVOPT.advmapY;
pos.w=ADVOPT.advmapW;
pos.h=ADVOPT.advmapH;
moveX = moveY = 0;
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
}
CTerrainRect::~CTerrainRect()
{
if(fadeSurface)
SDL_FreeSurface(fadeSurface);
}
void CTerrainRect::deactivate()
{
CIntObject::deactivate();
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
}
void CTerrainRect::clickLeft(tribool down, bool previousState)
{
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if(indeterminate(down))
return;
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(adventureInt->swipeEnabled)
{
if(handleSwipeStateChange((bool)down == true))
{
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
}
}
else
{
#endif
if(down == false)
return;
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
}
#endif
int3 mp = whichTileIsIt();
if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
return;
adventureInt->tileLClicked(mp);
}
void CTerrainRect::clickRight(tribool down, bool previousState)
{
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(adventureInt->swipeEnabled && isSwiping)
return;
#endif
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
int3 mp = whichTileIsIt();
if(CGI->mh->map->isInTheMap(mp) && down)
adventureInt->tileRClicked(mp);
}
void CTerrainRect::clickMiddle(tribool down, bool previousState)
{
handleSwipeStateChange((bool)down == true);
}
void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
{
handleHover(sEvent);
if(!adventureInt->swipeEnabled)
return;
handleSwipeMove(sEvent);
}
void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
{
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(sEvent.state == 0 || GH.multifinger) // any "button" is enough on mobile
#else
if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
#endif
{
return;
}
if(!isSwiping)
{
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
if(abs(sEvent.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
abs(sEvent.y - swipeInitialRealPos.y) > SwipeTouchSlop)
{
isSwiping = true;
}
}
if(isSwiping)
{
adventureInt->swipeTargetPosition.x =
swipeInitialMapPos.x + static_cast<si32>(swipeInitialRealPos.x - sEvent.x) / 32;
adventureInt->swipeTargetPosition.y =
swipeInitialMapPos.y + static_cast<si32>(swipeInitialRealPos.y - sEvent.y) / 32;
adventureInt->swipeMovementRequested = true;
}
}
bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
{
if(btnPressed)
{
swipeInitialRealPos = int3(GH.getCursorPosition().x, GH.getCursorPosition().y, 0);
swipeInitialMapPos = int3(adventureInt->position);
return true;
}
else if(isSwiping) // only accept this touch if it wasn't a swipe
{
isSwiping = false;
return true;
}
return false;
}
void CTerrainRect::handleHover(const SDL_MouseMotionEvent &sEvent)
{
int3 tHovered = whichTileIsIt(sEvent.x, sEvent.y);
int3 pom = adventureInt->verifyPos(tHovered);
if(tHovered != pom) //tile outside the map
{
CCS->curh->set(Cursor::Map::POINTER);
return;
}
if (pom != curHoveredTile)
{
curHoveredTile = pom;
adventureInt->tileHovered(pom);
}
}
void CTerrainRect::hover(bool on)
{
if (!on)
{
adventureInt->statusbar->clear();
CCS->curh->set(Cursor::Map::POINTER);
}
//Hoverable::hover(on);
}
void CTerrainRect::showPath(const Rect & extRect, SDL_Surface * to)
{
const static int pns[9][9] = {
{16, 17, 18, 7, -1, 19, 6, 5, -1},
{ 8, 9, 18, 7, -1, 19, 6, -1, 20},
{ 8, 1, 10, 7, -1, 19, -1, 21, 20},
{24, 17, 18, 15, -1, -1, 6, 5, 4},
{-1, -1, -1, -1, -1, -1, -1, -1, -1},
{ 8, 1, 2, -1, -1, 11, 22, 21, 20},
{24, 17, -1, 23, -1, 3, 14, 5, 4},
{24, -1, 2, 23, -1, 3, 22, 13, 4},
{-1, 1, 2, 23, -1, 3, 22, 21, 12}
}; //table of magic values TODO meaning, change variable name
for (int i = 0; i < -1 + (int)currentPath->nodes.size(); ++i)
{
const int3 &curPos = currentPath->nodes[i].coord, &nextPos = currentPath->nodes[i+1].coord;
if(curPos.z != adventureInt->position.z)
continue;
int pn=-1;//number of picture
if (i==0) //last tile
{
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
if (x<0 || y<0 || x>pos.w || y>pos.h)
continue;
pn=0;
}
else
{
const int3 &prevPos = currentPath->nodes[i-1].coord;
std::vector<CGPathNode> & cv = currentPath->nodes;
/* Vector directions
* 0 1 2
* \ | /
* 3 - 4 - 5
* / | \
* 6 7 8
*For example:
* |
* |__\
* /
* is id1=7, id2=5 (pns[7][5])
*/
bool pathContinuous = curPos.areNeighbours(nextPos) && curPos.areNeighbours(prevPos);
if(pathContinuous && cv[i].action != CGPathNode::EMBARK && cv[i].action != CGPathNode::DISEMBARK)
{
int id1=(curPos.x-nextPos.x+1)+3*(curPos.y-nextPos.y+1); //Direction of entering vector
int id2=(cv[i-1].coord.x-curPos.x+1)+3*(cv[i-1].coord.y-curPos.y+1); //Direction of exiting vector
pn=pns[id1][id2];
}
else //path discontinuity or sea/land transition (eg. when moving through Subterranean Gate or Boat)
{
pn = 0;
}
}
if (currentPath->nodes[i].turns)
pn+=25;
if (pn>=0)
{
const auto arrow = graphics->heroMoveArrows->getImage(pn);
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
if (x< -32 || y< -32 || x>pos.w || y>pos.h)
continue;
int hvx = (x + arrow->width()) - (pos.x + pos.w),
hvy = (y + arrow->height()) - (pos.y + pos.h);
Rect prevClip;
CSDL_Ext::getClipRect(to, prevClip);
CSDL_Ext::setClipRect(to, extRect); //preventing blitting outside of that rect
if(ADVOPT.smoothMove) //version for smooth hero move, with pos shifts
{
if (hvx<0 && hvy<0)
{
arrow->draw(to, x + moveX, y + moveY);
}
else if(hvx<0)
{
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width(), 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
else if (hvy<0)
{
Rect srcRect = CSDL_Ext::genRect(arrow->height(), arrow->width() - hvx, 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
else
{
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
arrow->draw(to, x + moveX, y + moveY, &srcRect);
}
}
else //standard version
{
if (hvx<0 && hvy<0)
{
arrow->draw(to, x, y);
}
else if(hvx<0)
{
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width(), 0, 0);
arrow->draw(to, x, y, &srcRect);
}
else if (hvy<0)
{
Rect srcRect = CSDL_Ext::genRect(arrow->height(), arrow->width() - hvx, 0, 0);
arrow->draw(to, x, y, &srcRect);
}
else
{
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
arrow->draw(to, x, y, &srcRect);
}
}
CSDL_Ext::setClipRect(to, prevClip);
}
} //for (int i=0;i<currentPath->nodes.size()-1;i++)
}
void CTerrainRect::show(SDL_Surface * to)
{
if (adventureInt->mode == EAdvMapMode::NORMAL)
{
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
info.otherheroAnim = true;
info.anim = adventureInt->anim;
info.heroAnim = adventureInt->heroAnim;
if (ADVOPT.smoothMove)
info.movement = int3(moveX, moveY, 0);
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
if (fadeAnim->isFading())
{
Rect r(pos);
fadeAnim->update();
fadeAnim->draw(to, r.topLeft());
}
if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
{
showPath(pos, to);
}
}
}
void CTerrainRect::showAll(SDL_Surface * to)
{
// world view map is static and doesn't need redraw every frame
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
{
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
info.scaled = true;
info.scale = adventureInt->worldViewScale;
adventureInt->worldViewOptions.adjustDrawingInfo(info);
CGI->mh->drawTerrainRectNew(to, &info);
}
}
void CTerrainRect::showAnim(SDL_Surface * to)
{
if (fadeAnim->isFading())
show(to);
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
}
int3 CTerrainRect::whichTileIsIt(const int x, const int y)
{
int3 ret;
ret.x = adventureInt->position.x + ((x-CGI->mh->offsetX-pos.x)/32);
ret.y = adventureInt->position.y + ((y-CGI->mh->offsetY-pos.y)/32);
ret.z = adventureInt->position.z;
return ret;
}
int3 CTerrainRect::whichTileIsIt()
{
return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
}
int3 CTerrainRect::tileCountOnScreen()
{
switch (adventureInt->mode)
{
default:
logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
return int3();
case EAdvMapMode::NORMAL:
return int3(tilesw, tilesh, 1);
case EAdvMapMode::WORLD_VIEW:
return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
}
}
void CTerrainRect::fadeFromCurrentView()
{
if (!ADVOPT.screenFading)
return;
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if (!fadeSurface)
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
}
bool CTerrainRect::needsAnimUpdate()
{
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
}

View File

@ -0,0 +1,64 @@
/*
* CTerrainRect.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
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../../lib/int3.h"
VCMI_LIB_NAMESPACE_BEGIN
struct CGPath;
VCMI_LIB_NAMESPACE_END
enum class EMapAnimRedrawStatus;
class CFadeAnimation;
/// Holds information about which tiles of the terrain are shown/not shown at the screen
class CTerrainRect : public CIntObject
{
SDL_Surface * fadeSurface;
EMapAnimRedrawStatus lastRedrawStatus;
std::shared_ptr<CFadeAnimation> fadeAnim;
int3 swipeInitialMapPos;
int3 swipeInitialRealPos;
bool isSwiping;
static constexpr float SwipeTouchSlop = 16.0f;
void handleHover(const SDL_MouseMotionEvent & sEvent);
void handleSwipeMove(const SDL_MouseMotionEvent & sEvent);
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
bool handleSwipeStateChange(bool btnPressed);
public:
int tilesw, tilesh; //width and height of terrain to blit in tiles
int3 curHoveredTile;
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
CGPath * currentPath;
CTerrainRect();
virtual ~CTerrainRect();
void deactivate() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void clickMiddle(tribool down, bool previousState) override;
void hover(bool on) override;
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
void showAnim(SDL_Surface * to);
void showPath(const Rect &extRect, SDL_Surface * to);
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos
/// @returns number of visible tiles on screen respecting current map scaling
int3 tileCountOnScreen();
/// animates view by caching current surface and crossfading it with normal screen
void fadeFromCurrentView();
bool needsAnimUpdate();
};

View File

@ -11,30 +11,24 @@
#include "StdInc.h"
#include "mapHandler.h"
#include "CBitmapHandler.h"
#include "gui/CAnimation.h"
#include "gui/SDL_Extensions.h"
#include "CGameInfo.h"
#include "../lib/mapObjects/CGHeroInstance.h"
#include "../lib/mapObjects/CObjectClassesHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CHeroHandler.h"
#include "../lib/CTownHandler.h"
#include "../lib/CModHandler.h"
#include "Graphics.h"
#include "../lib/mapping/CMap.h"
#include "../lib/CConfigHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/GameConstants.h"
#include "../lib/CStopWatch.h"
#include "CMT.h"
#include "CMusicHandler.h"
#include "../lib/CRandomGenerator.h"
#include "../lib/RoadHandler.h"
#include "../lib/RiverHandler.h"
#include "../lib/TerrainHandler.h"
#include "../lib/filesystem/ResourceID.h"
#include "../lib/JsonDetail.h"
#include "../render/CAnimation.h"
#include "../render/CFadeAnimation.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../CGameInfo.h"
#include "../render/Graphics.h"
#include "../render/IImage.h"
#include "../CMusicHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CObjectClassesHandler.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CStopWatch.h"
#include "../../lib/CRandomGenerator.h"
#include "../../lib/RoadHandler.h"
#include "../../lib/RiverHandler.h"
#include "../../lib/TerrainHandler.h"
#define ADVOPT (conf.go()->ac)

View File

@ -10,9 +10,9 @@
#pragma once
#include "../lib/int3.h"
#include "../lib/spells/ViewSpellInt.h"
#include "../lib/Rect.h"
#include "../../lib/int3.h"
#include "../../lib/spells/ViewSpellInt.h"
#include "../../lib/Rect.h"
#ifdef IN
#undef IN

View File

@ -21,8 +21,8 @@
#include "../CMusicHandler.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../render/Canvas.h"
#include "../render/CAnimation.h"
#include "../../CCallback.h"
#include "../../lib/battle/BattleAction.h"

View File

@ -22,11 +22,11 @@
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../widgets/AdventureMapClasses.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../render/Canvas.h"
#include "../render/IImage.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../adventureMap/CInGameConsole.h"
#include "../../CCallback.h"
#include "../../lib/BattleFieldHandler.h"

View File

@ -24,13 +24,12 @@
#include "BattleRenderer.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../gui/Canvas.h"
#include "../gui/CursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../windows/CAdvmapInterface.h"
#include "../render/Canvas.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../../CCallback.h"
#include "../../lib/CStack.h"

View File

@ -19,21 +19,21 @@
#include "BattleWindow.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../CVideoHandler.h"
#include "../Graphics.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../gui/CursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/AdventureMapClasses.h"
#include "../render/Canvas.h"
#include "../render/IImage.h"
#include "../widgets/Buttons.h"
#include "../widgets/Images.h"
#include "../widgets/TextControls.h"
#include "../windows/CMessage.h"
#include "../windows/CCreatureWindow.h"
#include "../windows/CSpellWindow.h"
#include "../render/CAnimation.h"
#include "../adventureMap/CInGameConsole.h"
#include "../../CCallback.h"
#include "../../lib/CStack.h"

View File

@ -20,9 +20,8 @@
#include "../CMusicHandler.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../gui/CGuiHandler.h"
#include "../render/Canvas.h"
#include "../../CCallback.h"
#include "../../lib/battle/CObstacleInstance.h"

View File

@ -15,8 +15,7 @@
#include "BattleStacksController.h"
#include "CreatureAnimation.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../render/Canvas.h"
#include "../gui/CGuiHandler.h"
#include "../CGameInfo.h"

View File

@ -20,8 +20,8 @@
#include "../CMusicHandler.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CAnimation.h"
#include "../gui/Canvas.h"
#include "../render/Canvas.h"
#include "../render/IImage.h"
#include "../../CCallback.h"
#include "../../lib/NetPacks.h"

View File

@ -25,13 +25,12 @@
#include "../CPlayerInterface.h"
#include "../CMusicHandler.h"
#include "../CGameInfo.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../gui/Canvas.h"
#include "../gui/SDL_Extensions.h"
#include "../../lib/spells/ISpellMechanics.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../render/Canvas.h"
#include "../../CCallback.h"
#include "../../lib/spells/ISpellMechanics.h"
#include "../../lib/battle/BattleHex.h"
#include "../../lib/CGameState.h"
#include "../../lib/CStack.h"

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "../gui/ColorFilter.h"
#include "../render/ColorFilter.h"
VCMI_LIB_NAMESPACE_BEGIN

View File

@ -17,17 +17,17 @@
#include "BattleActionsController.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CPlayerInterface.h"
#include "../CMusicHandler.h"
#include "../gui/Canvas.h"
#include "../gui/CursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CAnimation.h"
#include "../windows/CSpellWindow.h"
#include "../widgets/AdventureMapClasses.h"
#include "../widgets/Buttons.h"
#include "../widgets/Images.h"
#include "../windows/CMessage.h"
#include "../render/CAnimation.h"
#include "../render/Canvas.h"
#include "../adventureMap/CInGameConsole.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"

View File

@ -13,9 +13,9 @@
#include "../../lib/CConfigHandler.h"
#include "../../lib/CCreatureHandler.h"
#include "../gui/Canvas.h"
#include "../gui/ColorFilter.h"
#include "../gui/SDL_Extensions.h"
#include "../render/Canvas.h"
#include "../render/ColorFilter.h"
#include "../renderSDL/SDL_Extensions.h"
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };

View File

@ -11,7 +11,8 @@
#include "../../lib/FunctionList.h"
#include "../widgets/Images.h"
#include "../gui/CAnimation.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
#include <SDL_pixels.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
/*
* CAnimation.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
*
*/
#pragma once
#include "../../lib/GameConstants.h"
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
class Rect;
class Point;
VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
struct SDL_Color;
class CDefFile;
class ColorFilter;
/*
* Base class for images, can be used for non-animation pictures as well
*/
class IImage
{
public:
using SpecialPalette = std::array<SDL_Color, 7>;
//draws image on surface "where" at position
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0;
virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
//Change palette to specific player
virtual void playerColored(PlayerColor player)=0;
//set special color for flag
virtual void setFlagColor(PlayerColor player)=0;
//test transparency of specific pixel
virtual bool isTransparent(const Point & coords) const = 0;
virtual Point dimensions() const = 0;
int width() const;
int height() const;
//only indexed bitmaps, 16 colors maximum
virtual void shiftPalette(int from, int howMany) = 0;
virtual void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) = 0;
virtual void resetPalette(int colorID) = 0;
virtual void resetPalette() = 0;
virtual void setAlpha(uint8_t value) = 0;
//only indexed bitmaps with 7 special colors
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
virtual void horizontalFlip() = 0;
virtual void verticalFlip() = 0;
IImage();
virtual ~IImage();
/// loads image from specified file. Returns 0-sized images on failure
static std::shared_ptr<IImage> createFromFile( const std::string & path );
/// temporary compatibility method. Creates IImage from existing SDL_Surface
/// Surface will be shared, called must still free it with SDL_FreeSurface
static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
};
/// Class for handling animation
class CAnimation
{
private:
//source[group][position] - file with this frame, if string is empty - image located in def file
std::map<size_t, std::vector <JsonNode> > source;
//bitmap[group][position], store objects with loaded bitmaps
std::map<size_t, std::map<size_t, std::shared_ptr<IImage> > > images;
//animation file name
std::string name;
bool preloaded;
std::shared_ptr<CDefFile> defFile;
//loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded
bool loadFrame(size_t frame, size_t group);
//unloadFrame, returns true if image has been unloaded ( either deleted or decreased refCount)
bool unloadFrame(size_t frame, size_t group);
//initialize animation from file
void initFromJson(const JsonNode & input);
void init();
//to get rid of copy-pasting error message :]
void printError(size_t frame, size_t group, std::string type) const;
//not a very nice method to get image from another def file
//TODO: remove after implementing resource manager
std::shared_ptr<IImage> getFromExtraDef(std::string filename);
public:
CAnimation(std::string Name);
CAnimation();
~CAnimation();
//duplicates frame at [sourceGroup, sourceFrame] as last frame in targetGroup
//and loads it if animation is preloaded
void duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup);
//add custom surface to the selected position.
void setCustom(std::string filename, size_t frame, size_t group=0);
std::shared_ptr<IImage> getImage(size_t frame, size_t group=0, bool verbose=true) const;
void exportBitmaps(const boost::filesystem::path & path) const;
//all available frames
void load ();
void unload();
void preload();
//all frames from group
void loadGroup (size_t group);
void unloadGroup(size_t group);
//single image
void load (size_t frame, size_t group=0);
void unload(size_t frame, size_t group=0);
//total count of frames in group (including not loaded)
size_t size(size_t group=0) const;
void horizontalFlip();
void verticalFlip();
void playerColored(PlayerColor player);
void createFlippedGroup(const size_t sourceGroup, const size_t targetGroup);
};
const float DEFAULT_DELTA = 0.05f;
class CFadeAnimation
{
public:
enum class EMode
{
NONE, IN, OUT
};
private:
float delta;
SDL_Surface * fadingSurface;
bool fading;
float fadingCounter;
bool shouldFreeSurface;
float initialCounter() const;
bool isFinished() const;
public:
EMode fadingMode;
CFadeAnimation();
~CFadeAnimation();
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
void update();
void draw(SDL_Surface * targetSurface, const Point & targetPoint);
bool isFading() const { return fading; }
};

View File

@ -13,15 +13,16 @@
#include "CIntObject.h"
#include "CursorHandler.h"
#include "SDL_Extensions.h"
#include "../CGameInfo.h"
#include "../../lib/CThreadHelper.h"
#include "../../lib/CConfigHandler.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../CMT.h"
#include "../CPlayerInterface.h"
#include "../battle/BattleInterface.h"
#include "../../lib/CThreadHelper.h"
#include "../../lib/CConfigHandler.h"
#include <SDL_render.h>
#include <SDL_timer.h>
#include <SDL_events.h>

View File

@ -11,8 +11,8 @@
#include "CIntObject.h"
#include "CGuiHandler.h"
#include "SDL_Extensions.h"
#include "../CMessage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../windows/CMessage.h"
#include <SDL_pixels.h>
#include <SDL_surface.h>

View File

@ -10,7 +10,7 @@
#pragma once
#include "../../lib/Rect.h"
#include "../Graphics.h"
#include "../render/Graphics.h"
struct SDL_Surface;
class CGuiHandler;

View File

@ -11,9 +11,14 @@
#include "StdInc.h"
#include "CursorHandler.h"
#include "SDL_Extensions.h"
#include "CGuiHandler.h"
#include "CAnimation.h"
#include "../renderSDL/CursorSoftware.h"
#include "../renderSDL/CursorHardware.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../CMT.h"
#include "../../lib/CConfigHandler.h"
#include <SDL_render.h>
@ -311,148 +316,3 @@ void CursorHandler::show()
cursor->setVisible(true);
}
void CursorSoftware::render()
{
//texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads
if (needUpdate)
updateTexture();
Point renderPos = pos - pivot;
SDL_Rect destRect;
destRect.x = renderPos.x;
destRect.y = renderPos.y;
destRect.w = 40;
destRect.h = 40;
SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect);
}
void CursorSoftware::createTexture(const Point & dimensions)
{
if(cursorTexture)
SDL_DestroyTexture(cursorTexture);
if (cursorSurface)
SDL_FreeSurface(cursorSurface);
cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y);
cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y);
SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE);
SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND);
}
void CursorSoftware::updateTexture()
{
Point dimensions(-1, -1);
if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions())
createTexture(cursorImage->dimensions());
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
cursorImage->draw(cursorSurface);
SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch);
needUpdate = false;
}
void CursorSoftware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
{
assert(image != nullptr);
cursorImage = image;
pivot = pivotOffset;
needUpdate = true;
}
void CursorSoftware::setCursorPosition( const Point & newPos )
{
pos = newPos;
}
void CursorSoftware::setVisible(bool on)
{
visible = on;
}
CursorSoftware::CursorSoftware():
cursorTexture(nullptr),
cursorSurface(nullptr),
needUpdate(false),
visible(false),
pivot(0,0)
{
SDL_ShowCursor(SDL_DISABLE);
}
CursorSoftware::~CursorSoftware()
{
if(cursorTexture)
SDL_DestroyTexture(cursorTexture);
if (cursorSurface)
SDL_FreeSurface(cursorSurface);
}
CursorHardware::CursorHardware():
cursor(nullptr)
{
SDL_ShowCursor(SDL_DISABLE);
}
CursorHardware::~CursorHardware()
{
if(cursor)
SDL_FreeCursor(cursor);
}
void CursorHardware::setVisible(bool on)
{
#ifdef VCMI_APPLE
dispatch_async(dispatch_get_main_queue(), ^{
#endif
if (on)
SDL_ShowCursor(SDL_ENABLE);
else
SDL_ShowCursor(SDL_DISABLE);
#ifdef VCMI_APPLE
});
#endif
}
void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
{
auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y);
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
image->draw(cursorSurface);
auto oldCursor = cursor;
cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y);
if (!cursor)
logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError());
SDL_FreeSurface(cursorSurface);
#ifdef VCMI_APPLE
dispatch_async(dispatch_get_main_queue(), ^{
#endif
SDL_SetCursor(cursor);
if (oldCursor)
SDL_FreeCursor(oldCursor);
#ifdef VCMI_APPLE
});
#endif
}
void CursorHardware::setCursorPosition( const Point & newPos )
{
//no-op
}
void CursorHardware::render()
{
//no-op
}

View File

@ -9,14 +9,12 @@
*/
#pragma once
class CAnimation;
class IImage;
struct SDL_Surface;
struct SDL_Texture;
struct SDL_Cursor;
#include "../../lib/Point.h"
class ICursor;
class IImage;
class CAnimation;
namespace Cursor
{
enum class Type {
@ -112,57 +110,6 @@ namespace Cursor
};
}
class ICursor
{
public:
virtual ~ICursor() = default;
virtual void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) = 0;
virtual void setCursorPosition( const Point & newPos ) = 0;
virtual void render() = 0;
virtual void setVisible( bool on) = 0;
};
class CursorHardware : public ICursor
{
std::shared_ptr<IImage> cursorImage;
SDL_Cursor * cursor;
public:
CursorHardware();
~CursorHardware();
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
void setCursorPosition( const Point & newPos ) override;
void render() override;
void setVisible( bool on) override;
};
class CursorSoftware : public ICursor
{
std::shared_ptr<IImage> cursorImage;
SDL_Texture * cursorTexture;
SDL_Surface * cursorSurface;
Point pos;
Point pivot;
bool needUpdate;
bool visible;
void createTexture(const Point & dimensions);
void updateTexture();
public:
CursorSoftware();
~CursorSoftware();
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
void setCursorPosition( const Point & newPos ) override;
void render() override;
void setVisible( bool on) override;
};
/// handles mouse cursor
class CursorHandler final
{

View File

@ -1,392 +0,0 @@
/*
* Fonts.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
*
*/
#include "StdInc.h"
#include "Fonts.h"
#include <SDL_ttf.h>
#include "SDL_Extensions.h"
#include "../../lib/JsonNode.h"
#include "../../lib/vcmi_endian.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/CGeneralTextHandler.h"
size_t IFont::getStringWidth(const std::string & data) const
{
size_t width = 0;
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
width += getGlyphWidth(data.data() + i);
}
return width;
}
void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
renderText(surface, data, color, pos);
}
void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
Point size((int)getStringWidth(data), (int)getLineHeight());
renderText(surface, data, color, pos - size);
}
void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
Point size((int)getStringWidth(data), (int)getLineHeight());
renderText(surface, data, color, pos - size / 2);
}
void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
for(const std::string & line : data)
{
renderTextLeft(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}
void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
currPos.y -= (int)data.size() * (int)getLineHeight();
for(const std::string & line : data)
{
renderTextRight(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}
void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
currPos.y -= (int)data.size() * (int)getLineHeight() / 2;
for(const std::string & line : data)
{
renderTextCenter(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}
std::array<CBitmapFont::BitmapChar, CBitmapFont::totalChars> CBitmapFont::loadChars() const
{
std::array<BitmapChar, totalChars> ret;
size_t offset = 32;
for (auto & elem : ret)
{
elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4;
elem.width = read_le_u32(data.first.get() + offset); offset+=4;
elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4;
}
for (auto & elem : ret)
{
int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4;
elem.pixels = data.first.get() + 4128 + pixelOffset;
assert(pixelOffset + 4128 < data.second);
}
return ret;
}
CBitmapFont::CBitmapFont(const std::string & filename):
data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()),
chars(loadChars()),
height(data.first.get()[5])
{}
size_t CBitmapFont::getLineHeight() const
{
return height;
}
size_t CBitmapFont::getGlyphWidth(const char * data) const
{
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
if (localChar.size() == 1)
{
const BitmapChar & ch = chars[ui8(localChar[0])];
return ch.leftOffset + ch.width + ch.rightOffset;
}
return 0;
}
void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
{
Rect clipRect;
CSDL_Ext::getClipRect(surface, clipRect);
posX += character.leftOffset;
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
uint8_t bpp = surface->format->BytesPerPixel;
// start of line, may differ from 0 due to end of surface or clipped surface
int lineBegin = std::max<int>(0, clipRect.y - posY);
int lineEnd = std::min<int>(height, clipRect.y + clipRect.h - posY - 1);
// start end end of each row, may differ from 0
int rowBegin = std::max<int>(0, clipRect.x - posX);
int rowEnd = std::min<int>(character.width, clipRect.x + clipRect.w - posX - 1);
//for each line in symbol
for(int dy = lineBegin; dy <lineEnd; dy++)
{
uint8_t *dstLine = (uint8_t*)surface->pixels;
uint8_t *srcLine = character.pixels;
// shift source\destination pixels to current position
dstLine += (posY+dy) * surface->pitch + posX * bpp;
srcLine += dy * character.width;
//for each column in line
for(int dx = rowBegin; dx < rowEnd; dx++)
{
uint8_t* dstPixel = dstLine + dx*bpp;
switch(srcLine[dx])
{
case 1: //black "shadow"
colorPutter(dstPixel, 0, 0, 0);
break;
case 255: //text colour
colorPutter(dstPixel, color.r, color.g, color.b);
break;
default :
break; //transparency
}
}
}
posX += character.width;
posX += character.rightOffset;
}
void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
if (data.empty())
return;
assert(surface);
int posX = pos.x;
int posY = pos.y;
// Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles)
//assert(data[0] != '{');
//assert(data[data.size()-1] != '}');
SDL_LockSurface(surface);
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
if (localChar.size() == 1)
renderCharacter(surface, chars[ui8(localChar[0])], color, posX, posY);
}
SDL_UnlockSurface(surface);
}
std::pair<std::unique_ptr<ui8[]>, ui64> CTrueTypeFont::loadData(const JsonNode & config)
{
std::string filename = "Data/" + config["file"].String();
return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll();
}
TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config)
{
int pointSize = static_cast<int>(config["size"].Float());
if(!TTF_WasInit() && TTF_Init()==-1)
throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n");
return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize);
}
int CTrueTypeFont::getFontStyle(const JsonNode &config)
{
const JsonVector & names = config["style"].Vector();
int ret = 0;
for(const JsonNode & node : names)
{
if (node.String() == "bold")
ret |= TTF_STYLE_BOLD;
else if (node.String() == "italic")
ret |= TTF_STYLE_ITALIC;
}
return ret;
}
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
data(loadData(fontConfig)),
font(loadFont(fontConfig), TTF_CloseFont),
blended(fontConfig["blend"].Bool())
{
assert(font);
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
}
size_t CTrueTypeFont::getLineHeight() const
{
return TTF_FontHeight(font.get());
}
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
{
return getStringWidth(std::string(data, Unicode::getCharacterSize(*data)));
/*
int advance;
TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
return advance;
*/
}
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
{
int width;
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
return width;
}
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
renderText(surface, data, Colors::BLACK, pos + Point(1,1));
if (!data.empty())
{
SDL_Surface * rendered;
if (blended)
rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color);
else
rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color);
assert(rendered);
CSDL_Ext::blitSurface(rendered, surface, pos);
SDL_FreeSurface(rendered);
}
}
size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const
{
size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up
size_t charSize = rowSize * size; // glyph contains "size" rows
return index * charSize;
}
size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const
{
if (second > 0x7f )
second--;
return (first - 0x81) * (12*16 - 2) + (second - 0x40);
}
void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const
{
//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
Rect clipRect;
CSDL_Ext::getClipRect(surface, clipRect);
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
uint8_t bpp = surface->format->BytesPerPixel;
// start of line, may differ from 0 due to end of surface or clipped surface
int lineBegin = std::max<int>(0, clipRect.y - posY);
int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY);
// start end end of each row, may differ from 0
int rowBegin = std::max<int>(0, clipRect.x - posX);
int rowEnd = std::min<int>((int)size, clipRect.x + clipRect.w - posX);
//for each line in symbol
for(int dy = lineBegin; dy <lineEnd; dy++)
{
uint8_t *dstLine = (uint8_t*)surface->pixels;
uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex);
// shift source\destination pixels to current position
dstLine += (posY+dy) * surface->pitch + posX * bpp;
source += ((size + 7) / 8) * dy;
//for each column in line
for(int dx = rowBegin; dx < rowEnd; dx++)
{
// select current bit in bitmap
int bit = (source[dx / 8] << (dx % 8)) & 0x80;
uint8_t* dstPixel = dstLine + dx*bpp;
if (bit != 0)
colorPutter(dstPixel, color.r, color.g, color.b);
}
}
posX += (int)size + 1;
}
void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
int posX = pos.x;
int posY = pos.y;
SDL_LockSurface(surface);
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
if (localChar.size() == 1)
fallback->renderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY);
if (localChar.size() == 2)
renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY);
}
SDL_UnlockSurface(surface);
}
CBitmapHanFont::CBitmapHanFont(const JsonNode &config):
fallback(new CBitmapFont(config["fallback"].String())),
data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()),
size((size_t)config["size"].Float())
{
// basic tests to make sure that fonts are OK
// 1) fonts must contain 190 "sections", 126 symbols each.
assert(getCharacterIndex(0xfe, 0xff) == 190*126);
// 2) ensure that font size is correct - enough to fit all possible symbols
assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second);
}
size_t CBitmapHanFont::getLineHeight() const
{
return std::max(size + 1, fallback->getLineHeight());
}
size_t CBitmapHanFont::getGlyphWidth(const char * data) const
{
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
if (localChar.size() == 1)
return fallback->getGlyphWidth(data);
if (localChar.size() == 2)
return size + 1;
return 0;
}

View File

@ -1,136 +0,0 @@
/*
* Fonts.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
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
class Point;
VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
struct SDL_Color;
typedef struct _TTF_Font TTF_Font;
class CBitmapFont;
class CBitmapHanFont;
class IFont
{
protected:
/// Internal function to render font, see renderTextLeft
virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0;
public:
virtual ~IFont()
{}
/// Returns height of font
virtual size_t getLineHeight() const = 0;
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
virtual size_t getGlyphWidth(const char * data) const = 0;
/// Return width of the string
virtual size_t getStringWidth(const std::string & data) const;
/**
* @param surface - destination to print text on
* @param data - string to print
* @param color - font color
* @param pos - position of rendered font
*/
/// pos = topleft corner of the text
void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = center of the text
void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = bottomright corner of the text
void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = topleft corner of the text
void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
/// pos = center of the text
void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
/// pos = bottomright corner of the text
void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
};
class CBitmapFont : public IFont
{
static const size_t totalChars = 256;
struct BitmapChar
{
si32 leftOffset;
ui32 width;
si32 rightOffset;
ui8 *pixels; // pixels of this character, part of BitmapFont::data
};
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
const std::array<BitmapChar, totalChars> chars;
const ui8 height;
std::array<BitmapChar, totalChars> loadChars() const;
void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const;
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CBitmapFont(const std::string & filename);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
friend class CBitmapHanFont;
};
/// supports multi-byte characters for such languages like Chinese
class CBitmapHanFont : public IFont
{
std::unique_ptr<CBitmapFont> fallback;
// data, directly copied from file
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
// size of the font. Not available in file but needed for proper rendering
const size_t size;
size_t getCharacterDataOffset(size_t index) const;
size_t getCharacterIndex(ui8 first, ui8 second) const;
void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const;
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CBitmapHanFont(const JsonNode & config);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
};
class CTrueTypeFont : public IFont
{
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
const bool blended;
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
TTF_Font * loadFont(const JsonNode & config);
int getFontStyle(const JsonNode & config);
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CTrueTypeFont(const JsonNode & fontConfig);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
size_t getStringWidth(const std::string & data) const override;
};

View File

@ -14,7 +14,6 @@
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"

View File

@ -17,13 +17,10 @@
#include "CSelectionBase.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CVideoHandler.h"
#include "../CPlayerInterface.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../mainmenu/CMainMenu.h"
#include "../mainmenu/CPrologEpilogVideo.h"
#include "../widgets/CComponent.h"
@ -33,6 +30,9 @@
#include "../widgets/TextControls.h"
#include "../windows/GUIClasses.h"
#include "../windows/InfoWindows.h"
#include "../render/IImage.h"
#include "../render/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/CGeneralTextHandler.h"

View File

@ -15,10 +15,8 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/StartInfo.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CPlayerInterface.h"
CCampaignInfoScreen::CCampaignInfoScreen()

View File

@ -20,12 +20,10 @@
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CVideoHandler.h"
#include "../CPlayerInterface.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../mainmenu/CMainMenu.h"
#include "../widgets/CComponent.h"
@ -35,6 +33,7 @@
#include "../widgets/TextControls.h"
#include "../windows/GUIClasses.h"
#include "../windows/InfoWindows.h"
#include "../render/CAnimation.h"
#include "../../lib/NetPacksLobby.h"
#include "../../lib/CGeneralTextHandler.h"

View File

@ -14,7 +14,6 @@
#include "../CGameInfo.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"

View File

@ -14,7 +14,6 @@
#include "../CGameInfo.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"

View File

@ -14,10 +14,8 @@
#include "CLobbyScreen.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CPlayerInterface.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"
@ -26,6 +24,7 @@
#include "../widgets/TextControls.h"
#include "../windows/GUIClasses.h"
#include "../windows/InfoWindows.h"
#include "../render/CAnimation.h"
#include "../../CCallback.h"

View File

@ -14,12 +14,10 @@
#include "CMainMenu.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMusicHandler.h"
#include "../CVideoHandler.h"
#include "../CPlayerInterface.h"
#include "../CServerHandler.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"

View File

@ -20,7 +20,6 @@
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/filesystem/CCompressedStream.h"
#include "../gui/SDL_Extensions.h"
#include "../gui/CursorHandler.h"
#include "../CGameInfo.h"
@ -28,7 +27,6 @@
#include "../../lib/JsonNode.h"
#include "../CMusicHandler.h"
#include "../CVideoHandler.h"
#include "../Graphics.h"
#include "../../lib/serializer/Connection.h"
#include "../../lib/serializer/CTypeList.h"
#include "../../lib/VCMIDirs.h"
@ -36,10 +34,8 @@
#include "../windows/GUIClasses.h"
#include "../CPlayerInterface.h"
#include "../../CCallback.h"
#include "../CMessage.h"
#include "../Client.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CAnimation.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"
#include "../widgets/MiscWidgets.h"

View File

@ -0,0 +1,377 @@
/*
* CAnimation.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
*
*/
#include "StdInc.h"
#include "CAnimation.h"
#include "CDefFile.h"
#include "Graphics.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/JsonNode.h"
#include "../renderSDL/SDLImage.h"
std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
{
size_t pos = filename.find(':');
if (pos == -1)
return nullptr;
CAnimation anim(filename.substr(0, pos));
pos++;
size_t frame = atoi(filename.c_str()+pos);
size_t group = 0;
pos = filename.find(':', pos);
if (pos != -1)
{
pos++;
group = frame;
frame = atoi(filename.c_str()+pos);
}
anim.load(frame ,group);
auto ret = anim.images[group][frame];
anim.images.clear();
return ret;
}
bool CAnimation::loadFrame(size_t frame, size_t group)
{
if(size(group) <= frame)
{
printError(frame, group, "LoadFrame");
return false;
}
auto image = getImage(frame, group, false);
if(image)
{
return true;
}
//try to get image from def
if(source[group][frame].getType() == JsonNode::JsonType::DATA_NULL)
{
if(defFile)
{
auto frameList = defFile->getEntries();
if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present
{
images[group][frame] = std::make_shared<SDLImage>(defFile.get(), frame, group);
return true;
}
}
// still here? image is missing
printError(frame, group, "LoadFrame");
images[group][frame] = std::make_shared<SDLImage>("DEFAULT");
}
else //load from separate file
{
auto img = getFromExtraDef(source[group][frame]["file"].String());
if(!img)
img = std::make_shared<SDLImage>(source[group][frame]);
images[group][frame] = img;
return true;
}
return false;
}
bool CAnimation::unloadFrame(size_t frame, size_t group)
{
auto image = getImage(frame, group, false);
if(image)
{
images[group].erase(frame);
if(images[group].empty())
images.erase(group);
return true;
}
return false;
}
void CAnimation::initFromJson(const JsonNode & config)
{
std::string basepath;
basepath = config["basepath"].String();
JsonNode base(JsonNode::JsonType::DATA_STRUCT);
base["margins"] = config["margins"];
base["width"] = config["width"];
base["height"] = config["height"];
for(const JsonNode & group : config["sequences"].Vector())
{
size_t groupID = group["group"].Integer();//TODO: string-to-value conversion("moving" -> MOVING)
source[groupID].clear();
for(const JsonNode & frame : group["frames"].Vector())
{
JsonNode toAdd(JsonNode::JsonType::DATA_STRUCT);
JsonUtils::inherit(toAdd, base);
toAdd["file"].String() = basepath + frame.String();
source[groupID].push_back(toAdd);
}
}
for(const JsonNode & node : config["images"].Vector())
{
size_t group = node["group"].Integer();
size_t frame = node["frame"].Integer();
if (source[group].size() <= frame)
source[group].resize(frame+1);
JsonNode toAdd(JsonNode::JsonType::DATA_STRUCT);
JsonUtils::inherit(toAdd, base);
toAdd["file"].String() = basepath + node["file"].String();
source[group][frame] = toAdd;
}
}
void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
{
if(images.empty())
{
logGlobal->error("Nothing to export, animation is empty");
return;
}
boost::filesystem::path actualPath = path / "SPRITES" / name;
boost::filesystem::create_directories(actualPath);
size_t counter = 0;
for(const auto & groupPair : images)
{
size_t group = groupPair.first;
for(const auto & imagePair : groupPair.second)
{
size_t frame = imagePair.first;
const auto img = imagePair.second;
boost::format fmt("%d_%d.bmp");
fmt % group % frame;
img->exportBitmap(actualPath / fmt.str());
counter++;
}
}
logGlobal->info("Exported %d frames to %s", counter, actualPath.string());
}
void CAnimation::init()
{
if(defFile)
{
const std::map<size_t, size_t> defEntries = defFile->getEntries();
for (auto & defEntry : defEntries)
source[defEntry.first].resize(defEntry.second);
}
ResourceID resID(std::string("SPRITES/") + name, EResType::TEXT);
if (vstd::contains(graphics->imageLists, resID.getName()))
initFromJson(graphics->imageLists[resID.getName()]);
auto configList = CResourceHandler::get()->getResourcesWithName(resID);
for(auto & loader : configList)
{
auto stream = loader->load(resID);
std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
stream->read(textData.get(), stream->getSize());
const JsonNode config((char*)textData.get(), stream->getSize());
initFromJson(config);
}
}
void CAnimation::printError(size_t frame, size_t group, std::string type) const
{
logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame);
}
CAnimation::CAnimation(std::string Name):
name(Name),
preloaded(false),
defFile()
{
size_t dotPos = name.find_last_of('.');
if ( dotPos!=-1 )
name.erase(dotPos);
std::transform(name.begin(), name.end(), name.begin(), toupper);
ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION);
if(CResourceHandler::get()->existsResource(resource))
defFile = std::make_shared<CDefFile>(name);
init();
if(source.empty())
logAnim->error("Animation %s failed to load", Name);
}
CAnimation::CAnimation():
name(""),
preloaded(false),
defFile()
{
init();
}
CAnimation::~CAnimation() = default;
void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup)
{
if(!source.count(sourceGroup))
{
logAnim->error("Group %d missing in %s", sourceGroup, name);
return;
}
if(source[sourceGroup].size() <= sourceFrame)
{
logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name);
return;
}
//todo: clone actual loaded Image object
JsonNode clone(source[sourceGroup][sourceFrame]);
if(clone.getType() == JsonNode::JsonType::DATA_NULL)
{
std::string temp = name+":"+boost::lexical_cast<std::string>(sourceGroup)+":"+boost::lexical_cast<std::string>(sourceFrame);
clone["file"].String() = temp;
}
source[targetGroup].push_back(clone);
size_t index = source[targetGroup].size() - 1;
if(preloaded)
load(index, targetGroup);
}
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
{
if (source[group].size() <= frame)
source[group].resize(frame+1);
source[group][frame]["file"].String() = filename;
//FIXME: update image if already loaded
}
std::shared_ptr<IImage> CAnimation::getImage(size_t frame, size_t group, bool verbose) const
{
auto groupIter = images.find(group);
if (groupIter != images.end())
{
auto imageIter = groupIter->second.find(frame);
if (imageIter != groupIter->second.end())
return imageIter->second;
}
if (verbose)
printError(frame, group, "GetImage");
return nullptr;
}
void CAnimation::load()
{
for (auto & elem : source)
for (size_t image=0; image < elem.second.size(); image++)
loadFrame(image, elem.first);
}
void CAnimation::unload()
{
for (auto & elem : source)
for (size_t image=0; image < elem.second.size(); image++)
unloadFrame(image, elem.first);
}
void CAnimation::preload()
{
if(!preloaded)
{
preloaded = true;
load();
}
}
void CAnimation::loadGroup(size_t group)
{
if (vstd::contains(source, group))
for (size_t image=0; image < source[group].size(); image++)
loadFrame(image, group);
}
void CAnimation::unloadGroup(size_t group)
{
if (vstd::contains(source, group))
for (size_t image=0; image < source[group].size(); image++)
unloadFrame(image, group);
}
void CAnimation::load(size_t frame, size_t group)
{
loadFrame(frame, group);
}
void CAnimation::unload(size_t frame, size_t group)
{
unloadFrame(frame, group);
}
size_t CAnimation::size(size_t group) const
{
auto iter = source.find(group);
if (iter != source.end())
return iter->second.size();
return 0;
}
void CAnimation::horizontalFlip()
{
for(auto & group : images)
for(auto & image : group.second)
image.second->horizontalFlip();
}
void CAnimation::verticalFlip()
{
for(auto & group : images)
for(auto & image : group.second)
image.second->verticalFlip();
}
void CAnimation::playerColored(PlayerColor player)
{
for(auto & group : images)
for(auto & image : group.second)
image.second->playerColored(player);
}
void CAnimation::createFlippedGroup(const size_t sourceGroup, const size_t targetGroup)
{
for(size_t frame = 0; frame < size(sourceGroup); ++frame)
{
duplicateImage(sourceGroup, frame, targetGroup);
auto image = getImage(frame, targetGroup);
image->verticalFlip();
}
}

View File

@ -0,0 +1,93 @@
/*
* CAnimation.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
*
*/
#pragma once
#include "../../lib/GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
VCMI_LIB_NAMESPACE_END
class CDefFile;
class IImage;
/// Class for handling animation
class CAnimation
{
private:
//source[group][position] - file with this frame, if string is empty - image located in def file
std::map<size_t, std::vector <JsonNode> > source;
//bitmap[group][position], store objects with loaded bitmaps
std::map<size_t, std::map<size_t, std::shared_ptr<IImage> > > images;
//animation file name
std::string name;
bool preloaded;
std::shared_ptr<CDefFile> defFile;
//loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded
bool loadFrame(size_t frame, size_t group);
//unloadFrame, returns true if image has been unloaded ( either deleted or decreased refCount)
bool unloadFrame(size_t frame, size_t group);
//initialize animation from file
void initFromJson(const JsonNode & input);
void init();
//to get rid of copy-pasting error message :]
void printError(size_t frame, size_t group, std::string type) const;
//not a very nice method to get image from another def file
//TODO: remove after implementing resource manager
std::shared_ptr<IImage> getFromExtraDef(std::string filename);
public:
CAnimation(std::string Name);
CAnimation();
~CAnimation();
//duplicates frame at [sourceGroup, sourceFrame] as last frame in targetGroup
//and loads it if animation is preloaded
void duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup);
//add custom surface to the selected position.
void setCustom(std::string filename, size_t frame, size_t group=0);
std::shared_ptr<IImage> getImage(size_t frame, size_t group=0, bool verbose=true) const;
void exportBitmaps(const boost::filesystem::path & path) const;
//all available frames
void load ();
void unload();
void preload();
//all frames from group
void loadGroup (size_t group);
void unloadGroup(size_t group);
//single image
void load (size_t frame, size_t group=0);
void unload(size_t frame, size_t group=0);
//total count of frames in group (including not loaded)
size_t size(size_t group=0) const;
void horizontalFlip();
void verticalFlip();
void playerColored(PlayerColor player);
void createFlippedGroup(const size_t sourceGroup, const size_t targetGroup);
};

View File

@ -8,13 +8,15 @@
*
*/
#include "StdInc.h"
#include "CBitmapHandler.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../lib/filesystem/Filesystem.h"
#include <SDL_image.h>
#include "CBitmapHandler.h"
#include "gui/SDL_Extensions.h"
#include "../lib/vcmi_endian.h"
#include <SDL_image.h>
namespace BitmapHandler
{
SDL_Surface * loadH3PCX(ui8 * data, size_t size);

358
client/render/CDefFile.cpp Normal file
View File

@ -0,0 +1,358 @@
/*
* CDefFile.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
*
*/
#include "StdInc.h"
#include "CDefFile.h"
#include "IImageLoader.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/Point.h"
#include <SDL_pixels.h>
// Extremely simple file cache. TODO: smarter, more general solution
class CFileCache
{
static const int cacheSize = 50; //Max number of cached files
struct FileData
{
ResourceID name;
size_t size;
std::unique_ptr<ui8[]> data;
std::unique_ptr<ui8[]> getCopy()
{
auto ret = std::unique_ptr<ui8[]>(new ui8[size]);
std::copy(data.get(), data.get() + size, ret.get());
return ret;
}
FileData(ResourceID name_, size_t size_, std::unique_ptr<ui8[]> data_):
name{std::move(name_)},
size{size_},
data{std::move(data_)}
{}
};
std::deque<FileData> cache;
public:
std::unique_ptr<ui8[]> getCachedFile(ResourceID rid)
{
for(auto & file : cache)
{
if (file.name == rid)
return file.getCopy();
}
// Still here? Cache miss
if (cache.size() > cacheSize)
cache.pop_front();
auto data = CResourceHandler::get()->load(rid)->readAll();
cache.emplace_back(std::move(rid), data.second, std::move(data.first));
return cache.back().getCopy();
}
};
enum class DefType : uint32_t
{
SPELL = 0x40,
SPRITE = 0x41,
CREATURE = 0x42,
MAP = 0x43,
MAP_HERO = 0x44,
TERRAIN = 0x45,
CURSOR = 0x46,
INTERFACE = 0x47,
SPRITE_FRAME = 0x48,
BATTLE_HERO = 0x49
};
static CFileCache animationCache;
/*************************************************************************
* DefFile, class used for def loading *
*************************************************************************/
bool operator== (const SDL_Color & lhs, const SDL_Color & rhs)
{
return (lhs.a == rhs.a) && (lhs.b == rhs.b) &&(lhs.g == rhs.g) &&(lhs.r == rhs.r);
}
CDefFile::CDefFile(std::string Name):
data(nullptr),
palette(nullptr)
{
//First 8 colors in def palette used for transparency
static SDL_Color H3Palette[8] =
{
{ 0, 0, 0, 0},// transparency ( used in most images )
{ 0, 0, 0, 64},// shadow border ( used in battle, adventure map def's )
{ 0, 0, 0, 64},// shadow border ( used in fog-of-war def's )
{ 0, 0, 0, 128},// shadow body ( used in fog-of-war def's )
{ 0, 0, 0, 128},// shadow body ( used in battle, adventure map def's )
{ 0, 0, 0, 0},// selection ( used in battle def's )
{ 0, 0, 0, 128},// shadow body below selection ( used in battle def's )
{ 0, 0, 0, 64} // shadow border below selection ( used in battle def's )
};
data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION));
palette = std::unique_ptr<SDL_Color[]>(new SDL_Color[256]);
int it = 0;
ui32 type = read_le_u32(data.get() + it);
it+=4;
//int width = read_le_u32(data + it); it+=4;//not used
//int height = read_le_u32(data + it); it+=4;
it+=8;
ui32 totalBlocks = read_le_u32(data.get() + it);
it+=4;
for (ui32 i= 0; i<256; i++)
{
palette[i].r = data[it++];
palette[i].g = data[it++];
palette[i].b = data[it++];
palette[i].a = SDL_ALPHA_OPAQUE;
}
switch(static_cast<DefType>(type))
{
case DefType::SPELL:
palette[0] = H3Palette[0];
break;
case DefType::SPRITE:
case DefType::SPRITE_FRAME:
for(ui32 i= 0; i<8; i++)
palette[i] = H3Palette[i];
break;
case DefType::CREATURE:
palette[0] = H3Palette[0];
palette[1] = H3Palette[1];
palette[4] = H3Palette[4];
palette[5] = H3Palette[5];
palette[6] = H3Palette[6];
palette[7] = H3Palette[7];
break;
case DefType::MAP:
case DefType::MAP_HERO:
palette[0] = H3Palette[0];
palette[1] = H3Palette[1];
palette[4] = H3Palette[4];
//5 = owner flag, handled separately
break;
case DefType::TERRAIN:
palette[0] = H3Palette[0];
palette[1] = H3Palette[1];
palette[2] = H3Palette[2];
palette[3] = H3Palette[3];
palette[4] = H3Palette[4];
break;
case DefType::CURSOR:
palette[0] = H3Palette[0];
break;
case DefType::INTERFACE:
palette[0] = H3Palette[0];
palette[1] = H3Palette[1];
palette[4] = H3Palette[4];
//player colors handled separately
//TODO: disallow colorizing other def types
break;
case DefType::BATTLE_HERO:
palette[0] = H3Palette[0];
palette[1] = H3Palette[1];
palette[4] = H3Palette[4];
break;
default:
logAnim->error("Unknown def type %d in %s", type, Name);
break;
}
for (ui32 i=0; i<totalBlocks; i++)
{
size_t blockID = read_le_u32(data.get() + it);
it+=4;
size_t totalEntries = read_le_u32(data.get() + it);
it+=12;
//8 unknown bytes - skipping
//13 bytes for name of every frame in this block - not used, skipping
it+= 13 * (int)totalEntries;
for (ui32 j=0; j<totalEntries; j++)
{
size_t currOffset = read_le_u32(data.get() + it);
offset[blockID].push_back(currOffset);
it += 4;
}
}
}
void CDefFile::loadFrame(size_t frame, size_t group, IImageLoader &loader) const
{
std::map<size_t, std::vector <size_t> >::const_iterator it;
it = offset.find(group);
assert (it != offset.end());
const ui8 * FDef = data.get()+it->second[frame];
const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef);
SSpriteDef sprite;
sprite.format = read_le_u32(&sd.format);
sprite.fullWidth = read_le_u32(&sd.fullWidth);
sprite.fullHeight = read_le_u32(&sd.fullHeight);
sprite.width = read_le_u32(&sd.width);
sprite.height = read_le_u32(&sd.height);
sprite.leftMargin = read_le_u32(&sd.leftMargin);
sprite.topMargin = read_le_u32(&sd.topMargin);
ui32 currentOffset = sizeof(SSpriteDef);
//special case for some "old" format defs (SGTWMTA.DEF and SGTWMTB.DEF)
if(sprite.format == 1 && sprite.width > sprite.fullWidth && sprite.height > sprite.fullHeight)
{
sprite.leftMargin = 0;
sprite.topMargin = 0;
sprite.width = sprite.fullWidth;
sprite.height = sprite.fullHeight;
currentOffset -= 16;
}
const ui32 BaseOffset = currentOffset;
loader.init(Point(sprite.width, sprite.height),
Point(sprite.leftMargin, sprite.topMargin),
Point(sprite.fullWidth, sprite.fullHeight), palette.get());
switch(sprite.format)
{
case 0:
{
//pixel data is not compressed, copy data to surface
for(ui32 i=0; i<sprite.height; i++)
{
loader.load(sprite.width, FDef + currentOffset);
currentOffset += sprite.width;
loader.endLine();
}
break;
}
case 1:
{
//for each line we have offset of pixel data
const ui32 * RWEntriesLoc = reinterpret_cast<const ui32 *>(FDef+currentOffset);
currentOffset += sizeof(ui32) * sprite.height;
for(ui32 i=0; i<sprite.height; i++)
{
//get position of the line
currentOffset=BaseOffset + read_le_u32(RWEntriesLoc + i);
ui32 TotalRowLength = 0;
while(TotalRowLength<sprite.width)
{
ui8 segmentType = FDef[currentOffset++];
ui32 length = FDef[currentOffset++] + 1;
if(segmentType==0xFF)//Raw data
{
loader.load(length, FDef + currentOffset);
currentOffset+=length;
}
else// RLE
{
loader.load(length, segmentType);
}
TotalRowLength += length;
}
loader.endLine();
}
break;
}
case 2:
{
currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset);
for(ui32 i=0; i<sprite.height; i++)
{
ui32 TotalRowLength=0;
while(TotalRowLength<sprite.width)
{
ui8 segment=FDef[currentOffset++];
ui8 code = segment / 32;
ui8 length = (segment & 31) + 1;
if(code==7)//Raw data
{
loader.load(length, FDef + currentOffset);
currentOffset += length;
}
else//RLE
{
loader.load(length, code);
}
TotalRowLength+=length;
}
loader.endLine();
}
break;
}
case 3:
{
for(ui32 i=0; i<sprite.height; i++)
{
currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset+i*2*(sprite.width/32));
ui32 TotalRowLength=0;
while(TotalRowLength<sprite.width)
{
ui8 segment = FDef[currentOffset++];
ui8 code = segment / 32;
ui8 length = (segment & 31) + 1;
if(code==7)//Raw data
{
loader.load(length, FDef + currentOffset);
currentOffset += length;
}
else//RLE
{
loader.load(length, code);
}
TotalRowLength += length;
}
loader.endLine();
}
break;
}
default:
logGlobal->error("Error: unsupported format of def file: %d", sprite.format);
break;
}
}
CDefFile::~CDefFile() = default;
const std::map<size_t, size_t > CDefFile::getEntries() const
{
std::map<size_t, size_t > ret;
for (auto & elem : offset)
ret[elem.first] = elem.second.size();
return ret;
}

51
client/render/CDefFile.h Normal file
View File

@ -0,0 +1,51 @@
/*
* CDefFile.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
*
*/
#pragma once
#include "../../lib/vcmi_endian.h"
class IImageLoader;
struct SDL_Color;
/// Class for def loading
/// After loading will store general info (palette and frame offsets) and pointer to file itself
class CDefFile
{
private:
PACKED_STRUCT_BEGIN
struct SSpriteDef
{
ui32 size;
ui32 format; /// format in which pixel data is stored
ui32 fullWidth; /// full width and height of frame, including borders
ui32 fullHeight;
ui32 width; /// width and height of pixel data, borders excluded
ui32 height;
si32 leftMargin;
si32 topMargin;
} PACKED_STRUCT_END;
//offset[group][frame] - offset of frame data in file
std::map<size_t, std::vector <size_t> > offset;
std::unique_ptr<ui8[]> data;
std::unique_ptr<SDL_Color[]> palette;
public:
CDefFile(std::string Name);
~CDefFile();
//load frame as SDL_Surface
void loadFrame(size_t frame, size_t group, IImageLoader &loader) const;
const std::map<size_t, size_t> getEntries() const;
};

View File

@ -0,0 +1,101 @@
/*
* CFadeAnimation.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
*
*/
#include "StdInc.h"
#include "CFadeAnimation.h"
#include "../renderSDL/SDL_Extensions.h"
#include <SDL_surface.h>
float CFadeAnimation::initialCounter() const
{
if (fadingMode == EMode::OUT)
return 1.0f;
return 0.0f;
}
void CFadeAnimation::update()
{
if (!fading)
return;
if (fadingMode == EMode::OUT)
fadingCounter -= delta;
else
fadingCounter += delta;
if (isFinished())
{
fading = false;
if (shouldFreeSurface)
{
SDL_FreeSurface(fadingSurface);
fadingSurface = nullptr;
}
}
}
bool CFadeAnimation::isFinished() const
{
if (fadingMode == EMode::OUT)
return fadingCounter <= 0.0f;
return fadingCounter >= 1.0f;
}
CFadeAnimation::CFadeAnimation()
: delta(0), fadingSurface(nullptr), fading(false), fadingCounter(0), shouldFreeSurface(false),
fadingMode(EMode::NONE)
{
}
CFadeAnimation::~CFadeAnimation()
{
if (fadingSurface && shouldFreeSurface)
SDL_FreeSurface(fadingSurface);
}
void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd, float animDelta)
{
if (fading)
{
// in that case, immediately finish the previous fade
// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
logGlobal->warn("Tried to init fading animation that is already running.");
if (fadingSurface && shouldFreeSurface)
SDL_FreeSurface(fadingSurface);
}
if (animDelta <= 0.0f)
{
logGlobal->warn("Fade anim: delta should be positive; %f given.", animDelta);
animDelta = DEFAULT_DELTA;
}
if (sourceSurface)
fadingSurface = sourceSurface;
delta = animDelta;
fadingMode = mode;
fadingCounter = initialCounter();
fading = true;
shouldFreeSurface = freeSurfaceAtEnd;
}
void CFadeAnimation::draw(SDL_Surface * targetSurface, const Point &targetPoint)
{
if (!fading || !fadingSurface || fadingMode == EMode::NONE)
{
fading = false;
return;
}
CSDL_Ext::setAlpha(fadingSurface, (int)(fadingCounter * 255));
CSDL_Ext::blitSurface(fadingSurface, targetSurface, targetPoint); //FIXME
CSDL_Ext::setAlpha(fadingSurface, 255);
}

View File

@ -0,0 +1,53 @@
/*
* CFadeAnimation.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
*
*/
#pragma once
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif
VCMI_LIB_NAMESPACE_BEGIN
class Point;
VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
const float DEFAULT_DELTA = 0.05f;
class CFadeAnimation
{
public:
enum class EMode
{
NONE, IN, OUT
};
private:
float delta;
SDL_Surface * fadingSurface;
bool fading;
float fadingCounter;
bool shouldFreeSurface;
float initialCounter() const;
bool isFinished() const;
public:
EMode fadingMode;
CFadeAnimation();
~CFadeAnimation();
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
void update();
void draw(SDL_Surface * targetSurface, const Point & targetPoint);
bool isFading() const { return fading; }
};

View File

@ -10,10 +10,9 @@
#include "StdInc.h"
#include "Canvas.h"
#include "SDL_Extensions.h"
#include "CAnimation.h"
#include "../Graphics.h"
#include "../renderSDL/SDL_Extensions.h"
#include "IImage.h"
#include "Graphics.h"
#include <SDL_surface.h>

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "TextAlignment.h"
#include "../gui/TextAlignment.h"
#include "../../lib/Rect.h"
#include "../../lib/Color.h"

View File

@ -18,11 +18,15 @@
#include <vcmi/SkillService.h>
#include <vcmi/spells/Service.h>
#include "../renderSDL/SDL_Extensions.h"
#include "../renderSDL/CBitmapFont.h"
#include "../renderSDL/CBitmapHanFont.h"
#include "../renderSDL/CTrueTypeFont.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/filesystem/CBinaryReader.h"
#include "gui/SDL_Extensions.h"
#include "gui/CAnimation.h"
#include "../lib/CThreadHelper.h"
#include "../lib/CModHandler.h"
#include "CGameInfo.h"
#include "../lib/VCMI_Lib.h"

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "gui/Fonts.h"
#include "IFont.h"
#include "../lib/GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -22,6 +22,7 @@ struct InfoAboutTown;
class CGObjectInstance;
class ObjectTemplate;
class EntityService;
class JsonNode;
VCMI_LIB_NAMESPACE_END

28
client/render/ICursor.h Normal file
View File

@ -0,0 +1,28 @@
/*
* ICursor.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
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class Point;
VCMI_LIB_NAMESPACE_END
class IImage;
class ICursor
{
public:
virtual ~ICursor() = default;
virtual void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) = 0;
virtual void setCursorPosition( const Point & newPos ) = 0;
virtual void render() = 0;
virtual void setVisible( bool on) = 0;
};

80
client/render/IFont.cpp Normal file
View File

@ -0,0 +1,80 @@
/*
* IFont.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
*
*/
#include "StdInc.h"
#include "IFont.h"
#include "../../lib/Point.h"
#include "../../lib/CGeneralTextHandler.h"
//
size_t IFont::getStringWidth(const std::string & data) const
{
size_t width = 0;
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
width += getGlyphWidth(data.data() + i);
}
return width;
}
void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
renderText(surface, data, color, pos);
}
void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
Point size((int)getStringWidth(data), (int)getLineHeight());
renderText(surface, data, color, pos - size);
}
void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
Point size((int)getStringWidth(data), (int)getLineHeight());
renderText(surface, data, color, pos - size / 2);
}
void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
for(const std::string & line : data)
{
renderTextLeft(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}
void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
currPos.y -= (int)data.size() * (int)getLineHeight();
for(const std::string & line : data)
{
renderTextRight(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}
void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
{
Point currPos = pos;
currPos.y -= (int)data.size() * (int)getLineHeight() / 2;
for(const std::string & line : data)
{
renderTextCenter(surface, line, color, currPos);
currPos.y += (int)getLineHeight();
}
}

56
client/render/IFont.h Normal file
View File

@ -0,0 +1,56 @@
/*
* IFont.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
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class Point;
VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
struct SDL_Color;
class IFont
{
protected:
/// Internal function to render font, see renderTextLeft
virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0;
public:
virtual ~IFont()
{}
/// Returns height of font
virtual size_t getLineHeight() const = 0;
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
virtual size_t getGlyphWidth(const char * data) const = 0;
/// Return width of the string
virtual size_t getStringWidth(const std::string & data) const;
/**
* @param surface - destination to print text on
* @param data - string to print
* @param color - font color
* @param pos - position of rendered font
*/
/// pos = topleft corner of the text
void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = center of the text
void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = bottomright corner of the text
void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
/// pos = topleft corner of the text
void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
/// pos = center of the text
void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
/// pos = bottomright corner of the text
void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
};

77
client/render/IImage.h Normal file
View File

@ -0,0 +1,77 @@
/*
* IImage.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
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class PlayerColor;
class Rect;
class Point;
VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
struct SDL_Color;
class ColorFilter;
/*
* Base class for images, can be used for non-animation pictures as well
*/
class IImage
{
public:
using SpecialPalette = std::array<SDL_Color, 7>;
//draws image on surface "where" at position
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0;
virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
//Change palette to specific player
virtual void playerColored(PlayerColor player)=0;
//set special color for flag
virtual void setFlagColor(PlayerColor player)=0;
//test transparency of specific pixel
virtual bool isTransparent(const Point & coords) const = 0;
virtual Point dimensions() const = 0;
int width() const;
int height() const;
//only indexed bitmaps, 16 colors maximum
virtual void shiftPalette(int from, int howMany) = 0;
virtual void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) = 0;
virtual void resetPalette(int colorID) = 0;
virtual void resetPalette() = 0;
virtual void setAlpha(uint8_t value) = 0;
//only indexed bitmaps with 7 special colors
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
virtual void horizontalFlip() = 0;
virtual void verticalFlip() = 0;
IImage();
virtual ~IImage();
/// loads image from specified file. Returns 0-sized images on failure
static std::shared_ptr<IImage> createFromFile( const std::string & path );
/// temporary compatibility method. Creates IImage from existing SDL_Surface
/// Surface will be shared, called must still free it with SDL_FreeSurface
static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
};

View File

@ -0,0 +1,34 @@
/*
* IImageLoader.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
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class Point;
VCMI_LIB_NAMESPACE_END
class SDLImage;
struct SDL_Color;
class IImageLoader
{
public:
//load size raw pixels from data
virtual void load(size_t size, const ui8 * data) = 0;
//set size pixels to color
virtual void load(size_t size, ui8 color=0) = 0;
virtual void endLine() = 0;
//init image with these sizes and palette
virtual void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal) = 0;
virtual ~IImageLoader() = default;
};

View File

@ -0,0 +1,143 @@
/*
* CBitmapFont.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
*
*/
#include "StdInc.h"
#include "CBitmapFont.h"
#include "SDL_Extensions.h"
#include "../../lib/vcmi_endian.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/Rect.h"
#include <SDL_surface.h>
std::array<CBitmapFont::BitmapChar, CBitmapFont::totalChars> CBitmapFont::loadChars() const
{
std::array<BitmapChar, totalChars> ret;
size_t offset = 32;
for (auto & elem : ret)
{
elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4;
elem.width = read_le_u32(data.first.get() + offset); offset+=4;
elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4;
}
for (auto & elem : ret)
{
int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4;
elem.pixels = data.first.get() + 4128 + pixelOffset;
assert(pixelOffset + 4128 < data.second);
}
return ret;
}
CBitmapFont::CBitmapFont(const std::string & filename):
data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()),
chars(loadChars()),
height(data.first.get()[5])
{}
size_t CBitmapFont::getLineHeight() const
{
return height;
}
size_t CBitmapFont::getGlyphWidth(const char * data) const
{
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
if (localChar.size() == 1)
{
const BitmapChar & ch = chars[ui8(localChar[0])];
return ch.leftOffset + ch.width + ch.rightOffset;
}
return 0;
}
void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
{
Rect clipRect;
CSDL_Ext::getClipRect(surface, clipRect);
posX += character.leftOffset;
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
uint8_t bpp = surface->format->BytesPerPixel;
// start of line, may differ from 0 due to end of surface or clipped surface
int lineBegin = std::max<int>(0, clipRect.y - posY);
int lineEnd = std::min<int>(height, clipRect.y + clipRect.h - posY - 1);
// start end end of each row, may differ from 0
int rowBegin = std::max<int>(0, clipRect.x - posX);
int rowEnd = std::min<int>(character.width, clipRect.x + clipRect.w - posX - 1);
//for each line in symbol
for(int dy = lineBegin; dy <lineEnd; dy++)
{
uint8_t *dstLine = (uint8_t*)surface->pixels;
uint8_t *srcLine = character.pixels;
// shift source\destination pixels to current position
dstLine += (posY+dy) * surface->pitch + posX * bpp;
srcLine += dy * character.width;
//for each column in line
for(int dx = rowBegin; dx < rowEnd; dx++)
{
uint8_t* dstPixel = dstLine + dx*bpp;
switch(srcLine[dx])
{
case 1: //black "shadow"
colorPutter(dstPixel, 0, 0, 0);
break;
case 255: //text colour
colorPutter(dstPixel, color.r, color.g, color.b);
break;
default :
break; //transparency
}
}
}
posX += character.width;
posX += character.rightOffset;
}
void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
if (data.empty())
return;
assert(surface);
int posX = pos.x;
int posY = pos.y;
// Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles)
//assert(data[0] != '{');
//assert(data[data.size()-1] != '}');
SDL_LockSurface(surface);
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
if (localChar.size() == 1)
renderCharacter(surface, chars[ui8(localChar[0])], color, posX, posY);
}
SDL_UnlockSurface(surface);
}

View File

@ -0,0 +1,44 @@
/*
* CBitmapFont.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
*
*/
#pragma once
#include "../render/IFont.h"
class CBitmapFont : public IFont
{
static const size_t totalChars = 256;
struct BitmapChar
{
si32 leftOffset;
ui32 width;
si32 rightOffset;
ui8 *pixels; // pixels of this character, part of BitmapFont::data
};
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
const std::array<BitmapChar, totalChars> chars;
const ui8 height;
std::array<BitmapChar, totalChars> loadChars() const;
void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const;
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CBitmapFont(const std::string & filename);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
friend class CBitmapHanFont;
};

View File

@ -0,0 +1,127 @@
/*
* CBitmapHanFont.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
*
*/
#include "StdInc.h"
#include "CBitmapHanFont.h"
#include "CBitmapFont.h"
#include "SDL_Extensions.h"
#include "../../lib/JsonNode.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/Rect.h"
#include <SDL_surface.h>
size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const
{
size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up
size_t charSize = rowSize * size; // glyph contains "size" rows
return index * charSize;
}
size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const
{
if (second > 0x7f )
second--;
return (first - 0x81) * (12*16 - 2) + (second - 0x40);
}
void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const
{
//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
Rect clipRect;
CSDL_Ext::getClipRect(surface, clipRect);
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
uint8_t bpp = surface->format->BytesPerPixel;
// start of line, may differ from 0 due to end of surface or clipped surface
int lineBegin = std::max<int>(0, clipRect.y - posY);
int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY);
// start end end of each row, may differ from 0
int rowBegin = std::max<int>(0, clipRect.x - posX);
int rowEnd = std::min<int>((int)size, clipRect.x + clipRect.w - posX);
//for each line in symbol
for(int dy = lineBegin; dy <lineEnd; dy++)
{
uint8_t *dstLine = (uint8_t*)surface->pixels;
uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex);
// shift source\destination pixels to current position
dstLine += (posY+dy) * surface->pitch + posX * bpp;
source += ((size + 7) / 8) * dy;
//for each column in line
for(int dx = rowBegin; dx < rowEnd; dx++)
{
// select current bit in bitmap
int bit = (source[dx / 8] << (dx % 8)) & 0x80;
uint8_t* dstPixel = dstLine + dx*bpp;
if (bit != 0)
colorPutter(dstPixel, color.r, color.g, color.b);
}
}
posX += (int)size + 1;
}
void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
int posX = pos.x;
int posY = pos.y;
SDL_LockSurface(surface);
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
{
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
if (localChar.size() == 1)
fallback->renderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY);
if (localChar.size() == 2)
renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY);
}
SDL_UnlockSurface(surface);
}
CBitmapHanFont::CBitmapHanFont(const JsonNode &config):
fallback(new CBitmapFont(config["fallback"].String())),
data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()),
size((size_t)config["size"].Float())
{
// basic tests to make sure that fonts are OK
// 1) fonts must contain 190 "sections", 126 symbols each.
assert(getCharacterIndex(0xfe, 0xff) == 190*126);
// 2) ensure that font size is correct - enough to fit all possible symbols
assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second);
}
size_t CBitmapHanFont::getLineHeight() const
{
return std::max(size + 1, fallback->getLineHeight());
}
size_t CBitmapHanFont::getGlyphWidth(const char * data) const
{
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
if (localChar.size() == 1)
return fallback->getGlyphWidth(data);
if (localChar.size() == 2)
return size + 1;
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* CBitmapHanFont.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
*
*/
#pragma once
#include "../render/IFont.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
VCMI_LIB_NAMESPACE_END
class CBitmapFont;
/// supports multi-byte characters for such languages like Chinese
class CBitmapHanFont : public IFont
{
std::unique_ptr<CBitmapFont> fallback;
// data, directly copied from file
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
// size of the font. Not available in file but needed for proper rendering
const size_t size;
size_t getCharacterDataOffset(size_t index) const;
size_t getCharacterIndex(ui8 first, ui8 second) const;
void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const;
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CBitmapHanFont(const JsonNode & config);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
};

View File

@ -0,0 +1,102 @@
/*
* CTrueTypeFont.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
*
*/
#include "StdInc.h"
#include "CTrueTypeFont.h"
#include "SDL_Extensions.h"
#include "../../lib/JsonNode.h"
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/filesystem/Filesystem.h"
#include <SDL_ttf.h>
std::pair<std::unique_ptr<ui8[]>, ui64> CTrueTypeFont::loadData(const JsonNode & config)
{
std::string filename = "Data/" + config["file"].String();
return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll();
}
TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config)
{
int pointSize = static_cast<int>(config["size"].Float());
if(!TTF_WasInit() && TTF_Init()==-1)
throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n");
return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize);
}
int CTrueTypeFont::getFontStyle(const JsonNode &config)
{
const JsonVector & names = config["style"].Vector();
int ret = 0;
for(const JsonNode & node : names)
{
if (node.String() == "bold")
ret |= TTF_STYLE_BOLD;
else if (node.String() == "italic")
ret |= TTF_STYLE_ITALIC;
}
return ret;
}
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
data(loadData(fontConfig)),
font(loadFont(fontConfig), TTF_CloseFont),
blended(fontConfig["blend"].Bool())
{
assert(font);
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
}
size_t CTrueTypeFont::getLineHeight() const
{
return TTF_FontHeight(font.get());
}
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
{
return getStringWidth(std::string(data, Unicode::getCharacterSize(*data)));
/*
int advance;
TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
return advance;
*/
}
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
{
int width;
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
return width;
}
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
{
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
renderText(surface, data, Colors::BLACK, pos + Point(1,1));
if (!data.empty())
{
SDL_Surface * rendered;
if (blended)
rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color);
else
rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color);
assert(rendered);
CSDL_Ext::blitSurface(rendered, surface, pos);
SDL_FreeSurface(rendered);
}
}

View File

@ -0,0 +1,38 @@
/*
* CTrueTypeFont.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
*
*/
#pragma once
#include "../render/IFont.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
VCMI_LIB_NAMESPACE_END
typedef struct _TTF_Font TTF_Font;
class CTrueTypeFont : public IFont
{
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
const bool blended;
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
TTF_Font * loadFont(const JsonNode & config);
int getFontStyle(const JsonNode & config);
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
public:
CTrueTypeFont(const JsonNode & fontConfig);
size_t getLineHeight() const override;
size_t getGlyphWidth(const char * data) const override;
size_t getStringWidth(const std::string & data) const override;
};

View File

@ -0,0 +1,85 @@
/*
* CursorHardware.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
*
*/
#include "StdInc.h"
#include "CursorHardware.h"
#include "SDL_Extensions.h"
#include "../render/IImage.h"
#include <SDL_render.h>
#include <SDL_events.h>
#ifdef VCMI_APPLE
#include <dispatch/dispatch.h>
#endif
CursorHardware::CursorHardware():
cursor(nullptr)
{
SDL_ShowCursor(SDL_DISABLE);
}
CursorHardware::~CursorHardware()
{
if(cursor)
SDL_FreeCursor(cursor);
}
void CursorHardware::setVisible(bool on)
{
#ifdef VCMI_APPLE
dispatch_async(dispatch_get_main_queue(), ^{
#endif
if (on)
SDL_ShowCursor(SDL_ENABLE);
else
SDL_ShowCursor(SDL_DISABLE);
#ifdef VCMI_APPLE
});
#endif
}
void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
{
auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y);
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
image->draw(cursorSurface);
auto oldCursor = cursor;
cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y);
if (!cursor)
logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError());
SDL_FreeSurface(cursorSurface);
#ifdef VCMI_APPLE
dispatch_async(dispatch_get_main_queue(), ^{
#endif
SDL_SetCursor(cursor);
if (oldCursor)
SDL_FreeCursor(oldCursor);
#ifdef VCMI_APPLE
});
#endif
}
void CursorHardware::setCursorPosition( const Point & newPos )
{
//no-op
}
void CursorHardware::render()
{
//no-op
}

View File

@ -0,0 +1,36 @@
/*
* CursorHardware.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
*
*/
#pragma once
class CAnimation;
class IImage;
struct SDL_Surface;
struct SDL_Texture;
struct SDL_Cursor;
#include "../../lib/Point.h"
#include "../render/ICursor.h"
class CursorHardware : public ICursor
{
std::shared_ptr<IImage> cursorImage;
SDL_Cursor * cursor;
public:
CursorHardware();
~CursorHardware();
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
void setCursorPosition( const Point & newPos ) override;
void render() override;
void setVisible( bool on) override;
};

View File

@ -0,0 +1,103 @@
/*
* CursorSoftware.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
*
*/
#include "StdInc.h"
#include "CursorSoftware.h"
#include "SDL_Extensions.h"
#include "../render/IImage.h"
#include <SDL_render.h>
#include <SDL_events.h>
void CursorSoftware::render()
{
//texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads
if (needUpdate)
updateTexture();
Point renderPos = pos - pivot;
SDL_Rect destRect;
destRect.x = renderPos.x;
destRect.y = renderPos.y;
destRect.w = 40;
destRect.h = 40;
SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect);
}
void CursorSoftware::createTexture(const Point & dimensions)
{
if(cursorTexture)
SDL_DestroyTexture(cursorTexture);
if (cursorSurface)
SDL_FreeSurface(cursorSurface);
cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y);
cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y);
SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE);
SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND);
}
void CursorSoftware::updateTexture()
{
Point dimensions(-1, -1);
if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions())
createTexture(cursorImage->dimensions());
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
cursorImage->draw(cursorSurface);
SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch);
needUpdate = false;
}
void CursorSoftware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
{
assert(image != nullptr);
cursorImage = image;
pivot = pivotOffset;
needUpdate = true;
}
void CursorSoftware::setCursorPosition( const Point & newPos )
{
pos = newPos;
}
void CursorSoftware::setVisible(bool on)
{
visible = on;
}
CursorSoftware::CursorSoftware():
cursorTexture(nullptr),
cursorSurface(nullptr),
needUpdate(false),
visible(false),
pivot(0,0)
{
SDL_ShowCursor(SDL_DISABLE);
}
CursorSoftware::~CursorSoftware()
{
if(cursorTexture)
SDL_DestroyTexture(cursorTexture);
if (cursorSurface)
SDL_FreeSurface(cursorSurface);
}

View File

@ -0,0 +1,44 @@
/*
* CursorSoftware.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
*
*/
#pragma once
class CAnimation;
class IImage;
struct SDL_Surface;
struct SDL_Texture;
struct SDL_Cursor;
#include "../../lib/Point.h"
#include "../render/ICursor.h"
class CursorSoftware : public ICursor
{
std::shared_ptr<IImage> cursorImage;
SDL_Texture * cursorTexture;
SDL_Surface * cursorSurface;
Point pos;
Point pivot;
bool needUpdate;
bool visible;
void createTexture(const Point & dimensions);
void updateTexture();
public:
CursorSoftware();
~CursorSoftware();
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
void setCursorPosition( const Point & newPos ) override;
void render() override;
void setVisible( bool on) override;
};

View File

@ -0,0 +1,342 @@
/*
* SDLImage.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
*
*/
#include "StdInc.h"
#include "SDLImage.h"
#include "SDLImageLoader.h"
#include "SDL_Extensions.h"
#include "../render/ColorFilter.h"
#include "../render/CBitmapHandler.h"
#include "../render/CDefFile.h"
#include "../render/Graphics.h"
#include "../../lib/JsonNode.h"
#include <SDL_surface.h>
class SDLImageLoader;
std::shared_ptr<IImage> IImage::createFromFile( const std::string & path )
{
return std::shared_ptr<IImage>(new SDLImage(path));
}
std::shared_ptr<IImage> IImage::createFromSurface( SDL_Surface * source )
{
return std::shared_ptr<IImage>(new SDLImage(source, true));
}
IImage::IImage() = default;
IImage::~IImage() = default;
int IImage::width() const
{
return dimensions().x;
}
int IImage::height() const
{
return dimensions().y;
}
SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
originalPalette(nullptr)
{
SDLImageLoader loader(this);
data->loadFrame(frame, group, loader);
savePalette();
}
SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
originalPalette(nullptr)
{
surf = from;
if (surf == nullptr)
return;
savePalette();
if (extraRef)
surf->refcount++;
fullSize.x = surf->w;
fullSize.y = surf->h;
}
SDLImage::SDLImage(const JsonNode & conf)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
originalPalette(nullptr)
{
std::string filename = conf["file"].String();
surf = BitmapHandler::loadBitmap(filename);
if(surf == nullptr)
return;
savePalette();
const JsonNode & jsonMargins = conf["margins"];
margins.x = static_cast<int>(jsonMargins["left"].Integer());
margins.y = static_cast<int>(jsonMargins["top"].Integer());
fullSize.x = static_cast<int>(conf["width"].Integer());
fullSize.y = static_cast<int>(conf["height"].Integer());
if(fullSize.x == 0)
{
fullSize.x = margins.x + surf->w + (int)jsonMargins["right"].Integer();
}
if(fullSize.y == 0)
{
fullSize.y = margins.y + surf->h + (int)jsonMargins["bottom"].Integer();
}
}
SDLImage::SDLImage(std::string filename)
: surf(nullptr),
margins(0, 0),
fullSize(0, 0),
originalPalette(nullptr)
{
surf = BitmapHandler::loadBitmap(filename);
if(surf == nullptr)
{
logGlobal->error("Error: failed to load image %s", filename);
return;
}
else
{
savePalette();
fullSize.x = surf->w;
fullSize.y = surf->h;
}
}
void SDLImage::draw(SDL_Surface *where, int posX, int posY, const Rect *src) const
{
if(!surf)
return;
Rect destRect(posX, posY, surf->w, surf->h);
draw(where, &destRect, src);
}
void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) const
{
if (!surf)
return;
Rect sourceRect(0, 0, surf->w, surf->h);
Point destShift(0, 0);
if(src)
{
if(src->x < margins.x)
destShift.x += margins.x - src->x;
if(src->y < margins.y)
destShift.y += margins.y - src->y;
sourceRect = Rect(*src).intersect(Rect(margins.x, margins.y, surf->w, surf->h));
sourceRect -= margins;
}
else
destShift = margins;
if(dest)
destShift += dest->topLeft();
uint8_t perSurfaceAlpha;
if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0)
logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError());
if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE)
{
CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift);
}
else
{
CSDL_Ext::blitSurface(surf, sourceRect, where, destShift);
}
}
std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const
{
float scaleX = float(size.x) / width();
float scaleY = float(size.y) / height();
auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scaleX), (int)(surf->h * scaleY));
if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point
CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]);
else if(scaled->format && scaled->format->Amask)
SDL_SetSurfaceBlendMode(scaled, SDL_BLENDMODE_BLEND);//just in case
else
CSDL_Ext::setDefaultColorKey(scaled);//just in case
SDLImage * ret = new SDLImage(scaled, false);
ret->fullSize.x = (int) round((float)fullSize.x * scaleX);
ret->fullSize.y = (int) round((float)fullSize.y * scaleY);
ret->margins.x = (int) round((float)margins.x * scaleX);
ret->margins.y = (int) round((float)margins.y * scaleY);
return std::shared_ptr<IImage>(ret);
}
void SDLImage::exportBitmap(const boost::filesystem::path& path) const
{
SDL_SaveBMP(surf, path.string().c_str());
}
void SDLImage::playerColored(PlayerColor player)
{
graphics->blueToPlayersAdv(surf, player);
}
void SDLImage::setAlpha(uint8_t value)
{
CSDL_Ext::setAlpha (surf, value);
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
}
void SDLImage::setFlagColor(PlayerColor player)
{
if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL)
CSDL_Ext::setPlayerColor(surf, player);
}
bool SDLImage::isTransparent(const Point & coords) const
{
return CSDL_Ext::isTransparent(surf, coords.x, coords.y);
}
Point SDLImage::dimensions() const
{
return fullSize;
}
void SDLImage::horizontalFlip()
{
margins.y = fullSize.y - surf->h - margins.y;
//todo: modify in-place
SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf);
SDL_FreeSurface(surf);
surf = flipped;
}
void SDLImage::verticalFlip()
{
margins.x = fullSize.x - surf->w - margins.x;
//todo: modify in-place
SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf);
SDL_FreeSurface(surf);
surf = flipped;
}
// Keep the original palette, in order to do color switching operation
void SDLImage::savePalette()
{
// For some images that don't have palette, skip this
if(surf->format->palette == nullptr)
return;
if(originalPalette == nullptr)
originalPalette = SDL_AllocPalette(DEFAULT_PALETTE_COLORS);
SDL_SetPaletteColors(originalPalette, surf->format->palette->colors, 0, DEFAULT_PALETTE_COLORS);
}
void SDLImage::shiftPalette(int from, int howMany)
{
//works with at most 16 colors, if needed more -> increase values
assert(howMany < 16);
if(surf->format->palette)
{
SDL_Color palette[16];
for(int i=0; i<howMany; ++i)
{
palette[(i+1)%howMany] = surf->format->palette->colors[from + i];
}
CSDL_Ext::setColors(surf, palette, from, howMany);
}
}
void SDLImage::adjustPalette(const ColorFilter & shifter, size_t colorsToSkip)
{
if(originalPalette == nullptr)
return;
SDL_Palette* palette = surf->format->palette;
// Note: here we skip first colors in the palette that are predefined in H3 images
for(int i = colorsToSkip; i < palette->ncolors; i++)
{
palette->colors[i] = shifter.shiftColor(originalPalette->colors[i]);
}
}
void SDLImage::resetPalette()
{
if(originalPalette == nullptr)
return;
// Always keept the original palette not changed, copy a new palette to assign to surface
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors, 0, originalPalette->ncolors);
}
void SDLImage::resetPalette( int colorID )
{
if(originalPalette == nullptr)
return;
// Always keept the original palette not changed, copy a new palette to assign to surface
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors + colorID, colorID, 1);
}
void SDLImage::setSpecialPallete(const IImage::SpecialPalette & SpecialPalette)
{
if(surf->format->palette)
{
CSDL_Ext::setColors(surf, const_cast<SDL_Color *>(SpecialPalette.data()), 1, 7);
}
}
SDLImage::~SDLImage()
{
SDL_FreeSurface(surf);
if(originalPalette != nullptr)
{
SDL_FreePalette(originalPalette);
originalPalette = nullptr;
}
}

View File

@ -0,0 +1,79 @@
/*
* SDLImage.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
*
*/
#pragma once
#include "../render/IImage.h"
#include "../../lib/Point.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
VCMI_LIB_NAMESPACE_END
class CDefFile;
struct SDL_Surface;
struct SDL_Palette;
/*
* Wrapper around SDL_Surface
*/
class SDLImage : public IImage
{
public:
const static int DEFAULT_PALETTE_COLORS = 256;
//Surface without empty borders
SDL_Surface * surf;
//size of left and top borders
Point margins;
//total size including borders
Point fullSize;
public:
//Load image from def file
SDLImage(CDefFile *data, size_t frame, size_t group=0);
//Load from bitmap file
SDLImage(std::string filename);
SDLImage(const JsonNode & conf);
//Create using existing surface, extraRef will increase refcount on SDL_Surface
SDLImage(SDL_Surface * from, bool extraRef);
~SDLImage();
// Keep the original palette, in order to do color switching operation
void savePalette();
void draw(SDL_Surface * where, int posX=0, int posY=0, const Rect *src=nullptr) const override;
void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const override;
std::shared_ptr<IImage> scaleFast(const Point & size) const override;
void exportBitmap(const boost::filesystem::path & path) const override;
void playerColored(PlayerColor player) override;
void setFlagColor(PlayerColor player) override;
bool isTransparent(const Point & coords) const override;
Point dimensions() const override;
void horizontalFlip() override;
void verticalFlip() override;
void shiftPalette(int from, int howMany) override;
void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) override;
void resetPalette(int colorID) override;
void resetPalette() override;
void setAlpha(uint8_t value) override;
void setSpecialPallete(const SpecialPalette & SpecialPalette) override;
friend class SDLImageLoader;
private:
SDL_Palette * originalPalette;
};

View File

@ -0,0 +1,74 @@
/*
* SDLImageLoader.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
*
*/
#include "StdInc.h"
#include "SDLImageLoader.h"
#include "SDLImage.h"
#include "../../lib/Point.h"
#include <SDL_surface.h>
SDLImageLoader::SDLImageLoader(SDLImage * Img):
image(Img),
lineStart(nullptr),
position(nullptr)
{
}
void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal)
{
//Init image
image->surf = SDL_CreateRGBSurface(0, SpriteSize.x, SpriteSize.y, 8, 0, 0, 0, 0);
image->margins = Margins;
image->fullSize = FullSize;
//Prepare surface
SDL_Palette * p = SDL_AllocPalette(SDLImage::DEFAULT_PALETTE_COLORS);
SDL_SetPaletteColors(p, pal, 0, SDLImage::DEFAULT_PALETTE_COLORS);
SDL_SetSurfacePalette(image->surf, p);
SDL_FreePalette(p);
SDL_LockSurface(image->surf);
lineStart = position = (ui8*)image->surf->pixels;
}
inline void SDLImageLoader::load(size_t size, const ui8 * data)
{
if (size)
{
memcpy((void *)position, data, size);
position += size;
}
}
inline void SDLImageLoader::load(size_t size, ui8 color)
{
if (size)
{
memset((void *)position, color, size);
position += size;
}
}
inline void SDLImageLoader::endLine()
{
lineStart += image->surf->pitch;
position = lineStart;
}
SDLImageLoader::~SDLImageLoader()
{
SDL_UnlockSurface(image->surf);
SDL_SetColorKey(image->surf, SDL_TRUE, 0);
//TODO: RLE if compressed and bpp>1
}

View File

@ -0,0 +1,32 @@
/*
* SDLImageLoader.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
*
*/
#pragma once
#include "../render/IImageLoader.h"
class SDLImageLoader : public IImageLoader
{
SDLImage * image;
ui8 * lineStart;
ui8 * position;
public:
//load size raw pixels from data
void load(size_t size, const ui8 * data);
//set size pixels to color
void load(size_t size, ui8 color=0);
void endLine();
//init image with these sizes and palette
void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal);
SDLImageLoader(SDLImage * Img);
~SDLImageLoader();
};

View File

@ -10,7 +10,9 @@
#include "StdInc.h"
#include "SDLRWwrapper.h"
#include "../lib/filesystem/CInputStream.h"
#include "../../lib/filesystem/CInputStream.h"
#include <SDL_rwops.h>
static inline CInputStream* get_stream(SDL_RWops* context)

View File

@ -9,14 +9,11 @@
*/
#include "StdInc.h"
#include "SDL_Extensions.h"
#include "SDL_PixelAccess.h"
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../Graphics.h"
#include "../CMT.h"
#include "../render/Graphics.h"
#include <SDL_version.h>
#include <SDL_render.h>
#include <SDL_video.h>
#include <SDL_events.h>

File diff suppressed because it is too large Load Diff

View File

@ -1,430 +0,0 @@
/*
* AdventureMapClasses.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
*
*/
#pragma once
#include "ObjectLists.h"
#include "../../lib/FunctionList.h"
VCMI_LIB_NAMESPACE_BEGIN
class CArmedInstance;
class CGGarrison;
class CGObjectInstance;
class CGHeroInstance;
class CGTownInstance;
struct Component;
struct InfoAboutArmy;
struct InfoAboutHero;
struct InfoAboutTown;
VCMI_LIB_NAMESPACE_END
class CAnimation;
class CAnimImage;
class CShowableAnim;
class CFilledTexture;
class CButton;
class CComponent;
class CHeroTooltip;
class CTownTooltip;
class CTextBox;
class IImage;
/// Base UI Element for hero\town lists
class CList : public CIntObject
{
protected:
class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
{
CList * parent;
std::shared_ptr<CIntObject> selection;
public:
CListItem(CList * parent);
~CListItem();
void clickRight(tribool down, bool previousState) override;
void clickLeft(tribool down, bool previousState) override;
void hover(bool on) override;
void onSelect(bool on);
/// create object with selection rectangle
virtual std::shared_ptr<CIntObject> genSelection()=0;
/// reaction on item selection (e.g. enable selection border)
/// NOTE: item may be deleted in selected state
virtual void select(bool on)=0;
/// open item (town or hero screen)
virtual void open()=0;
/// show right-click tooltip
virtual void showTooltip()=0;
/// get hover text for status bar
virtual std::string getHoverText()=0;
};
std::shared_ptr<CListBox> listBox;
const size_t size;
/**
* @brief CList - protected constructor
* @param size - maximal amount of visible at once items
* @param position - cordinates
* @param btnUp - path to image to use as top button
* @param btnDown - path to image to use as bottom button
* @param listAmount - amount of items in the list
* @param helpUp - index in zelp.txt for button help tooltip
* @param helpDown - index in zelp.txt for button help tooltip
* @param create - function for creating items in listbox
* @param destroy - function for deleting items in listbox
*/
CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create);
//for selection\deselection
std::shared_ptr<CListItem> selected;
void select(std::shared_ptr<CListItem> which);
friend class CListItem;
std::shared_ptr<CButton> scrollUp;
std::shared_ptr<CButton> scrollDown;
/// should be called when list is invalidated
void update();
public:
/// functions that will be called when selection changes
CFunctionList<void()> onSelect;
/// return index of currently selected element
int getSelectedIndex();
/// set of methods to switch selection
void selectIndex(int which);
void selectNext();
void selectPrev();
};
/// List of heroes which is shown at the right of the adventure map screen
class CHeroList : public CList
{
/// Empty hero item used as placeholder for unused entries in list
class CEmptyHeroItem : public CIntObject
{
std::shared_ptr<CAnimImage> movement;
std::shared_ptr<CAnimImage> mana;
std::shared_ptr<CPicture> portrait;
public:
CEmptyHeroItem();
};
class CHeroItem : public CListItem
{
std::shared_ptr<CAnimImage> movement;
std::shared_ptr<CAnimImage> mana;
std::shared_ptr<CAnimImage> portrait;
public:
const CGHeroInstance * const hero;
CHeroItem(CHeroList * parent, const CGHeroInstance * hero);
std::shared_ptr<CIntObject> genSelection() override;
void update();
void select(bool on) override;
void open() override;
void showTooltip() override;
std::string getHoverText() override;
};
std::shared_ptr<CIntObject> createHeroItem(size_t index);
public:
/**
* @brief CHeroList
* @param size, position, btnUp, btnDown @see CList::CList
*/
CHeroList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific hero and scroll if needed
void select(const CGHeroInstance * hero = nullptr);
/// Update hero. Will add or remove it from the list if needed
void update(const CGHeroInstance * hero = nullptr);
};
/// List of towns which is shown at the right of the adventure map screen or in the town screen
class CTownList : public CList
{
class CTownItem : public CListItem
{
std::shared_ptr<CAnimImage> picture;
public:
const CGTownInstance * const town;
CTownItem(CTownList *parent, const CGTownInstance * town);
std::shared_ptr<CIntObject> genSelection() override;
void update();
void select(bool on) override;
void open() override;
void showTooltip() override;
std::string getHoverText() override;
};
std::shared_ptr<CIntObject> createTownItem(size_t index);
public:
/**
* @brief CTownList
* @param size, position, btnUp, btnDown @see CList::CList
*/
CTownList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific town and scroll if needed
void select(const CGTownInstance * town = nullptr);
/// Update town. Will add or remove it from the list if needed
void update(const CGTownInstance * town = nullptr);
};
class CMinimap;
class CMinimapInstance : public CIntObject
{
CMinimap * parent;
SDL_Surface * minimap;
int level;
//get color of selected tile on minimap
const SDL_Color & getTileColor(const int3 & pos);
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
//draw minimap already scaled.
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
void drawScaled(int level);
public:
CMinimapInstance(CMinimap * parent, int level);
~CMinimapInstance();
void showAll(SDL_Surface * to) override;
void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
void refreshTile(const int3 & pos);
};
/// Minimap which is displayed at the right upper corner of adventure map
class CMinimap : public CIntObject
{
protected:
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
std::shared_ptr<CMinimapInstance> minimap;
int level;
//to initialize colors
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > loadColors();
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover (bool on) override;
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
void moveAdvMapSelection();
public:
// terrainID -> (normal color, blocked color)
const std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > colors;
CMinimap(const Rect & position);
//should be called to invalidate whole map - different player or level
int3 translateMousePosition();
void update();
void setLevel(int level);
void setAIRadar(bool on);
void showAll(SDL_Surface * to) override;
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
};
/// Info box which shows next week/day information, hold the current date
class CInfoBar : public CIntObject
{
//all visible information located in one object - for ease of replacing
class CVisibleInfo : public CIntObject
{
public:
void show(SDL_Surface * to) override;
protected:
std::shared_ptr<CPicture> background;
std::list<std::shared_ptr<CIntObject>> forceRefresh;
CVisibleInfo();
};
class EmptyVisibleInfo : public CVisibleInfo
{
public:
EmptyVisibleInfo();
};
class VisibleHeroInfo : public CVisibleInfo
{
std::shared_ptr<CHeroTooltip> heroTooltip;
public:
VisibleHeroInfo(const CGHeroInstance * hero);
};
class VisibleTownInfo : public CVisibleInfo
{
std::shared_ptr<CTownTooltip> townTooltip;
public:
VisibleTownInfo(const CGTownInstance * town);
};
class VisibleDateInfo : public CVisibleInfo
{
std::shared_ptr<CShowableAnim> animation;
std::shared_ptr<CLabel> label;
std::string getNewDayName();
public:
VisibleDateInfo();
};
class VisibleEnemyTurnInfo : public CVisibleInfo
{
std::shared_ptr<CAnimImage> banner;
std::shared_ptr<CShowableAnim> glass;
std::shared_ptr<CShowableAnim> sand;
public:
VisibleEnemyTurnInfo(PlayerColor player);
};
class VisibleGameStatusInfo : public CVisibleInfo
{
std::shared_ptr<CLabel> allyLabel;
std::shared_ptr<CLabel> enemyLabel;
std::vector<std::shared_ptr<CAnimImage>> flags;
std::vector<std::shared_ptr<CAnimImage>> hallIcons;
std::vector<std::shared_ptr<CLabel>> hallLabels;
public:
VisibleGameStatusInfo();
};
class VisibleComponentInfo : public CVisibleInfo
{
std::shared_ptr<CComponent> comp;
std::shared_ptr<CTextBox> text;
public:
VisibleComponentInfo(const Component & compToDisplay, std::string message);
};
enum EState
{
EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT
};
std::shared_ptr<CVisibleInfo> visibleInfo;
EState state;
//removes all information about current state, deactivates timer (if any)
void reset();
void tick() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover(bool on) override;
void playNewDaySound();
public:
CInfoBar(const Rect & pos);
/// show new day/week animation
void showDate();
/// show component for 3 seconds. Used to display picked up resources
void showComponent(const Component & comp, std::string message);
/// print enemy turn progress
void startEnemyTurn(PlayerColor color);
/// reset to default view - selected object
void showSelection();
/// show hero\town information
void showHeroSelection(const CGHeroInstance * hero);
void showTownSelection(const CGTownInstance * town);
/// for 3 seconds shows amount of town halls and players status
void showGameStatus();
};
/// simple panel that contains other displayable elements; used to separate groups of controls
class CAdvMapPanel : public CIntObject
{
std::vector<std::shared_ptr<CButton>> colorableButtons;
std::vector<std::shared_ptr<CIntObject>> otherObjects;
/// the surface passed to this obj will be freed in dtor
std::shared_ptr<IImage> background;
public:
CAdvMapPanel(std::shared_ptr<IImage> bg, Point position);
void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
void addChildColorableButton(std::shared_ptr<CButton> button);
/// recolors all buttons to given player color
void setPlayerColor(const PlayerColor & clr);
void showAll(SDL_Surface * to) override;
};
/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
class CAdvMapWorldViewPanel : public CAdvMapPanel
{
/// data that allows reconstruction of panel info icons
std::vector<std::pair<int, Point>> iconsData;
/// ptrs to child-pictures constructed from iconsData
std::vector<std::shared_ptr<CAnimImage>> currentIcons;
/// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
std::shared_ptr<CFilledTexture> backgroundFiller;
std::shared_ptr<CAnimation> icons;
public:
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
virtual ~CAdvMapWorldViewPanel();
void addChildIcon(std::pair<int, Point> data, int indexOffset);
/// recreates all pictures from given def to recolor them according to current player color
void recolorIcons(const PlayerColor & color, int indexOffset);
};
class CInGameConsole : public CIntObject
{
private:
std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add>
boost::mutex texts_mx; // protects texts
std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work
int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1
int defaultTimeout; //timeout for new texts (in ms)
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
std::weak_ptr<IStatusBar> currentStatusBar;
public:
std::string enteredText;
void show(SDL_Surface * to) override;
void print(const std::string &txt);
void keyPressed (const SDL_KeyboardEvent & key) override; //call-in
void textInputed(const SDL_TextInputEvent & event) override;
void textEdited(const SDL_TextEditingEvent & event) override;
void startEnteringText();
void endEnteringText(bool processEnteredText);
void refreshEnteredText();
CInGameConsole();
};

View File

@ -18,9 +18,10 @@
#include "../CPlayerInterface.h"
#include "../battle/BattleInterface.h"
#include "../battle/BattleInterfaceClasses.h"
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../windows/InfoWindows.h"
#include "../render/CAnimation.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"

Some files were not shown because too many files have changed in this diff Show More