mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented proper rendering order generation for battlefield objects
This commit is contained in:
		| @@ -14,6 +14,7 @@ | ||||
| #include "CBattleControlPanel.h" | ||||
| #include "CBattleInterface.h" | ||||
| #include "CBattleInterfaceClasses.h" | ||||
| #include "CBattleFieldController.h" | ||||
| #include "CBattleStacksController.h" | ||||
|  | ||||
| #include "../CMusicHandler.h" | ||||
| @@ -121,21 +122,18 @@ void CBattleEffectsController::startAction(const BattleAction* action) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleEffectsController::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & destTile) | ||||
| void CBattleEffectsController::collectRenderableObjects(CBattleFieldRenderer & renderer) | ||||
| { | ||||
| 	for (auto & elem : battleEffects) | ||||
| 	{ | ||||
| 		if (!elem.position.isValid() && destTile != BattleHex::HEX_AFTER_ALL) | ||||
| 			continue; | ||||
| 		renderer.insert( EBattleFieldLayer::EFFECTS, elem.position, [&elem](CBattleFieldRenderer::RendererPtr canvas) | ||||
| 		{ | ||||
| 			int currentFrame = static_cast<int>(floor(elem.currentFrame)); | ||||
| 			currentFrame %= elem.animation->size(); | ||||
|  | ||||
| 		if (elem.position.isValid() && elem.position != destTile) | ||||
| 			continue; | ||||
| 			auto img = elem.animation->getImage(currentFrame); | ||||
|  | ||||
| 		int currentFrame = static_cast<int>(floor(elem.currentFrame)); | ||||
| 		currentFrame %= elem.animation->size(); | ||||
|  | ||||
| 		auto img = elem.animation->getImage(currentFrame); | ||||
|  | ||||
| 		canvas->draw(img, Point(elem.x, elem.y)); | ||||
| 			canvas->draw(img, Point(elem.x, elem.y)); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -23,6 +23,7 @@ struct SDL_Surface; | ||||
| class CAnimation; | ||||
| class CCanvas; | ||||
| class CBattleInterface; | ||||
| class CBattleFieldRenderer; | ||||
| class CPointEffectAnimation; | ||||
|  | ||||
| namespace EBattleEffect | ||||
| @@ -77,7 +78,7 @@ public: | ||||
|  | ||||
| 	void battleTriggerEffect(const BattleTriggerEffect & bte); | ||||
|  | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & destTile); | ||||
| 	void collectRenderableObjects(CBattleFieldRenderer & renderer); | ||||
|  | ||||
| 	friend class CPointEffectAnimation; | ||||
| }; | ||||
|   | ||||
| @@ -13,9 +13,11 @@ | ||||
| #include "CBattleInterface.h" | ||||
| #include "CBattleActionsController.h" | ||||
| #include "CBattleInterfaceClasses.h" | ||||
| #include "CBattleEffectsController.h" | ||||
| #include "CBattleSiegeController.h" | ||||
| #include "CBattleStacksController.h" | ||||
| #include "CBattleObstacleController.h" | ||||
| #include "CBattleProjectileController.h" | ||||
|  | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CPlayerInterface.h" | ||||
| @@ -86,6 +88,17 @@ CBattleFieldController::CBattleFieldController(CBattleInterface * owner): | ||||
| 		stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE); | ||||
| } | ||||
|  | ||||
| void CBattleFieldController::renderBattlefield(std::shared_ptr<CCanvas> canvas) | ||||
| { | ||||
| 	showBackground(canvas); | ||||
|  | ||||
| 	CBattleFieldRenderer renderer(owner); | ||||
|  | ||||
| 	renderer.execute(canvas); | ||||
|  | ||||
| 	owner->projectilesController->showProjectiles(canvas); | ||||
| } | ||||
|  | ||||
| void CBattleFieldController::showBackground(std::shared_ptr<CCanvas> canvas) | ||||
| { | ||||
| 	if (owner->stacksController->getActiveStack() != nullptr ) //&& creAnims[stacksController->getActiveStack()->ID]->isIdle() //show everything with range | ||||
| @@ -618,3 +631,62 @@ 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); | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,45 @@ 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<CCanvas>; | ||||
| 	using RenderFunctor = std::function<void(RendererPtr)>; | ||||
|  | ||||
| private: | ||||
| 	CBattleInterface * owner; | ||||
|  | ||||
| 	struct RenderableInstance | ||||
| 	{ | ||||
| 		RenderFunctor functor; | ||||
| 		EBattleFieldLayer layer; | ||||
| 		BattleHex tile; | ||||
| 	}; | ||||
| 	std::vector<RenderableInstance> 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; | ||||
| @@ -54,6 +93,7 @@ class CBattleFieldController : public CIntObject | ||||
| 	std::set<BattleHex> getHighlightedHexesStackRange(); | ||||
| 	std::set<BattleHex> getHighlightedHexesSpellRange(); | ||||
|  | ||||
| 	void showBackground(std::shared_ptr<CCanvas> canvas); | ||||
| 	void showBackgroundImage(std::shared_ptr<CCanvas> canvas); | ||||
| 	void showBackgroundImageWithHexes(std::shared_ptr<CCanvas> canvas); | ||||
| 	void showHighlightedHexes(std::shared_ptr<CCanvas> canvas); | ||||
| @@ -61,9 +101,8 @@ class CBattleFieldController : public CIntObject | ||||
| public: | ||||
| 	CBattleFieldController(CBattleInterface * owner); | ||||
|  | ||||
| 	void showBackground(std::shared_ptr<CCanvas> canvas); | ||||
|  | ||||
| 	void redrawBackgroundWithHexes(); | ||||
| 	void renderBattlefield(std::shared_ptr<CCanvas> canvas); | ||||
|  | ||||
| 	Rect hexPositionLocal(BattleHex hex) const; | ||||
| 	Rect hexPosition(BattleHex hex) const; | ||||
|   | ||||
| @@ -899,9 +899,7 @@ void CBattleInterface::show(SDL_Surface *to) | ||||
|  | ||||
| 	++animCount; | ||||
|  | ||||
| 	fieldController->showBackground(canvas); | ||||
| 	showBattlefieldObjects(canvas); | ||||
| 	projectilesController->showProjectiles(canvas); | ||||
| 	fieldController->renderBattlefield(canvas); | ||||
|  | ||||
| 	if(battleActionsStarted) | ||||
| 		stacksController->updateBattleAnimations(); | ||||
| @@ -915,29 +913,22 @@ void CBattleInterface::show(SDL_Surface *to) | ||||
| 	//activateStack(); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ) | ||||
| void CBattleInterface::collectRenderableObjects(CBattleFieldRenderer & renderer) | ||||
| { | ||||
| 	if (siegeController) | ||||
| 		siegeController->showBattlefieldObjects(canvas, location); | ||||
| 	obstacleController->showBattlefieldObjects(canvas, location); | ||||
| 	stacksController->showBattlefieldObjects(canvas, location); | ||||
| 	effectsController->showBattlefieldObjects(canvas, location); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas) | ||||
| { | ||||
| 	showBattlefieldObjects(canvas, BattleHex::HEX_BEFORE_ALL); | ||||
|  | ||||
| 	// show heroes after "beforeAll" - e.g. topmost wall in siege | ||||
| 	if (attackingHero) | ||||
| 		attackingHero->show(canvas->getSurface()); | ||||
| 	{ | ||||
| 		renderer.insert(EBattleFieldLayer::HEROES, BattleHex(0),[this](CBattleFieldRenderer::RendererPtr canvas) | ||||
| 		{ | ||||
| 			attackingHero->show(canvas->getSurface()); | ||||
| 		}); | ||||
| 	} | ||||
| 	if (defendingHero) | ||||
| 		defendingHero->show(canvas->getSurface()); | ||||
|  | ||||
| 	for (int i = 0; i < GameConstants::BFIELD_SIZE; ++i) | ||||
| 		showBattlefieldObjects(canvas, BattleHex(i)); | ||||
|  | ||||
| 	showBattlefieldObjects(canvas, BattleHex::HEX_AFTER_ALL); | ||||
| 	{ | ||||
| 		renderer.insert(EBattleFieldLayer::HEROES, BattleHex(GameConstants::BFIELD_WIDTH-1),[this](CBattleFieldRenderer::RendererPtr canvas) | ||||
| 		{ | ||||
| 			defendingHero->show(canvas->getSurface()); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::showInterface(std::shared_ptr<CCanvas> canvas) | ||||
|   | ||||
| @@ -47,6 +47,7 @@ class CBattleProjectileController; | ||||
| class CBattleSiegeController; | ||||
| class CBattleObstacleController; | ||||
| class CBattleFieldController; | ||||
| class CBattleFieldRenderer; | ||||
| class CBattleControlPanel; | ||||
| class CBattleStacksController; | ||||
| class CBattleActionsController; | ||||
| @@ -99,9 +100,6 @@ private: | ||||
|  | ||||
| 	void showInterface(std::shared_ptr<CCanvas> canvas); | ||||
|  | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas); | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ); | ||||
|  | ||||
| 	void setHeroAnimation(ui8 side, int phase); | ||||
| public: | ||||
| 	std::unique_ptr<CBattleProjectileController> projectilesController; | ||||
| @@ -145,6 +143,8 @@ public: | ||||
| 	void show(SDL_Surface *to) override; | ||||
| 	void showAll(SDL_Surface *to) override; | ||||
|  | ||||
| 	void collectRenderableObjects(CBattleFieldRenderer & renderer); | ||||
|  | ||||
| 	//call-ins | ||||
| 	void startAction(const BattleAction* action); | ||||
| 	void stackReset(const CStack * stack); | ||||
|   | ||||
| @@ -126,9 +126,9 @@ void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr<CCanvas> c | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleObstacleController::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ) | ||||
| void CBattleObstacleController::collectRenderableObjects(CBattleFieldRenderer & renderer) | ||||
| { | ||||
| 	for (auto &obstacle : owner->curInt->cb->battleGetAllObstacles()) | ||||
| 	for (auto obstacle : owner->curInt->cb->battleGetAllObstacles()) | ||||
| 	{ | ||||
| 		if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE) | ||||
| 			continue; | ||||
| @@ -136,15 +136,14 @@ void CBattleObstacleController::showBattlefieldObjects(std::shared_ptr<CCanvas> | ||||
| 		if (obstacle->obstacleType == CObstacleInstance::MOAT) | ||||
| 			continue; | ||||
|  | ||||
| 		if ( obstacle->pos != location) | ||||
| 			continue; | ||||
|  | ||||
| 		auto img = getObstacleImage(*obstacle); | ||||
| 		if(img) | ||||
| 		{ | ||||
| 			Point p = getObstaclePosition(img, *obstacle); | ||||
| 			canvas->draw(img, p); | ||||
| 		} | ||||
| 		renderer.insert(EBattleFieldLayer::OBSTACLES, obstacle->pos, [this, obstacle]( CBattleFieldRenderer::RendererPtr canvas ){ | ||||
| 			auto img = getObstacleImage(*obstacle); | ||||
| 			if(img) | ||||
| 			{ | ||||
| 				Point p = getObstaclePosition(img, *obstacle); | ||||
| 				canvas->draw(img, p); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class IImage; | ||||
| class CCanvas; | ||||
| class CAnimation; | ||||
| class CBattleInterface; | ||||
| class CBattleFieldRenderer; | ||||
| struct Point; | ||||
|  | ||||
| class CBattleObstacleController | ||||
| @@ -47,5 +48,5 @@ public: | ||||
| 	void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles); | ||||
| 	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset); | ||||
|  | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ); | ||||
| 	void collectRenderableObjects(CBattleFieldRenderer & renderer); | ||||
| }; | ||||
|   | ||||
| @@ -228,10 +228,6 @@ void CBattleProjectileController::showProjectiles(std::shared_ptr<CCanvas> canva | ||||
| 	for ( auto it = projectiles.begin(); it != projectiles.end();) | ||||
| 	{ | ||||
| 		auto projectile = *it; | ||||
| 		// Check if projectile is already visible (shooter animation did the shot) | ||||
| 		//if (!it->shotDone) | ||||
| 		//	continue; | ||||
|  | ||||
| 		if ( projectile->playing ) | ||||
| 			projectile->show(canvas); | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "CBattleInterface.h" | ||||
| #include "CBattleInterfaceClasses.h" | ||||
| #include "CBattleStacksController.h" | ||||
| #include "CBattleFieldController.h" | ||||
|  | ||||
| #include "../CMusicHandler.h" | ||||
| #include "../CGameInfo.h" | ||||
| @@ -279,7 +280,7 @@ const CStack * CBattleSiegeController::getTurretStack(EWallVisual::EWallVisual w | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ) | ||||
| void CBattleSiegeController::collectRenderableObjects(CBattleFieldRenderer & renderer) | ||||
| { | ||||
| 	for (int i = EWallVisual::WALL_FIRST; i <= EWallVisual::WALL_LAST; ++i) | ||||
| 	{ | ||||
| @@ -288,16 +289,25 @@ void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> can | ||||
| 		if ( !getWallPieceExistance(wallPiece)) | ||||
| 			continue; | ||||
|  | ||||
| 		if ( getWallPiecePosition(wallPiece) != location) | ||||
| 		if ( getWallPiecePosition(wallPiece) == BattleHex::INVALID) | ||||
| 			continue; | ||||
|  | ||||
| 		if (wallPiece == EWallVisual::KEEP_BATTLEMENT || | ||||
| 			wallPiece == EWallVisual::BOTTOM_BATTLEMENT || | ||||
| 			wallPiece == EWallVisual::UPPER_BATTLEMENT) | ||||
| 		{ | ||||
| 			owner->stacksController->showStack(canvas, getTurretStack(wallPiece)); | ||||
| 			renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ | ||||
| 				owner->stacksController->showStack(canvas, getTurretStack(wallPiece)); | ||||
| 			}); | ||||
| 			renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ | ||||
| 				showWallPiece(canvas, wallPiece, owner->pos.topLeft()); | ||||
| 			}); | ||||
| 		} | ||||
| 		showWallPiece(canvas, wallPiece, owner->pos.topLeft()); | ||||
| 		renderer.insert( EBattleFieldLayer::WALLS, getWallPiecePosition(wallPiece), [this, wallPiece](CBattleFieldRenderer::RendererPtr canvas){ | ||||
| 			showWallPiece(canvas, wallPiece, owner->pos.topLeft()); | ||||
| 		}); | ||||
|  | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -25,6 +25,7 @@ struct Point; | ||||
| struct SDL_Surface; | ||||
| class CCanvas; | ||||
| class CBattleInterface; | ||||
| class CBattleFieldRenderer; | ||||
| class IImage; | ||||
|  | ||||
| namespace EWallVisual | ||||
| @@ -98,7 +99,7 @@ public: | ||||
|  | ||||
| 	/// call-ins from other battle controllers | ||||
| 	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset); | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ); | ||||
| 	void collectRenderableObjects(CBattleFieldRenderer & renderer); | ||||
|  | ||||
| 	/// queries from other battle controllers | ||||
| 	bool isAttackableByCatapult(BattleHex hex) const; | ||||
|   | ||||
| @@ -93,66 +93,54 @@ CBattleStacksController::CBattleStacksController(CBattleInterface * owner): | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ) | ||||
| BattleHex CBattleStacksController::getStackCurrentPosition(const CStack * stack) | ||||
| { | ||||
| 	auto getCurrentPosition = [&](const CStack *stack) -> BattleHex | ||||
| 	{ | ||||
| 		for (auto & anim : currentAnimations) | ||||
| 		{ | ||||
| 			// certainly ugly workaround but fixes quite annoying bug | ||||
| 			// stack position will be updated only *after* movement is finished | ||||
| 			// before this - stack is always at its initial position. Thus we need to find | ||||
| 			// its current position. Which can be found only in this class | ||||
| 			if (CStackMoveAnimation *move = dynamic_cast<CStackMoveAnimation*>(anim)) | ||||
| 			{ | ||||
| 				if (move->stack == stack) | ||||
| 					return move->currentHex; | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
| 	if ( !stackAnimation[stack->ID]->isMoving()) | ||||
| 		return stack->getPosition(); | ||||
| 	}; | ||||
|  | ||||
| 	if (stack->hasBonusOfType(Bonus::FLYING)) | ||||
| 		return BattleHex::HEX_AFTER_ALL; | ||||
|  | ||||
| 	for (auto & anim : currentAnimations) | ||||
| 	{ | ||||
| 		// certainly ugly workaround but fixes quite annoying bug | ||||
| 		// stack position will be updated only *after* movement is finished | ||||
| 		// before this - stack is always at its initial position. Thus we need to find | ||||
| 		// its current position. Which can be found only in this class | ||||
| 		if (CStackMoveAnimation *move = dynamic_cast<CStackMoveAnimation*>(anim)) | ||||
| 		{ | ||||
| 			if (move->stack == stack) | ||||
| 				return move->currentHex; | ||||
| 		} | ||||
| 	} | ||||
| 	return stack->getPosition(); | ||||
| } | ||||
|  | ||||
| void CBattleStacksController::collectRenderableObjects(CBattleFieldRenderer & renderer) | ||||
| { | ||||
| 	auto stacks = owner->curInt->cb->battleGetAllStacks(false); | ||||
|  | ||||
| 	for (auto & stack : stacks) | ||||
| 	for (auto stack : stacks) | ||||
| 	{ | ||||
| 		if (stackAnimation.find(stack->ID) == stackAnimation.end()) //e.g. for summoned but not yet handled stacks | ||||
| 			continue; | ||||
|  | ||||
| 		//FIXME: hack to ignore ghost stacks | ||||
| 		if ((stackAnimation[stack->ID]->getType() == CCreatureAnim::DEAD || stackAnimation[stack->ID]->getType() == CCreatureAnim::HOLDING) && stack->isGhost()) | ||||
| 			continue;//ignore | ||||
|  | ||||
| 		if (stackAnimation[stack->ID]->isDead()) | ||||
| 		{ | ||||
| 			//if ( location == stack->getPosition() ) | ||||
| 			if ( location == BattleHex::HEX_BEFORE_ALL ) //FIXME: any cases when using BEFORE_ALL won't work? | ||||
| 				showStack(canvas, stack); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		// standing - blit at current position | ||||
| 		if (!stackAnimation[stack->ID]->isMoving()) | ||||
| 		{ | ||||
| 			if ( location == stack->getPosition() ) | ||||
| 				showStack(canvas, stack); | ||||
| 			continue; | ||||
| 		} | ||||
| 		auto layer = stackAnimation[stack->ID]->isDead() ? EBattleFieldLayer::CORPSES : EBattleFieldLayer::STACKS; | ||||
| 		auto location = getStackCurrentPosition(stack); | ||||
|  | ||||
| 		// flying creature - just blit them over everyone else | ||||
| 		if (stack->hasBonusOfType(Bonus::FLYING)) | ||||
| 		{ | ||||
| 			if ( location == BattleHex::HEX_AFTER_ALL) | ||||
| 				showStack(canvas, stack); | ||||
| 			continue; | ||||
| 		} | ||||
| 		renderer.insert(layer, location, [this, stack]( CBattleFieldRenderer::RendererPtr renderer ){ | ||||
| 			showStack(renderer, stack); | ||||
| 		}); | ||||
|  | ||||
| 		// else - unit moving on ground | ||||
| 		if (stackNeedsAmountBox(stack)) | ||||
| 		{ | ||||
| 			if ( location == getCurrentPosition(stack) ) | ||||
| 				showStack(canvas, stack); | ||||
| 			continue; | ||||
| 			renderer.insert(EBattleFieldLayer::STACK_AMOUNTS, location, [this, stack]( CBattleFieldRenderer::RendererPtr renderer ){ | ||||
| 				showStackAmountBox(renderer, stack); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -342,9 +330,6 @@ void CBattleStacksController::showStack(std::shared_ptr<CCanvas> canvas, const C | ||||
| { | ||||
| 	stackAnimation[stack->ID]->nextFrame(canvas, facingRight(stack)); // do actual blit | ||||
| 	stackAnimation[stack->ID]->incrementFrame(float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000); | ||||
|  | ||||
| 	if (stackNeedsAmountBox(stack)) | ||||
| 		showStackAmountBox(canvas, stack); | ||||
| } | ||||
|  | ||||
| void CBattleStacksController::updateBattleAnimations() | ||||
|   | ||||
| @@ -28,6 +28,7 @@ class CBattleInterface; | ||||
| class CBattleAnimation; | ||||
| class CCreatureAnimation; | ||||
| class CBattleAnimation; | ||||
| class CBattleFieldRenderer; | ||||
| class IImage; | ||||
|  | ||||
| class CBattleStacksController | ||||
| @@ -55,6 +56,7 @@ class CBattleStacksController | ||||
|  | ||||
| 	bool stackNeedsAmountBox(const CStack * stack); | ||||
| 	void showStackAmountBox(std::shared_ptr<CCanvas> canvas, const CStack * stack); | ||||
| 	BattleHex getStackCurrentPosition(const CStack * stack); | ||||
|  | ||||
| 	std::shared_ptr<IImage> getStackAmountBox(const CStack * stack); | ||||
|  | ||||
| @@ -87,7 +89,7 @@ public: | ||||
| 	void showAliveStack(std::shared_ptr<CCanvas> canvas, const CStack * stack); | ||||
| 	void showStack(std::shared_ptr<CCanvas> canvas, const CStack * stack); | ||||
|  | ||||
| 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location ); | ||||
| 	void collectRenderableObjects(CBattleFieldRenderer & renderer); | ||||
|  | ||||
| 	void addNewAnim(CBattleAnimation *anim); //adds new anim to pendingAnims | ||||
| 	void updateBattleAnimations(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user