Просмотр исходного кода

Reviewed usage of EBlitMode, now specified clearly in all cases

Ivan Savenko 1 год назад
Родитель
Сommit
0d6ec0d224

+ 1 - 1
client/CPlayerInterface.cpp

@@ -1145,7 +1145,7 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component
 		const CGTownInstance * t = dynamic_cast<const CGTownInstance *>(cb->getObj(obj));
 		if(t)
 		{
-			auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0);
+			auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
 			image->scaleFast(Point(35, 23));
 			images.push_back(image);
 		}

+ 1 - 1
client/ClientCommandManager.cpp

@@ -388,7 +388,7 @@ void ClientCommandManager::handleDef2bmpCommand(std::istringstream& singleWordBu
 {
 	std::string URI;
 	singleWordBuffer >> URI;
-	auto anim = GH.renderHandler().loadAnimation(AnimationPath::builtin(URI));
+	auto anim = GH.renderHandler().loadAnimation(AnimationPath::builtin(URI), EImageBlitMode::ALPHA);
 	anim->exportBitmaps(VCMIDirs::get().userExtractedPath());
 }
 

+ 2 - 1
client/adventureMap/AdventureMapInterface.cpp

@@ -31,6 +31,7 @@
 #include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
 #include "../render/Canvas.h"
+#include "../render/IImage.h"
 #include "../render/IRenderHandler.h"
 #include "../CMT.h"
 #include "../PlayerLocalState.h"
@@ -178,7 +179,7 @@ void AdventureMapInterface::dim(Canvas & to)
 		{
 			if(!std::dynamic_pointer_cast<AdventureMapInterface>(window) && std::dynamic_pointer_cast<CIntObject>(window) && isBigWindow(window))
 			{
-				to.fillTexture(GH.renderHandler().loadImage(ImagePath::builtin("DiBoxBck")));
+				to.fillTexture(GH.renderHandler().loadImage(ImagePath::builtin("DiBoxBck"), EImageBlitMode::OPAQUE));
 				return;
 			}
 		}

+ 1 - 1
client/battle/BattleAnimationClasses.cpp

@@ -883,7 +883,7 @@ uint32_t CastAnimation::getAttackClimaxFrame() const
 
 EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects, bool reversed):
 	BattleAnimation(owner),
-	animation(GH.renderHandler().loadAnimation(animationName)),
+	animation(GH.renderHandler().loadAnimation(animationName, EImageBlitMode::ALPHA)),
 	effectFlags(effects),
 	effectFinished(false),
 	reversed(reversed)

+ 5 - 5
client/battle/BattleFieldController.cpp

@@ -123,17 +123,17 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
 
 	//preparing cells and hexes
 	cellBorder = GH.renderHandler().loadImage(ImagePath::builtin("CCELLGRD.BMP"), EImageBlitMode::COLORKEY);
-	cellShade = GH.renderHandler().loadImage(ImagePath::builtin("CCELLSHD.BMP"));
+	cellShade = GH.renderHandler().loadImage(ImagePath::builtin("CCELLSHD.BMP"), EImageBlitMode::ALPHA);
 	cellUnitMovementHighlight = GH.renderHandler().loadImage(ImagePath::builtin("UnitMovementHighlight.PNG"), EImageBlitMode::COLORKEY);
 	cellUnitMaxMovementHighlight = GH.renderHandler().loadImage(ImagePath::builtin("UnitMaxMovementHighlight.PNG"), EImageBlitMode::COLORKEY);
 
-	attackCursors = GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT"));
-	spellCursors = GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"));
+	attackCursors = GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT"), EImageBlitMode::COLORKEY);
+	spellCursors = GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"), EImageBlitMode::COLORKEY);
 
 	initializeHexEdgeMaskToFrameIndex();
 
-	rangedFullDamageLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsGreen.json"));
-	shootingRangeLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsRed.json"));
+	rangedFullDamageLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsGreen.json"), EImageBlitMode::COLORKEY);
+	shootingRangeLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsRed.json"), EImageBlitMode::COLORKEY);
 
 	flipRangeLimitImagesIntoPositions(rangedFullDamageLimitImages);
 	flipRangeLimitImagesIntoPositions(shootingRangeLimitImages);

+ 3 - 6
client/battle/BattleInterfaceClasses.cpp

@@ -397,7 +397,7 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
 	else
 		animationPath = hero->type->heroClass->imageBattleMale;
 
-	animation = GH.renderHandler().loadAnimation(animationPath);
+	animation = GH.renderHandler().loadAnimation(animationPath, EImageBlitMode::ALPHA);
 
 	pos.w = 64;
 	pos.h = 136;
@@ -408,9 +408,9 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
 		animation->verticalFlip();
 
 	if(defender)
-		flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGR"));
+		flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGR"), EImageBlitMode::COLORKEY);
 	else
