1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

More robust management of body/shadow/overlay split

This commit is contained in:
Ivan Savenko
2024-11-17 17:54:55 +00:00
parent c82db9d574
commit 251155d913
19 changed files with 163 additions and 176 deletions

View File

@@ -28,9 +28,7 @@ ImageScaled::ImageScaled(const ImageLocator & inputLocator, const std::shared_pt
, alphaValue(SDL_ALPHA_OPAQUE)
, blitMode(mode)
{
setBodyEnabled(true);
if (mode == EImageBlitMode::ALPHA)
setShadowEnabled(true);
prepareImages();
}
std::shared_ptr<const ISharedImage> ImageScaled::getSharedImage() const
@@ -92,8 +90,7 @@ void ImageScaled::setOverlayColor(const ColorRGBA & color)
void ImageScaled::playerColored(PlayerColor player)
{
playerColor = player;
if (body)
setBodyEnabled(true); // regenerate
prepareImages();
}
void ImageScaled::shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove)
@@ -106,41 +103,63 @@ void ImageScaled::adjustPalette(const ColorFilter &shifter, uint32_t colorsToSki
// TODO: implement
}
void ImageScaled::setShadowEnabled(bool on)
void ImageScaled::prepareImages()
{
assert(blitMode == EImageBlitMode::ALPHA);
if (on)
switch(blitMode)
{
locator.layer = EImageLayer::SHADOW;
locator.playerColored = PlayerColor::CANNOT_DETERMINE;
shadow = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
}
else
shadow = nullptr;
}
case EImageBlitMode::OPAQUE:
case EImageBlitMode::COLORKEY:
case EImageBlitMode::SIMPLE:
locator.layer = blitMode;
locator.playerColored = playerColor;
body = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
break;
void ImageScaled::setBodyEnabled(bool on)
{
if (on)
case EImageBlitMode::WITH_SHADOW_AND_OVERLAY:
case EImageBlitMode::ONLY_BODY:
locator.layer = EImageBlitMode::ONLY_BODY;
locator.playerColored = playerColor;
body = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
break;
case EImageBlitMode::WITH_SHADOW:
case EImageBlitMode::ONLY_BODY_IGNORE_OVERLAY:
locator.layer = EImageBlitMode::ONLY_BODY_IGNORE_OVERLAY;
locator.playerColored = playerColor;
body = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
break;
case EImageBlitMode::ONLY_SHADOW:
case EImageBlitMode::ONLY_OVERLAY:
body = nullptr;
break;
}
switch(blitMode)
{
locator.layer = blitMode == EImageBlitMode::ALPHA ? EImageLayer::BODY : EImageLayer::ALL;
locator.playerColored = playerColor;
body = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
case EImageBlitMode::SIMPLE:
case EImageBlitMode::WITH_SHADOW:
case EImageBlitMode::ONLY_SHADOW:
case EImageBlitMode::WITH_SHADOW_AND_OVERLAY:
locator.layer = EImageBlitMode::ONLY_SHADOW;
locator.playerColored = PlayerColor::CANNOT_DETERMINE;
shadow = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
break;
default:
shadow = nullptr;
break;
}
else
body = nullptr;
}
void ImageScaled::setOverlayEnabled(bool on)
{
assert(blitMode == EImageBlitMode::ALPHA);
if (on)
switch(blitMode)
{
locator.layer = EImageLayer::OVERLAY;
locator.playerColored = PlayerColor::CANNOT_DETERMINE;
overlay = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
case EImageBlitMode::ONLY_OVERLAY:
case EImageBlitMode::WITH_SHADOW_AND_OVERLAY:
locator.layer = EImageBlitMode::ONLY_OVERLAY;
locator.playerColored = PlayerColor::CANNOT_DETERMINE;
overlay = GH.renderHandler().loadImage(locator, blitMode)->getSharedImage();
break;
default:
overlay = nullptr;
break;
}
else
overlay = nullptr;
}

View File

@@ -44,6 +44,7 @@ private:
uint8_t alphaValue;
EImageBlitMode blitMode;
void prepareImages();
public:
ImageScaled(const ImageLocator & locator, const std::shared_ptr<const ISharedImage> & source, EImageBlitMode mode);
@@ -60,8 +61,5 @@ public:
void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override;
void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override;
void setShadowEnabled(bool on) override;
void setBodyEnabled(bool on) override;
void setOverlayEnabled(bool on) override;
std::shared_ptr<const ISharedImage> getSharedImage() const override;
};

