From 2ddec370989cee85a16ac3f8a11e55bcaec4e9a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 28 Jun 2020 14:41:44 +0200 Subject: [PATCH] - added a texture format for single frame ANMs so that they can be handled like normal images. The intermission code is doing weird things with them that isn't really portable. --- source/CMakeLists.txt | 3 +- source/common/2d/v_draw.cpp | 2 + .../common/scripting/interface/vmnatives.cpp | 3 +- source/{core => common/textures}/animlib.cpp | 0 source/{core => common/textures}/animlib.h | 0 source/common/textures/formats/anmtexture.cpp | 172 ++++++++++++++++++ source/common/textures/image.cpp | 2 + source/common/textures/texturemanager.cpp | 2 +- source/common/textures/texturemanager.h | 7 +- 9 files changed, 185 insertions(+), 6 deletions(-) rename source/{core => common/textures}/animlib.cpp (100%) rename source/{core => common/textures}/animlib.h (100%) create mode 100644 source/common/textures/formats/anmtexture.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 3ddc669ce..ff539c3c4 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -783,7 +783,6 @@ set (PCH_SOURCES build/src/timer.cpp build/src/voxmodel.cpp - core/animlib.cpp core/mathutil.cpp core/rts.cpp core/ct_chat.cpp @@ -846,6 +845,7 @@ set (PCH_SOURCES common/textures/skyboxtexture.cpp common/textures/animtexture.cpp common/textures/v_collection.cpp + common/textures/animlib.cpp common/textures/formats/automaptexture.cpp common/textures/formats/brightmaptexture.cpp common/textures/formats/buildtexture.cpp @@ -864,6 +864,7 @@ set (PCH_SOURCES common/textures/formats/shadertexture.cpp common/textures/formats/tgatexture.cpp common/textures/formats/stbtexture.cpp + common/textures/formats/anmtexture.cpp common/textures/hires/hqresize.cpp common/models/models_md3.cpp common/models/models_md2.cpp diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index 8c7f6aee6..c25b43a7c 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -187,6 +187,7 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t va_start(tags.list, tags_first); DrawParms parms; + if (!img || !img->isValid()) return; bool res = ParseDrawTextureTags(drawer, img, x, y, tags_first, tags, &parms, false); va_end(tags.list); if (!res) @@ -208,6 +209,7 @@ static void DrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y { DrawParms parms; uint32_t tag = ListGetInt(args); + if (!img || !img->isValid()) return; bool res = ParseDrawTextureTags(drawer, img, x, y, tag, args, &parms, false); if (!res) return; drawer->AddTexture(img, parms); diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index b62e22993..74cba2701 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -78,7 +78,8 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) static int CheckForTexture(const FString& name, int type, int flags) { - return TexMan.CheckForTexture(name, static_cast(type), flags).GetIndex(); + // ForceLookup is intentionally blocked here, this flag is for internal use only. + return TexMan.CheckForTexture(name, static_cast(type), (flags & ~FTextureManager::TEXMAN_ForceLookup)).GetIndex(); } DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, CheckForTexture, CheckForTexture) diff --git a/source/core/animlib.cpp b/source/common/textures/animlib.cpp similarity index 100% rename from source/core/animlib.cpp rename to source/common/textures/animlib.cpp diff --git a/source/core/animlib.h b/source/common/textures/animlib.h similarity index 100% rename from source/core/animlib.h rename to source/common/textures/animlib.h diff --git a/source/common/textures/formats/anmtexture.cpp b/source/common/textures/formats/anmtexture.cpp new file mode 100644 index 000000000..bacf53b53 --- /dev/null +++ b/source/common/textures/formats/anmtexture.cpp @@ -0,0 +1,172 @@ +/* +** anmtexture.cpp +** Texture class for reading the first frame of Build ANM files +** +**--------------------------------------------------------------------------- +** Copyright 2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "files.h" +#include "filesystem.h" +#include "bitmap.h" +#include "imagehelpers.h" +#include "image.h" +#include "animlib.h" + +//========================================================================== +// +// +//========================================================================== + +class FAnmTexture : public FImageSource +{ + +public: + FAnmTexture (int lumpnum, int w, int h); + void ReadFrame(uint8_t *buffer, uint8_t *palette); + TArray CreatePalettedPixels(int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion) override; +}; + + +//========================================================================== +// +// +// +//========================================================================== + +FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) +{ + int x, y, comp; + file.Seek(0, FileReader::SeekSet); + char check[4]; + file.Read(check, 4); + if (memcmp(check, "LPF ", 4)) return nullptr; + file.Seek(0, FileReader::SeekSet); + auto buffer = file.ReadPadded(1); + + anim_t anim; + if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + { + return nullptr; + } + numframes = ANIM_NumFrames(&anim); + if (result >= 1) + { + return new FAnmTexture(lumpnum, 320, 200); + } + + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FAnmTexture::FAnmTexture (int lumpnum, int w, int h) + : FImageSource(lumpnum) +{ + Width = w; + Height = h; + LeftOffset = 0; + TopOffset = 0; +} + +void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + + anim_t anim; + if (ANIM_LoadAnim(&anim, source, lump.GetSize()) >= 0) + { + numframes = ANIM_NumFrames(&anim); + if (result >= 1) + { + memcpy(palette, ANIM_GetPalette(anim), 768); + memcpy(pixels, ANIM_DrawFrame(1), Width*Height); + return; + } + } + memset(pixels, 0, Width*Height); + memset(palette, 0, 768); +} + +//========================================================================== +// +// +// +//========================================================================== + +TArray FAnmTexture::CreatePalettedPixels(int conversion) +{ + TArray pixels(Width*Height, true); + uint8_t buffer[64000]; + uint8_t palette[768]; + uint8_t remap[256]; + + ReadFrame(buffer, palette); + for(int i=0;i<256;i++) + { + remap[i] = ColorMatcher.Pick(palette[i*3], palette[i*3+1], palette[i*3+2]); + } + ImageHelpers::FlipNonSquareBlockRemap (pixels.Data(), buffer, Width, Height, Width, remap); + return Pixels; +} + +//========================================================================== +// +// +// +//========================================================================== + +int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion) +{ + uint8_t buffer[64000]; + uint8_t palette[768]; + ReadFrame(buffer, palette); + + auto dpix = bmp.GetPixels(); + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int index = buffer[i]; + dpix[p + 0] = Palette[index * 3 + 2]; + dpix[p + 1] = Palette[index * 3 + 1]; + dpix[p + 2] = Palette[index * 3]; + dpix[p + 3] = 255; + } + + return -1; +} + + \ No newline at end of file diff --git a/source/common/textures/image.cpp b/source/common/textures/image.cpp index e70c76e39..73d6f5227 100644 --- a/source/common/textures/image.cpp +++ b/source/common/textures/image.cpp @@ -331,6 +331,7 @@ FImageSource *DDSImage_TryCreate(FileReader &, int lumpnum); FImageSource *PCXImage_TryCreate(FileReader &, int lumpnum); FImageSource *TGAImage_TryCreate(FileReader &, int lumpnum); FImageSource *StbImage_TryCreate(FileReader &, int lumpnum); +FImageSource *AnmImage_TryCreate(FileReader &, int lumpnum); FImageSource *RawPageImage_TryCreate(FileReader &, int lumpnum); FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum); FImageSource *PatchImage_TryCreate(FileReader &, int lumpnum); @@ -350,6 +351,7 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat) { PCXImage_TryCreate, false }, { StbImage_TryCreate, false }, { TGAImage_TryCreate, false }, + { AnmImage_TryCreate, false }, { RawPageImage_TryCreate, false }, { FlatImage_TryCreate, true }, // flat detection is not reliable, so only consider this for real flats. { PatchImage_TryCreate, false }, diff --git a/source/common/textures/texturemanager.cpp b/source/common/textures/texturemanager.cpp index 60ed0c747..c396f3437 100644 --- a/source/common/textures/texturemanager.cpp +++ b/source/common/textures/texturemanager.cpp @@ -240,7 +240,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset { // We intentionally only look for textures in subdirectories. // Any graphic being placed in the zip's root directory can not be found by this. - if (strchr(name, '/')) + if (strchr(name, '/') || (flags & TEXMAN_ForceLookup)) { FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; int lump = fileSystem.CheckNumForFullName(name); diff --git a/source/common/textures/texturemanager.h b/source/common/textures/texturemanager.h index d9da9d20d..6001a1c0a 100644 --- a/source/common/textures/texturemanager.h +++ b/source/common/textures/texturemanager.h @@ -47,9 +47,9 @@ public: } // This only gets used in UI code so we do not need PALVERS handling. - FGameTexture* GetGameTextureByName(const char *name, bool animate = false) + FGameTexture* GetGameTextureByName(const char *name, bool animate = false, int flags = 0) { - FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch); + FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch, flags); return InternalGetTexture(texnum.GetIndex(), animate, true); } @@ -88,7 +88,8 @@ public: TEXMAN_AllowSkins = 8, TEXMAN_ShortNameOnly = 16, TEXMAN_DontCreate = 32, - TEXMAN_Localize = 64 + TEXMAN_Localize = 64, + TEXMAN_ForceLookup = 128 }; enum