-		flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGL"));
+		flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGL"), EImageBlitMode::COLORKEY);
 
 	flagAnimation->playerColored(hero->tempOwner);
 
@@ -503,7 +503,6 @@ HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * posit
 	if(initializeBackground)
 	{
 		background = std::make_shared<CPicture>(ImagePath::builtin("CHRPOP"));
-		background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
 		background->setPlayerColor(hero.owner);
 	}
 
@@ -571,10 +570,8 @@ StackInfoBasicPanel::StackInfoBasicPanel(const CStack * stack, bool initializeBa
 	{
 		background = std::make_shared<CPicture>(ImagePath::builtin("CCRPOP"));
 		background->pos.y += 37;
-		background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
 		background->setPlayerColor(stack->getOwner());
 		background2 = std::make_shared<CPicture>(ImagePath::builtin("CHRPOP"));
-		background2->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
 		background2->setPlayerColor(stack->getOwner());
 	}
 

+ 3 - 3
client/battle/BattleObstacleController.cpp

@@ -58,7 +58,7 @@ void BattleObstacleController::loadObstacleImage(const CObstacleInstance & oi)
 		}
 		else
 		{
-			auto animation = GH.renderHandler().loadAnimation(animationName);
+			auto animation = GH.renderHandler().loadAnimation(animationName, EImageBlitMode::COLORKEY);
 			animationsCache[animationName] = animation;
 		}
 	}
@@ -84,7 +84,7 @@ void BattleObstacleController::obstacleRemoved(const std::vector<ObstacleChanges
 		if(animationPath.empty())
 			continue;
 
-		auto animation = GH.renderHandler().loadAnimation(animationPath);
+		auto animation = GH.renderHandler().loadAnimation(animationPath, EImageBlitMode::COLORKEY);
 		auto first = animation->getImage(0, 0);
 		if(!first)
 			continue;
@@ -110,7 +110,7 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
 		if(!oi->visibleForSide(side.value(), owner.getBattle()->battleHasNativeStack(side.value())))
 			continue;
 
-		auto animation = GH.renderHandler().loadAnimation(oi->getAppearAnimation());
+		auto animation = GH.renderHandler().loadAnimation(oi->getAppearAnimation(), EImageBlitMode::ALPHA);
 		auto first = animation->getImage(0, 0);
 		if(!first)
 			continue;

+ 1 - 1
client/battle/BattleProjectileController.cpp

@@ -192,7 +192,7 @@ void BattleProjectileController::initStackProjectile(const CStack * stack)
 
 std::shared_ptr<CAnimation> BattleProjectileController::createProjectileImage(const AnimationPath & path )
 {
-	std::shared_ptr<CAnimation> projectile = GH.renderHandler().loadAnimation(path);
+	std::shared_ptr<CAnimation> projectile = GH.renderHandler().loadAnimation(path, EImageBlitMode::COLORKEY);
 
 	if(projectile->size(1) != 0)
 		logAnim->error("Expected empty group 1 in stack projectile");

+ 3 - 3
client/battle/BattleSiegeController.cpp

@@ -182,7 +182,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
 		if ( !getWallPieceExistence(EWallVisual::EWallVisual(g)) )
 			continue;
 
-		wallPieceImages[g] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED));
+		wallPieceImages[g] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED), EImageBlitMode::COLORKEY);
 	}
 }
 
@@ -248,7 +248,7 @@ void BattleSiegeController::gateStateChanged(const EGateState state)
 		wallPieceImages[EWallVisual::GATE] = nullptr;
 
 	if (stateId != EWallState::NONE)
-		wallPieceImages[EWallVisual::GATE] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::GATE,  stateId));
+		wallPieceImages[EWallVisual::GATE] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::GATE,  stateId), EImageBlitMode::COLORKEY);
 
 	if (playSound)
 		CCS->soundh->playSound(soundBase::DRAWBRG);
@@ -357,7 +357,7 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
 
 		auto wallState = EWallState(owner.getBattle()->battleGetWallState(attackInfo.attackedPart));
 
-		wallPieceImages[wallId] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState));
+		wallPieceImages[wallId] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState), EImageBlitMode::COLORKEY);
 	}
 }
 

+ 2 - 2
client/battle/CreatureAnimation.cpp

