Esempio n. 1
0
	bool convertWritable(SImage& image, convert_options_t opt)
	{
		// Firstly, make image paletted
		image.convertPaletted(opt.pal_target, opt.pal_current);

		// Secondly, remove any alpha information
		image.fillAlpha(255);

		// Quick hack for COLORMAP size
		// TODO: Remove me when a proper COLORMAP editor is implemented
		if (image.getWidth() == 256 && image.getHeight() >= 32 && image.getHeight() <= 34)
			return true;

		// Check for fullscreen/autopage size
		if (image.getWidth() == 320)
			return true;

		// And finally, find a suitable flat size and crop to that size
		int width = 0;
		int height = 0;

		for (unsigned a = 1; a < n_valid_flat_sizes; a++)
		{
			// Ignore non-writable flat sizes
			if (valid_flat_size[a][2] == 0)
				continue;

			// Check for exact match (no need to crop)
			if (image.getWidth() == valid_flat_size[a][0] &&
			        image.getHeight() == valid_flat_size[a][1])
				return true;

			// If the flat will fit within this size, crop to the previous size
			// (this works because flat sizes list is in size-order)
			if (image.getWidth() <= (int)valid_flat_size[a][0] &&
			        image.getHeight() <= (int)valid_flat_size[a][1] &&
			        width > 0 && height > 0)
			{
				image.crop(0, 0, width, height);
				return true;
			}

			// Save 'previous' valid size
			width = valid_flat_size[a][0];
			height = valid_flat_size[a][1];
		}

		return false;
	}
Esempio n. 2
0
/* GfxEntryPanel::detectOffsetType
 * Detects the offset view type of the current entry
 *******************************************************************/
int GfxEntryPanel::detectOffsetType()
{
	if (!entry)
		return GFXVIEW_DEFAULT;

	if (!entry->getParent())
		return GFXVIEW_DEFAULT;

	// Check what section of the archive the entry is in
	string section = entry->getParent()->detectNamespace(entry);

	if (section == "sprites")
	{
		SImage* img = getImage();
		int left = -img->offset().x;
		int right = -img->offset().x + img->getWidth();
		int top = -img->offset().y;
		int bottom = -img->offset().y + img->getHeight();

		if (top >= 0 && bottom <= 216 && left >= 0 && right <= 336)
			return GFXVIEW_HUD;
		else
			return GFXVIEW_SPRITE;
	}

	// Check for png image
	if (entry->getType()->getFormat() == "img_png")
	{
		if (getImage()->offset().x == 0 &&
		        getImage()->offset().y == 0)
			return GFXVIEW_DEFAULT;
		else
		{
			SImage* img = getImage();
			int left = -img->offset().x;
			int right = -img->offset().x + img->getWidth();
			int top = -img->offset().y;
			int bottom = -img->offset().y + img->getHeight();

			if (top >= 0 && bottom <= 216 && left >= 0 && right <= 336)
				return GFXVIEW_HUD;
			else
				return GFXVIEW_SPRITE;
		}
	}

	return GFXVIEW_DEFAULT;
}
Esempio n. 3
0
/* TextureXPanel::newTextureFromPatch
 * Creates a new texture called [name] from [patch]. The new texture
 * will be set to the dimensions of the patch, with the patch added
 * at 0,0
 *******************************************************************/
CTexture* TextureXPanel::newTextureFromPatch(string name, string patch)
{
	// Create new texture
	CTexture* tex = new CTexture();
	tex->setName(name);
	tex->setState(2);

	// Setup texture scale
	if (texturex.getFormat() == TXF_TEXTURES)
	{
		tex->setScale(1, 1);
		tex->setExtended(true);
	}
	else
		tex->setScale(0, 0);

	// Add patch
	tex->addPatch(patch, 0, 0);

	// Load patch image (to determine dimensions)
	SImage image;
	tex->loadPatchImage(0, image);

	// Set dimensions
	tex->setWidth(image.getWidth());
	tex->setHeight(image.getHeight());

	// Update variables
	modified = true;

	// Return the new texture
	return tex;
}
Esempio n. 4
0
/* GfxEntryPanel::statusString
 * Returns a string with extended editing/entry info for the status
 * bar
 *******************************************************************/
string GfxEntryPanel::statusString()
{
	// Setup status string
	SImage* image = getImage();
	string status = S_FMT("%dx%d", image->getWidth(), image->getHeight());

	// Colour format
	if (image->getType() == RGBA)
		status += ", 32bpp";
	else
		status += ", 8bpp";

	// PNG stuff
	if (entry->getType()->getFormat() == "img_png")
	{
		// alPh
		if (EntryOperations::getalPhChunk(entry))
			status += ", alPh";

		// tRNS
		if (EntryOperations::gettRNSChunk(entry))
			status += ", tRNS";
	}

	return status;
}
Esempio n. 5
0
	bool writeImage(SImage& image, MemChunk& data, Palette* pal, int index)
	{
		// Can't write if RGBA
		if (image.getType() == RGBA)
			return false;

		// Check size
		if (!validSize(image.getWidth(), image.getHeight()))
			return false;

		// Just dump image data to memchunk
		data.clear();
		data.write(imageData(image), image.getWidth() * image.getHeight());

		return true;
	}