View File

@@ -303,22 +303,14 @@ std::shared_ptr<const ISharedImage> RenderHandler::scaleImage(const ImageLocator
if (imageFiles.count(locator))
return imageFiles.at(locator);
auto handle = image->createImageReference(locator.layer == EImageLayer::ALL ? EImageBlitMode::OPAQUE : EImageBlitMode::ALPHA);
auto handle = image->createImageReference(locator.layer);
assert(locator.scalingFactor != 1); // should be filtered-out before
handle->setBodyEnabled(locator.layer == EImageLayer::ALL || locator.layer == EImageLayer::BODY);
if (locator.layer != EImageLayer::ALL)
{
handle->setOverlayEnabled(locator.layer == EImageLayer::OVERLAY);
handle->setShadowEnabled( locator.layer == EImageLayer::SHADOW);
}
if (locator.layer == EImageLayer::ALL && locator.playerColored != PlayerColor::CANNOT_DETERMINE)
if (locator.playerColored != PlayerColor::CANNOT_DETERMINE)
handle->playerColored(locator.playerColored);
handle->scaleInteger(locator.scalingFactor);
// TODO: try to optimize image size (possibly even before scaling?) - trim image borders if they are completely transparent
auto result = handle->getSharedImage();
storeCachedImage(locator, result);
return result;
@@ -331,9 +323,9 @@ std::shared_ptr<IImage> RenderHandler::loadImage(const ImageLocator & locator, E
if(adjustedLocator.image)
{
std::string imgPath = (*adjustedLocator.image).getName();
if(adjustedLocator.layer == EImageLayer::OVERLAY)
if(adjustedLocator.layer == EImageBlitMode::ONLY_OVERLAY)
imgPath += "-OVERLAY";
if(adjustedLocator.layer == EImageLayer::SHADOW)
if(adjustedLocator.layer == EImageBlitMode::ONLY_SHADOW)
imgPath += "-SHADOW";
if(CResourceHandler::get()->existsResource(ImagePath::builtin(imgPath)) ||
@@ -394,7 +386,7 @@ std::shared_ptr<IImage> RenderHandler::loadImage(const ImagePath & path, EImageB
std::shared_ptr<IImage> RenderHandler::createImage(SDL_Surface * source)
{
return std::make_shared<SDLImageShared>(source)->createImageReference(EImageBlitMode::ALPHA);
return std::make_shared<SDLImageShared>(source)->createImageReference(EImageBlitMode::SIMPLE);
}
std::shared_ptr<CAnimation> RenderHandler::loadAnimation(const AnimationPath & path, EImageBlitMode mode)

View File

@@ -180,7 +180,7 @@ void SDLImageShared::draw(SDL_Surface * where, SDL_Palette * palette, const Poin
if (palette && surf->format->palette)
SDL_SetSurfacePalette(surf, palette);
if(surf->format->palette && mode == EImageBlitMode::ALPHA)
if(surf->format->palette && mode != EImageBlitMode::OPAQUE && mode != EImageBlitMode::COLORKEY)
{
CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift, alpha);
}
@@ -425,7 +425,7 @@ void SDLImageIndexed::shiftPalette(uint32_t firstColorID, uint32_t colorsToMove,
void SDLImageIndexed::adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask)
{
// If shadow is enabled, following colors must be skipped unconditionally
if (shadowEnabled)
if (blitMode == EImageBlitMode::WITH_SHADOW || blitMode == EImageBlitMode::WITH_SHADOW_AND_OVERLAY)
colorsToSkipMask |= (1 << 0) + (1 << 1) + (1 << 4);
// Note: here we skip first colors in the palette that are predefined in H3 images
@@ -445,15 +445,10 @@ SDLImageIndexed::SDLImageIndexed(const std::shared_ptr<const ISharedImage> & ima
:SDLImageBase::SDLImageBase(image, mode)
,originalPalette(originalPalette)
{
currentPalette = SDL_AllocPalette(originalPalette->ncolors);
SDL_SetPaletteColors(currentPalette, originalPalette->colors, 0, originalPalette->ncolors);
if (mode == EImageBlitMode::ALPHA)
{
setOverlayColor(Colors::TRANSPARENCY);
setShadowTransparency(1.0);
}
preparePalette();
}
SDLImageIndexed::~SDLImageIndexed()
@@ -500,36 +495,42 @@ void SDLImageIndexed::setOverlayColor(const ColorRGBA & color)
}
}
void SDLImageIndexed::setShadowEnabled(bool on)
void SDLImageIndexed::preparePalette()
{
if (on)
setShadowTransparency(1.0);
switch(blitMode)
{
case EImageBlitMode::ONLY_SHADOW:
case EImageBlitMode::ONLY_OVERLAY:
adjustPalette(ColorFilter::genAlphaShifter(0), 0);
break;
}
if (!on && blitMode == EImageBlitMode::ALPHA)
setShadowTransparency(0.0);
switch(blitMode)
{
case EImageBlitMode::SIMPLE:
case EImageBlitMode::WITH_SHADOW:
case EImageBlitMode::ONLY_SHADOW:
case EImageBlitMode::WITH_SHADOW_AND_OVERLAY:
setShadowTransparency(1.0);
break;
case EImageBlitMode::ONLY_BODY:
case EImageBlitMode::ONLY_BODY_IGNORE_OVERLAY:
case EImageBlitMode::ONLY_OVERLAY:
setShadowTransparency(0.0);
break;
}
shadowEnabled = on;
}
void SDLImageIndexed::setBodyEnabled(bool on)
{
if (on)
adjustPalette(ColorFilter::genEmptyShifter(), 0);
else
adjustPalette(ColorFilter::genAlphaShifter(0), 0);
bodyEnabled = on;
}
void SDLImageIndexed::setOverlayEnabled(bool on)
{
if (on)
setOverlayColor(Colors::WHITE_TRUE);
if (!on && blitMode == EImageBlitMode::ALPHA)
setOverlayColor(Colors::TRANSPARENCY);
overlayEnabled = on;
switch(blitMode)
{
case EImageBlitMode::ONLY_OVERLAY:
case EImageBlitMode::WITH_SHADOW_AND_OVERLAY:
setOverlayColor(Colors::WHITE_TRUE);
break;
case EImageBlitMode::ONLY_SHADOW:
case EImageBlitMode::ONLY_BODY:
setOverlayColor(Colors::TRANSPARENCY);
break;
}
}
SDLImageShared::~SDLImageShared()
@@ -609,21 +610,6 @@ void SDLImageBase::setBlitMode(EImageBlitMode mode)
blitMode = mode;
}
void SDLImageRGB::setShadowEnabled(bool on)
{
// Not supported. Theoretically we can try to extract all pixels of specific colors, but better to use 8-bit images or composite images
}
void SDLImageRGB::setBodyEnabled(bool on)
{
// Not supported. Theoretically we can try to extract all pixels of specific colors, but better to use 8-bit images or composite images
}
void SDLImageRGB::setOverlayEnabled(bool on)
{
// Not supported. Theoretically we can try to extract all pixels of specific colors, but better to use 8-bit images or composite images
}
void SDLImageRGB::setOverlayColor(const ColorRGBA & color)
{}

View File

@@ -89,11 +89,8 @@ class SDLImageIndexed final : public SDLImageBase
SDL_Palette * currentPalette = nullptr;
SDL_Palette * originalPalette = nullptr;
bool bodyEnabled = true;
bool shadowEnabled = false;
bool overlayEnabled = false;
void setShadowTransparency(float factor);
void preparePalette();
public:
SDLImageIndexed(const std::shared_ptr<const ISharedImage> & image, SDL_Palette * palette, EImageBlitMode mode);
~SDLImageIndexed();
@@ -106,10 +103,6 @@ public:
void scaleInteger(int factor) override;
void scaleTo(const Point & size) override;
void exportBitmap(const boost::filesystem::path & path) const override;
void setShadowEnabled(bool on) override;
void setBodyEnabled(bool on) override;
void setOverlayEnabled(bool on) override;
};
class SDLImageRGB final : public SDLImageBase
@@ -125,8 +118,4 @@ public:
void scaleInteger(int factor) override;
void scaleTo(const Point & size) override;
void exportBitmap(const boost::filesystem::path & path) const override;
void setShadowEnabled(bool on) override;
void setBodyEnabled(bool on) override;
void setOverlayEnabled(bool on) override;
};