Esempio n. 1
0
// -----------------------------------------------------------------------------
// Detects offset hacks such as that used by the wall torch thing in Heretic.
// If the Y offset is noticeably larger than the sprite height, that means the
// thing is supposed to be rendered above its real position.
// -----------------------------------------------------------------------------
int MapTextureManager::verticalOffset(std::string_view name) const
{
	// Don't bother looking for nameless sprites
	if (name.empty())
		return 0;

	// Get sprite matching name
	auto entry = App::resources().getPatchEntry(name, "sprites", archive_);
	if (!entry)
		entry = App::resources().getPatchEntry(name, "", archive_);
	if (entry)
	{
		SImage image;
		Misc::loadImageFromEntry(&image, entry);
		int h = image.height();
		int o = image.offset().y;
		if (o > h)
			return o - h;
		else
			return 0;
	}

	return 0;
}
Esempio 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;
}