Esempio n. 6
0
/* CTexture::parseDefine
 * Parses a HIRESTEX define block
 *******************************************************************/
bool CTexture::parseDefine(Tokenizer& tz)
{
	this->type = "Define";
	this->extended = true;
	this->defined = true;
	name = tz.getToken().Upper();
	def_width = tz.getInteger();
	def_height = tz.getInteger();
	width = def_width;
	height = def_height;
	ArchiveEntry* entry = theResourceManager->getPatchEntry(name);
	if (entry)
	{
		SImage image;
		if (image.open(entry->getMCData()))
		{
			width = image.getWidth();
			height = image.getHeight();
			scale_x = (double)width / (double)def_width;
			scale_y = (double)height / (double)def_height;
		}
	}
	CTPatchEx* patch = new CTPatchEx(name);
	patches.push_back(patch);
	return true;
}
Esempio n. 7
0
	int canWrite(SImage& image)
	{
		// If it's the correct size and colour format, it's writable
		if (image.getType() == PALMASK &&
		        validSize(image.getWidth(), image.getHeight()))
			return WRITABLE;

		// Otherwise, it can be converted via palettising and cropping
		return CONVERTIBLE;
	}
Esempio n. 8
0
	int canWrite(SImage& image)
	{
		// If it's the correct size and colour format, it's writable
		int width  = image.getWidth();
		int height = image.getHeight();

		// Shouldn't happen but...
		if (width < 0 || height < 0)
			return NOTWRITABLE;

		if (image.getType() == PALMASK && validSize(image.getWidth(), image.getHeight()))
			return WRITABLE;

		// Otherwise, check if it can be cropped to a valid size
		for (unsigned a = 0; a < n_valid_flat_sizes; a++)
			if (((unsigned)width >= valid_flat_size[a][0] && (unsigned)height >= valid_flat_size[a][1]
				 && valid_flat_size[a][2] == 1)
				|| gfx_extraconv)
				return CONVERTIBLE;

		return NOTWRITABLE;
	}
Esempio n. 9
0
/* MapTextureManager::getVerticalOffset
 * Detects offset hacks such as that used by the wall torch thing in
 * Heretic (type 50). 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::getVerticalOffset(string name)
{
	// Don't bother looking for nameless sprites
	if (name.IsEmpty())
		return 0;

	// Get sprite matching name
	ArchiveEntry* entry = theResourceManager->getPatchEntry(name, "sprites", archive);
	if (!entry) entry = theResourceManager->getPatchEntry(name, "", archive);
	if (entry)
	{
		SImage image;
		Misc::loadImageFromEntry(&image, entry);
		int h = image.getHeight();
		int o = image.offset().y;
		if (o > h)
			return o - h;
		else
			return 0;
	}

	return 0;
}
Esempio n. 10
0
/* EntryOperations::createTexture
 * Same as addToPatchTable, but also creates a single-patch texture
 * from each added patch
 *******************************************************************/