@@ -199,8 +199,8 @@ CreatureAnimation::CreatureAnimation(const AnimationPath & name_, TSpeedControll
 	  speedController(controller),
 	  once(false)
 {
-	forward = GH.renderHandler().loadAnimation(name_);
-	reverse = GH.renderHandler().loadAnimation(name_);
+	forward = GH.renderHandler().loadAnimation(name_, EImageBlitMode::ALPHA);
+	reverse = GH.renderHandler().loadAnimation(name_, EImageBlitMode::ALPHA);
 
 	// if necessary, add one frame into vcmi-only group DEAD
 	if(forward->size(size_t(ECreatureAnimType::DEAD)) == 0)

+ 5 - 5
client/gui/CursorHandler.cpp

@@ -47,10 +47,10 @@ CursorHandler::CursorHandler()
 
 	cursors =
 	{
-		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRADVNTR")),
-		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT")),
-		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRDEFLT")),
-		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"))
+		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRADVNTR"), EImageBlitMode::COLORKEY),
+		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT"), EImageBlitMode::COLORKEY),
+		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRDEFLT"), EImageBlitMode::COLORKEY),
+		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"), EImageBlitMode::COLORKEY)
 	};
 
 	set(Cursor::Map::POINTER);
@@ -101,7 +101,7 @@ void CursorHandler::dragAndDropCursor(std::shared_ptr<IImage> image)
 
 void CursorHandler::dragAndDropCursor (const AnimationPath & path, size_t index)
 {
-	auto anim = GH.renderHandler().loadAnimation(path);
+	auto anim = GH.renderHandler().loadAnimation(path, EImageBlitMode::COLORKEY);
 	dragAndDropCursor(anim->getImage(index));
 }
 

+ 1 - 1
client/lobby/SelectionTab.cpp

@@ -884,7 +884,7 @@ SelectionTab::ListItem::ListItem(Point position)
 	: CIntObject(LCLICK, position)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
-	pictureEmptyLine = std::make_shared<CPicture>(GH.renderHandler().loadImage(ImagePath::builtin("camcust")), Rect(25, 121, 349, 26), -8, -14);
+	pictureEmptyLine = std::make_shared<CPicture>(ImagePath::builtin("camcust"), Rect(25, 121, 349, 26), -8, -14);
 	labelName = std::make_shared<CLabel>(184, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, "", 185);
 	labelName->setAutoRedraw(false);
 	labelAmountOfPlayers = std::make_shared<CLabel>(8, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);

+ 6 - 12
client/mapView/MapRenderer.cpp

@@ -104,12 +104,9 @@ void MapTileStorage::load(size_t index, const AnimationPath & filename, EImageBl
 	for(auto & entry : terrainAnimations)
 	{
 		if (!filename.empty())
-			entry = GH.renderHandler().loadAnimation(filename);
+			entry = GH.renderHandler().loadAnimation(filename, blitMode);
 		else
 			entry = GH.renderHandler().createAnimation();
-
-		for(size_t i = 0; i < entry->size(); ++i)
-			entry->getImage(i)->setBlitMode(blitMode);
 	}
 
 	terrainAnimations[1]->verticalFlip();
@@ -249,7 +246,7 @@ uint8_t MapRendererRoad::checksum(IMapRendererContext & context, const int3 & co
 
 MapRendererBorder::MapRendererBorder()
 {
-	animation = GH.renderHandler().loadAnimation(AnimationPath::builtin("EDG"));
+	animation = GH.renderHandler().loadAnimation(AnimationPath::builtin("EDG"), EImageBlitMode::OPAQUE);
 }
 
 size_t MapRendererBorder::getIndexForTile(IMapRendererContext & context, const int3 & tile)
@@ -310,11 +307,8 @@ uint8_t MapRendererBorder::checksum(IMapRendererContext & context, const int3 &
 
 MapRendererFow::MapRendererFow()
 {
-	fogOfWarFullHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRC"));
-	fogOfWarPartialHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRE"));
-
-	for(size_t i = 0; i < fogOfWarFullHide->size(); ++i)
-		fogOfWarFullHide->getImage(i)->setBlitMode(EImageBlitMode::OPAQUE);
+	fogOfWarFullHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRC"), EImageBlitMode::OPAQUE);
+	fogOfWarPartialHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRE"), EImageBlitMode::ALPHA);
 
 	static const std::vector<int> rotations = {22, 15, 2, 13, 12, 16, 28, 17, 20, 19, 7, 24, 26, 25, 30, 32, 27};
 
@@ -398,7 +392,7 @@ std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const AnimationPath
 	if(it != animations.end())
 		return it->second;
 
-	auto ret = GH.renderHandler().loadAnimation(filename);
+	auto ret = GH.renderHandler().loadAnimation(filename, EImageBlitMode::ALPHA);
 	animations[filename] = ret;
 
 	if(generateMovementGroups)
@@ -619,7 +613,7 @@ uint8_t MapRendererOverlay::checksum(IMapRendererContext & context, const int3 &
 }
 
 MapRendererPath::MapRendererPath()
-	: pathNodes(GH.renderHandler().loadAnimation(AnimationPath::builtin("ADAG")))
+	: pathNodes(GH.renderHandler().loadAnimation(AnimationPath::builtin("ADAG"), EImageBlitMode::ALPHA))
 {
 }
 

+ 1 - 4
client/mapView/MapViewCache.cpp

@@ -31,14 +31,11 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
 	: model(model)
 	, cachedLevel(0)
 	, mapRenderer(new MapRenderer())
-	, iconsStorage(GH.renderHandler().loadAnimation(AnimationPath::builtin("VwSymbol")))
+	, iconsStorage(GH.renderHandler().loadAnimation(AnimationPath::builtin("VwSymbol"), EImageBlitMode::COLORKEY))
 	, intermediate(new Canvas(Point(32, 32)))
 	, terrain(new Canvas(model->getCacheDimensionsPixels()))
 	, terrainTransition(new Canvas(model->getPixelsVisibleDimensions()))
 {
-	for(size_t i = 0; i < iconsStorage->size(); ++i)
-		iconsStorage->getImage(i)->setBlitMode(EImageBlitMode::COLORKEY);
-
 	Point visibleSize = model->getTilesVisibleDimensions();
 	terrainChecksum.resize(boost::extents[visibleSize.x][visibleSize.y]);
 	tilesUpToDate.resize(boost::extents[visibleSize.x][visibleSize.y]);

+ 5 - 4
client/render/CAnimation.cpp

@@ -34,9 +34,9 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
 
 	//try to get image from def
 	if(source[group][frame].isNull())
-		image = GH.renderHandler().loadImage(name, frame, group);
+		image = GH.renderHandler().loadImage(name, frame, group, mode);
 	else
-		image = GH.renderHandler().loadImage(source[group][frame]);
+		image = GH.renderHandler().loadImage(source[group][frame], mode);
 
 	if(image)
 	{
@@ -104,9 +104,10 @@ 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.getOriginalName(), group, frame);
 }
 
-CAnimation::CAnimation(const AnimationPath & Name, std::map<size_t, std::vector <JsonNode> > layout):
+CAnimation::CAnimation(const AnimationPath & Name, std::map<size_t, std::vector <JsonNode> > layout, EImageBlitMode mode):
 	name(boost::starts_with(Name.getName(), "SPRITES") ? Name : Name.addPrefix("SPRITES/")),
-	source(layout)
+	source(layout),
+	mode(mode)
 {
 	if(source.empty())
 		logAnim->error("Animation %s failed to load", Name.getOriginalName());

+ 5 - 2
client/render/CAnimation.h

@@ -9,6 +9,8 @@
  */
 #pragma once
 
+#include "IImage.h"
+
 #include "../../lib/GameConstants.h"
 #include "../../lib/filesystem/ResourcePath.h"
 
@@ -17,7 +19,6 @@ class JsonNode;
 VCMI_LIB_NAMESPACE_END
 
 class CDefFile;
-class IImage;
 class RenderHandler;
 
 /// Class for handling animation
@@ -33,6 +34,8 @@ private:
 	//animation file name
 	AnimationPath name;
 
+	EImageBlitMode mode;
+
 	//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);
 
@@ -44,7 +47,7 @@ private:
 
 	std::shared_ptr<IImage> getImageImpl(size_t frame, size_t group=0, bool verbose=true);
 public:
-	CAnimation(const AnimationPath & Name, std::map<size_t, std::vector <JsonNode> > layout);
+	CAnimation(const AnimationPath & Name, std::map<size_t, std::vector <JsonNode> > layout, EImageBlitMode mode);
 	CAnimation();
 	~CAnimation();
 

+ 8 - 4
client/render/IImage.h

@@ -26,13 +26,17 @@ class ColorFilter;
 /// Defines which blit method will be selected when image is used for rendering
 enum class EImageBlitMode
 {
-	/// Image can have no transparency and can be only used as background
+	/// Preferred for images that don't need any background
+	/// Indexed or RGBA: Image can have no transparency and can be only used as background
 	OPAQUE,
 
-	/// Image can have only a single color as transparency and has no semi-transparent areas
+	/// Preferred for images that may need transparency
+	/// Indexed: Image can have only a single color as transparency and has no semi-transparent areas
+	/// RGBA: full alpha transparency range, e.g. shadows
 	COLORKEY,
 
-	/// Image might have full alpha transparency range, e.g. shadows
+	/// Should be avoided if possible, use only for images that use def's with semi-transparency
+	/// Indexed or RGBA: Image might have full alpha transparency range, e.g. shadows
 	ALPHA
 };
 
@@ -85,7 +89,7 @@ public:
 	virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
 	virtual bool isTransparent(const Point & coords) const = 0;
 
-	virtual std::shared_ptr<IImage> createImageReference() = 0;
+	virtual std::shared_ptr<IImage> createImageReference(EImageBlitMode mode) = 0;
 
 	virtual std::shared_ptr<IConstImage> horizontalFlip() const = 0;
 	virtual std::shared_ptr<IConstImage> verticalFlip() const = 0;

+ 3 - 4
client/render/IRenderHandler.h

@@ -30,17 +30,16 @@ public:
 	virtual void onLibraryLoadingFinished(const Services * services) = 0;
 
 	/// Loads image using given path
-	virtual std::shared_ptr<IImage> loadImage(const JsonNode & config) = 0;
-	virtual std::shared_ptr<IImage> loadImage(const ImagePath & path) = 0;
+	virtual std::shared_ptr<IImage> loadImage(const JsonNode & config, EImageBlitMode mode) = 0;
 	virtual std::shared_ptr<IImage> loadImage(const ImagePath & path, EImageBlitMode mode) = 0;
-	virtual std::shared_ptr<IImage> loadImage(const AnimationPath & path, int frame, int group) = 0;
+	virtual std::shared_ptr<IImage> loadImage(const AnimationPath & path, int frame, int group, EImageBlitMode mode) = 0;
 
 	/// temporary compatibility method. Creates IImage from existing SDL_Surface
 	/// Surface will be shared, caller must still free it with SDL_FreeSurface
 	virtual std::shared_ptr<IImage> createImage(SDL_Surface * source) = 0;
 
 	/// Loads animation using given path
-	virtual std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path) = 0;
+	virtual std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path, EImageBlitMode mode) = 0;
 
 	/// Creates empty CAnimation. Temporary compatibility method
 	virtual std::shared_ptr<CAnimation> createAnimation() = 0;

+ 10 - 15
client/renderSDL/RenderHandler.cpp

@@ -164,7 +164,7 @@ RenderHandler::AnimationLayoutMap & RenderHandler::getAnimationLayout(const Anim
 
 std::shared_ptr<IConstImage> RenderHandler::loadImageFromSingleFile(const ImagePath & path)
 {
-	auto result = std::make_shared<SDLImageConst>(path, EImageBlitMode::COLORKEY);
+	auto result = std::make_shared<SDLImageConst>(path);
 	imageFiles[ImageLocator(path)] = result;
 	return result;
 }
@@ -223,37 +223,32 @@ std::shared_ptr<IConstImage> RenderHandler::loadImageImpl(const ImageLocator & l
 	return result;
 }
 
-std::shared_ptr<IImage> RenderHandler::loadImage(const JsonNode & config)
+std::shared_ptr<IImage> RenderHandler::loadImage(const JsonNode & config, EImageBlitMode mode)
 {
 	if (config.isString())
-		return loadImageImpl(ImageLocator(ImagePath::fromJson(config)))->createImageReference();
+		return loadImageImpl(ImageLocator(ImagePath::fromJson(config)))->createImageReference(mode);
 	else
-		return loadImageImpl(ImageLocator(config))->createImageReference();
+		return loadImageImpl(ImageLocator(config))->createImageReference(mode);
 }
 
-std::shared_ptr<IImage> RenderHandler::loadImage(const AnimationPath & path, int frame, int group)
+std::shared_ptr<IImage> RenderHandler::loadImage(const AnimationPath & path, int frame, int group, EImageBlitMode mode)
 {
-	return loadImageImpl(ImageLocator(path, frame, group))->createImageReference();
-}
-
-std::shared_ptr<IImage> RenderHandler::loadImage(const ImagePath & path)
-{
-	return loadImage(path, EImageBlitMode::ALPHA);
+	return loadImageImpl(ImageLocator(path, frame, group))->createImageReference(mode);
 }
 
 std::shared_ptr<IImage> RenderHandler::loadImage(const ImagePath & path, EImageBlitMode mode)
 {
-	return loadImageImpl(ImageLocator(path))->createImageReference();
+	return loadImageImpl(ImageLocator(path))->createImageReference(mode);
 }
 
 std::shared_ptr<IImage> RenderHandler::createImage(SDL_Surface * source)
 {
-	return std::make_shared<SDLImageConst>(source, EImageBlitMode::ALPHA)->createImageReference();
+	return std::make_shared<SDLImageConst>(source)->createImageReference(EImageBlitMode::ALPHA);
 }
 
-std::shared_ptr<CAnimation> RenderHandler::loadAnimation(const AnimationPath & path)
+std::shared_ptr<CAnimation> RenderHandler::loadAnimation(const AnimationPath & path, EImageBlitMode mode)
 {
-	return std::make_shared<CAnimation>(path, getAnimationLayout(path));
+	return std::make_shared<CAnimation>(path, getAnimationLayout(path), mode);
 }
 
 std::shared_ptr<CAnimation> RenderHandler::createAnimation()

+ 3 - 4
client/renderSDL/RenderHandler.h

@@ -58,12 +58,11 @@ public:
 	// IRenderHandler implementation
 	void onLibraryLoadingFinished(const Services * services) override;
 
-	std::shared_ptr<IImage> loadImage(const JsonNode & config) override;
-	std::shared_ptr<IImage> loadImage(const ImagePath & path) override;
+	std::shared_ptr<IImage> loadImage(const JsonNode & config, EImageBlitMode mode) override;
 	std::shared_ptr<IImage> loadImage(const ImagePath & path, EImageBlitMode mode) override;
-	std::shared_ptr<IImage> loadImage(const AnimationPath & path, int frame, int group) override;
+	std::shared_ptr<IImage> loadImage(const AnimationPath & path, int frame, int group, EImageBlitMode mode) override;
 
-	std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path) override;
+	std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path, EImageBlitMode mode) override;
 
 	std::shared_ptr<IImage> createImage(SDL_Surface * source) override;
 	std::shared_ptr<CAnimation> createAnimation() override;

+ 15 - 15
client/renderSDL/SDLImage.cpp

@@ -44,7 +44,7 @@ SDLImageConst::SDLImageConst(CDefFile * data, size_t frame, size_t group)
 	savePalette();
 }
 
-SDLImageConst::SDLImageConst(SDL_Surface * from, EImageBlitMode mode)
+SDLImageConst::SDLImageConst(SDL_Surface * from)
 	: surf(nullptr),
 	margins(0, 0),
 	fullSize(0, 0),
@@ -61,7 +61,7 @@ SDLImageConst::SDLImageConst(SDL_Surface * from, EImageBlitMode mode)
 	fullSize.y = surf->h;
 }
 
-SDLImageConst::SDLImageConst(const ImagePath & filename, EImageBlitMode mode)
+SDLImageConst::SDLImageConst(const ImagePath & filename)
 	: surf(nullptr),
 	margins(0, 0),
 	fullSize(0, 0),
@@ -111,10 +111,10 @@ void SDLImageConst::draw(SDL_Surface * where, SDL_Palette * palette, const Point
 
 	SDL_SetSurfaceAlphaMod(surf, alpha);
 
-	if (mode == EImageBlitMode::OPAQUE)
-		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
-	else
+	if (mode != EImageBlitMode::OPAQUE && surf->format->Amask != 0)
 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
+	else
+		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
 
 	if (palette && surf->format->palette)
 		SDL_SetSurfacePalette(surf, palette);
@@ -151,7 +151,7 @@ std::shared_ptr<SDLImageConst> SDLImageConst::scaleFast(const Point & size) cons
 	else
 		CSDL_Ext::setDefaultColorKey(scaled);//just in case
 
-	auto ret = std::make_shared<SDLImageConst>(scaled, EImageBlitMode::ALPHA);
+	auto ret = std::make_shared<SDLImageConst>(scaled);
 
 	ret->fullSize.x = (int) round((float)fullSize.x * scaleX);
 	ret->fullSize.y = (int) round((float)fullSize.y * scaleY);
@@ -194,18 +194,18 @@ Point SDLImageConst::dimensions() const
 	return fullSize;
 }
 
-std::shared_ptr<IImage> SDLImageConst::createImageReference()
+std::shared_ptr<IImage> SDLImageConst::createImageReference(EImageBlitMode mode)
 {
 	if (surf->format->palette)
-		return std::make_shared<SDLImageIndexed>(shared_from_this());
+		return std::make_shared<SDLImageIndexed>(shared_from_this(), mode);
 	else
-		return std::make_shared<SDLImageRGB>(shared_from_this());
+		return std::make_shared<SDLImageRGB>(shared_from_this(), mode);
 }
 
 std::shared_ptr<IConstImage> SDLImageConst::horizontalFlip() const
 {
 	SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf);
-	auto ret = std::make_shared<SDLImageConst>(flipped, EImageBlitMode::ALPHA);
+	auto ret = std::make_shared<SDLImageConst>(flipped);
 	ret->fullSize = fullSize;
 	ret->margins.x = margins.x;
 	ret->margins.y = fullSize.y - surf->h - margins.y;
@@ -217,7 +217,7 @@ std::shared_ptr<IConstImage> SDLImageConst::horizontalFlip() const
 std::shared_ptr<IConstImage> SDLImageConst::verticalFlip() const
 {
 	SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf);
-	auto ret = std::make_shared<SDLImageConst>(flipped, EImageBlitMode::ALPHA);
+	auto ret = std::make_shared<SDLImageConst>(flipped);
 	ret->fullSize = fullSize;
 	ret->margins.x = fullSize.x - surf->w - margins.x;
 	ret->margins.y = margins.y;
@@ -265,8 +265,8 @@ void SDLImageIndexed::adjustPalette(const ColorFilter & shifter, uint32_t colors
 	}
 }
 
-SDLImageIndexed::SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image)
-	:SDLImageBase::SDLImageBase(image)
+SDLImageIndexed::SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image, EImageBlitMode mode)
+	:SDLImageBase::SDLImageBase(image, mode)
 {
 	auto originalPalette = image->getPalette();
 
@@ -296,10 +296,10 @@ SDLImageConst::~SDLImageConst()
 	SDL_FreePalette(originalPalette);
 }
 
