Ejemplo n.º 1
0
// -----------------------------------------------------------------------------
// Search for errors in texture list, return true if any are found
// -----------------------------------------------------------------------------
bool TextureXList::findErrors()
{
	bool ret = false;

	// Texture errors:
	// 1. A texture without any patch
	// 2. A texture with missing patches
	// 3. A texture with columns not covered by a patch

	for (unsigned a = 0; a < textures_.size(); a++)
	{
		if (textures_[a]->nPatches() == 0)
		{
			ret = true;
			Log::warning("Texture {}: {} does not have any patch", a, textures_[a]->name());
		}
		else
		{
			vector<uint8_t> columns(textures_[a]->width());
			memset(columns.data(), 0, textures_[a]->width());
			for (size_t i = 0; i < textures_[a]->nPatches(); ++i)
			{
				auto patch = textures_[a]->patches_[i]->patchEntry();
				if (patch == nullptr)
				{
					ret = true;
					Log::warning(
						"Texture {}: {}: patch {} cannot be found in any open archive",
						a,
						textures_[a]->name(),
						textures_[a]->patches_[i]->name());
					// Don't list missing columns when we don't know the size of the patch
					memset(columns.data(), 1, textures_[a]->width());
				}
				else
				{
					SImage img;
					img.open(patch->data());
					size_t start = std::max<size_t>(0, textures_[a]->patches_[i]->xOffset());
					size_t end   = std::min<size_t>(textures_[a]->width(), img.width() + start);
					for (size_t c = start; c < end; ++c)
						columns[c] = 1;
				}
			}
			for (size_t c = 0; c < textures_[a]->width(); ++c)
			{
				if (columns[c] == 0)
				{
					ret = true;
					Log::warning("Texture {}: {}: column {} without a patch", a, textures_[a]->name(), c);
					break;
				}
			}
		}
	}
	return ret;
}
Ejemplo n.º 2
0
// -----------------------------------------------------------------------------
// Returns the texture matching [name], loading it from resources if necessary.
// If [mixed] is true, flats are also searched if no matching texture is found
// -----------------------------------------------------------------------------
const MapTextureManager::Texture& MapTextureManager::texture(std::string_view name, bool mixed)
{
	// Get texture matching name
	auto& mtex = textures_[StrUtil::upper(name)];

	// Get desired filter type
	auto filter = OpenGL::TexFilter::Linear;
	if (map_tex_filter == 0)
		filter = OpenGL::TexFilter::NearestLinearMin;
	else if (map_tex_filter == 1)
		filter = OpenGL::TexFilter::Linear;
	else if (map_tex_filter == 2)
		filter = OpenGL::TexFilter::LinearMipmap;
	else if (map_tex_filter == 3)
		filter = OpenGL::TexFilter::NearestMipmap;

	// If the texture is loaded
	if (mtex.gl_id)
	{
		// If the texture filter matches the desired one, return it
		auto& tex_info = OpenGL::Texture::info(mtex.gl_id);
		if (tex_info.filter == filter)
			return mtex;
		else
		{
			// Otherwise, reload the texture
			OpenGL::Texture::clear(mtex.gl_id);
			mtex.gl_id = 0;
		}
	}

	// Texture not found or unloaded, look for it

	// Look for stand-alone textures first
	auto etex         = App::resources().getTextureEntry(name, "hires", archive_);
	auto textypefound = CTexture::Type::HiRes;
	if (etex == nullptr)
	{
		etex         = App::resources().getTextureEntry(name, "textures", archive_);
		textypefound = CTexture::Type::Texture;
	}
	if (etex)
	{
		SImage image;
		// Get image format hint from type, if any
		if (Misc::loadImageFromEntry(&image, etex))
		{
			mtex.gl_id = OpenGL::Texture::createFromImage(image, palette_.get(), filter);

			// Handle hires texture scale
			if (textypefound == CTexture::Type::HiRes)
			{
				auto ref = App::resources().getTextureEntry(name, "textures", archive_);
				if (ref)
				{
					SImage imgref;
					if (Misc::loadImageFromEntry(&imgref, ref))
					{
						int w, h, sw, sh;
						w                  = image.width();
						h                  = image.height();
						sw                 = imgref.width();
						sh                 = imgref.height();
						mtex.world_panning = true;
						mtex.scale         = { (double)sw / (double)w, (double)sh / (double)h };
					}
				}
			}
		}
	}

	// Try composite textures then
	auto ctex = App::resources().getTexture(name, archive_);
	if (ctex) // Composite textures take precedence over the textures directory
	{
		textypefound = CTexture::Type::WallTexture;
		SImage image;
		if (ctex->toImage(image, archive_, palette_.get(), true))
		{
			mtex.gl_id = OpenGL::Texture::createFromImage(image, palette_.get(), filter);

			double sx = ctex->scaleX();
			if (sx == 0)
				sx = 1.0;
			double sy = ctex->scaleY();
			if (sy == 0)
				sy = 1.0;

			mtex.world_panning = ctex->worldPanning();
			mtex.scale         = { 1.0 / sx, 1.0 / sy };
		}
	}

	// Not found
	if (!mtex.gl_id)
	{
		// Try flats if mixed
		if (mixed)
			return flat(name, false);

		// Otherwise use missing texture
		mtex.gl_id = OpenGL::Texture::missingTexture();
	}

	return mtex;
}