Example #1
0
/* TextureXList::writeTEXTUREXData
 * Writes the texture list in TEXTUREX format to [texturex], using
 * [patch_table] for patch information. Returns true on success,
 * false otherwise
 *******************************************************************/
bool TextureXList::writeTEXTUREXData(ArchiveEntry* texturex, PatchTable& patch_table) {
	// Check entry was given
	if (!texturex)
		return false;

	if (texturex->isLocked())
		return false;

	wxLogMessage("Writing " + getTextureXFormatString() + " format TEXTUREx entry");

	/* Total size of a TEXTUREx lump, in bytes:
		Header: 4 + (4 * numtextures)
		Textures:
			22 * numtextures (normal format)
			14 * numtextures (nameless format)
			18 * numtextures (Strife 1.1 format)
		Patches:
			10 * sum of patchcounts (normal and nameless formats)
			 6 * sum of patchcounts (Strife 1.1 format)
	*/
	size_t numpatchrefs = 0;
	size_t numtextures = textures.size();
	for (size_t i = 0; i < numtextures; ++i) {
		numpatchrefs += textures[i]->nPatches();
	}
	wxLogMessage("%i patch references in %i textures", numpatchrefs, numtextures);

	size_t datasize = 0;
	size_t headersize = 4 + (4 * numtextures);
	switch (txformat) {
		case TXF_NORMAL:	datasize = 4 + (26 * numtextures) + (10 * numpatchrefs); break;
		case TXF_NAMELESS:	datasize = 4 + (18 * numtextures) + (10 * numpatchrefs); break;
		case TXF_STRIFE11:	datasize = 4 + (22 * numtextures) + ( 6 * numpatchrefs); break;
		// Some compilers insist on having default cases.
		default: return false;
	}

	MemChunk txdata(datasize);
	int32_t* offsets = new int32_t[numtextures];
	int32_t foo = wxINT32_SWAP_ON_BE((signed) numtextures);

	// Write header
	txdata.seek(0, SEEK_SET);
	SAFEFUNC(txdata.write(&foo, 4));

	// Go to beginning of texture definitions
	SAFEFUNC(txdata.seek(4 + (numtextures*4), SEEK_SET));

	// Write texture entries
	for (size_t i = 0; i < numtextures; ++i) {
		// Get texture to write
		CTexture* tex = textures[i];

		// Set offset
		offsets[i] = (signed)txdata.currentPos();

		// Write texture entry
		switch (txformat) {
			case TXF_NORMAL:
			{
				// Create 'normal' doom format texture definition
				ftdef_t txdef;
				memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
				strncpy(txdef.name, CHR(tex->getName().Upper()), tex->getName().Len());
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.columndir[0]	= 0;
				txdef.columndir[1]	= 0;
				txdef.patchcount	= tex->nPatches();

				// Check for WorldPanning flag
				if (tex->world_panning)
					txdef.flags |= TX_WORLDPANNING;

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 22));

				break;
			}
			case TXF_NAMELESS:
			{
				// Create nameless texture definition
				nltdef_t txdef;
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.columndir[0]	= 0;
				txdef.columndir[1]	= 0;
				txdef.patchcount	= tex->nPatches();

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 8));

				break;
			}
			case TXF_STRIFE11:
			{
				// Create strife format texture definition
				stdef_t txdef;
				memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
				strncpy(txdef.name, CHR(tex->getName().Upper()), tex->getName().Len());
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.patchcount	= tex->nPatches();

				// Check for WorldPanning flag
				if (tex->world_panning)
					txdef.flags |= TX_WORLDPANNING;

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 18));

				break;
			}
			default: return false;
		}

		// Write patch references
		for (size_t k = 0; k < tex->nPatches(); ++k) {
			// Get patch to write
			CTPatch* patch = tex->getPatch(k);

			// Create patch definition
			tx_patch_t pdef;
			pdef.left = patch->xOffset();
			pdef.top = patch->yOffset();

			// Check for 'invalid' patch
			if (patch->getName().StartsWith("INVPATCH")) {
				// Get raw patch index from name
				string number = patch->getName();
				number.Replace("INVPATCH", "");
				long index;
				number.ToLong(&index);
				pdef.patch = index;
			}
			else
				pdef.patch = patch_table.patchIndex(patch->getName());	// Note this will be -1 if the patch doesn't exist in the patch table. This should never happen with the texture editor, though.

			// Write common data
			SAFEFUNC(txdata.write(&pdef, 6));

			// In non-Strife formats, there's some added rubbish
			if (txformat != TXF_STRIFE11) {
				foo = 0;
				SAFEFUNC(txdata.write(&foo, 4));
			}
		}
	}

	// Write offsets
	SAFEFUNC(txdata.seek(4, SEEK_SET));
	SAFEFUNC(txdata.write(offsets, 4*numtextures));

	// Write data to the TEXTUREx entry
	texturex->importMemChunk(txdata);

	// Update entry type
	EntryType::detectEntryType(texturex);

	// Clean up
	delete[] offsets;

	return true;
}
Example #2
0
// -----------------------------------------------------------------------------
// Writes the texture list in TEXTUREX format to [texturex], using [patch_table]
// for patch information.
// Returns true on success, false otherwise
// -----------------------------------------------------------------------------
bool TextureXList::writeTEXTUREXData(ArchiveEntry* texturex, const PatchTable& patch_table)
{
	// Check entry was given
	if (!texturex)
		return false;

	if (texturex->isLocked())
		return false;

	Log::info("Writing " + textureXFormatString() + " format TEXTUREx entry");

	/* Total size of a TEXTUREx lump, in bytes:
		Header: 4 + (4 * numtextures)
		Textures:
			22 * numtextures (normal format)
			14 * numtextures (nameless format)
			18 * numtextures (Strife 1.1 format)
		Patches:
			10 * sum of patchcounts (normal and nameless formats)
			 6 * sum of patchcounts (Strife 1.1 format)
	*/
	size_t numpatchrefs = 0;
	size_t numtextures  = textures_.size();
	for (size_t i = 0; i < numtextures; ++i)
	{
		numpatchrefs += textures_[i]->nPatches();
	}
	Log::info("{} patch references in {} textures", numpatchrefs, numtextures);

	size_t datasize   = 0;
	size_t headersize = 4 + (4 * numtextures);
	switch (txformat_)
	{
	case Format::Normal: datasize = 4 + (26 * numtextures) + (10 * numpatchrefs); break;
	case Format::Nameless: datasize = 4 + (18 * numtextures) + (10 * numpatchrefs); break;
	case Format::Strife11:
		datasize = 4 + (22 * numtextures) + (6 * numpatchrefs);
		break;
		// Some compilers insist on having default cases.
	default: return false;
	}

	MemChunk        txdata(datasize);
	vector<int32_t> offsets(numtextures);
	int32_t         foo = wxINT32_SWAP_ON_BE((signed)numtextures);

	// Write header
	txdata.seek(0, SEEK_SET);
	SAFEFUNC(txdata.write(&foo, 4));

	// Go to beginning of texture definitions
	SAFEFUNC(txdata.seek(4 + (numtextures * 4), SEEK_SET));

	// Write texture entries
	for (size_t i = 0; i < numtextures; ++i)
	{
		// Get texture to write
		auto tex = textures_[i].get();

		// Set offset
		offsets[i] = (signed)txdata.currentPos();

		// Write texture entry
		switch (txformat_)
		{
		case Format::Normal:
		{
			// Create 'normal' doom format texture definition
			FullTexDef txdef;
			memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
			strncpy(txdef.name, tex->name().data(), tex->name().size());
			for (auto& c : txdef.name)
				c = toupper(c);
			txdef.flags        = 0;
			txdef.scale[0]     = (tex->scaleX() * 8);
			txdef.scale[1]     = (tex->scaleY() * 8);
			txdef.width        = tex->width();
			txdef.height       = tex->height();
			txdef.columndir[0] = 0;
			txdef.columndir[1] = 0;
			txdef.patchcount   = tex->nPatches();

			// Check for WorldPanning flag
			if (tex->world_panning_)
				txdef.flags |= Flags::WorldPanning;

			// Write texture definition
			SAFEFUNC(txdata.write(&txdef, 22));

			break;
		}
		case Format::Nameless:
		{
			// Create nameless texture definition
			NamelessTexDef txdef;
			txdef.flags        = 0;
			txdef.scale[0]     = (tex->scaleX() * 8);
			txdef.scale[1]     = (tex->scaleY() * 8);
			txdef.width        = tex->width();
			txdef.height       = tex->height();
			txdef.columndir[0] = 0;
			txdef.columndir[1] = 0;
			txdef.patchcount   = tex->nPatches();

			// Write texture definition
			SAFEFUNC(txdata.write(&txdef, 8));

			break;
		}
		case Format::Strife11:
		{
			// Create strife format texture definition
			StrifeTexDef txdef;
			memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
			strncpy(txdef.name, tex->name().data(), tex->name().size());
			for (auto& c : txdef.name)
				c = toupper(c);
			txdef.flags      = 0;
			txdef.scale[0]   = (tex->scaleX() * 8);
			txdef.scale[1]   = (tex->scaleY() * 8);
			txdef.width      = tex->width();
			txdef.height     = tex->height();
			txdef.patchcount = tex->nPatches();

			// Check for WorldPanning flag
			if (tex->world_panning_)
				txdef.flags |= Flags::WorldPanning;

			// Write texture definition
			SAFEFUNC(txdata.write(&txdef, 18));

			break;
		}
		default: return false;
		}

		// Write patch references
		for (size_t k = 0; k < tex->nPatches(); ++k)
		{
			// Get patch to write
			auto patch = tex->patch(k);

			// Create patch definition
			Patch pdef;
			pdef.left = patch->xOffset();
			pdef.top  = patch->yOffset();

			// Check for 'invalid' patch
			if (StrUtil::startsWith(patch->name(), "INVPATCH"))
			{
				// Get raw patch index from name
				std::string_view number = patch->name();
				number.remove_prefix(8);
				pdef.patch = StrUtil::asInt(number);
			}
			else
				pdef.patch = patch_table.patchIndex(
					patch->name()); // Note this will be -1 if the patch doesn't exist in the patch table. This
									// should never happen with the texture editor, though.

			// Write common data
			SAFEFUNC(txdata.write(&pdef, 6));

			// In non-Strife formats, there's some added rubbish
			if (txformat_ != Format::Strife11)
			{
				foo = 0;
				SAFEFUNC(txdata.write(&foo, 4));
			}
		}
	}

	// Write offsets
	SAFEFUNC(txdata.seek(4, SEEK_SET));
	SAFEFUNC(txdata.write(offsets.data(), 4 * numtextures));

	// Write data to the TEXTUREx entry
	texturex->importMemChunk(txdata);

	// Update entry type
	EntryType::detectEntryType(texturex);

	return true;
}