/* 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; }
/* 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; }