FTextureID FTextureManager::PalCheck(FTextureID tex) { //if (vid_nopalsubstitutions) return tex; int *newtex = PalettedVersions.CheckKey(tex.GetIndex()); if (newtex == NULL || *newtex == 0) return tex; return *newtex; }
static void ParseFloor (FScanner &sc) { FTextureID picnum; int terrain; bool opt = sc.CheckString("optional"); sc.MustGetString (); picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); if (!picnum.Exists()) { if (!opt) { Printf("Unknown flat %s\n", sc.String); } sc.MustGetString(); return; } sc.MustGetString (); terrain = P_FindTerrain (sc.String); if (terrain == -1) { Printf ("Unknown terrain %s\n", sc.String); terrain = 0; } TerrainTypes.Set(picnum.GetIndex(), terrain); }
bool FTextureManager::AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2) { int index1 = picnum1.GetIndex(); int index2 = picnum2.GetIndex(); if (unsigned(index1) >= Textures.Size() || unsigned(index2) >= Textures.Size()) return false; FTexture *texture1 = Textures[index1].Texture; FTexture *texture2 = Textures[index2].Texture; // both textures must be the same type. if (texture1 == NULL || texture2 == NULL || texture1->UseType != texture2->UseType) return false; // both textures must be from the same file for(unsigned i = 0; i < FirstTextureForFile.Size() - 1; i++) { if (index1 >= FirstTextureForFile[i] && index1 < FirstTextureForFile[i+1]) { return (index2 >= FirstTextureForFile[i] && index2 < FirstTextureForFile[i+1]); } } return false; }
void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, bool free) { int index = picnum.GetIndex(); if (unsigned(index) >= Textures.Size()) return; FTexture *oldtexture = Textures[index].Texture; strcpy (newtexture->Name, oldtexture->Name); newtexture->UseType = oldtexture->UseType; Textures[index].Texture = newtexture; newtexture->id = oldtexture->id; if (free) { delete oldtexture; } else { oldtexture->id.SetInvalid(); } }
FTexture *FTextureManager::FindTexture(const char *texname, int usetype, BITFIELD flags) { FTextureID texnum = CheckForTexture (texname, usetype, flags); return !texnum.isValid()? NULL : Textures[texnum.GetIndex()].Texture; }
void SetHUDIcon(PClass *cls, FTextureID tex) { cls->Meta.SetMetaInt(HUMETA_AltIcon, tex.GetIndex()); }
//========================================================================== // // Creates all 3D floors defined by one linedef // //========================================================================== static int P_Set3DFloor(line_t * line, int param, int param2, int alpha) { int s; int flags; int tag = line->args[0]; sector_t * sec = line->frontsector, *ss; FSectorTagIterator itr(tag); while ((s = itr.Next()) >= 0) { ss = &level.sectors[s]; if (param == 0) { flags = FF_EXISTS | FF_RENDERALL | FF_SOLID | FF_INVERTSECTOR; alpha = 255; for (auto l: sec->Lines) { if (l->special == Sector_SetContents && l->frontsector == sec) { alpha = clamp<int>(l->args[1], 0, 100); if (l->args[2] & 1) flags &= ~FF_SOLID; if (l->args[2] & 2) flags |= FF_SEETHROUGH; if (l->args[2] & 4) flags |= FF_SHOOTTHROUGH; if (l->args[2] & 8) flags |= FF_ADDITIVETRANS; if (alpha != 100) flags |= FF_TRANSLUCENT;//|FF_BOTHPLANES|FF_ALLSIDES; if (l->args[0]) { // Yes, Vavoom's 3D-floor definitions suck! // The content list changed in r1783 of Vavoom to be unified // among all its supported games, so it has now ten different // values instead of just five. static DWORD vavoomcolors[] = { VC_EMPTY, VC_WATER, VC_LAVA, VC_NUKAGE, VC_SLIME, VC_HELLSLIME, VC_BLOOD, VC_SLUDGE, VC_HAZARD, VC_BOOMWATER }; flags |= FF_SWIMMABLE | FF_BOTHPLANES | FF_ALLSIDES | FF_FLOOD; l->frontsector->ColorMap = GetSpecialLights(l->frontsector->ColorMap->Color, vavoomcolors[l->args[0]], l->frontsector->ColorMap->Desaturate); } alpha = (alpha * 255) / 100; break; } } } else if (param == 4) { flags = FF_EXISTS | FF_RENDERPLANES | FF_INVERTPLANES | FF_NOSHADE | FF_FIX; if (param2 & 1) flags |= FF_SEETHROUGH; // marker for allowing missing texture checks alpha = 255; } else { static const int defflags[] = { 0, FF_SOLID, FF_SWIMMABLE | FF_BOTHPLANES | FF_ALLSIDES | FF_SHOOTTHROUGH | FF_SEETHROUGH, FF_SHOOTTHROUGH | FF_SEETHROUGH, }; flags = defflags[param & 3] | FF_EXISTS | FF_RENDERALL; if (param & 4) flags |= FF_ALLSIDES | FF_BOTHPLANES; if (param & 16) flags ^= FF_SEETHROUGH; if (param & 32) flags ^= FF_SHOOTTHROUGH; if (param2 & 1) flags |= FF_NOSHADE; if (param2 & 2) flags |= FF_DOUBLESHADOW; if (param2 & 4) flags |= FF_FOG; if (param2 & 8) flags |= FF_THINFLOOR; if (param2 & 16) flags |= FF_UPPERTEXTURE; if (param2 & 32) flags |= FF_LOWERTEXTURE; if (param2 & 64) flags |= FF_ADDITIVETRANS | FF_TRANSLUCENT; // if flooding is used the floor must be non-solid and is automatically made shootthrough and seethrough if ((param2 & 128) && !(flags & FF_SOLID)) flags |= FF_FLOOD | FF_SEETHROUGH | FF_SHOOTTHROUGH; if (param2 & 512) flags |= FF_FADEWALLS; if (param2&1024) flags |= FF_RESET; FTextureID tex = line->sidedef[0]->GetTexture(side_t::top); if (!tex.Exists() && alpha < 255) { alpha = -tex.GetIndex(); } alpha = clamp(alpha, 0, 255); if (alpha == 0) flags &= ~(FF_RENDERALL | FF_BOTHPLANES | FF_ALLSIDES); else if (alpha != 255) flags |= FF_TRANSLUCENT; } P_Add3DFloor(ss, sec, line, flags, alpha); } // To be 100% safe this should be done even if the alpha by texture value isn't used. if (!line->sidedef[0]->GetTexture(side_t::top).isValid()) line->sidedef[0]->SetTexture(side_t::top, FNullTextureID()); return 1; }
void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist) { SpriteHits *spritelist = new SpriteHits[sprites.Size()]; SpriteHits **spritehitlist = new SpriteHits*[TexMan.NumTextures()]; TMap<PClassActor*, bool>::Iterator it(actorhitlist); TMap<PClassActor*, bool>::Pair *pair; BYTE *modellist = new BYTE[Models.Size()]; memset(modellist, 0, Models.Size()); memset(spritehitlist, 0, sizeof(SpriteHits**) * TexMan.NumTextures()); // this isn't done by the main code so it needs to be done here first: // check skybox textures and mark the separate faces as used for (int i = 0; i<TexMan.NumTextures(); i++) { // HIT_Wall must be checked for MBF-style sky transfers. if (texhitlist[i] & (FTextureManager::HIT_Sky | FTextureManager::HIT_Wall)) { FTexture *tex = TexMan.ByIndex(i); if (tex->gl_info.bSkybox) { FSkyBox *sb = static_cast<FSkyBox*>(tex); for (int i = 0; i<6; i++) { if (sb->faces[i]) { int index = sb->faces[i]->id.GetIndex(); texhitlist[index] |= FTextureManager::HIT_Flat; } } } } } // Check all used actors. // 1. mark all sprites associated with its states // 2. mark all model data and skins associated with its states while (it.NextPair(pair)) { PClassActor *cls = pair->Key; int gltrans = GLTranslationPalette::GetInternalTranslation(GetDefaultByType(cls)->Translation); for (int i = 0; i < cls->NumOwnedStates; i++) { spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true); FSpriteModelFrame * smf = gl_FindModelFrame(cls, cls->OwnedStates[i].sprite, cls->OwnedStates[i].Frame, false); if (smf != NULL) { for (int i = 0; i < MAX_MODELS_PER_FRAME; i++) { if (smf->skinIDs[i].isValid()) { texhitlist[smf->skinIDs[i].GetIndex()] |= FTexture::TEX_Flat; } else if (smf->modelIDs[i] != -1) { Models[smf->modelIDs[i]]->PushSpriteMDLFrame(smf, i); Models[smf->modelIDs[i]]->AddSkins(texhitlist); } if (smf->modelIDs[i] != -1) { modellist[smf->modelIDs[i]] = 1; } } } } } // mark all sprite textures belonging to the marked sprites. for (int i = (int)(sprites.Size() - 1); i >= 0; i--) { if (spritelist[i].CountUsed()) { int j, k; for (j = 0; j < sprites[i].numframes; j++) { const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; for (k = 0; k < 16; k++) { FTextureID pic = frame->Texture[k]; if (pic.isValid()) { spritehitlist[pic.GetIndex()] = &spritelist[i]; } } } } } // delete everything unused before creating any new resources to avoid memory usage peaks. // delete unused models for (unsigned i = 0; i < Models.Size(); i++) { if (!modellist[i]) Models[i]->DestroyVertexBuffer(); } // delete unused textures int cnt = TexMan.NumTextures(); for (int i = cnt - 1; i >= 0; i--) { FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { if (!texhitlist[i]) { if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true); } if (spritehitlist[i] == nullptr || (*spritehitlist[i]).CountUsed() == 0) { if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true); } } } if (gl_precache) { // cache all used textures for (int i = cnt - 1; i >= 0; i--) { FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { PrecacheTexture(tex, texhitlist[i]); if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0) { PrecacheSprite(tex, *spritehitlist[i]); } } } // cache all used models for (unsigned i = 0; i < Models.Size(); i++) { if (modellist[i]) Models[i]->BuildVertexBuffer(); } } delete[] spritehitlist; delete[] spritelist; delete[] modellist; }