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:
		| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| }; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
| {} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user