diff --git a/client/battle/CreatureAnimation.cpp b/client/battle/CreatureAnimation.cpp index 31ab870cf..60a59cf54 100644 --- a/client/battle/CreatureAnimation.cpp +++ b/client/battle/CreatureAnimation.cpp @@ -200,8 +200,8 @@ CreatureAnimation::CreatureAnimation(const AnimationPath & name_, TSpeedControll speedController(controller), once(false) { - forward = GH.renderHandler().loadAnimation(name_, EImageBlitMode::WITH_SHADOW_AND_OVERLAY); - reverse = GH.renderHandler().loadAnimation(name_, EImageBlitMode::WITH_SHADOW_AND_OVERLAY); + forward = GH.renderHandler().loadAnimation(name_, EImageBlitMode::WITH_SHADOW_AND_SELECTION); + reverse = GH.renderHandler().loadAnimation(name_, EImageBlitMode::WITH_SHADOW_AND_SELECTION); // if necessary, add one frame into vcmi-only group DEAD if(forward->size(size_t(ECreatureAnimType::DEAD)) == 0) diff --git a/client/mapView/MapRenderer.cpp b/client/mapView/MapRenderer.cpp index d3c0a88c7..c43ee60f1 100644 --- a/client/mapView/MapRenderer.cpp +++ b/client/mapView/MapRenderer.cpp @@ -407,7 +407,7 @@ std::shared_ptr MapRendererObjects::getAnimation(const AnimationPath if(it != animations.end()) return it->second; - auto ret = GH.renderHandler().loadAnimation(filename, enableOverlay ? EImageBlitMode::WITH_SHADOW_AND_OVERLAY : EImageBlitMode::WITH_SHADOW); + auto ret = GH.renderHandler().loadAnimation(filename, enableOverlay ? EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: EImageBlitMode::WITH_SHADOW); animations[filename] = ret; if(generateMovementGroups) diff --git a/client/render/IImage.h b/client/render/IImage.h index ec27276a6..9c2216553 100644 --- a/client/render/IImage.h +++ b/client/render/IImage.h @@ -47,19 +47,23 @@ enum class EImageBlitMode : uint8_t WITH_SHADOW, /// RGBA, may consist from 3 separate parts: base, shadow, and overlay - WITH_SHADOW_AND_OVERLAY, + WITH_SHADOW_AND_SELECTION, + WITH_SHADOW_AND_FLAG_COLOR, /// RGBA, contains only body, with shadow and overlay disabled - ONLY_BODY, + ONLY_BODY_HIDE_SELECTION, + ONLY_BODY_HIDE_FLAG_COLOR, /// RGBA, contains only body, with shadow disabled and overlay treated as part of body ONLY_BODY_IGNORE_OVERLAY, /// RGBA, contains only shadow - ONLY_SHADOW, + ONLY_SHADOW_HIDE_SELECTION, + ONLY_SHADOW_HIDE_FLAG_COLOR, /// RGBA, contains only overlay - ONLY_OVERLAY, + ONLY_SELECTION, + ONLY_FLAG_COLOR, }; enum class EScalingAlgorithm : int8_t diff --git a/client/renderSDL/RenderHandler.cpp b/client/renderSDL/RenderHandler.cpp index 92469f4d3..aa771c3e9 100644 --- a/client/renderSDL/RenderHandler.cpp +++ b/client/renderSDL/RenderHandler.cpp @@ -230,6 +230,7 @@ std::shared_ptr RenderHandler::loadImageFromFileUncached(const Ima if (generated) return generated; + logGlobal->error("Failed to load image %s", locator.image->getOriginalName()); return std::make_shared(ImagePath::builtin("DEFAULT")); } @@ -292,9 +293,9 @@ std::shared_ptr RenderHandler::loadScaledImage(const ImageLocato std::string imagePathString = pathToLoad.getName(); - if(locator.layer == EImageBlitMode::ONLY_OVERLAY) + if(locator.layer == EImageBlitMode::ONLY_FLAG_COLOR || locator.layer == EImageBlitMode::ONLY_SELECTION) imagePathString += "-OVERLAY"; - if(locator.layer == EImageBlitMode::ONLY_SHADOW) + if(locator.layer == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION || locator.layer == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR) imagePathString += "-SHADOW"; if(locator.playerColored.isValidPlayer()) imagePathString += "-" + boost::to_upper_copy(GameConstants::PLAYER_COLOR_NAMES[locator.playerColored.getNum()]); @@ -347,7 +348,10 @@ std::shared_ptr RenderHandler::loadImage(const AnimationPath & path, int if (!locator.empty()) return loadImage(locator); else + { + logGlobal->error("Failed to load non-existing image"); return loadImage(ImageLocator(ImagePath::builtin("DEFAULT"), mode)); + } } std::shared_ptr RenderHandler::loadImage(const ImagePath & path, EImageBlitMode mode) diff --git a/client/renderSDL/ScalableImage.cpp b/client/renderSDL/ScalableImage.cpp index 93ec8d803..40a22c722 100644 --- a/client/renderSDL/ScalableImage.cpp +++ b/client/renderSDL/ScalableImage.cpp @@ -97,8 +97,10 @@ void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette { switch(blitMode) { - case EImageBlitMode::ONLY_SHADOW: - case EImageBlitMode::ONLY_OVERLAY: + case EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR: + case EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION: + case EImageBlitMode::ONLY_FLAG_COLOR: + case EImageBlitMode::ONLY_SELECTION: adjustPalette(originalPalette, blitMode, ColorFilter::genAlphaShifter(0), 0); break; } @@ -107,37 +109,49 @@ void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette { case EImageBlitMode::SIMPLE: case EImageBlitMode::WITH_SHADOW: - case EImageBlitMode::ONLY_SHADOW: - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: + case EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR: + case EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION: + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: setShadowTransparency(originalPalette, 1.0); break; - case EImageBlitMode::ONLY_BODY: + case EImageBlitMode::ONLY_BODY_HIDE_SELECTION: + case EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR: case EImageBlitMode::ONLY_BODY_IGNORE_OVERLAY: - case EImageBlitMode::ONLY_OVERLAY: + case EImageBlitMode::ONLY_FLAG_COLOR: + case EImageBlitMode::ONLY_SELECTION: setShadowTransparency(originalPalette, 0.0); break; } switch(blitMode) { - case EImageBlitMode::ONLY_OVERLAY: - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: - setOverlayColor(originalPalette, Colors::WHITE_TRUE); + case EImageBlitMode::ONLY_FLAG_COLOR: + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + setOverlayColor(originalPalette, Colors::WHITE_TRUE, false); break; - case EImageBlitMode::ONLY_SHADOW: - case EImageBlitMode::ONLY_BODY: - setOverlayColor(originalPalette, Colors::TRANSPARENCY); + case EImageBlitMode::ONLY_SELECTION: + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: + setOverlayColor(originalPalette, Colors::WHITE_TRUE, true); + break; + case EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR: + case EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR: + setOverlayColor(originalPalette, Colors::TRANSPARENCY, false); + break; + case EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION: + case EImageBlitMode::ONLY_BODY_HIDE_SELECTION: + setOverlayColor(originalPalette, Colors::TRANSPARENCY, true); break; } } -void ScalableImageParameters::setOverlayColor(const SDL_Palette * originalPalette, const ColorRGBA & color) +void ScalableImageParameters::setOverlayColor(const SDL_Palette * originalPalette, const ColorRGBA & color, bool includeShadow) { palette->colors[5] = CSDL_Ext::toSDL(addColors(targetPalette[5], color)); - for (int i : {6,7}) + if (includeShadow) { - if (colorsSimilar(originalPalette->colors[i], sourcePalette[i])) + for (int i : {6,7}) palette->colors[i] = CSDL_Ext::toSDL(addColors(targetPalette[i], color)); } } @@ -183,7 +197,7 @@ void ScalableImageParameters::setShadowTransparency(const SDL_Palette * original void ScalableImageParameters::adjustPalette(const SDL_Palette * originalPalette, EImageBlitMode blitMode, const ColorFilter & shifter, uint32_t colorsToSkipMask) { // If shadow is enabled, following colors must be skipped unconditionally - if (blitMode == EImageBlitMode::WITH_SHADOW || blitMode == EImageBlitMode::WITH_SHADOW_AND_OVERLAY) + if (blitMode == EImageBlitMode::WITH_SHADOW || blitMode == EImageBlitMode::WITH_SHADOW_AND_SELECTION || blitMode == EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR) colorsToSkipMask |= (1 << 0) + (1 << 1) + (1 << 4); // Note: here we skip first colors in the palette that are predefined in H3 images @@ -353,7 +367,7 @@ void ScalableImageInstance::setOverlayColor(const ColorRGBA & color) parameters.ovelayColorMultiplier = color; if (parameters.palette) - parameters.setOverlayColor(image->getPalette(), color); + parameters.setOverlayColor(image->getPalette(), color, blitMode == EImageBlitMode::WITH_SHADOW_AND_SELECTION); } void ScalableImageInstance::playerColored(const PlayerColor & player) @@ -414,7 +428,7 @@ std::shared_ptr ScalableImageShared::loadOrGenerateImage(EIm { // optional images for 1x resolution - only try load them, don't attempt to generate // this block should never be called for 'body' layer - that image is loaded unconditionally before construction - assert(mode == EImageBlitMode::ONLY_SHADOW || mode == EImageBlitMode::ONLY_OVERLAY || color != PlayerColor::CANNOT_DETERMINE); + assert(mode == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR || mode == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION || mode == EImageBlitMode::ONLY_FLAG_COLOR || mode == EImageBlitMode::ONLY_SELECTION || color != PlayerColor::CANNOT_DETERMINE); return nullptr; } @@ -427,7 +441,7 @@ std::shared_ptr ScalableImageShared::loadOrGenerateImage(EIm { if (scaling == 1) { - if (mode == EImageBlitMode::ONLY_SHADOW || mode == EImageBlitMode::ONLY_OVERLAY || color != PlayerColor::CANNOT_DETERMINE) + if (mode == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR || mode == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION || mode == EImageBlitMode::ONLY_FLAG_COLOR || mode == EImageBlitMode::ONLY_SELECTION || color != PlayerColor::CANNOT_DETERMINE) { ScalableImageParameters parameters(getPalette(), mode); return loadedImage->scaleInteger(scalingFactor, parameters.palette, mode); @@ -464,9 +478,13 @@ void ScalableImageShared::loadScaledImages(int8_t scalingFactor, PlayerColor col scaled[scalingFactor].body[0] = loadOrGenerateImage(locator.layer, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].body[0]); break; - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: - case EImageBlitMode::ONLY_BODY: - scaled[scalingFactor].body[0] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].body[0]); + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: + case EImageBlitMode::ONLY_BODY_HIDE_SELECTION: + scaled[scalingFactor].body[0] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY_HIDE_SELECTION, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].body[0]); + break; + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + case EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR: + scaled[scalingFactor].body[0] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].body[0]); break; case EImageBlitMode::WITH_SHADOW: @@ -486,9 +504,13 @@ void ScalableImageShared::loadScaledImages(int8_t scalingFactor, PlayerColor col scaled[scalingFactor].playerColored[1+color.getNum()] = loadOrGenerateImage(locator.layer, scalingFactor, color, scaled[1].playerColored[1+color.getNum()]); break; - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: - case EImageBlitMode::ONLY_BODY: - scaled[scalingFactor].playerColored[1+color.getNum()] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY, scalingFactor, color, scaled[1].playerColored[1+color.getNum()]); + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: + case EImageBlitMode::ONLY_BODY_HIDE_SELECTION: + scaled[scalingFactor].playerColored[1+color.getNum()] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY_HIDE_SELECTION, scalingFactor, color, scaled[1].playerColored[1+color.getNum()]); + break; + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + case EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR: + scaled[scalingFactor].playerColored[1+color.getNum()] = loadOrGenerateImage(EImageBlitMode::ONLY_BODY_HIDE_FLAG_COLOR, scalingFactor, color, scaled[1].playerColored[1+color.getNum()]); break; case EImageBlitMode::WITH_SHADOW: @@ -503,9 +525,13 @@ void ScalableImageShared::loadScaledImages(int8_t scalingFactor, PlayerColor col switch(locator.layer) { case EImageBlitMode::WITH_SHADOW: - case EImageBlitMode::ONLY_SHADOW: - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: - scaled[scalingFactor].shadow[0] = loadOrGenerateImage(EImageBlitMode::ONLY_SHADOW, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].shadow[0]); + case EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION: + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: + scaled[scalingFactor].shadow[0] = loadOrGenerateImage(EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].shadow[0]); + break; + case EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR: + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + scaled[scalingFactor].shadow[0] = loadOrGenerateImage(EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].shadow[0]); break; default: break; @@ -516,9 +542,13 @@ void ScalableImageShared::loadScaledImages(int8_t scalingFactor, PlayerColor col { switch(locator.layer) { - case EImageBlitMode::ONLY_OVERLAY: - case EImageBlitMode::WITH_SHADOW_AND_OVERLAY: - scaled[scalingFactor].overlay[0] = loadOrGenerateImage(EImageBlitMode::ONLY_OVERLAY, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].overlay[0]); + case EImageBlitMode::ONLY_FLAG_COLOR: + case EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR: + scaled[scalingFactor].overlay[0] = loadOrGenerateImage(EImageBlitMode::ONLY_FLAG_COLOR, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].overlay[0]); + break; + case EImageBlitMode::ONLY_SELECTION: + case EImageBlitMode::WITH_SHADOW_AND_SELECTION: + scaled[scalingFactor].overlay[0] = loadOrGenerateImage(EImageBlitMode::ONLY_SELECTION, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].overlay[0]); break; default: break; diff --git a/client/renderSDL/ScalableImage.h b/client/renderSDL/ScalableImage.h index d662f9a01..7578130c2 100644 --- a/client/renderSDL/ScalableImage.h +++ b/client/renderSDL/ScalableImage.h @@ -39,7 +39,7 @@ struct ScalableImageParameters : boost::noncopyable void setShadowTransparency(const SDL_Palette * originalPalette, float factor); void shiftPalette(const SDL_Palette * originalPalette, uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove); void playerColored(PlayerColor player); - void setOverlayColor(const SDL_Palette * originalPalette, const ColorRGBA & color); + void setOverlayColor(const SDL_Palette * originalPalette, const ColorRGBA & color, bool includeShadow); void preparePalette(const SDL_Palette * originalPalette, EImageBlitMode blitMode); void adjustPalette(const SDL_Palette * originalPalette, EImageBlitMode blitMode, const ColorFilter & shifter, uint32_t colorsToSkipMask); }; diff --git a/client/widgets/Images.cpp b/client/widgets/Images.cpp index 6693300e3..4757e5736 100644 --- a/client/widgets/Images.cpp +++ b/client/widgets/Images.cpp @@ -195,12 +195,12 @@ CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, size_t Group, i { pos.x += x; pos.y += y; - anim = GH.renderHandler().loadAnimation(name, (Flags & CCreatureAnim::CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_OVERLAY : EImageBlitMode::COLORKEY); + anim = GH.renderHandler().loadAnimation(name, (Flags & CCreatureAnim::CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_SELECTION: EImageBlitMode::COLORKEY); init(); } CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, Rect targetPos, size_t Group, ui8 Flags): - anim(GH.renderHandler().loadAnimation(name, (Flags & CCreatureAnim::CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_OVERLAY : EImageBlitMode::COLORKEY)), + anim(GH.renderHandler().loadAnimation(name, (Flags & CCreatureAnim::CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_SELECTION : EImageBlitMode::COLORKEY)), frame(Frame), group(Group), flags(Flags), @@ -318,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, (Flags & CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_OVERLAY : EImageBlitMode::COLORKEY)), + anim(GH.renderHandler().loadAnimation(name, (Flags & CREATURE_MODE) ? EImageBlitMode::WITH_SHADOW_AND_SELECTION : EImageBlitMode::COLORKEY)), group(Group), frame(0), first(0),