-SDLImageBase::SDLImageBase(const std::shared_ptr<SDLImageConst> & image)
+SDLImageBase::SDLImageBase(const std::shared_ptr<SDLImageConst> & image, EImageBlitMode mode)
 	:image(image)
 	, alphaValue(SDL_ALPHA_OPAQUE)
-	, blitMode(EImageBlitMode::ALPHA)
+	, blitMode(mode)
 {}
 
 void SDLImageRGB::draw(SDL_Surface * where, const Point & pos, const Rect * src) const

+ 5 - 5
client/renderSDL/SDLImage.h

@@ -42,9 +42,9 @@ public:
 	//Load image from def file
 	SDLImageConst(CDefFile *data, size_t frame, size_t group=0);
 	//Load from bitmap file
-	SDLImageConst(const ImagePath & filename, EImageBlitMode blitMode);
+	SDLImageConst(const ImagePath & filename);
 	//Create using existing surface, extraRef will increase refcount on SDL_Surface
-	SDLImageConst(SDL_Surface * from, EImageBlitMode blitMode);
+	SDLImageConst(SDL_Surface * from);
 	~SDLImageConst();
 
 	void draw(SDL_Surface * where, SDL_Palette * palette, const Point & dest, const Rect * src, uint8_t alpha, EImageBlitMode mode) const;