bool EntryOperations::createTexture(vector<ArchiveEntry*> entries)
{
	// Check any entries were given
	if (entries.size() == 0)
		return true;

	// Get parent archive
	Archive* parent = entries[0]->getParent();

	// Create texture entries if needed
	if (!TextureXEditor::setupTextureEntries(parent))
		return false;

	// Find texturex entry to add to
	Archive::search_options_t opt;
	opt.match_type = EntryType::getType("texturex");
	ArchiveEntry* texturex = parent->findFirst(opt);

	// Check it exists
	bool zdtextures = false;
	if (!texturex)
	{
		opt.match_type = EntryType::getType("zdtextures");
		texturex = parent->findFirst(opt);

		if (!texturex)
			return false;
		else
			zdtextures = true;
	}

	// Find patch table in parent archive
	ArchiveEntry* pnames = NULL;
	if (!zdtextures)
	{
		opt.match_type = EntryType::getType("pnames");
		pnames = parent->findLast(opt);

		// Check it exists
		if (!pnames)
			return false;
	}

	// Check entries aren't locked (texture editor open or iwad)
	if ((pnames && pnames->isLocked()) || texturex->isLocked())
	{
		if (parent->isReadOnly())
			wxMessageBox("Cannot perform this action on an IWAD", "Error", wxICON_ERROR);
		else
			wxMessageBox("Cannot perform this action because one or more texture related entries is locked. Please close the archive's texture editor if it is open.", "Error", wxICON_ERROR);

		return false;
	}

	TextureXList tx;
	PatchTable ptable;
	if (zdtextures)
	{
		// Load TEXTURES
		tx.readTEXTURESData(texturex);
	}
	else
	{
		// Load patch table
		ptable.loadPNAMES(pnames);

		// Load TEXTUREx
		tx.readTEXTUREXData(texturex, ptable);
	}

	// Create textures from entries
	SImage image;
	for (unsigned a = 0; a < entries.size(); a++)
	{
		// Check entry type
		if (!(entries[a]->getType()->extraProps().propertyExists("image")))
		{
			wxLogMessage("Entry %s is not a valid image", entries[a]->getName());
			continue;
		}

		// Check entry name
		string name = entries[a]->getName(true);
		if (name.Length() > 8)
		{
			wxLogMessage("Entry %s has too long a name to add to the patch table (name must be 8 characters max)", entries[a]->getName());
			continue;
		}

		// Add to patch table
		if (!zdtextures)
			ptable.addPatch(name);

		// Load patch to temp image
		Misc::loadImageFromEntry(&image, entries[a]);

		// Create texture
		CTexture* ntex = new CTexture(zdtextures);
		ntex->setName(name);
		ntex->addPatch(name, 0, 0);
		ntex->setWidth(image.getWidth());
		ntex->setHeight(image.getHeight());

		// Setup texture scale
		if (tx.getFormat() == TXF_TEXTURES)
			ntex->setScale(1, 1);
		else
			ntex->setScale(0, 0);

		// Add to texture list
		tx.addTexture(ntex);
	}

	if (zdtextures)
	{
		// Write texture data back to textures entry
		tx.writeTEXTURESData(texturex);
	}
	else
	{
		// Write patch table data back to pnames entry
		ptable.writePNAMES(pnames);

		// Write texture data back to texturex entry
		tx.writeTEXTUREXData(texturex, ptable);
	}

	return true;
}
/* MapTextureManager::getTexture
 * Returns the texture matching [name]. Loads it from resources if
 * necessary. If [mixed] is true, flats are also searched if no
 * matching texture is found
 *******************************************************************/
GLTexture* MapTextureManager::getTexture(string name, bool mixed)
{
	// Get texture matching name
	map_tex_t& mtex = textures[name.Upper()];

	// Get desired filter type
	int filter = 1;
	if (map_tex_filter == 0)
		filter = GLTexture::NEAREST_LINEAR_MIN;
	else if (map_tex_filter == 1)
		filter = GLTexture::LINEAR;
	else if (map_tex_filter == 2)
		filter = GLTexture::LINEAR_MIPMAP;
	else if (map_tex_filter == 3)
		filter = GLTexture::NEAREST_MIPMAP;

	// If the texture is loaded
	if (mtex.texture)
	{
		// If the texture filter matches the desired one, return it
		if (mtex.texture->getFilter() == filter)
			return mtex.texture;
		else
		{
			// Otherwise, reload the texture
			if (mtex.texture != &(GLTexture::missingTex())) delete mtex.texture;
			mtex.texture = NULL;
		}
	}

	// Texture not found or unloaded, look for it
	//Palette8bit* pal = getResourcePalette();

	// Look for stand-alone textures first
	ArchiveEntry* etex = theResourceManager->getTextureEntry(name, "hires", archive);
	int textypefound = TEXTYPE_HIRES;
	if (etex == NULL)
	{
		etex = theResourceManager->getTextureEntry(name, "textures", archive);
		textypefound = TEXTYPE_TEXTURE;
	}
	if (etex)
	{
		SImage image;
		// Get image format hint from type, if any
		if (Misc::loadImageFromEntry(&image, etex))
		{
			mtex.texture = new GLTexture(false);
			mtex.texture->setFilter(filter);
			mtex.texture->loadImage(&image, palette);

			// Handle hires texture scale
			if (textypefound == TEXTYPE_HIRES)
			{
				ArchiveEntry* ref = theResourceManager->getTextureEntry(name, "textures", archive);
				if (ref)
				{
					SImage imgref;
					if (Misc::loadImageFromEntry(&imgref, ref))
					{
						int w, h, sw, sh;
						w = image.getWidth();
						h = image.getHeight();
						sw = imgref.getWidth();
						sh = imgref.getHeight();
						mtex.texture->setScale((double)sw/(double)w, (double)sh/(double)h);
					}
				}
			}
		}
	}

	// Try composite textures then
	CTexture* ctex = theResourceManager->getTexture(name, archive);
	if (ctex && (!mtex.texture || textypefound == TEXTYPE_FLAT))
	{
		textypefound = TEXTYPE_WALLTEXTURE;
		SImage image;
		if (ctex->toImage(image, archive, palette))
		{
			mtex.texture = new GLTexture(false);
			mtex.texture->setFilter(filter);
			mtex.texture->loadImage(&image, palette);
			double sx = ctex->getScaleX(); if (sx == 0) sx = 1.0;
			double sy = ctex->getScaleY(); if (sy == 0) sy = 1.0;
			mtex.texture->setScale(1.0/sx, 1.0/sy);
		}
	}

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

		// Otherwise use missing texture
		else
			mtex.texture = &(GLTexture::missingTex());
	}

	return mtex.texture;
}