Exemple #1
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;
}
Exemple #2
0
/* TextureXList::readTEXTUREXData
 * Reads in a doom-format TEXTUREx entry. Returns true on success,
 * false otherwise
 *******************************************************************/
bool TextureXList::readTEXTUREXData(ArchiveEntry* texturex, PatchTable& patch_table, bool add) {
	// Check entries were actually given
	if (!texturex)
		return false;

	// Clear current textures if needed
	if (!add) clear();

	// Update palette
	theMainWindow->getPaletteChooser()->setGlobalFromArchive(texturex->getParent());

	// Read TEXTUREx

	// Read header
	texturex->seek(0, SEEK_SET);
	int32_t		n_tex = 0;
	int32_t*	offsets = NULL;

	// Number of textures
	if (!texturex->read(&n_tex, 4)) {
		wxLogMessage("Error: TEXTUREx entry is corrupt (can't read texture count)");
		return false;
	}
	n_tex = wxINT32_SWAP_ON_BE(n_tex);

	// If it's an empty TEXTUREx entry, stop here
	if (n_tex == 0)
		return true;

	// Texture definition offsets
	offsets = new int32_t[n_tex];
	if (!texturex->read(offsets, n_tex * 4)) {
		wxLogMessage("Error: TEXTUREx entry is corrupt (can't read first offset)");
		return false;
	}

	// Read the first texture definition to try to identify the format
	if (!texturex->seek(wxINT32_SWAP_ON_BE(offsets[0]), SEEK_SET)) {
		wxLogMessage("Error: TEXTUREx entry is corrupt (can't read first definition)");
		return false;
	}
	// Look at the name field. Is it present or not?
	char tempname[8];
	if (!texturex->read(&tempname, 8)) {
		wxLogMessage("Error: TEXTUREx entry is corrupt (can't read first name)");
		return false;
	}
	// Let's pretend it is and see what happens.
	txformat = TXF_NORMAL;

	// Only the characters A-Z (uppercase), 0-9, and [ ] - _ should be used in texture names.
	for (uint8_t a = 0; a < 8; ++a) {
		if (a > 0 && tempname[a] == 0)
			// We found a null-terminator for the string, so we can assume it's okay.
			break;
		if (tempname[a] >= 'a' && tempname[a] <= 'z') {
			txformat = TXF_JAGUAR;
			//wxLogMessage("Jaguar texture");
			break;
		}
		else if (!((tempname[a] >= 'A' && tempname[a] <= '[') ||
			  (tempname[a] >= '0' && tempname[a] <= '9') ||
			   tempname[a] == ']' || tempname[a] == '-' || tempname[a] == '_'))
			// We're out of character range, so this is probably not a texture name.
		{
			txformat = TXF_NAMELESS;
			//wxLogMessage("Nameless texture");
			break;
		}
	}

	// Now let's see if it is the abridged Strife format or not.
	if (txformat == TXF_NORMAL) {
		// No need to test this again since it was already tested before.
		texturex->seek(offsets[0], SEEK_SET);
		ftdef_t temp;
		if (!texturex->read(&temp, 22)) {
			wxLogMessage("Error: TEXTUREx entry is corrupt (can't test definition)");
			return false;
		}
		// Test condition adapted from ZDoom; apparently the first two bytes of columndir
		// may be set to garbage values by some editors and are therefore unreliable.
		if (wxINT16_SWAP_ON_BE(temp.patchcount <= 0) || (temp.columndir[1] != 0))
			txformat = TXF_STRIFE11;
	}

	// Read all texture definitions
	for (int32_t a = 0; a < n_tex; a++) {
		// Skip to texture definition
		if (!texturex->seek(offsets[a], SEEK_SET)) {
			wxLogMessage("Error: TEXTUREx entry is corrupt (can't find definition)");
			return false;
		}

		// Read definition
		tdef_t tdef;
		if (txformat == TXF_NAMELESS) {
			nltdef_t nameless;
			// Auto-naming mechanism taken from DeuTex
			if (a > 99999) {
				wxLogMessage("Error: More than 100000 nameless textures");
				return false;
			}
			char temp[9] = "";
			sprintf (temp, "TEX%05d", a);
			memcpy(tdef.name, temp, 8);

			// Read texture info
			if (!texturex->read(&nameless, 8)) {
				wxLogMessage("Error: TEXTUREx entry is corrupt (can't read nameless definition #%d)", a);
				return false;
			}

			// Copy data to permanent structure
			tdef.flags = nameless.flags;
			tdef.scale[0] = nameless.scale[0];
			tdef.scale[1] = nameless.scale[1];
			tdef.width = nameless.width;
			tdef.height = nameless.height;
		}
		else if (!texturex->read(&tdef, 16)) {
			wxLogMessage("Error: TEXTUREx entry is corrupt, (can't read texture definition #%d)", a);
			return false;
		}

		// Skip unused
		if (txformat != TXF_STRIFE11) {
			if (!texturex->seek(4, SEEK_CUR)) {
				wxLogMessage("Error: TEXTUREx entry is corrupt (can't skip dummy data past #%d)", a);
				return false;
			}
		}

		// Create texture
		CTexture* tex = new CTexture();
		tex->name = wxString::FromAscii(tdef.name, 8);
		tex->width = wxINT16_SWAP_ON_BE(tdef.width);
		tex->height = wxINT16_SWAP_ON_BE(tdef.height);
		tex->scale_x = tdef.scale[0]/8.0;
		tex->scale_y = tdef.scale[1]/8.0;

		// Set flags
		if (tdef.flags & TX_WORLDPANNING)
			tex->world_panning = true;

		// Read patches
		int16_t n_patches = 0;
		if (!texturex->read(&n_patches, 2)) {
			wxLogMessage("Error: TEXTUREx entry is corrupt (can't read patchcount #%d)", a);
			return false;
		}

		//wxLogMessage("Texture #%d: %d patch%s", a, n_patches, n_patches == 1 ? "" : "es");

		for (uint16_t p = 0; p < n_patches; p++) {
			// Read patch definition
			tx_patch_t pdef;
			if (!texturex->read(&pdef, 6)) {
				wxLogMessage("Error: TEXTUREx entry is corrupt (can't read patch definition #%d:%d)", a, p);
				wxLogMessage("Lump size %d, offset %d", texturex->getSize(), texturex->currentPos());
				return false;
			}

			// Skip unused
			if (txformat != TXF_STRIFE11) {
				if (!texturex->seek(4, SEEK_CUR)) {
					wxLogMessage("Error: TEXTUREx entry is corrupt (can't skip dummy data past #%d:%d)", a, p);
					return false;
				}
			}


			// Add it to the texture
			string patch;
			if (txformat == TXF_JAGUAR) {
				patch = tex->name.Upper();
			} else {
				patch = patch_table.patchName(pdef.patch);
			}
			if (patch.IsEmpty()) {
				//wxLogMessage("Warning: Texture %s contains patch %d which is invalid - may be incorrect PNAMES entry", CHR(tex->getName()), pdef.patch);
				patch = S_FMT("INVPATCH%04d", pdef.patch);
			}

			tex->addPatch(patch, pdef.left, pdef.top);
		}

		// Add texture to list
		addTexture(tex);
	}

	// Clean up
	delete[] offsets;

	return true;
}
Exemple #3
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;
}