@@ -52,7 +52,7 @@ public:
 	void exportBitmap(const boost::filesystem::path & path) const override;
 	Point dimensions() const override;
 	bool isTransparent(const Point & coords) const override;
-	std::shared_ptr<IImage> createImageReference() override;
+	std::shared_ptr<IImage> createImageReference(EImageBlitMode mode) override;
 	std::shared_ptr<IConstImage> horizontalFlip() const override;
 	std::shared_ptr<IConstImage> verticalFlip() const override;
 	std::shared_ptr<SDLImageConst> scaleFast(const Point & size) const;
@@ -71,7 +71,7 @@ protected:
 	EImageBlitMode blitMode;
 
 public:
-	SDLImageBase(const std::shared_ptr<SDLImageConst> & image);
+	SDLImageBase(const std::shared_ptr<SDLImageConst> & image, EImageBlitMode mode);
 
 	void scaleFast(const Point & size) override;
 	void exportBitmap(const boost::filesystem::path & path) const override;
@@ -86,7 +86,7 @@ class SDLImageIndexed final : public SDLImageBase
 	SDL_Palette * currentPalette = nullptr;
 
 public:
-	SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image);
+	SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image, EImageBlitMode mode);
 	~SDLImageIndexed();
 
 	void draw(SDL_Surface * where, const Point & pos, const Rect * src) const override;

