diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 0b3bd919d..0996c81d9 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -11,6 +11,7 @@ set(client_SRCS battle/CBattleInterface.cpp battle/CBattleObstacleController.cpp battle/CBattleProjectileController.cpp + battle/CBattleRenderer.cpp battle/CBattleSiegeController.cpp battle/CBattleStacksController.cpp battle/CCreatureAnimation.cpp @@ -93,6 +94,7 @@ set(client_HEADERS battle/CBattleInterface.h battle/CBattleObstacleController.h battle/CBattleProjectileController.h + battle/CBattleRenderer.h battle/CBattleSiegeController.h battle/CBattleStacksController.h battle/CCreatureAnimation.h diff --git a/client/battle/CBattleEffectsController.cpp b/client/battle/CBattleEffectsController.cpp index 9441c0f48..cc1691b9b 100644 --- a/client/battle/CBattleEffectsController.cpp +++ b/client/battle/CBattleEffectsController.cpp @@ -16,6 +16,7 @@ #include "CBattleInterfaceClasses.h" #include "CBattleFieldController.h" #include "CBattleStacksController.h" +#include "CBattleRenderer.h" #include "../CMusicHandler.h" #include "../CGameInfo.h" @@ -122,11 +123,11 @@ void CBattleEffectsController::startAction(const BattleAction* action) } } -void CBattleEffectsController::collectRenderableObjects(CBattleFieldRenderer & renderer) +void CBattleEffectsController::collectRenderableObjects(CBattleRenderer & renderer) { for (auto & elem : battleEffects) { - renderer.insert( EBattleFieldLayer::EFFECTS, elem.position, [&elem](CBattleFieldRenderer::RendererPtr canvas) + renderer.insert( EBattleFieldLayer::EFFECTS, elem.position, [&elem](CBattleRenderer::RendererPtr canvas) { int currentFrame = static_cast(floor(elem.currentFrame)); currentFrame %= elem.animation->size(); diff --git a/client/battle/CBattleEffectsController.h b/client/battle/CBattleEffectsController.h index 8df53f091..5318dadb2 100644 --- a/client/battle/CBattleEffectsController.h +++ b/client/battle/CBattleEffectsController.h @@ -23,7 +23,7 @@ struct SDL_Surface; class CAnimation; class CCanvas; class CBattleInterface; -class CBattleFieldRenderer; +class CBattleRenderer; class CPointEffectAnimation; namespace EBattleEffect @@ -78,7 +78,7 @@ public: void battleTriggerEffect(const BattleTriggerEffect & bte); - void collectRenderableObjects(CBattleFieldRenderer & renderer); + void collectRenderableObjects(CBattleRenderer & renderer); friend class CPointEffectAnimation; }; diff --git a/client/battle/CBattleFieldController.cpp b/client/battle/CBattleFieldController.cpp index 72ffc16e4..fde72f597 100644 --- a/client/battle/CBattleFieldController.cpp +++ b/client/battle/CBattleFieldController.cpp @@ -18,6 +18,7 @@ #include "CBattleStacksController.h" #include "CBattleObstacleController.h" #include "CBattleProjectileController.h" +#include "CBattleRenderer.h" #include "../CGameInfo.h" #include "../CPlayerInterface.h" @@ -92,7 +93,7 @@ void CBattleFieldController::renderBattlefield(std::shared_ptr canvas) { showBackground(canvas); - CBattleFieldRenderer renderer(owner); + CBattleRenderer renderer(owner); renderer.execute(canvas); @@ -631,62 +632,3 @@ bool CBattleFieldController::stackCountOutsideHex(const BattleHex & number) cons { return stackCountOutsideHexes[number]; } - -void CBattleFieldRenderer::collectObjects() -{ - owner->collectRenderableObjects(*this); - owner->effectsController->collectRenderableObjects(*this); - owner->obstacleController->collectRenderableObjects(*this); - owner->siegeController->collectRenderableObjects(*this); - owner->stacksController->collectRenderableObjects(*this); -} - -void CBattleFieldRenderer::sortObjects() -{ - auto getRow = [](const RenderableInstance & object) -> int - { - if (object.tile.isValid()) - return object.tile.getY(); - - if ( object.tile == BattleHex::HEX_BEFORE_ALL ) - return -1; - - if ( object.tile == BattleHex::HEX_AFTER_ALL ) - return GameConstants::BFIELD_HEIGHT; - - if ( object.tile == BattleHex::INVALID ) - return GameConstants::BFIELD_HEIGHT; - - assert(0); - return GameConstants::BFIELD_HEIGHT; - }; - - std::stable_sort(objects.begin(), objects.end(), [&](const RenderableInstance & left, const RenderableInstance & right){ - if ( getRow(left) != getRow(right)) - return getRow(left) < getRow(right); - return left.layer < right.layer; - }); -} - -void CBattleFieldRenderer::renderObjects(CBattleFieldRenderer::RendererPtr targetCanvas) -{ - for (auto const & object : objects) - object.functor(targetCanvas); -} - -CBattleFieldRenderer::CBattleFieldRenderer(CBattleInterface * owner): - owner(owner) -{ -} - -void CBattleFieldRenderer::insert(EBattleFieldLayer layer, BattleHex tile, CBattleFieldRenderer::RenderFunctor functor) -{ - objects.push_back({ functor, layer, tile }); -} - -void CBattleFieldRenderer::execute(CBattleFieldRenderer::RendererPtr targetCanvas) -{ - collectObjects(); - sortObjects(); - renderObjects(targetCanvas); -} diff --git a/client/battle/CBattleFieldController.h b/client/battle/CBattleFieldController.h index 2961377d2..24317b7ef 100644 --- a/client/battle/CBattleFieldController.h +++ b/client/battle/CBattleFieldController.h @@ -27,45 +27,6 @@ class CCanvas; class IImage; class CBattleInterface; -enum class EBattleFieldLayer { - // confirmed ordering requirements: - OBSTACLES = 0, - CORPSES = 0, - WALLS = 1, - HEROES = 1, - STACKS = 1, // after corpses, obstacles - BATTLEMENTS = 2, // after stacks - STACK_AMOUNTS = 2, // after stacks, obstacles, corpses - EFFECTS = 3, // after obstacles, battlements -}; - -class CBattleFieldRenderer -{ -public: - using RendererPtr = std::shared_ptr; - using RenderFunctor = std::function; - -private: - CBattleInterface * owner; - - struct RenderableInstance - { - RenderFunctor functor; - EBattleFieldLayer layer; - BattleHex tile; - }; - std::vector objects; - - void collectObjects(); - void sortObjects(); - void renderObjects(RendererPtr targetCanvas); -public: - CBattleFieldRenderer(CBattleInterface * owner); - - void insert(EBattleFieldLayer layer, BattleHex tile, RenderFunctor functor); - void execute(RendererPtr targetCanvas); -}; - class CBattleFieldController : public CIntObject { CBattleInterface * owner; diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index a30165d10..5ec5f438d 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -21,6 +21,7 @@ #include "CBattleFieldController.h" #include "CBattleControlPanel.h" #include "CBattleStacksController.h" +#include "CBattleRenderer.h" #include "../CGameInfo.h" #include "../CMessage.h" @@ -913,18 +914,18 @@ void CBattleInterface::show(SDL_Surface *to) //activateStack(); } -void CBattleInterface::collectRenderableObjects(CBattleFieldRenderer & renderer) +void CBattleInterface::collectRenderableObjects(CBattleRenderer & renderer) { if (attackingHero) { - renderer.insert(EBattleFieldLayer::HEROES, BattleHex(0),[this](CBattleFieldRenderer::RendererPtr canvas) + renderer.insert(EBattleFieldLayer::HEROES, BattleHex(0),[this](CBattleRenderer::RendererPtr canvas) { attackingHero->show(canvas->getSurface()); }); } if (defendingHero) { - renderer.insert(EBattleFieldLayer::HEROES, BattleHex(GameConstants::BFIELD_WIDTH-1),[this](CBattleFieldRenderer::RendererPtr canvas) + renderer.insert(EBattleFieldLayer::HEROES, BattleHex(GameConstants::BFIELD_WIDTH-1),[this](CBattleRenderer::RendererPtr canvas) { defendingHero->show(canvas->getSurface()); }); diff --git a/client/battle/CBattleInterface.h b/client/battle/CBattleInterface.h index 1069941d3..e824a6ce5 100644 --- a/client/battle/CBattleInterface.h +++ b/client/battle/CBattleInterface.h @@ -47,7 +47,7 @@ class CBattleProjectileController; class CBattleSiegeController; class CBattleObstacleController; class CBattleFieldController; -class CBattleFieldRenderer; +class CBattleRenderer; class CBattleControlPanel; class CBattleStacksController; class CBattleActionsController; @@ -143,7 +143,7 @@ public: void show(SDL_Surface *to) override; void showAll(SDL_Surface *to) override; - void collectRenderableObjects(CBattleFieldRenderer & renderer); + void collectRenderableObjects(CBattleRenderer & renderer); //call-ins void startAction(const BattleAction* action); diff --git a/client/battle/CBattleObstacleController.cpp b/client/battle/CBattleObstacleController.cpp index 90f7f3cc1..7a48dc1ce 100644 --- a/client/battle/CBattleObstacleController.cpp +++ b/client/battle/CBattleObstacleController.cpp @@ -14,6 +14,7 @@ #include "CBattleFieldController.h" #include "CBattleAnimations.h" #include "CBattleStacksController.h" +#include "CBattleRenderer.h" #include "../CPlayerInterface.h" #include "../gui/CAnimation.h" @@ -126,7 +127,7 @@ void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr c } } -void CBattleObstacleController::collectRenderableObjects(CBattleFieldRenderer & renderer) +void CBattleObstacleController::collectRenderableObjects(CBattleRenderer & renderer) { for (auto obstacle : owner->curInt->cb->battleGetAllObstacles()) { @@ -136,7 +137,7 @@ void CBattleObstacleController::collectRenderableObjects(CBattleFieldRenderer & if (obstacle->obstacleType == CObstacleInstance::MOAT) continue; - renderer.insert(EBattleFieldLayer::OBSTACLES, obstacle->pos, [this, obstacle]( CBattleFieldRenderer::RendererPtr canvas ){ + renderer.insert(EBattleFieldLayer::OBSTACLES, obstacle->pos, [this, obstacle]( CBattleRenderer::RendererPtr canvas ){ auto img = getObstacleImage(*obstacle); if(img) { diff --git a/client/battle/CBattleObstacleController.h b/client/battle/CBattleObstacleController.h index 586a68300..b4914fa8e 100644 --- a/client/battle/CBattleObstacleController.h +++ b/client/battle/CBattleObstacleController.h @@ -21,7 +21,7 @@ class IImage; class CCanvas; class CAnimation; class CBattleInterface; -class CBattleFieldRenderer; +class CBattleRenderer; struct Point; class CBattleObstacleController @@ -48,5 +48,5 @@ public: void showObstacles(SDL_Surface *to, std::vector> &obstacles); void showAbsoluteObstacles(std::shared_ptr canvas, const Point & offset); - void collectRenderableObjects(CBattleFieldRenderer & renderer); + void collectRenderableObjects(CBattleRenderer & renderer); }; diff --git a/client/battle/CBattleRenderer.cpp b/client/battle/CBattleRenderer.cpp new file mode 100644 index 000000000..10e834be9 --- /dev/null +++ b/client/battle/CBattleRenderer.cpp @@ -0,0 +1,77 @@ +/* + * CBattleFieldController.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 "CBattleRenderer.h" + +#include "CBattleInterface.h" + +#include "CBattleEffectsController.h" +#include "CBattleSiegeController.h" +#include "CBattleStacksController.h" +#include "CBattleObstacleController.h" + +void CBattleRenderer::collectObjects() +{ + owner->collectRenderableObjects(*this); + owner->effectsController->collectRenderableObjects(*this); + owner->obstacleController->collectRenderableObjects(*this); + owner->siegeController->collectRenderableObjects(*this); + owner->stacksController->collectRenderableObjects(*this); +} + +void CBattleRenderer::sortObjects() +{ + auto getRow = [](const RenderableInstance & object) -> int + { + if (object.tile.isValid()) + return object.tile.getY(); + + if ( object.tile == BattleHex::HEX_BEFORE_ALL ) + return -1; + + if ( object.tile == BattleHex::HEX_AFTER_ALL ) + return GameConstants::BFIELD_HEIGHT; + + if ( object.tile == BattleHex::INVALID ) + return GameConstants::BFIELD_HEIGHT; + + assert(0); + return GameConstants::BFIELD_HEIGHT; + }; + + std::stable_sort(objects.begin(), objects.end(), [&](const RenderableInstance & left, const RenderableInstance & right){ + if ( getRow(left) != getRow(right)) + return getRow(left) < getRow(right); + return left.layer < right.layer; + }); +} + +void CBattleRenderer::renderObjects(CBattleRenderer::RendererPtr targetCanvas) +{ + for (auto const & object : objects) + object.functor(targetCanvas); +} + +CBattleRenderer::CBattleRenderer(CBattleInterface * owner): + owner(owner) +{ +} + +void CBattleRenderer::insert(EBattleFieldLayer layer, BattleHex tile, CBattleRenderer::RenderFunctor functor) +{ + objects.push_back({ functor, layer, tile }); +} + +void CBattleRenderer::execute(CBattleRenderer::RendererPtr targetCanvas) +{ + collectObjects(); + sortObjects(); + renderObjects(targetCanvas); +} diff --git a/client/battle/CBattleRenderer.h b/client/battle/CBattleRenderer.h new file mode 100644 index 000000000..6db70ab2f --- /dev/null +++ b/client/battle/CBattleRenderer.h @@ -0,0 +1,66 @@ +/* + * CBattleFieldController.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/battle/BattleHex.h" + +VCMI_LIB_NAMESPACE_BEGIN + +//class CStack; + +VCMI_LIB_NAMESPACE_END + +//struct SDL_Surface; +//struct Rect; +//struct Point; +// +//class CClickableHex; +class CCanvas; +//class IImage; +class CBattleInterface; + +enum class EBattleFieldLayer { + // confirmed ordering requirements: + OBSTACLES = 0, + CORPSES = 0, + WALLS = 1, + HEROES = 1, + STACKS = 1, // after corpses, obstacles + BATTLEMENTS = 2, // after stacks + STACK_AMOUNTS = 2, // after stacks, obstacles, corpses + EFFECTS = 3, // after obstacles, battlements +}; + +class CBattleRenderer +{ +public: + using RendererPtr = std::shared_ptr; + using RenderFunctor = std::function; + +private: + CBattleInterface * owner; + + struct RenderableInstance + { + RenderFunctor functor; + EBattleFieldLayer layer; + BattleHex tile; + }; + std::vector objects; + + void collectObjects(); + void sortObjects(); + void renderObjects(RendererPtr targetCanvas); +public: + CBattleRenderer(CBattleInterface * owner); + + void insert(EBattleFieldLayer layer, BattleHex tile, RenderFunctor functor); + void execute(RendererPtr targetCanvas); +}; diff --git a/client/battle/CBattleSiegeController.cpp b/client/battle/CBattleSiegeController.cpp index d95f0b7c4..dfa184ba1 100644 --- a/client/battle/CBattleSiegeController.cpp +++ b/client/battle/CBattleSiegeController.cpp @@ -15,6 +15,7 @@ #include "CBattleInterfaceClasses.h" #include "CBattleStacksController.h" #include "CBattleFieldController.h" +#include "CBattleRenderer.h" #include "../CMusicHandler.h" #include "../CGameInfo.h" @@ -280,7 +281,7 @@ const CStack * CBattleSiegeController::getTurretStack(EWallVisual::EWallVisual w return nullptr; } -void CBattleSiegeController::collectRenderableObjects(CBattleFieldRenderer & renderer) +void CBattleSiegeController::collectRenderableObjects(CBattleRenderer & renderer) { for (int i = EWallVisual::WALL_FIRST; i <= EWallVisual::WALL_LAST; ++i) { @@ -296,14 +297,14 @@ void CBattleSiegeController::collectRenderableObjects(CBattleFieldRenderer & ren wallPiece == EWallVisual::BOTTOM_BATTLEMENT || wallPiece == EWallVisual::UPPER_BATTLEMENT) { - renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ + renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleRenderer::RendererPtr canvas){ owner->stacksController->showStack(canvas, getTurretStack(wallPiece)); }); - renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ + renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleRenderer::RendererPtr canvas){ showWallPiece(canvas, wallPiece, owner->pos.topLeft()); }); } - renderer.insert( EBattleFieldLayer::WALLS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ + renderer.insert( EBattleFieldLayer::WALLS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleRenderer::RendererPtr canvas){ showWallPiece(canvas, wallPiece, owner->pos.topLeft()); }); diff --git a/client/battle/CBattleSiegeController.h b/client/battle/CBattleSiegeController.h index 01f2e328e..886f8995e 100644 --- a/client/battle/CBattleSiegeController.h +++ b/client/battle/CBattleSiegeController.h @@ -25,7 +25,7 @@ struct Point; struct SDL_Surface; class CCanvas; class CBattleInterface; -class CBattleFieldRenderer; +class CBattleRenderer; class IImage; namespace EWallVisual @@ -99,7 +99,7 @@ public: /// call-ins from other battle controllers void showAbsoluteObstacles(std::shared_ptr canvas, const Point & offset); - void collectRenderableObjects(CBattleFieldRenderer & renderer); + void collectRenderableObjects(CBattleRenderer & renderer); /// queries from other battle controllers bool isAttackableByCatapult(BattleHex hex) const; diff --git a/client/battle/CBattleStacksController.cpp b/client/battle/CBattleStacksController.cpp index 155e6a8b8..7afce86cc 100644 --- a/client/battle/CBattleStacksController.cpp +++ b/client/battle/CBattleStacksController.cpp @@ -18,6 +18,7 @@ #include "CBattleEffectsController.h" #include "CBattleProjectileController.h" #include "CBattleControlPanel.h" +#include "CBattleRenderer.h" #include "CCreatureAnimation.h" @@ -116,7 +117,7 @@ BattleHex CBattleStacksController::getStackCurrentPosition(const CStack * stack) return stack->getPosition(); } -void CBattleStacksController::collectRenderableObjects(CBattleFieldRenderer & renderer) +void CBattleStacksController::collectRenderableObjects(CBattleRenderer & renderer) { auto stacks = owner->curInt->cb->battleGetAllStacks(false); @@ -132,13 +133,13 @@ void CBattleStacksController::collectRenderableObjects(CBattleFieldRenderer & re auto layer = stackAnimation[stack->ID]->isDead() ? EBattleFieldLayer::CORPSES : EBattleFieldLayer::STACKS; auto location = getStackCurrentPosition(stack); - renderer.insert(layer, location, [this, stack]( CBattleFieldRenderer::RendererPtr renderer ){ + renderer.insert(layer, location, [this, stack]( CBattleRenderer::RendererPtr renderer ){ showStack(renderer, stack); }); if (stackNeedsAmountBox(stack)) { - renderer.insert(EBattleFieldLayer::STACK_AMOUNTS, location, [this, stack]( CBattleFieldRenderer::RendererPtr renderer ){ + renderer.insert(EBattleFieldLayer::STACK_AMOUNTS, location, [this, stack]( CBattleRenderer::RendererPtr renderer ){ showStackAmountBox(renderer, stack); }); } diff --git a/client/battle/CBattleStacksController.h b/client/battle/CBattleStacksController.h index 01f3482e9..0f4238b60 100644 --- a/client/battle/CBattleStacksController.h +++ b/client/battle/CBattleStacksController.h @@ -28,7 +28,7 @@ class CBattleInterface; class CBattleAnimation; class CCreatureAnimation; class CBattleAnimation; -class CBattleFieldRenderer; +class CBattleRenderer; class IImage; class CBattleStacksController @@ -89,7 +89,7 @@ public: void showAliveStack(std::shared_ptr canvas, const CStack * stack); void showStack(std::shared_ptr canvas, const CStack * stack); - void collectRenderableObjects(CBattleFieldRenderer & renderer); + void collectRenderableObjects(CBattleRenderer & renderer); void addNewAnim(CBattleAnimation *anim); //adds new anim to pendingAnims void updateBattleAnimations();