void FTextureManager::InitPalettedVersions() { int lump, lastlump = 0; PalettedVersions.Clear(); while ((lump = Wads.FindLump("PALVERS", &lastlump)) != -1) { FMemLump data = Wads.ReadLump(lump); Scanner sc((const char*)data.GetMem(), data.GetSize()); while (sc.GetNextToken()) { FTextureID pic1 = CheckForTexture(sc->str, FTexture::TEX_Any); if (!pic1.isValid()) { sc.ScriptMessage(Scanner::WARNING, "Unknown texture %s to replace", sc->str.GetChars()); } sc.GetNextToken(); FTextureID pic2 = CheckForTexture(sc->str, FTexture::TEX_Any); if (!pic2.isValid()) { sc.ScriptMessage(Scanner::WARNING, "Unknown texture %s to use as replacement", sc->str.GetChars()); } if (pic1.isValid() && pic2.isValid()) { PalettedVersions[pic1.GetIndex()] = pic2.GetIndex(); } } } }
void FTextureManager::Init() { DeleteAll(); // Init Build Tile data if it hasn't been done already //if (BuildTileFiles.Size() == 0) CountBuildTiles (); FTexture::InitGrayMap(); // Texture 0 is a dummy texture used to indicate "no texture" AddTexture (new FDummyTexture); int wadcnt = Wads.GetNumWads(); for(int i = 0; i< wadcnt; i++) { AddTexturesForWad(i); } // Add one marker so that the last WAD is easier to handle and treat // Build tiles as a completely separate block. //FirstTextureForFile.Push(Textures.Size()); //InitBuildTiles (); //FirstTextureForFile.Push(Textures.Size()); DefaultTexture = CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0); //InitAnimated(); InitAnimDefs(); FixAnimations(); InitSwitchList(); InitPalettedVersions(); }
void FTextureManager::ParseCameraTexture(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; int width, height; int fitwidth, fitheight; FString picname; sc.MustGetString (); picname = sc.String; sc.MustGetNumber (); width = sc.Number; sc.MustGetNumber (); height = sc.Number; FTextureID picnum = CheckForTexture (picname, FTexture::TEX_Flat, texflags); FTexture *viewer = new FCanvasTexture (picname, width, height); if (picnum.Exists()) { FTexture *oldtex = Texture(picnum); fitwidth = oldtex->GetScaledWidth (); fitheight = oldtex->GetScaledHeight (); viewer->UseType = oldtex->UseType; ReplaceTexture (picnum, viewer, true); } else { fitwidth = width; fitheight = height; // [GRB] No need for oldtex viewer->UseType = FTexture::TEX_Wall; AddTexture (viewer); } if (sc.GetString()) { if (sc.Compare ("fit")) { sc.MustGetNumber (); fitwidth = sc.Number; sc.MustGetNumber (); fitheight = sc.Number; } else { sc.UnGet (); } } if (sc.GetString()) { if (sc.Compare("WorldPanning")) { viewer->bWorldPanning = true; } else { sc.UnGet(); } } viewer->SetScaledSize(fitwidth, fitheight); }
void FTextureManager::ParseWarp(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; bool isflat = false; bool type2 = sc.Compare ("warp2"); // [GRB] sc.MustGetString (); if (sc.Compare ("flat")) { isflat = true; sc.MustGetString (); } else if (sc.Compare ("texture")) { isflat = false; sc.MustGetString (); } else { sc.ScriptError (NULL); } FTextureID picnum = CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); if (picnum.isValid()) { FTexture *warper = Texture(picnum); // don't warp a texture more than once if (!warper->bWarped) { if (type2) warper = new FWarp2Texture (warper); else warper = new FWarpTexture (warper); ReplaceTexture (picnum, warper, false); } if (sc.CheckFloat()) { static_cast<FWarpTexture*>(warper)->SetSpeed(float(sc.Float)); } // No decals on warping textures, by default. // Warping information is taken from the last warp // definition for this texture. warper->bNoDecals = true; if (sc.GetString ()) { if (sc.Compare ("allowdecals")) { warper->bNoDecals = false; } else { sc.UnGet (); } } } }
void FTextureManager::InitAnimDefs () { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; int lump, lastlump = 0; while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1) { FScanner sc(lump); while (sc.GetString ()) { if (sc.Compare ("flat")) { ParseAnim (sc, FTexture::TEX_Flat); } else if (sc.Compare ("texture")) { ParseAnim (sc, FTexture::TEX_Wall); } else if (sc.Compare ("switch")) { ProcessSwitchDef (sc); } // [GRB] Added warping type 2 else if (sc.Compare ("warp") || sc.Compare ("warp2")) { ParseWarp(sc); } else if (sc.Compare ("cameratexture")) { ParseCameraTexture(sc); } else if (sc.Compare ("animatedDoor")) { ParseAnimatedDoor (sc); } else if (sc.Compare("skyoffset")) { sc.MustGetString (); FTextureID picnum = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); sc.MustGetNumber(); if (picnum.Exists()) { Texture(picnum)->SkyOffset = sc.Number; } } else { sc.ScriptError (NULL); } } } }
void FTextureManager::InitSwitchList () { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; int lump = Wads.CheckNumForName ("SWITCHES"); if (lump != -1) { FMemLump lumpdata = Wads.ReadLump (lump); const char *alphSwitchList = (const char *)lumpdata.GetMem(); const char *list_p; FSwitchDef *def1, *def2; for (list_p = alphSwitchList; list_p[18] || list_p[19]; list_p += 20) { // [RH] Check for switches that aren't really switches if (stricmp (list_p, list_p+9) == 0) { Printf ("Switch %s in SWITCHES has the same 'on' state\n", list_p); continue; } // [RH] Skip this switch if its textures can't be found. if (CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags).Exists() && CheckForTexture (list_p + 9 /* .name2 */, FTexture::TEX_Wall, texflags).Exists()) { def1 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def1->PreTexture = def2->frames[0].Texture = CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags); def2->PreTexture = def1->frames[0].Texture = CheckForTexture (list_p + 9, FTexture::TEX_Wall, texflags); def1->Sound = def2->Sound = 0; def1->NumFrames = def2->NumFrames = 1; def1->frames[0].TimeMin = def2->frames[0].TimeMin = 0; def1->frames[0].TimeRnd = def2->frames[0].TimeRnd = 0; AddSwitchPair(def1, def2); } } } mSwitchDefs.ShrinkToFit (); qsort (&mSwitchDefs[0], mSwitchDefs.Size(), sizeof(FSwitchDef *), SortSwitchDefs); }
FTextureID FTextureManager::ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FTextureID framenum; sc.MustGetString (); if (IsNum (sc.String)) { framenum = basepicnum + (atoi(sc.String) - 1); } else { framenum = CheckForTexture (sc.String, usetype, texflags); if (!framenum.Exists() && !allowMissing) { sc.ScriptError ("Unknown texture %s", sc.String); } } return framenum; }
FTextureID FTextureManager::GetTexture (const char *name, int usetype, BITFIELD flags) { FTextureID i; if (name == NULL || name[0] == 0) { return FTextureID(0); } else { i = CheckForTexture (name, usetype, flags | TEXMAN_TryAny); } if (!i.Exists()) { // Use a default texture instead of aborting like Doom did Printf ("Unknown texture: \"%s\"\n", name); i = DefaultTexture; } return FTextureID(i); }
void FTextureManager::AddPatches (int lumpnum) { FWadLump *file = Wads.ReopenLumpNum (lumpnum); DWORD numpatches, i; char name[9]; *file >> numpatches; name[8] = 0; for (i = 0; i < numpatches; ++i) { file->Read (name, 8); if (CheckForTexture (name, FTexture::TEX_WallPatch, 0) == -1) { CreateTexture (Wads.CheckNumForName (name, ns_patches), FTexture::TEX_WallPatch); } //StartScreen->Progress(); } delete file; }
void FTextureManager::ProcessSwitchDef (FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FString picname; FSwitchDef *def1, *def2; FTextureID picnum; int gametype; bool quest = false; def1 = def2 = NULL; sc.MustGetString (); if (sc.Compare ("doom")) { gametype = GAME_DoomChex; sc.CheckNumber(); // skip the gamemission filter } else if (sc.Compare ("heretic")) { gametype = GAME_Heretic; } else if (sc.Compare ("hexen")) { gametype = GAME_Hexen; } else if (sc.Compare ("strife")) { gametype = GAME_Strife; } else if (sc.Compare ("any")) { gametype = GAME_Any; } else { // There is no game specified; just treat as any //max = 240; gametype = GAME_Any; sc.UnGet (); } sc.MustGetString (); picnum = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); picname = sc.String; while (sc.GetString ()) { if (sc.Compare ("quest")) { quest = true; } else if (sc.Compare ("on")) { if (def1 != NULL) { sc.ScriptError ("Switch already has an on state"); } def1 = ParseSwitchDef (sc, !picnum.Exists()); } else if (sc.Compare ("off")) { if (def2 != NULL) { sc.ScriptError ("Switch already has an off state"); } def2 = ParseSwitchDef (sc, !picnum.Exists()); } else { sc.UnGet (); break; } } if (def1 == NULL || !picnum.Exists() || (gametype != GAME_Any && !(gametype & gameinfo.gametype))) { if (def2 != NULL) { M_Free (def2); } if (def1 != NULL) { M_Free (def1); } return; } // If the switch did not have an off state, create one that just returns // it to the original texture without doing anything interesting if (def2 == NULL) { def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def2->Sound = def1->Sound; def2->NumFrames = 1; def2->frames[0].TimeMin = 0; def2->frames[0].TimeRnd = 0; def2->frames[0].Texture = picnum; } def1->PreTexture = picnum; def2->PreTexture = def1->frames[def1->NumFrames-1].Texture; if (def1->PreTexture == def2->PreTexture) { sc.ScriptError ("The on state for switch %s must end with a texture other than %s", picname.GetChars(), picname.GetChars()); } AddSwitchPair(def1, def2); def1->QuestPanel = def2->QuestPanel = quest; }
void FTextureManager::AddTexturesForWad(int wadnum) { int firsttexture = Textures.Size(); int lumpcount = Wads.GetNumLumps(); FirstTextureForFile.Push(firsttexture); // First step: Load sprites AddGroup(wadnum, ns_sprites, FTexture::TEX_Sprite); // When loading a Zip, all graphics in the patches/ directory should be // added as well. AddGroup(wadnum, ns_patches, FTexture::TEX_WallPatch); // Second step: TEXTUREx lumps //LoadTextureX(wadnum); // Third step: Flats AddGroup(wadnum, ns_flats, FTexture::TEX_Flat); // Fourth step: Textures (TX_) AddGroup(wadnum, ns_newtextures, FTexture::TEX_Override); // Sixth step: Try to find any lump in the WAD that may be a texture and load as a TEX_MiscPatch int firsttx = Wads.GetFirstLump(wadnum); int lasttx = Wads.GetLastLump(wadnum); for (int i= firsttx; i <= lasttx; i++) { char name[9]; Wads.GetLumpName(name, i); name[8]=0; // Ignore anything not in the global namespace int ns = Wads.GetLumpNamespace(i); if (ns == ns_global) { // In Zips all graphics must be in a separate namespace. if (Wads.GetLumpFlags(i) & LUMPF_ZIPFILE) continue; // Ignore lumps with empty names. if (Wads.CheckLumpName(i, "")) continue; // Ignore anything belonging to a map if (Wads.CheckLumpName(i, "PLANES")) continue; // Don't bother looking at this lump if something later overrides it. if (Wads.CheckNumForName(name, ns_graphics) != i) continue; // skip this if it has already been added as a wall patch. if (CheckForTexture(name, FTexture::TEX_WallPatch, 0).Exists()) continue; } else if (ns == ns_graphics) { // Don't bother looking this lump if something later overrides it. if (Wads.CheckNumForName(name, ns_graphics) != i) continue; } else continue; // Try to create a texture from this lump and add it. // Unfortunately we have to look at everything that comes through here... FTexture *out = FTexture::CreateTexture(i, FTexture::TEX_MiscPatch); if (out != NULL) { AddTexture (out); } } // Check for text based texture definitions LoadTextureDefs(wadnum, "TEXTURES"); //LoadTextureDefs(wadnum, "HIRESTEX"); // Seventh step: Check for hires replacements. AddHiresTextures(wadnum); SortTexturesByType(firsttexture, Textures.Size()); }
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 FTextureManager::ParseAnimatedDoor(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FDoorAnimation anim; TArray<FTextureID> frames; bool error = false; FTextureID v; sc.MustGetString(); anim.BaseTexture = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!anim.BaseTexture.Exists()) { error = true; } else { Texture(anim.BaseTexture)->bNoDecals = true; } while (sc.GetString()) { if (sc.Compare ("opensound")) { sc.MustGetString (); anim.OpenSound = sc.String; } else if (sc.Compare ("closesound")) { sc.MustGetString (); anim.CloseSound = sc.String; } else if (sc.Compare ("pic")) { sc.MustGetString (); if (IsNum (sc.String)) { v = anim.BaseTexture + (atoi(sc.String) - 1); } else { v = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!v.Exists() && anim.BaseTexture.Exists() && !error) { sc.ScriptError ("Unknown texture %s", sc.String); } } frames.Push(v); } else if (sc.Compare("allowdecals")) { if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = false; } else { sc.UnGet (); break; } } if (!error) { anim.TextureFrames = new FTextureID[frames.Size()]; memcpy (anim.TextureFrames, &frames[0], sizeof(FTextureID) * frames.Size()); anim.NumTextureFrames = frames.Size(); mAnimatedDoors.Push (anim); } }
void FTextureManager::ParseAnim (FScanner &sc, int usetype) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; TArray<FAnimDef::FAnimFrame> frames (32); FTextureID picnum; int defined = 0; bool optional = false, missing = false; FAnimDef *ani = NULL; BYTE type = FAnimDef::ANIM_Forward; sc.MustGetString (); if (sc.Compare ("optional")) { optional = true; sc.MustGetString (); } picnum = CheckForTexture (sc.String, usetype, texflags); if (!picnum.Exists()) { if (optional) { missing = true; } else { Printf (PRINT_BOLD, "ANIMDEFS: Can't find %s\n", sc.String); } } // no decals on animating textures, by default if (picnum.isValid()) { Texture(picnum)->bNoDecals = true; } while (sc.GetString ()) { if (sc.Compare ("allowdecals")) { if (picnum.isValid()) { Texture(picnum)->bNoDecals = false; } continue; } else if (sc.Compare ("Oscillate")) { if (type == FAnimDef::ANIM_Random) { sc.ScriptError ("You cannot use \"random\" and \"oscillate\" together in a single animation."); } type = FAnimDef::ANIM_OscillateUp; } else if (sc.Compare("Random")) { if (type == FAnimDef::ANIM_OscillateUp) { sc.ScriptError ("You cannot use \"random\" and \"oscillate\" together in a single animation."); } type = FAnimDef::ANIM_Random; } else if (sc.Compare ("range")) { if (picnum.Exists() && Texture(picnum)->Name.IsEmpty()) { // long texture name: We cannot do ranged anims on these because they have no defined order sc.ScriptError ("You cannot use \"range\" for long texture names."); } if (defined == 2) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } if (defined == 1) { sc.ScriptError ("You can only use one \"range\" per animation."); } defined = 1; ani = ParseRangeAnim (sc, picnum, usetype, missing); } else if (sc.Compare ("pic")) { if (defined == 1) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } defined = 2; ParsePicAnim (sc, picnum, usetype, missing, frames); } else { sc.UnGet (); break; } } // If base pic is not present, don't add this anim // ParseRangeAnim adds the anim itself, but ParsePicAnim does not. if (picnum.isValid() && defined == 2) { if (frames.Size() < 2) { sc.ScriptError ("Animation needs at least 2 frames"); } ani = AddComplexAnim (picnum, frames); } if (ani != NULL && type != FAnimDef::ANIM_Forward) { if (ani->AnimType == FAnimDef::ANIM_Backward && type == FAnimDef::ANIM_OscillateUp) ani->AnimType = FAnimDef::ANIM_OscillateDown; else ani->AnimType = type; } }
FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FSwitchDef *def; TArray<FSwitchDef::frame> frames; FSwitchDef::frame thisframe; FTextureID picnum; bool bad; FSoundID sound; bad = false; while (sc.GetString ()) { if (sc.Compare ("sound")) { if (sound != 0) { sc.ScriptError ("Switch state already has a sound"); } sc.MustGetString (); sound = sc.String; } else if (sc.Compare ("pic")) { sc.MustGetString (); picnum = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!picnum.Exists() && !ignoreBad) { //Printf ("Unknown switch texture %s\n", sc.String); bad = true; } thisframe.Texture = picnum; sc.MustGetString (); if (sc.Compare ("tics")) { sc.MustGetNumber (); thisframe.TimeMin = sc.Number & 65535; thisframe.TimeRnd = 0; } else if (sc.Compare ("rand")) { int min, max; sc.MustGetNumber (); min = sc.Number & 65535; sc.MustGetNumber (); max = sc.Number & 65535; if (min > max) { swapvalues (min, max); } thisframe.TimeMin = min; thisframe.TimeRnd = (max - min + 1); } else { thisframe.TimeMin = 0; // Shush, GCC. thisframe.TimeRnd = 0; sc.ScriptError ("Must specify a duration for switch frame"); } frames.Push(thisframe); } else { sc.UnGet (); break; } } if (frames.Size() == 0) { sc.ScriptError ("Switch state needs at least one frame"); } if (bad) { return NULL; } def = (FSwitchDef *)M_Malloc (myoffsetof (FSwitchDef, frames[0]) + frames.Size()*sizeof(frames[0])); def->Sound = sound; def->NumFrames = frames.Size(); memcpy (&def->frames[0], &frames[0], frames.Size() * sizeof(frames[0])); def->PairDef = NULL; return def; }
void FTextureManager::ParseAnim (FScanner &sc, int usetype) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; TArray<FAnimDef::FAnimFrame> frames (32); FTextureID picnum; int defined = 0; bool optional = false, missing = false; sc.MustGetString (); if (sc.Compare ("optional")) { optional = true; sc.MustGetString (); } picnum = CheckForTexture (sc.String, usetype, texflags); if (!picnum.Exists()) { if (optional) { missing = true; } else { Printf (PRINT_BOLD, "ANIMDEFS: Can't find %s\n", sc.String); } } // no decals on animating textures, by default if (picnum.isValid()) { Texture(picnum)->bNoDecals = true; } while (sc.GetString ()) { if (sc.Compare ("allowdecals")) { if (picnum.isValid()) { Texture(picnum)->bNoDecals = false; } continue; } else if (sc.Compare ("range")) { if (defined == 2) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } if (defined == 1) { sc.ScriptError ("You can only use one \"range\" per animation."); } defined = 1; ParseRangeAnim (sc, picnum, usetype, missing); } else if (sc.Compare ("pic")) { if (defined == 1) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } defined = 2; ParsePicAnim (sc, picnum, usetype, missing, frames); } else { sc.UnGet (); break; } } // If base pic is not present, don't add this anim // ParseRangeAnim adds the anim itself, but ParsePicAnim does not. if (picnum.isValid() && defined == 2) { if (frames.Size() < 2) { sc.ScriptError ("Animation needs at least 2 frames"); } AddComplexAnim (picnum, frames); } }
void FTextureManager::InitAnimated (void) { const BITFIELD texflags = TEXMAN_Overridable; // I think better not! This is only for old ANIMATED definitions that // don't know about ZDoom's more flexible texture system. // | FTextureManager::TEXMAN_TryAny; int lumpnum = Wads.CheckNumForName ("ANIMATED"); if (lumpnum != -1) { FMemLump animatedlump = Wads.ReadLump (lumpnum); int animatedlen = Wads.LumpLength(lumpnum); const char *animdefs = (const char *)animatedlump.GetMem(); const char *anim_p; FTextureID pic1, pic2; int animtype; DWORD animspeed; // Init animation animtype = FAnimDef::ANIM_Forward; for (anim_p = animdefs; *anim_p != -1; anim_p += 23) { // make sure the current chunk of data is inside the lump boundaries. if (anim_p + 22 >= animdefs + animatedlen) { I_Error("Tried to read past end of ANIMATED lump."); } if (*anim_p /* .istexture */ & 1) { // different episode ? if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() || !(pic2 = CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists()) continue; // [RH] Bit 1 set means allow decals on walls with this texture Texture(pic2)->bNoDecals = Texture(pic1)->bNoDecals = !(*anim_p & 2); } else { if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() || !(pic2 = CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists()) continue; } FTexture *tex1 = Texture(pic1); FTexture *tex2 = Texture(pic2); animspeed = (BYTE(anim_p[19]) << 0) | (BYTE(anim_p[20]) << 8) | (BYTE(anim_p[21]) << 16) | (BYTE(anim_p[22]) << 24); // SMMU-style swirly hack? Don't apply on already-warping texture if (animspeed > 65535 && tex1 != NULL && !tex1->bWarped) { FTexture *warper = new FWarp2Texture (tex1); ReplaceTexture (pic1, warper, false); } // These tests were not really relevant for swirling textures, or even potentially // harmful, so they have been moved to the else block. else { if (tex1->UseType != tex2->UseType) { // not the same type - continue; } if (debuganimated) { Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n", tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()), tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); } if (pic1 == pic2) { // This animation only has one frame. Skip it. (Doom aborted instead.) Printf ("Animation %s in ANIMATED has only one frame\n", anim_p + 10); continue; } // [RH] Allow for backward animations as well as forward. else if (pic1 > pic2) { swapvalues (pic1, pic2); animtype = FAnimDef::ANIM_Backward; } // Speed is stored as tics, but we want ms so scale accordingly. AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, Scale (animspeed, 1000, 35)); } } } }
void FTextureManager::ParseWarp(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; bool isflat = false; bool type2 = sc.Compare ("warp2"); // [GRB] sc.MustGetString (); if (sc.Compare ("flat")) { isflat = true; sc.MustGetString (); } else if (sc.Compare ("texture")) { isflat = false; sc.MustGetString (); } else { sc.ScriptError (NULL); } FTextureID picnum = CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); if (picnum.isValid()) { FTexture *warper = Texture(picnum); if (warper->Name.IsEmpty()) { // long texture name: We cannot do warps on these due to the way the texture manager implements warping as a texture replacement. sc.ScriptError ("You cannot use \"warp\" for long texture names."); } // don't warp a texture more than once if (!warper->bWarped) { warper = new FWarpTexture (warper, type2? 2:1); ReplaceTexture (picnum, warper, false); } if (sc.CheckFloat()) { static_cast<FWarpTexture*>(warper)->SetSpeed(float(sc.Float)); } // No decals on warping textures, by default. // Warping information is taken from the last warp // definition for this texture. warper->bNoDecals = true; if (sc.GetString ()) { if (sc.Compare ("allowdecals")) { warper->bNoDecals = false; } else { sc.UnGet (); } } } }