+ 15 - 7
client/widgets/Images.cpp

@@ -50,7 +50,7 @@ CPicture::CPicture( const ImagePath & bmpname )
 {}
 
 CPicture::CPicture( const ImagePath & bmpname, const Point & position )
-	: bg(GH.renderHandler().loadImage(bmpname))
+	: bg(GH.renderHandler().loadImage(bmpname, EImageBlitMode::COLORKEY))
 	, needRefresh(false)
 {
 	pos.x += position.x;
@@ -68,6 +68,14 @@ CPicture::CPicture( const ImagePath & bmpname, const Point & position )
 	}
 }
 
+CPicture::CPicture(const ImagePath & bmpname, const Rect &SrcRect, int x, int y)
+	: CPicture(bmpname, Point(x,y))
+{
+	srcRect = SrcRect;
+	pos.w = srcRect->w;
+	pos.h = srcRect->h;
+}
+
 CPicture::CPicture(std::shared_ptr<IImage> image, const Rect &SrcRect, int x, int y)
 	: CPicture(image, Point(x,y))
 {
@@ -113,7 +121,7 @@ void CPicture::setPlayerColor(PlayerColor player)
 
 CFilledTexture::CFilledTexture(const ImagePath & imageName, Rect position)
 	: CIntObject(0, position.topLeft())
-	, texture(GH.renderHandler().loadImage(imageName))
+	, texture(GH.renderHandler().loadImage(imageName, EImageBlitMode::COLORKEY))
 {
 	pos.w = position.w;
 	pos.h = position.h;
@@ -122,7 +130,7 @@ CFilledTexture::CFilledTexture(const ImagePath & imageName, Rect position)
 
 CFilledTexture::CFilledTexture(const ImagePath & imageName, Rect position, Rect imageArea)
 	: CIntObject(0, position.topLeft())
-	, texture(GH.renderHandler().loadImage(imageName))
+	, texture(GH.renderHandler().loadImage(imageName, EImageBlitMode::COLORKEY))
 	, imageArea(imageArea)
 {
 	pos.w = position.w;
@@ -176,7 +184,7 @@ CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, size_t Group, i
 {
 	pos.x += x;
 	pos.y += y;
-	anim = GH.renderHandler().loadAnimation(name);
+	anim = GH.renderHandler().loadAnimation(name, EImageBlitMode::COLORKEY);
 	init();
 }
 
@@ -192,7 +200,7 @@ CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, size_t Group, i
 //}
 
 CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, Rect targetPos, size_t Group, ui8 Flags):
-	anim(GH.renderHandler().loadAnimation(name)),
+	anim(GH.renderHandler().loadAnimation(name, EImageBlitMode::COLORKEY)),
 	frame(Frame),
 	group(Group),
 	flags(Flags),
@@ -268,7 +276,7 @@ void CAnimImage::showAll(Canvas & to)
 void CAnimImage::setAnimationPath(const AnimationPath & name, size_t frame)
 {
 	this->frame = frame;
-	anim = GH.renderHandler().loadAnimation(name);
+	anim = GH.renderHandler().loadAnimation(name, EImageBlitMode::COLORKEY);
 	init();
 }
 
@@ -310,7 +318,7 @@ bool CAnimImage::isPlayerColored() const
 }
 
 CShowableAnim::CShowableAnim(int x, int y, const AnimationPath & name, ui8 Flags, ui32 frameTime, size_t Group, uint8_t alpha):
-	anim(GH.renderHandler().loadAnimation(name)),
+	anim(GH.renderHandler().loadAnimation(name, EImageBlitMode::ALPHA)),
 	group(Group),
 	frame(0),
 	first(0),

+ 1 - 0
client/widgets/Images.h

@@ -44,6 +44,7 @@ public:
 
 	/// wrap section of an existing Image
 	CPicture(std::shared_ptr<IImage> image, const Rect &SrcRext, int x = 0, int y = 0); //wrap subrect of given surface
+	CPicture(const ImagePath & bmpname, const Rect &SrcRext, int x = 0, int y = 0); //wrap subrect of given surface
 
 	/// Loads image from specified file name
 	CPicture(const ImagePath & bmpname);

+ 1 - 1
client/windows/CCastleInterface.cpp

@@ -885,7 +885,7 @@ void CCastleBuildings::enterCastleGate()
 			availableTowns.push_back(t->id.getNum());//add to the list
 			if(settings["general"]["enableUiEnhancements"].Bool())
 			{
-				auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0);
+				auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE);
 				image->scaleFast(Point(35, 23));
 				images.push_back(image);
 			}

