Pārlūkot izejas kodu

Improved ordering of movement animation, fixes potential visual artifact

Ivan Savenko 2 gadi atpakaļ
vecāks
revīzija
d8a70de068

+ 6 - 1
client/battle/BattleInterface.cpp

@@ -725,16 +725,21 @@ void BattleInterface::setAnimationCondition( EAnimationEvents event, bool state)
 	size_t index = static_cast<size_t>(event);
 	animationEvents[index].setn(state);
 
+	decltype(awaitingEvents) executingEvents;
+
 	for (auto it = awaitingEvents.begin(); it != awaitingEvents.end();)
 	{
 		if (it->event == event && it->eventState == state)
 		{
-			it->action();
+			executingEvents.push_back(*it);
 			it = awaitingEvents.erase(it);
 		}
 		else
 			++it;
 	}
+
+	for (auto const & event : executingEvents)
+		event.action();
 }
 
 bool BattleInterface::getAnimationCondition( EAnimationEvents event)

+ 45 - 20
client/battle/BattleStacksController.cpp

@@ -346,26 +346,35 @@ void BattleStacksController::update()
 	updateBattleAnimations();
 }
 
-void BattleStacksController::updateBattleAnimations()
+void BattleStacksController::initializeBattleAnimations()
+{
+	auto copiedVector = currentAnimations;
+	for (auto & elem : copiedVector)
+		if (elem && !elem->isInitialized())
+			elem->tryInitialize();
+}
+
+void BattleStacksController::stepFrameBattleAnimations()
 {
 	// operate on copy - to prevent potential iterator invalidation due to push_back's
 	// FIXME? : remove remaining calls to addNewAnim from BattleAnimation::nextFrame (only Catapult explosion at the time of writing)
-
 	auto copiedVector = currentAnimations;
-
 	for (auto & elem : copiedVector)
 		if (elem && elem->isInitialized())
 			elem->nextFrame();
+}
 
-	for (auto & elem : copiedVector)
-		if (elem && !elem->isInitialized())
-			elem->tryInitialize();
-
+void BattleStacksController::updateBattleAnimations()
+{
 	bool hadAnimations = !currentAnimations.empty();
+	initializeBattleAnimations();
+	stepFrameBattleAnimations();
 	vstd::erase(currentAnimations, nullptr);
 
 	if (hadAnimations && currentAnimations.empty())
 		owner.setAnimationCondition(EAnimationEvents::ACTION, false);
+
+	initializeBattleAnimations();
 }
 
 void BattleStacksController::addNewAnim(BattleAnimation *anim)
@@ -493,24 +502,40 @@ void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleH
 	assert(destHex.size() > 0);
 	assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
 
-	if(shouldRotate(stack, stack->getPosition(), destHex[0]))
-	{
-		addNewAnim(new ReverseAnimation(owner, stack, stack->getPosition()));
-		owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
-	}
+	bool stackTeleports = stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1));
+	owner.setAnimationCondition(EAnimationEvents::MOVEMENT, true);
 
-	addNewAnim(new MovementStartAnimation(owner, stack));
-	owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
+	auto enqueMoveEnd = [&](){
+		addNewAnim(new MovementEndAnimation(owner, stack, destHex.back()));
+		owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, [&](){
+			owner.setAnimationCondition(EAnimationEvents::MOVEMENT, false);
+		});
+	};
 
-	// if creature can teleport, e.g Devils - skip movement animation
-	if (!stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1)) )
+	auto enqueMove = [&](){
+		if (!stackTeleports)
+		{
+			addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
+			owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMoveEnd);
+		}
+		else
+			enqueMoveEnd();
+	};
+
+	auto enqueMoveStart = [&](){
+		addNewAnim(new MovementStartAnimation(owner, stack));
+		owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMove);
+	};
+
+	if(shouldRotate(stack, stack->getPosition(), destHex[0]))
 	{
-		addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
-		owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
+		addNewAnim(new ReverseAnimation(owner, stack, stack->getPosition()));
+		owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMoveStart);
 	}
+	else
+		enqueMoveStart();
 
-	addNewAnim(new MovementEndAnimation(owner, stack, destHex.back()));
-	owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
+	owner.waitForAnimationCondition(EAnimationEvents::MOVEMENT, false);
 }
 
 bool BattleStacksController::shouldAttackFacingRight(const CStack * attacker, const CStack * defender)

+ 3 - 0
client/battle/BattleStacksController.h

@@ -95,6 +95,9 @@ class BattleStacksController
 	void executeAttackAnimations();
 	void removeExpiredColorFilters();
 
+	void initializeBattleAnimations();
+	void stepFrameBattleAnimations();
+
 	void updateBattleAnimations();
 	void updateHoveredStacks();