mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Created separate classes for shared, unchangeable image and image
manipulators owned by UI elements
This commit is contained in:
		| @@ -1143,9 +1143,9 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component | ||||
| 		const CGTownInstance * t = dynamic_cast<const CGTownInstance *>(cb->getObj(obj)); | ||||
| 		if(t) | ||||
| 		{ | ||||
| 			std::shared_ptr<CAnimation> a = GH.renderHandler().loadAnimation(AnimationPath::builtin("ITPA")); | ||||
| 			a->preload(); | ||||
| 			images.push_back(a->getImage(t->town->clientInfo.icons[t->hasFort()][false] + 2)->scaleFast(Point(35, 23))); | ||||
| 			auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0); | ||||
| 			image->scaleFast(Point(35, 23)); | ||||
| 			images.push_back(image); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -81,14 +81,14 @@ void Canvas::draw(const std::shared_ptr<IImage>& image, const Point & pos) | ||||
| { | ||||
| 	assert(image); | ||||
| 	if (image) | ||||
| 		image->draw(surface, renderArea.x + pos.x, renderArea.y + pos.y); | ||||
| 		image->draw(surface, pos + renderArea.topLeft()); | ||||
| } | ||||
|  | ||||
| void Canvas::draw(const std::shared_ptr<IImage>& image, const Point & pos, const Rect & sourceRect) | ||||
| { | ||||
| 	assert(image); | ||||
| 	if (image) | ||||
| 		image->draw(surface, renderArea.x + pos.x, renderArea.y + pos.y, &sourceRect); | ||||
| 		image->draw(surface, pos + renderArea.topLeft(), &sourceRect); | ||||
| } | ||||
|  | ||||
| void Canvas::draw(const Canvas & image, const Point & pos) | ||||
| @@ -192,7 +192,7 @@ void Canvas::fillTexture(const std::shared_ptr<IImage>& image) | ||||
| 	for (int y=0; y < surface->h; y+= imageArea.h) | ||||
| 	{ | ||||
| 		for (int x=0; x < surface->w; x+= imageArea.w) | ||||
| 			image->draw(surface, renderArea.x + x, renderArea.y + y); | ||||
| 			image->draw(surface, Point(renderArea.x + x, renderArea.y + y)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -135,9 +135,7 @@ Graphics::Graphics() | ||||
| 	//(!) do not load any CAnimation here | ||||
| } | ||||
|  | ||||
| void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player) | ||||
| { | ||||
| 	if(sur->format->palette) | ||||
| void Graphics::setPlayerPalette(SDL_Palette * targetPalette, PlayerColor player) | ||||
| { | ||||
| 	SDL_Color palette[32]; | ||||
| 	if(player.isValidPlayer()) | ||||
| @@ -145,61 +143,26 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player) | ||||
| 		for(int i=0; i<32; ++i) | ||||
| 			palette[i] = CSDL_Ext::toSDL(playerColorPalette[player][i]); | ||||
| 	} | ||||
| 		else if(player == PlayerColor::NEUTRAL) | ||||
| 	else | ||||
| 	{ | ||||
| 		for(int i=0; i<32; ++i) | ||||
| 			palette[i] = CSDL_Ext::toSDL(neutralColorPalette[i]); | ||||
| 	} | ||||
| 		else | ||||
| 		{ | ||||
| 			logGlobal->error("Wrong player id in blueToPlayersAdv (%s)!", player.toString()); | ||||
| 			return; | ||||
| 		} | ||||
| //FIXME: not all player colored images have player palette at last 32 indexes | ||||
| //NOTE: following code is much more correct but still not perfect (bugged with status bar) | ||||
| 		CSDL_Ext::setColors(sur, palette, 224, 32); | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
| 		SDL_Color * bluePalette = playerColorPalette + 32; | ||||
|  | ||||
| 		SDL_Palette * oldPalette = sur->format->palette; | ||||
|  | ||||
| 		SDL_Palette * newPalette = SDL_AllocPalette(256); | ||||
|  | ||||
| 		for(size_t destIndex = 0; destIndex < 256; destIndex++) | ||||
| 		{ | ||||
| 			SDL_Color old = oldPalette->colors[destIndex]; | ||||
|  | ||||
| 			bool found = false; | ||||
|  | ||||
| 			for(size_t srcIndex = 0; srcIndex < 32; srcIndex++) | ||||
| 			{ | ||||
| 				if(old.b == bluePalette[srcIndex].b && old.g == bluePalette[srcIndex].g && old.r == bluePalette[srcIndex].r) | ||||
| 				{ | ||||
| 					found = true; | ||||
| 					newPalette->colors[destIndex] = palette[srcIndex]; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			if(!found) | ||||
| 				newPalette->colors[destIndex] = old; | ||||
| 	SDL_SetPaletteColors(targetPalette, palette, 224, 32); | ||||
| } | ||||
|  | ||||
| 		SDL_SetSurfacePalette(sur, newPalette); | ||||
|  | ||||
| 		SDL_FreePalette(newPalette); | ||||
|  | ||||
| #endif // 0 | ||||
| void Graphics::setPlayerFlagColor(SDL_Palette * targetPalette, PlayerColor player) | ||||
| { | ||||
| 	if(player.isValidPlayer()) | ||||
| 	{ | ||||
| 		SDL_Color color = CSDL_Ext::toSDL(playerColors[player.getNum()]); | ||||
| 		SDL_SetPaletteColors(targetPalette, &color, 5, 1); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		//TODO: implement. H3 method works only for images with palettes. | ||||
| 		// Add some kind of player-colored overlay? | ||||
| 		// Or keep palette approach here and replace only colors of specific value(s) | ||||
| 		// Or just wait for OpenGL support? | ||||
| 		logGlobal->warn("Image must have palette to be player-colored!"); | ||||
| 		SDL_Color color = CSDL_Ext::toSDL(neutralColor); | ||||
| 		SDL_SetPaletteColors(targetPalette, &color, 5, 1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -27,7 +27,7 @@ class JsonNode; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| struct SDL_Surface; | ||||
| struct SDL_Palette; | ||||
| class IFont; | ||||
|  | ||||
| /// Handles fonts, hero images, town images, various graphics | ||||
| @@ -60,7 +60,8 @@ public: | ||||
| 	//functions | ||||
| 	Graphics(); | ||||
|  | ||||
| 	void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player | ||||
| 	void setPlayerPalette(SDL_Palette * sur, PlayerColor player); | ||||
| 	void setPlayerFlagColor(SDL_Palette * sur, PlayerColor player); | ||||
| }; | ||||
|  | ||||
| extern Graphics * graphics; | ||||
|   | ||||
| @@ -46,10 +46,10 @@ public: | ||||
| 	static constexpr int32_t SPECIAL_PALETTE_MASK_CREATURES = 0b11110011; | ||||
|  | ||||
| 	//draws image on surface "where" at position | ||||
| 	virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0; | ||||
| 	virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0; | ||||
| 	virtual void draw(SDL_Surface * where, const Point & pos, const Rect * src = nullptr) const = 0; | ||||
| 	//virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0; | ||||
|  | ||||
| 	virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0; | ||||
| 	virtual void scaleFast(const Point & size) = 0; | ||||
|  | ||||
| 	virtual void exportBitmap(const boost::filesystem::path & path) const = 0; | ||||
|  | ||||
| @@ -81,3 +81,15 @@ public: | ||||
|  | ||||
| 	virtual ~IImage() = default; | ||||
| }; | ||||
|  | ||||
| class IConstImage | ||||
| { | ||||
| public: | ||||
| 	virtual Point dimensions() const = 0; | ||||
| 	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 ~IConstImage() = default; | ||||
| }; | ||||
|   | ||||
| @@ -14,8 +14,6 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| class Point; | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| class SDLImage; | ||||
|  | ||||
| struct SDL_Color; | ||||
|  | ||||
| class IImageLoader | ||||
|   | ||||
| @@ -49,7 +49,7 @@ void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivot | ||||
|  | ||||
| 	CSDL_Ext::fillSurface(cursorSurface, CSDL_Ext::toSDL(Colors::TRANSPARENCY)); | ||||
|  | ||||
| 	image->draw(cursorSurface); | ||||
| 	image->draw(cursorSurface, Point(0,0)); | ||||
|  | ||||
| 	auto oldCursor = cursor; | ||||
| 	cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y); | ||||
|   | ||||
| @@ -58,7 +58,7 @@ void CursorSoftware::updateTexture() | ||||
|  | ||||
| 	CSDL_Ext::fillSurface(cursorSurface, CSDL_Ext::toSDL(Colors::TRANSPARENCY)); | ||||
|  | ||||
| 	cursorImage->draw(cursorSurface); | ||||
| 	cursorImage->draw(cursorSurface, Point(0,0)); | ||||
| 	SDL_UpdateTexture(cursorTexture, nullptr, cursorSurface->pixels, cursorSurface->pitch); | ||||
| 	needUpdate = false; | ||||
| } | ||||
|   | ||||
| @@ -134,13 +134,13 @@ std::shared_ptr<IImage> RenderHandler::loadImage(const AnimationPath & path, int | ||||
|  | ||||
| 	auto it = animationFrames.find(locator); | ||||
| 	if (it != animationFrames.end()) | ||||
| 		return it->second; | ||||
| 		return it->second->createImageReference(); | ||||
|  | ||||
| 	auto defFile = getAnimationFile(path); | ||||
| 	auto result = std::make_shared<SDLImage>(defFile.get(), frame, group); | ||||
| 	auto result = std::make_shared<SDLImageConst>(defFile.get(), frame, group); | ||||
|  | ||||
| 	animationFrames[locator] = result; | ||||
| 	return result; | ||||
| 	return result->createImageReference(); | ||||
| } | ||||
|  | ||||
| //std::vector<std::shared_ptr<IImage>> RenderHandler::loadImageGroup(const AnimationPath & path, int group) | ||||
| @@ -165,16 +165,16 @@ std::shared_ptr<IImage> RenderHandler::loadImage(const ImagePath & path, EImageB | ||||
| { | ||||
| 	auto it = imageFiles.find(path); | ||||
| 	if (it != imageFiles.end()) | ||||
| 		return it->second; | ||||
| 		return it->second->createImageReference(); | ||||
|  | ||||
| 	auto result = std::make_shared<SDLImage>(path, mode); | ||||
| 	auto result = std::make_shared<SDLImageConst>(path, mode); | ||||
| 	imageFiles[path] = result; | ||||
| 	return result; | ||||
| 	return result->createImageReference(); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<IImage> RenderHandler::createImage(SDL_Surface * source) | ||||
| { | ||||
| 	return std::make_shared<SDLImage>(source, EImageBlitMode::ALPHA); | ||||
| 	return std::make_shared<SDLImageConst>(source, EImageBlitMode::ALPHA)->createImageReference(); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<CAnimation> RenderHandler::loadAnimation(const AnimationPath & path) | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include "../render/IRenderHandler.h" | ||||
|  | ||||
| class CDefFile; | ||||
| class IConstImage; | ||||
|  | ||||
| class RenderHandler : public IRenderHandler | ||||
| { | ||||
| @@ -35,8 +36,8 @@ class RenderHandler : public IRenderHandler | ||||
|  | ||||
| 	std::map<AnimationPath, std::shared_ptr<CDefFile>> animationFiles; | ||||
| 	std::map<AnimationPath, AnimationLayoutMap> animationLayouts; | ||||
| 	std::map<ImagePath, std::shared_ptr<IImage>> imageFiles; | ||||
| 	std::map<AnimationLocator, std::shared_ptr<IImage>> animationFrames; | ||||
| 	std::map<ImagePath, std::shared_ptr<IConstImage>> imageFiles; | ||||
| 	std::map<AnimationLocator, std::shared_ptr<IConstImage>> animationFrames; | ||||
|  | ||||
| 	std::shared_ptr<CDefFile> getAnimationFile(const AnimationPath & path); | ||||
| 	const AnimationLayoutMap & getAnimationLayout(const AnimationPath & path); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* | ||||
| /* | ||||
|  * SDLImage.cpp, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
| @@ -32,7 +32,7 @@ int IImage::height() const | ||||
| 	return dimensions().y; | ||||
| } | ||||
|  | ||||
| SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group) | ||||
| SDLImageConst::SDLImageConst(CDefFile * data, size_t frame, size_t group) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| @@ -42,10 +42,9 @@ SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group) | ||||
| 	data->loadFrame(frame, group, loader); | ||||
|  | ||||
| 	savePalette(); | ||||
| 	setBlitMode(EImageBlitMode::ALPHA); | ||||
| } | ||||
|  | ||||
| SDLImage::SDLImage(SDL_Surface * from, EImageBlitMode mode) | ||||
| SDLImageConst::SDLImageConst(SDL_Surface * from, EImageBlitMode mode) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| @@ -56,14 +55,13 @@ SDLImage::SDLImage(SDL_Surface * from, EImageBlitMode mode) | ||||
| 		return; | ||||
|  | ||||
| 	savePalette(); | ||||
| 	setBlitMode(mode); | ||||
|  | ||||
| 	surf->refcount++; | ||||
| 	fullSize.x = surf->w; | ||||
| 	fullSize.y = surf->h; | ||||
| } | ||||
|  | ||||
| SDLImage::SDLImage(const ImagePath & filename, EImageBlitMode mode) | ||||
| SDLImageConst::SDLImageConst(const ImagePath & filename, EImageBlitMode mode) | ||||
| 	: surf(nullptr), | ||||
| 	margins(0, 0), | ||||
| 	fullSize(0, 0), | ||||
| @@ -79,22 +77,13 @@ SDLImage::SDLImage(const ImagePath & filename, EImageBlitMode mode) | ||||
| 	else | ||||
| 	{ | ||||
| 		savePalette(); | ||||
| 		setBlitMode(mode); | ||||
| 		fullSize.x = surf->w; | ||||
| 		fullSize.y = surf->h; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SDLImage::draw(SDL_Surface *where, int posX, int posY, const Rect *src) const | ||||
| { | ||||
| 	if(!surf) | ||||
| 		return; | ||||
|  | ||||
| 	Rect destRect(posX, posY, surf->w, surf->h); | ||||
| 	draw(where, &destRect, src); | ||||
| } | ||||
|  | ||||
| void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) const | ||||
| void SDLImageConst::draw(SDL_Surface * where, SDL_Palette * palette, const Point & dest, const Rect * src, uint8_t alpha, EImageBlitMode mode) const | ||||
| { | ||||
| 	if (!surf) | ||||
| 		return; | ||||
| @@ -118,14 +107,19 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons | ||||
| 	else | ||||
| 		destShift = margins; | ||||
|  | ||||
| 	if(dest) | ||||
| 		destShift += dest->topLeft(); | ||||
| 	destShift += dest; | ||||
|  | ||||
| 	uint8_t perSurfaceAlpha; | ||||
| 	if (SDL_GetSurfaceAlphaMod(surf, &perSurfaceAlpha) != 0) | ||||
| 		logGlobal->error("SDL_GetSurfaceAlphaMod faied! %s", SDL_GetError()); | ||||
| 	SDL_SetSurfaceAlphaMod(surf, alpha); | ||||
|  | ||||
| 	if(surf->format->BitsPerPixel == 8 && perSurfaceAlpha == SDL_ALPHA_OPAQUE && blitMode == EImageBlitMode::ALPHA) | ||||
| 	if (mode == EImageBlitMode::OPAQUE) | ||||
| 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE); | ||||
| 	else | ||||
| 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND); | ||||
|  | ||||
| 	if (palette && surf->format->palette) | ||||
| 		SDL_SetSurfacePalette(surf, palette); | ||||
|  | ||||
| 	if(surf->format->BitsPerPixel == 8 && alpha == SDL_ALPHA_OPAQUE && mode == EImageBlitMode::ALPHA) | ||||
| 	{ | ||||
| 		CSDL_Ext::blit8bppAlphaTo24bpp(surf, sourceRect, where, destShift); | ||||
| 	} | ||||
| @@ -135,10 +129,18 @@ void SDLImage::draw(SDL_Surface* where, const Rect * dest, const Rect* src) cons | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const | ||||
| const SDL_Palette * SDLImageConst::getPalette() const | ||||
| { | ||||
| 	float scaleX = float(size.x) / width(); | ||||
| 	float scaleY = float(size.y) / height(); | ||||
| 	if (originalPalette == nullptr) | ||||
| 		throw std::runtime_error("Palette not found!"); | ||||
|  | ||||
| 	return originalPalette; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<SDLImageConst> SDLImageConst::scaleFast(const Point & size) const | ||||
| { | ||||
| 	float scaleX = float(size.x) / dimensions().x; | ||||
| 	float scaleY = float(size.y) / dimensions().y; | ||||
|  | ||||
| 	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, (int)(surf->w * scaleX), (int)(surf->h * scaleY)); | ||||
|  | ||||
| @@ -149,7 +151,7 @@ std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const | ||||
| 	else | ||||
| 		CSDL_Ext::setDefaultColorKey(scaled);//just in case | ||||
|  | ||||
| 	auto * ret = new SDLImage(scaled, EImageBlitMode::ALPHA); | ||||
| 	auto ret = std::make_shared<SDLImageConst>(scaled, EImageBlitMode::ALPHA); | ||||
|  | ||||
| 	ret->fullSize.x = (int) round((float)fullSize.x * scaleX); | ||||
| 	ret->fullSize.y = (int) round((float)fullSize.y * scaleY); | ||||
| @@ -160,45 +162,26 @@ std::shared_ptr<IImage> SDLImage::scaleFast(const Point & size) const | ||||
| 	// erase our own reference | ||||
| 	SDL_FreeSurface(scaled); | ||||
|  | ||||
| 	return std::shared_ptr<IImage>(ret); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void SDLImage::exportBitmap(const boost::filesystem::path& path) const | ||||
| void SDLImageConst::exportBitmap(const boost::filesystem::path& path) const | ||||
| { | ||||
| 	SDL_SaveBMP(surf, path.string().c_str()); | ||||
| } | ||||
|  | ||||
| void SDLImage::playerColored(PlayerColor player) | ||||
| void SDLImageIndexed::playerColored(PlayerColor player) | ||||
| { | ||||
| 	if (!surf) | ||||
| 		return; | ||||
| 	graphics->blueToPlayersAdv(surf, player); | ||||
| 	graphics->setPlayerPalette(currentPalette, player); | ||||
| } | ||||
|  | ||||
| void SDLImage::setAlpha(uint8_t value) | ||||
| { | ||||
| 	CSDL_Ext::setAlpha (surf, value); | ||||
| 	if (value != 255) | ||||
| 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND); | ||||
| } | ||||
|  | ||||
| void SDLImage::setBlitMode(EImageBlitMode mode) | ||||
| { | ||||
| 	blitMode = mode; | ||||
|  | ||||
| 	if (blitMode != EImageBlitMode::OPAQUE && surf->format->Amask != 0) | ||||
| 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND); | ||||
| 	else | ||||
| 		SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE); | ||||
| } | ||||
|  | ||||
| void SDLImage::setFlagColor(PlayerColor player) | ||||
| void SDLImageIndexed::setFlagColor(PlayerColor player) | ||||
| { | ||||
| 	if(player.isValidPlayer() || player==PlayerColor::NEUTRAL) | ||||
| 		CSDL_Ext::setPlayerColor(surf, player); | ||||
| 		graphics->setPlayerFlagColor(currentPalette, player); | ||||
| } | ||||
|  | ||||
| bool SDLImage::isTransparent(const Point & coords) const | ||||
| bool SDLImageConst::isTransparent(const Point & coords) const | ||||
| { | ||||
| 	if (surf) | ||||
| 		return CSDL_Ext::isTransparent(surf, coords.x, coords.y); | ||||
| @@ -206,33 +189,45 @@ bool SDLImage::isTransparent(const Point & coords) const | ||||
| 		return true; | ||||
| } | ||||
|  | ||||
| Point SDLImage::dimensions() const | ||||
| Point SDLImageConst::dimensions() const | ||||
| { | ||||
| 	return fullSize; | ||||
| } | ||||
|  | ||||
| void SDLImage::horizontalFlip() | ||||
| std::shared_ptr<IImage> SDLImageConst::createImageReference() | ||||
| { | ||||
| 	margins.y = fullSize.y - surf->h - margins.y; | ||||
|  | ||||
| 	//todo: modify in-place | ||||
| 	SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf); | ||||
| 	SDL_FreeSurface(surf); | ||||
| 	surf = flipped; | ||||
| 	if (surf->format->palette) | ||||
| 		return std::make_shared<SDLImageIndexed>(shared_from_this()); | ||||
| 	else | ||||
| 		return std::make_shared<SDLImageRGB>(shared_from_this()); | ||||
| } | ||||
|  | ||||
| void SDLImage::verticalFlip() | ||||
| std::shared_ptr<SDLImageConst> SDLImageConst::horizontalFlip() const | ||||
| { | ||||
| 	margins.x = fullSize.x - surf->w - margins.x; | ||||
| 	SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf); | ||||
| 	auto ret = std::make_shared<SDLImageConst>(flipped, EImageBlitMode::ALPHA); | ||||
| 	ret->fullSize = fullSize; | ||||
| 	ret->margins.x = margins.x; | ||||
| 	ret->margins.y = fullSize.y - surf->h - margins.y; | ||||
| 	ret->fullSize = fullSize; | ||||
|  | ||||
| 	//todo: modify in-place | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<SDLImageConst> SDLImageConst::verticalFlip() const | ||||
| { | ||||
| 	SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf); | ||||
| 	SDL_FreeSurface(surf); | ||||
| 	surf = flipped; | ||||
| 	auto ret = std::make_shared<SDLImageConst>(flipped, EImageBlitMode::ALPHA); | ||||
| 	ret->fullSize = fullSize; | ||||
| 	ret->margins.x = fullSize.x - surf->w - margins.x; | ||||
| 	ret->margins.y = margins.y; | ||||
| 	ret->fullSize = fullSize; | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| // Keep the original palette, in order to do color switching operation | ||||
| void SDLImage::savePalette() | ||||
| void SDLImageConst::savePalette() | ||||
| { | ||||
| 	// For some images that don't have palette, skip this | ||||
| 	if(surf->format->palette == nullptr) | ||||
| @@ -244,53 +239,132 @@ void SDLImage::savePalette() | ||||
| 	SDL_SetPaletteColors(originalPalette, surf->format->palette->colors, 0, DEFAULT_PALETTE_COLORS); | ||||
| } | ||||
|  | ||||
| void SDLImage::shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) | ||||
| { | ||||
| 	if(surf->format->palette) | ||||
| void SDLImageIndexed::shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) | ||||
| { | ||||
| 	const SDL_Palette * originalPalette = image->getPalette(); | ||||
|  | ||||
| 	std::vector<SDL_Color> shifterColors(colorsToMove); | ||||
|  | ||||
| 	for(uint32_t i=0; i<colorsToMove; ++i) | ||||
| 		{ | ||||
| 		shifterColors[(i+distanceToMove)%colorsToMove] = originalPalette->colors[firstColorID + i]; | ||||
| 		} | ||||
| 		CSDL_Ext::setColors(surf, shifterColors.data(), firstColorID, colorsToMove); | ||||
| 	} | ||||
|  | ||||
| 	SDL_SetPaletteColors(currentPalette, shifterColors.data(), firstColorID, colorsToMove); | ||||
| } | ||||
|  | ||||
| void SDLImage::adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) | ||||
| void SDLImageIndexed::adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) | ||||
| { | ||||
| 	if(originalPalette == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	SDL_Palette* palette = surf->format->palette; | ||||
| 	const SDL_Palette * originalPalette = image->getPalette(); | ||||
|  | ||||
| 	// Note: here we skip first colors in the palette that are predefined in H3 images | ||||
| 	for(int i = 0; i < palette->ncolors; i++) | ||||
| 	for(int i = 0; i < currentPalette->ncolors; i++) | ||||
| 	{ | ||||
| 		if(i < std::numeric_limits<uint32_t>::digits && ((colorsToSkipMask >> i) & 1) == 1) | ||||
| 			continue; | ||||
|  | ||||
| 		palette->colors[i] = CSDL_Ext::toSDL(shifter.shiftColor(CSDL_Ext::fromSDL(originalPalette->colors[i]))); | ||||
| 		currentPalette->colors[i] = CSDL_Ext::toSDL(shifter.shiftColor(CSDL_Ext::fromSDL(originalPalette->colors[i]))); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SDLImage::setSpecialPalette(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask) | ||||
| SDLImageIndexed::SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image) | ||||
| 	:SDLImageBase::SDLImageBase(image) | ||||
| { | ||||
| 	if(surf->format->palette) | ||||
| 	auto originalPalette = image->getPalette(); | ||||
|  | ||||
| 	currentPalette = SDL_AllocPalette(originalPalette->ncolors); | ||||
| 	SDL_SetPaletteColors(currentPalette, originalPalette->colors, 0, originalPalette->ncolors); | ||||
| } | ||||
|  | ||||
| SDLImageIndexed::~SDLImageIndexed() | ||||
| { | ||||
| 		size_t last = std::min<size_t>(specialPalette.size(), surf->format->palette->ncolors); | ||||
| 	SDL_FreePalette(currentPalette); | ||||
| } | ||||
|  | ||||
| void SDLImageIndexed::setSpecialPallete(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask) | ||||
| { | ||||
| 	size_t last = std::min<size_t>(specialPalette.size(), currentPalette->ncolors); | ||||
|  | ||||
| 	for (size_t i = 0; i < last; ++i) | ||||
| 	{ | ||||
| 		if(i < std::numeric_limits<uint32_t>::digits && ((colorsToSkipMask >> i) & 1) == 1) | ||||
| 				surf->format->palette->colors[i] = CSDL_Ext::toSDL(specialPalette[i]); | ||||
| 		} | ||||
| 			currentPalette->colors[i] = CSDL_Ext::toSDL(specialPalette[i]); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| SDLImage::~SDLImage() | ||||
| SDLImageConst::~SDLImageConst() | ||||
| { | ||||
| 	SDL_FreeSurface(surf); | ||||
| 	SDL_FreePalette(originalPalette); | ||||
| } | ||||
|  | ||||
| SDLImageBase::SDLImageBase(const std::shared_ptr<SDLImageConst> & image) | ||||
| 	:image(image) | ||||
| 	, alphaValue(SDL_ALPHA_OPAQUE) | ||||
| 	, blitMode(EImageBlitMode::ALPHA) | ||||
| {} | ||||
|  | ||||
| void SDLImageRGB::draw(SDL_Surface * where, const Point & pos, const Rect * src) const | ||||
| { | ||||
| 	image->draw(where, nullptr, pos, src, alphaValue, blitMode); | ||||
| } | ||||
|  | ||||
| void SDLImageIndexed::draw(SDL_Surface * where, const Point & pos, const Rect * src) const | ||||
| { | ||||
| 	image->draw(where, currentPalette, pos, src, alphaValue, blitMode); | ||||
| } | ||||
|  | ||||
| void SDLImageBase::scaleFast(const Point & size) | ||||
| { | ||||
| 	image = image->scaleFast(size); | ||||
| } | ||||
|  | ||||
| void SDLImageBase::exportBitmap(const boost::filesystem::path & path) const | ||||
| { | ||||
| 	image->exportBitmap(path); | ||||
| } | ||||
|  | ||||
| bool SDLImageBase::isTransparent(const Point & coords) const | ||||
| { | ||||
| 	return image->isTransparent(coords); | ||||
| } | ||||
|  | ||||
| Point SDLImageBase::dimensions() const | ||||
| { | ||||
| 	return image->dimensions(); | ||||
| } | ||||
|  | ||||
| void SDLImageBase::setAlpha(uint8_t value) | ||||
| { | ||||
| 	alphaValue = value; | ||||
| } | ||||
|  | ||||
| void SDLImageBase::setBlitMode(EImageBlitMode mode) | ||||
| { | ||||
| 	blitMode = mode; | ||||
| } | ||||
|  | ||||
| void SDLImageBase::horizontalFlip() | ||||
| { | ||||
| 	image = image->horizontalFlip(); | ||||
| } | ||||
|  | ||||
| void SDLImageBase::verticalFlip() | ||||
| { | ||||
| 	image = image->verticalFlip(); | ||||
| } | ||||
|  | ||||
| void SDLImageRGB::setSpecialPallete(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) | ||||
| {} | ||||
|  | ||||
| void SDLImageRGB::playerColored(PlayerColor player) | ||||
| {} | ||||
|  | ||||
| void SDLImageRGB::setFlagColor(PlayerColor player) | ||||
| {} | ||||
|  | ||||
| void SDLImageRGB::shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) | ||||
| {} | ||||
|  | ||||
| void SDLImageRGB::adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) | ||||
| {} | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -24,9 +24,9 @@ struct SDL_Palette; | ||||
| /* | ||||
|  * Wrapper around SDL_Surface | ||||
|  */ | ||||
| class SDLImage : public IImage | ||||
| class SDLImageConst final : public IConstImage, public std::enable_shared_from_this<SDLImageConst>, boost::noncopyable | ||||
| { | ||||
| 	const static int DEFAULT_PALETTE_COLORS = 256; | ||||
| 	static constexpr int DEFAULT_PALETTE_COLORS = 256; | ||||
| 	 | ||||
| 	//Surface without empty borders | ||||
| 	SDL_Surface * surf; | ||||
| @@ -37,40 +37,78 @@ class SDLImage : public IImage | ||||
| 	//total size including borders | ||||
| 	Point fullSize; | ||||
|  | ||||
| 	EImageBlitMode blitMode; | ||||
|  | ||||
| public: | ||||
| 	//Load image from def file | ||||
| 	SDLImage(CDefFile *data, size_t frame, size_t group=0); | ||||
| 	//Load from bitmap file | ||||
| 	SDLImage(const ImagePath & filename, EImageBlitMode blitMode); | ||||
|  | ||||
| 	//Create using existing surface, extraRef will increase refcount on SDL_Surface | ||||
| 	SDLImage(SDL_Surface * from, EImageBlitMode blitMode); | ||||
| 	~SDLImage(); | ||||
|  | ||||
| 	// Keep the original palette, in order to do color switching operation | ||||
| 	void savePalette(); | ||||
|  | ||||
| 	void draw(SDL_Surface * where, int posX=0, int posY=0, const Rect *src=nullptr) const override; | ||||
| 	void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const override; | ||||
| 	std::shared_ptr<IImage> scaleFast(const Point & size) const override; | ||||
| 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); | ||||
| 	//Create using existing surface, extraRef will increase refcount on SDL_Surface | ||||
| 	SDLImageConst(SDL_Surface * from, EImageBlitMode blitMode); | ||||
| 	~SDLImageConst(); | ||||
|  | ||||
| 	void draw(SDL_Surface * where, SDL_Palette * palette, const Point & dest, const Rect * src, uint8_t alpha, EImageBlitMode mode) const; | ||||
|  | ||||
| 	void exportBitmap(const boost::filesystem::path & path) const override; | ||||
| 	void playerColored(PlayerColor player) override; | ||||
| 	void setFlagColor(PlayerColor player) override; | ||||
| 	bool isTransparent(const Point & coords) const override; | ||||
| 	Point dimensions() const override; | ||||
| 	bool isTransparent(const Point & coords) const override; | ||||
| 	std::shared_ptr<IImage> createImageReference() override; | ||||
| 	std::shared_ptr<SDLImageConst> horizontalFlip() const; | ||||
| 	std::shared_ptr<SDLImageConst> verticalFlip() const; | ||||
| 	std::shared_ptr<SDLImageConst> scaleFast(const Point & size) const; | ||||
|  | ||||
| 	void horizontalFlip() override; | ||||
| 	void verticalFlip() override; | ||||
|  | ||||
| 	void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override; | ||||
| 	void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override; | ||||
|  | ||||
| 	void setAlpha(uint8_t value) override; | ||||
| 	void setBlitMode(EImageBlitMode mode) override; | ||||
|  | ||||
| 	void setSpecialPalette(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) override; | ||||
| 	const SDL_Palette * getPalette() const; | ||||
|  | ||||
| 	friend class SDLImageLoader; | ||||
| }; | ||||
|  | ||||
| class SDLImageBase : public IImage, boost::noncopyable | ||||
| { | ||||
| protected: | ||||
| 	std::shared_ptr<SDLImageConst> image; | ||||
|  | ||||
| 	uint8_t alphaValue; | ||||
| 	EImageBlitMode blitMode; | ||||
|  | ||||
| public: | ||||
| 	SDLImageBase(const std::shared_ptr<SDLImageConst> & image); | ||||
|  | ||||
| 	void scaleFast(const Point & size) override; | ||||
| 	void exportBitmap(const boost::filesystem::path & path) const override; | ||||
| 	bool isTransparent(const Point & coords) const override; | ||||
| 	Point dimensions() const override; | ||||
| 	void setAlpha(uint8_t value) override; | ||||
| 	void setBlitMode(EImageBlitMode mode) override; | ||||
| 	void horizontalFlip() override; | ||||
| 	void verticalFlip() override; | ||||
| }; | ||||
|  | ||||
| class SDLImageIndexed final : public SDLImageBase | ||||
| { | ||||
| 	SDL_Palette * currentPalette = nullptr; | ||||
|  | ||||
| public: | ||||
| 	SDLImageIndexed(const std::shared_ptr<SDLImageConst> & image); | ||||
| 	~SDLImageIndexed(); | ||||
|  | ||||
| 	void draw(SDL_Surface * where, const Point & pos, const Rect * src) const override; | ||||
| 	void setSpecialPallete(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) override; | ||||
| 	void playerColored(PlayerColor player) override; | ||||
| 	void setFlagColor(PlayerColor player) override; | ||||
| 	void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override; | ||||
| 	void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override; | ||||
| }; | ||||
|  | ||||
| class SDLImageRGB final : public SDLImageBase | ||||
| { | ||||
| public: | ||||
| 	using SDLImageBase::SDLImageBase; | ||||
|  | ||||
| 	void draw(SDL_Surface * where, const Point & pos, const Rect * src) const override; | ||||
| 	void playerColored(PlayerColor player) override; | ||||
| 	void setFlagColor(PlayerColor player) override; | ||||
| 	void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override; | ||||
| 	void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override; | ||||
| }; | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| #include <SDL_surface.h> | ||||
|  | ||||
| SDLImageLoader::SDLImageLoader(SDLImage * Img): | ||||
| SDLImageLoader::SDLImageLoader(SDLImageConst * Img): | ||||
| 	image(Img), | ||||
| 	lineStart(nullptr), | ||||
| 	position(nullptr) | ||||
| @@ -32,8 +32,8 @@ void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_C | ||||
| 	image->fullSize = FullSize; | ||||
|  | ||||
| 	//Prepare surface | ||||
| 	SDL_Palette * p = SDL_AllocPalette(SDLImage::DEFAULT_PALETTE_COLORS); | ||||
| 	SDL_SetPaletteColors(p, pal, 0, SDLImage::DEFAULT_PALETTE_COLORS); | ||||
| 	SDL_Palette * p = SDL_AllocPalette(SDLImageConst::DEFAULT_PALETTE_COLORS); | ||||
| 	SDL_SetPaletteColors(p, pal, 0, SDLImageConst::DEFAULT_PALETTE_COLORS); | ||||
| 	SDL_SetSurfacePalette(image->surf, p); | ||||
| 	SDL_FreePalette(p); | ||||
|  | ||||
|   | ||||
| @@ -11,9 +11,11 @@ | ||||
|  | ||||
| #include "../render/IImageLoader.h" | ||||
|  | ||||
| class SDLImageConst; | ||||
|  | ||||
| class SDLImageLoader : public IImageLoader | ||||
| { | ||||
| 	SDLImage * image; | ||||
| 	SDLImageConst * image; | ||||
| 	ui8 * lineStart; | ||||
| 	ui8 * position; | ||||
| public: | ||||
| @@ -25,7 +27,7 @@ public: | ||||
| 	//init image with these sizes and palette | ||||
| 	void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal); | ||||
|  | ||||
| 	SDLImageLoader(SDLImage * Img); | ||||
| 	SDLImageLoader(SDLImageConst * Img); | ||||
| 	~SDLImageLoader(); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -524,23 +524,6 @@ void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &co | ||||
| 	drawBorder(sur, r.x, r.y, r.w, r.h, color, depth); | ||||
| } | ||||
|  | ||||
| void CSDL_Ext::setPlayerColor(SDL_Surface * sur, const PlayerColor & player) | ||||
| { | ||||
| 	if(player==PlayerColor::UNFLAGGABLE) | ||||
| 		return; | ||||
| 	if(sur->format->BitsPerPixel==8) | ||||
| 	{ | ||||
| 		ColorRGBA color = (player == PlayerColor::NEUTRAL | ||||
| 							? graphics->neutralColor | ||||
| 							: graphics->playerColors[player.getNum()]); | ||||
|  | ||||
| 		SDL_Color colorSDL = toSDL(color); | ||||
| 		CSDL_Ext::setColors(sur, &colorSDL, 5, 1); | ||||
| 	} | ||||
| 	else | ||||
| 		logGlobal->warn("Warning, setPlayerColor called on not 8bpp surface!"); | ||||
| } | ||||
|  | ||||
| CSDL_Ext::TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing) | ||||
| { | ||||
| #define CASE_BPP(BytesPerPixel)							\ | ||||
|   | ||||
| @@ -86,7 +86,6 @@ using TColorPutterAlpha = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, | ||||
|  | ||||
| 	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color & color, int depth = 1); | ||||
| 	void drawBorder(SDL_Surface * sur, const Rect & r, const SDL_Color & color, int depth = 1); | ||||
| 	void setPlayerColor(SDL_Surface * sur, const PlayerColor & player); //sets correct color of flags; -1 for neutral | ||||
|  | ||||
| 	SDL_Surface * newSurface(int w, int h, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given | ||||
| 	SDL_Surface * newSurface(int w, int h); //creates new surface, with flags/format same as in screen surface | ||||
|   | ||||
| @@ -100,7 +100,7 @@ void CPicture::setAlpha(uint8_t value) | ||||
|  | ||||
| void CPicture::scaleTo(Point size) | ||||
| { | ||||
| 	bg = bg->scaleFast(size); | ||||
| 	bg->scaleFast(size); | ||||
|  | ||||
| 	pos.w = bg->width(); | ||||
| 	pos.h = bg->height(); | ||||
| @@ -262,11 +262,8 @@ void CAnimImage::showAll(Canvas & to) | ||||
| 		if(auto img = anim->getImage(targetFrame, group)) | ||||
| 		{ | ||||
| 			if(isScaled()) | ||||
| 			{ | ||||
| 				auto scaled = img->scaleFast(scaledSize); | ||||
| 				to.draw(scaled, pos.topLeft()); | ||||
| 			} | ||||
| 			else | ||||
| 				img->scaleFast(scaledSize); | ||||
|  | ||||
| 			to.draw(img, pos.topLeft()); | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -885,9 +885,9 @@ void CCastleBuildings::enterCastleGate() | ||||
| 			availableTowns.push_back(t->id.getNum());//add to the list | ||||
| 			if(settings["general"]["enableUiEnhancements"].Bool()) | ||||
| 			{ | ||||
| 				std::shared_ptr<CAnimation> a = GH.renderHandler().loadAnimation(AnimationPath::builtin("ITPA")); | ||||
| 				a->preload(); | ||||
| 				images.push_back(a->getImage(t->town->clientInfo.icons[t->hasFort()][false] + 2)->scaleFast(Point(35, 23))); | ||||
| 				auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0); | ||||
| 				image->scaleFast(Point(35, 23)); | ||||
| 				images.push_back(image); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -237,9 +237,10 @@ void CWindowWithArtifacts::setCursorAnimation(const CArtifactInstance & artInst) | ||||
| 	if(artInst.isScroll() && settings["general"]["enableUiEnhancements"].Bool()) | ||||
| 	{ | ||||
| 		assert(artInst.getScrollSpellID().num >= 0); | ||||
| 		const auto animation = GH.renderHandler().loadAnimation(AnimationPath::builtin("spellscr")); | ||||
| 		animation->load(artInst.getScrollSpellID().num); | ||||
| 		CCS->curh->dragAndDropCursor(animation->getImage(artInst.getScrollSpellID().num)->scaleFast(Point(44, 34))); | ||||
| 		auto image = GH.renderHandler().loadImage(AnimationPath::builtin("spellscr"), artInst.getScrollSpellID().num, 0); | ||||
| 		image->scaleFast(Point(44,34)); | ||||
|  | ||||
| 		CCS->curh->dragAndDropCursor(image); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user