+ 1 - 1
client/windows/CMessage.cpp

@@ -41,7 +41,7 @@ void CMessage::init()
 {
 	for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
 	{
-		dialogBorders[i] = GH.renderHandler().loadAnimation(AnimationPath::builtin("DIALGBOX"));
+		dialogBorders[i] = GH.renderHandler().loadAnimation(AnimationPath::builtin("DIALGBOX"), EImageBlitMode::OPAQUE);
 
 		for(int j = 0; j < dialogBorders[i]->size(0); j++)
 		{

+ 1 - 1
client/windows/CSpellWindow.cpp

@@ -215,7 +215,7 @@ CSpellWindow::~CSpellWindow()
 
 std::shared_ptr<IImage> CSpellWindow::createBigSpellBook()
 {
-	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(ImagePath::builtin("SpelBack"));
+	std::shared_ptr<IImage> img = GH.renderHandler().loadImage(ImagePath::builtin("SpelBack"), EImageBlitMode::OPAQUE);
 	Canvas canvas = Canvas(Point(800, 600));
 	// edges
 	canvas.draw(img, Point(0, 0), Rect(15, 38, 90, 45));

+ 1 - 1
client/windows/CWindowWithArtifacts.cpp

@@ -237,7 +237,7 @@ void CWindowWithArtifacts::setCursorAnimation(const CArtifactInstance & artInst)
 	if(artInst.isScroll() && settings["general"]["enableUiEnhancements"].Bool())
 	{
 		assert(artInst.getScrollSpellID().num >= 0);
-		auto image = GH.renderHandler().loadImage(AnimationPath::builtin("spellscr"), artInst.getScrollSpellID().num, 0);
+		auto image = GH.renderHandler().loadImage(AnimationPath::builtin("spellscr"), artInst.getScrollSpellID().num, 0, EImageBlitMode::COLORKEY);
 		image->scaleFast(Point(44,34));
 
 		CCS->curh->dragAndDropCursor(image);