- updated to GZDoom's new texture management system.

This commit is contained in:
Christoph Oelckers 2020-05-25 23:59:07 +02:00
parent 7a1fda2cc2
commit c4017de12f
68 changed files with 2046 additions and 1782 deletions

View file

@ -783,6 +783,7 @@ set (PCH_SOURCES
common/textures/bitmap.cpp
common/textures/m_png.cpp
common/textures/texture.cpp
common/textures/gametexture.cpp
common/textures/image.cpp
common/textures/imagetexture.cpp
common/textures/texturemanager.cpp
@ -1018,6 +1019,7 @@ include_directories(
common/textures
common/textures/formats
common/textures/hires
common/textures
common/filesystem
common/utility
common/console

View file

@ -856,7 +856,7 @@ void videoClearScreen(int32_t dacol);
void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *pic = nullptr, int basepal = 0);
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture *pic = nullptr, int basepal = 0);
void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col);
void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p);
void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p);
@ -864,13 +864,13 @@ void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p);
////////// specialized rotatesprite wrappers for (very) often used cases //////////
static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture* pic = nullptr, int basepal = 0)
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture* pic = nullptr, int basepal = 0)
{
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2, pic, basepal);
}
// Don't clip at all, i.e. the whole screen real estate is available:
static FORCE_INLINE void rotatesprite_fs(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, FTexture* pic = nullptr, int basepal = 0)
int8_t dashade, uint8_t dapalnum, int32_t dastat, FGameTexture* pic = nullptr, int basepal = 0)
{
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0,0,xdim-1,ydim-1, pic, basepal);
}

View file

@ -14,14 +14,14 @@
#define IDP2_MAGIC 0x32504449
#define IDP3_MAGIC 0x33504449
class FTexture;
class FGameTexture;
class FHardwareTexture;
struct mdmodel_t
{
int32_t mdnum, shadeoff;
float scale, bscale, zadd, yoffset;
FTexture *texture;
FGameTexture *texture;
int32_t flags;
};
@ -200,7 +200,7 @@ struct voxmodel_t : public mdmodel_t
EXTERN mdmodel_t **models;
FTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact);
FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact);
void mdinit(void);
void freeallmodels(void);
int32_t polymost_mddraw(tspriteptr_t tspr);

View file

@ -50,7 +50,7 @@ void VPXTexture::SetFrame(const void *data_, int width, int height)
Width = width;
Height = height;
data = data_;
SystemTextures.Clean(true, true);
SystemTextures.Clean();
}
//===========================================================================
@ -412,27 +412,27 @@ read_ivf_frame:
/////////////// DRAWING! ///////////////
static int sampler;
static VPXTexture* vpxtex[2];
static FGameTexture* vpxtex[2];
static int which;
void animvpx_setup_glstate(int32_t animvpx_flags)
{
////////// GL STATE //////////
vpxtex[0] = new VPXTexture;
vpxtex[1] = new VPXTexture;
vpxtex[0] = MakeGameTexture(new VPXTexture, nullptr, ETextureType::Special);
vpxtex[1] = MakeGameTexture(new VPXTexture, nullptr, ETextureType::Special);
if ((animvpx_flags & CUTSCENE_TEXTUREFILTER && hw_texfilter == TEXFILTER_ON) || animvpx_flags & CUTSCENE_FORCEFILTER ||
(!(animvpx_flags & CUTSCENE_TEXTUREFILTER) && !(animvpx_flags & CUTSCENE_FORCENOFILTER))) // if no flags, then use filter for IVFs
(!(animvpx_flags & CUTSCENE_TEXTUREFILTER) && !(animvpx_flags & CUTSCENE_FORCENOFILTER))) // if no flags, then use filter for IVFs
{
sampler = SamplerClampXY;
sampler = CLAMP_XY;
}
else
{
sampler = SamplerNoFilterClampXY;
sampler = CLAMP_XY;
}
GLInterface.ClearScreen(0, true);
GLInterface.ClearScreen(0, true);
}
void animvpx_restore_glstate(void)
@ -454,7 +454,8 @@ int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
return 2; // shouldn't happen
which ^= 1;
vpxtex[which]->SetFrame(codec->pic, codec->width, codec->height);
static_cast<VPXTexture*>(vpxtex[which]->GetTexture())->SetFrame(codec->pic, codec->width, codec->height);
vpxtex[which]->CleanHardwareData();
float vid_wbyh = ((float)codec->width)/codec->height;
if (animvpx_aspect > 0)

View file

@ -3083,7 +3083,7 @@ static int32_t dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z,
void twod_rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FTexture* pic, int basepal)
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FGameTexture* pic, int basepal)
{
F2DDrawer::RenderCommand dg = {};
int method = 0;
@ -3122,7 +3122,7 @@ void twod_rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t pic
int light = clamp(scale((numshades - dashade), 255, numshades), 0, 255);
auto p = PalEntry((uint8_t)(alpha * 255), light, light, light);
vec2_t const siz = { dg.mTexture->GetDisplayWidth(), dg.mTexture->GetDisplayHeight() };
vec2_t const siz = { (int)dg.mTexture->GetDisplayWidth(), (int)dg.mTexture->GetDisplayHeight() };
vec2_16_t ofs = { 0, 0 };
if (!(dastat & RS_TOPLEFT))
@ -5327,7 +5327,7 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect)
//
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *tex, int basepal)
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture *tex, int basepal)
{
if (!tex && (unsigned)picnum >= MAXTILES)
return;

View file

@ -463,7 +463,7 @@ int32_t md_undefinemodel(int32_t modelid)
//Note: even though it says md2model, it works for both md2model&md3model
FTexture *mdloadskin(idmodel_t *m, int32_t number, int32_t pal, int32_t surf, bool *exact)
FGameTexture *mdloadskin(idmodel_t *m, int32_t number, int32_t pal, int32_t surf, bool *exact)
{
int32_t i;
mdskinmap_t *sk, *skzero = NULL;
@ -482,7 +482,7 @@ FTexture *mdloadskin(idmodel_t *m, int32_t number, int32_t pal, int32_t surf, bo
{
if (exact) *exact = true;
//Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
return TexMan.GetTexture(sk->texture);
return TexMan.GetGameTexture(sk->texture);
}
//If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; }
@ -501,7 +501,7 @@ FTexture *mdloadskin(idmodel_t *m, int32_t number, int32_t pal, int32_t surf, bo
{
//Printf("Using def skin 0,0 as fallback, pal=%d\n", pal);
if (exact) *exact = false;
return TexMan.GetTexture(skzero->texture);
return TexMan.GetGameTexture(skzero->texture);
}
else
return nullptr;
@ -1711,7 +1711,7 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
if (!tex)
continue;
FTexture *det = nullptr, *glow = nullptr;
FGameTexture *det = nullptr, *glow = nullptr;
float detscale = 1.f;
// The data lookup here is one incredible mess. Thanks to whoever cooked this up... :(

View file

@ -502,7 +502,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
{
float const r = 1.f / dd[i];
if (tileGetTexture(globalpicnum)->isCanvas())
if (tileGetTexture(globalpicnum)->GetTexture()->isHardwareCanvas())
{
//update texcoords, canvas textures are upside down!
vt->SetTexCoord(

View file

@ -234,7 +234,7 @@ void F2DDrawer::AddIndices(int firstvert, TArray<int> &v)
//
//==========================================================================
bool F2DDrawer::SetStyle(FTexture *tex, DrawParms &parms, PalEntry &vertexcolor, RenderCommand &quad)
bool F2DDrawer::SetStyle(FGameTexture *tex, DrawParms &parms, PalEntry &vertexcolor, RenderCommand &quad)
{
FRenderStyle style = parms.style;
float alpha;
@ -390,7 +390,7 @@ void F2DDrawer::SetColorOverlay(PalEntry color, float alpha, PalEntry &vertexcol
//
//==========================================================================
void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
{
if (parms.style.BlendOp == STYLEOP_None) return; // not supposed to be drawn.
@ -472,7 +472,7 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
//
//==========================================================================
void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms)
{
// [MK] bail out if vertex/coord array sizes are mismatched
if ( shape->mVertices.Size() != shape->mCoords.Size() )
@ -550,12 +550,11 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
//
//==========================================================================
void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double fadelevel,
uint32_t *indices, size_t indexcount)
{
RenderCommand poly;
poly.mType = DrawTypeTriangles;
@ -630,7 +629,7 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
//
//==========================================================================
void F2DDrawer::AddPoly(FTexture* img, FVector4* vt, size_t vtcount, unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2)
void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2)
{
RenderCommand dg = {};
int method = 0;
@ -677,7 +676,7 @@ void F2DDrawer::AddPoly(FTexture* img, FVector4* vt, size_t vtcount, unsigned in
//
//==========================================================================
void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, bool local_origin)
{
float fU1, fU2, fV1, fV2;
@ -693,17 +692,17 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FTexture *
// scaling is not used here.
if (!local_origin)
{
fU1 = float(left) / src->GetDisplayWidth();
fV1 = float(top) / src->GetDisplayHeight();
fU2 = float(right) / src->GetDisplayWidth();
fV2 = float(bottom) / src->GetDisplayHeight();
fU1 = float(left) / (float)src->GetDisplayWidth();
fV1 = float(top) / (float)src->GetDisplayHeight();
fU2 = float(right) / (float)src->GetDisplayWidth();
fV2 = float(bottom) / (float)src->GetDisplayHeight();
}
else
{
fU1 = 0;
fV1 = 0;
fU2 = float(right - left) / src->GetDisplayWidth();
fV2 = float(bottom - top) / src->GetDisplayHeight();
fU2 = float(right - left) / (float)src->GetDisplayWidth();
fV2 = float(bottom - top) / (float)src->GetDisplayHeight();
}
dg.mVertIndex = (int)mVertices.Reserve(4);
auto ptr = &mVertices[dg.mVertIndex];
@ -755,7 +754,7 @@ void F2DDrawer::ClearScreen(PalEntry color)
//
//==========================================================================
void F2DDrawer::AddLine(float x1, float y1, float x2, float y2, int clipx1, int clipy1, int clipx2, int clipy2, uint32_t color, uint8_t alpha)
void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1, int clipy1, int clipx2, int clipy2, uint32_t color, uint8_t alpha)
{
PalEntry p = (PalEntry)color;
p.a = alpha;

View file

@ -124,7 +124,7 @@ public:
int mIndexIndex;
int mIndexCount;
FTexture *mTexture;
FGameTexture *mTexture;
int mTranslationId;
PalEntry mSpecialColormap[2];
int mScissor[4];
@ -170,19 +170,19 @@ public:
void AddIndices(int firstvert, int count, ...);
private:
void AddIndices(int firstvert, TArray<int> &v);
bool SetStyle(FTexture *tex, DrawParms &parms, PalEntry &color0, RenderCommand &quad);
bool SetStyle(FGameTexture *tex, DrawParms &parms, PalEntry &color0, RenderCommand &quad);
void SetColorOverlay(PalEntry color, float alpha, PalEntry &vertexcolor, PalEntry &overlaycolor);
public:
void AddTexture(FTexture *img, DrawParms &parms);
void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms);
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
void AddTexture(FGameTexture* img, DrawParms& parms);
void AddShape(FGameTexture *img, DShape2D *shape, DrawParms &parms);
void AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount);
void AddPoly(FTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2);
void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2);
void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex,
int clipx1, int clipy1, int clipx2, int clipy2);
void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false);
void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, bool local_origin = false);
void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style = nullptr);
void ClearScreen(PalEntry color = 0xff000000);
@ -190,7 +190,7 @@ public:
void AddClear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
void AddLine(float x1, float y1, float x2, float y2, int cx, int cy, int cx2, int cy2, uint32_t color, uint8_t alpha = 255);
void AddLine(double x1, double y1, double x2, double y2, int cx, int cy, int cx2, int cy2, uint32_t color, uint8_t alpha = 255);
void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255);
void AddPixel(int x1, int y1, uint32_t color);

View file

@ -180,7 +180,7 @@ int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
//
//==========================================================================
void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_first, ...)
void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, ...)
{
Va_List tags;
va_start(tags.list, tags_first);
@ -203,7 +203,7 @@ void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_
int ListGetInt(VMVa_List &tags);
static void DrawTexture(F2DDrawer *drawer, FTexture *img, double x, double y, VMVa_List &args)
static void DrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y, VMVa_List &args)
{
DrawParms parms;
uint32_t tag = ListGetInt(args);
@ -224,7 +224,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture)
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
FTexture *tex = TexMan.ByIndex(texid, animate);
auto tex = TexMan.GameByIndex(texid, animate);
VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 };
DrawTexture(twod, tex, x, y, args);
return 0;
@ -236,7 +236,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture)
//
//==========================================================================
void DrawShape(F2DDrawer *drawer, FTexture *img, DShape2D *shape, int tags_first, ...)
void DrawShape(F2DDrawer *drawer, FGameTexture *img, DShape2D *shape, int tags_first, ...)
{
Va_List tags;
va_start(tags.list, tags_first);
@ -248,7 +248,7 @@ void DrawShape(F2DDrawer *drawer, FTexture *img, DShape2D *shape, int tags_first
drawer->AddShape(img, shape, parms);
}
void DrawShape(F2DDrawer *drawer, FTexture *img, DShape2D *shape, VMVa_List &args)
void DrawShape(F2DDrawer *drawer, FGameTexture *img, DShape2D *shape, VMVa_List &args)
{
DrawParms parms;
uint32_t tag = ListGetInt(args);
@ -269,7 +269,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawShape)
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
FTexture *tex = TexMan.ByIndex(texid, animate);
auto tex = TexMan.GameByIndex(texid, animate);
VMVa_List args = { param + 3, 0, numparam - 4, va_reginfo + 3 };
DrawShape(twod, tex, shape, args);
@ -334,7 +334,7 @@ DEFINE_ACTION_FUNCTION(_Screen, GetClipRect)
//
//==========================================================================
bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FTexture *img, double xx, double yy)
bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, double xx, double yy)
{
auto GetWidth = [=]() { return drawer->GetWidth(); };
auto GetHeight = [=]() {return drawer->GetHeight(); };
@ -342,8 +342,8 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FTexture *img, double
{
parms->x = xx;
parms->y = yy;
parms->texwidth = img->GetDisplayWidthDouble();
parms->texheight = img->GetDisplayHeightDouble();
parms->texwidth = img->GetDisplayWidth();
parms->texheight = img->GetDisplayHeight();
if (parms->top == INT_MAX || parms->fortext)
{
parms->top = img->GetDisplayTopOffset();
@ -354,11 +354,11 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FTexture *img, double
}
if (parms->destwidth == INT_MAX || parms->fortext)
{
parms->destwidth = img->GetDisplayWidthDouble();
parms->destwidth = img->GetDisplayWidth();
}
if (parms->destheight == INT_MAX || parms->fortext)
{
parms->destheight = img->GetDisplayHeightDouble();
parms->destheight = img->GetDisplayHeight();
}
switch (parms->cleanmode)
@ -387,10 +387,12 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FTexture *img, double
case DTA_FullscreenEx:
{
double aspect;
double srcwidth = img->GetDisplayWidthDouble();
double srcheight = img->GetDisplayHeightDouble();
double srcwidth = img->GetDisplayWidth();
double srcheight = img->GetDisplayHeight();
int autoaspect = parms->fsscalemode;
aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 400)? 1.333 : srcwidth / srcheight;
if (srcheight == 200) aspect = srcwidth / 240.;
else if (srcheight == 400) aspect = srcwidth / 480;
else aspect = srcwidth / srcheight;
parms->x = parms->y = 0;
parms->keepratio = true;
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
@ -531,7 +533,7 @@ static inline FSpecialColormap * ListGetSpecialColormap(VMVa_List &tags)
//==========================================================================
template<class T>
bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext)
bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext)
{
INTBOOL boolval;
int intval;
@ -724,8 +726,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)twod->fullscreenautoaspect;
parms->virtWidth = img->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
parms->virtWidth = img->GetDisplayWidth();
parms->virtHeight = img->GetDisplayHeight();
}
break;
@ -738,8 +740,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)intval;
parms->virtWidth = img->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
parms->virtWidth = img->GetDisplayWidth();
parms->virtHeight = img->GetDisplayHeight();
}
break;
@ -785,19 +787,19 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
break;
case DTA_SrcX:
parms->srcx = ListGetDouble(tags) / img->GetDisplayWidthDouble();
parms->srcx = ListGetDouble(tags) / img->GetDisplayWidth();
break;
case DTA_SrcY:
parms->srcy = ListGetDouble(tags) / img->GetDisplayHeightDouble();
parms->srcy = ListGetDouble(tags) / img->GetDisplayHeight();
break;
case DTA_SrcWidth:
parms->srcwidth = ListGetDouble(tags) / img->GetDisplayWidthDouble();
parms->srcwidth = ListGetDouble(tags) / img->GetDisplayWidth();
break;
case DTA_SrcHeight:
parms->srcheight = ListGetDouble(tags) / img->GetDisplayHeightDouble();
parms->srcheight = ListGetDouble(tags) / img->GetDisplayHeight();
break;
case DTA_TopOffset:
@ -829,8 +831,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
if (fortext) return false;
if (ListGetInt(tags))
{
parms->left = img->GetDisplayWidthDouble() * 0.5;
parms->top = img->GetDisplayHeightDouble() * 0.5;
parms->left = img->GetDisplayWidth() * 0.5;
parms->top = img->GetDisplayHeight() * 0.5;
}
break;
@ -839,8 +841,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
if (fortext) return false;
if (ListGetInt(tags))
{
parms->left = img->GetDisplayWidthDouble() * 0.5;
parms->top = img->GetDisplayHeightDouble();
parms->left = img->GetDisplayWidth() * 0.5;
parms->top = img->GetDisplayHeight();
}
break;
@ -1038,8 +1040,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y,
}
// explicitly instantiate both versions for v_text.cpp.
template bool ParseDrawTextureTags<Va_List>(F2DDrawer* drawer, FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext);
template bool ParseDrawTextureTags<VMVa_List>(F2DDrawer* drawer, FTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext);
template bool ParseDrawTextureTags<Va_List>(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext);
template bool ParseDrawTextureTags<VMVa_List>(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext);
//==========================================================================
//
@ -1131,7 +1133,7 @@ void VirtualToRealCoordsInt(F2DDrawer *drawer, int &x, int &y, int &w, int &h,
//
//==========================================================================
void FillBorder (F2DDrawer *drawer, FTexture *img)
void FillBorder (F2DDrawer *drawer, FGameTexture *img)
{
auto Width = drawer->GetWidth();
auto Height = drawer->GetHeight();
@ -1351,7 +1353,7 @@ void DrawBorder (F2DDrawer *drawer, FTextureID picnum, int x1, int y1, int x2, i
{
if (picnum.isValid())
{
drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetTexture(picnum, false));
drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetGameTexture(picnum, false));
}
else
{

View file

@ -203,20 +203,21 @@ inline int active_con_scale(F2DDrawer *drawer)
#endif
template<class T>
bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, bool fortext);
bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, bool fortext);
template<class T>
void DrawTextCommon(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const T* string, DrawParms& parms);
bool SetTextureParms(F2DDrawer *drawer, DrawParms* parms, FTexture* img, double x, double y);
bool SetTextureParms(F2DDrawer *drawer, DrawParms* parms, FGameTexture* img, double x, double y);
void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char* string, int tag_first, ...);
void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char32_t* string, int tag_first, ...);
void DrawChar(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...);
void DrawTexture(F2DDrawer* drawer, FTexture* img, double x, double y, int tags_first, ...);
void DrawTexture(F2DDrawer* drawer, FGameTexture* img, double x, double y, int tags_first, ...);
void DoDim(F2DDrawer* drawer, PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr);
void Dim(F2DDrawer* drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr);
void FillBorder(F2DDrawer *drawer, FTexture* img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
void FillBorder(F2DDrawer *drawer, FGameTexture* img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
void DrawFrame(F2DDrawer* drawer, int left, int top, int width, int height);
void DrawBorder(F2DDrawer* drawer, FTextureID, int x1, int y1, int x2, int y2);

View file

@ -53,7 +53,7 @@ int ListGetInt(VMVa_List &tags);
//
//==========================================================================
#if 0
FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
FGameTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
{
int w;
const uint8_t *ch;
@ -61,7 +61,7 @@ FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
int cy;
int trans = -1;
int kerning;
FTexture *pic;
FGameTexture *pic;
kerning = font->GetDefaultKerning();
@ -170,7 +170,7 @@ void DrawChar(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double
if (normalcolor >= NumTextColors)
normalcolor = CR_UNTRANSLATED;
FTexture* pic;
FGameTexture* pic;
int dummy;
bool redirected;
@ -200,7 +200,7 @@ void DrawChar(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double
if (normalcolor >= NumTextColors)
normalcolor = CR_UNTRANSLATED;
FTexture *pic;
FGameTexture *pic;
int dummy;
bool redirected;
@ -256,7 +256,7 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d
int boldcolor;
int trans = -1;
int kerning;
FTexture *pic;
FGameTexture *pic;
if (parms.celly == 0) parms.celly = font->GetHeight() + 1;
parms.celly *= parms.scaley;

View file

@ -1082,16 +1082,17 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
}
FTextureID chk = value;
if (chk.GetIndex() >= TexMan.NumTextures()) chk.SetNull();
FTexture *pic = TexMan.GetTexture(chk);
auto pic = TexMan.GetGameTexture(chk);
const char *name;
auto lump = pic->GetSourceLump();
if (fileSystem.GetLinkedTexture(pic->SourceLump) == pic)
if (fileSystem.GetLinkedTexture(lump) == pic)
{
name = fileSystem.GetFileFullName(pic->SourceLump);
name = fileSystem.GetFileFullName(lump);
}
else
{
name = pic->Name;
name = pic->GetName();
}
arc.WriteKey(key);
arc.w->StartArray();

View file

@ -57,7 +57,7 @@ extern FILE* hashfile;
struct FileSystem::LumpRecord
{
FResourceLump *lump;
FTexture* linkedTexture;
FGameTexture* linkedTexture;
LumpShortName shortName;
FString longName;
int rfnum;
@ -725,7 +725,7 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const
//
//==========================================================================
void FileSystem::SetLinkedTexture(int lump, FTexture *tex)
void FileSystem::SetLinkedTexture(int lump, FGameTexture *tex)
{
if ((size_t)lump < NumEntries)
{
@ -739,7 +739,7 @@ void FileSystem::SetLinkedTexture(int lump, FTexture *tex)
//
//==========================================================================
FTexture *FileSystem::GetLinkedTexture(int lump)
FGameTexture *FileSystem::GetLinkedTexture(int lump)
{
if ((size_t)lump < NumEntries)
{

View file

@ -16,7 +16,7 @@
class FResourceFile;
struct FResourceLump;
class FTexture;
class FGameTexture;
union LumpShortName
{
@ -38,7 +38,7 @@ public:
~FileData ();
void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); }
size_t GetSize () { return Block.Len(); }
FString GetString () { return Block; }
const FString &GetString () const { return Block; }
private:
FileData (const FString &source);
@ -124,8 +124,8 @@ public:
inline int CheckNumForFullName (const FString &name, int wadfile) { return CheckNumForFullName(name.GetChars(), wadfile); }
inline int GetNumForFullName (const FString &name) { return GetNumForFullName(name.GetChars()); }
void SetLinkedTexture(int lump, FTexture *tex);
FTexture *GetLinkedTexture(int lump);
void SetLinkedTexture(int lump, FGameTexture *tex);
FGameTexture *GetLinkedTexture(int lump);
void ReadFile (int lump, void *dest);

View file

@ -3,6 +3,8 @@
#ifndef __RESFILE_H
#define __RESFILE_H
#include <limits.h>
#include "files.h"
struct LumpFilterInfo
@ -17,7 +19,6 @@ struct LumpFilterInfo
};
class FResourceFile;
class FTexture;
// [RH] Namespaces from BOOM.
// These are needed here in the low level part so that WAD files can be properly set up.

View file

@ -73,7 +73,6 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
int i;
FTextureID lump;
char buffer[12];
int maxyoffs;
DVector2 Scale = { 1, 1 };
noTranslate = notranslate;
@ -91,9 +90,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
translateUntranslated = false;
int FixedWidth = 0;
maxyoffs = 0;
TMap<int, FTexture*> charMap;
TMap<int, FGameTexture*> charMap;
int minchar = INT_MAX;
int maxchar = INT_MIN;
@ -231,13 +228,13 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
Type = Multilump;
if (position < minchar) minchar = position;
if (position > maxchar) maxchar = position;
charMap.Insert(position, TexMan.GetTexture(lump));
charMap.Insert(position, TexMan.GetGameTexture(lump));
}
}
}
else
{
FTexture *texs[256] = {};
FGameTexture *texs[256] = {};
if (lcount > 256 - start) lcount = 256 - start;
for (i = 0; i < lcount; i++)
{
@ -247,8 +244,8 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
TexMan.ListTextures(buffer, array, true);
for (auto entry : array)
{
FTexture *tex = TexMan.GetTexture(entry, false);
if (tex && tex->GetSourceLump() >= 0 && fileSystem.GetFileContainer(tex->GetSourceLump()) <= fileSystem.GetMaxIwadNum() && tex->GetUseType() == ETextureType::MiscPatch)
auto tex = TexMan.GetGameTexture(entry, false);
if (tex && !tex->isUserContent() && tex->GetUseType() == ETextureType::MiscPatch)
{
texs[i] = tex;
}
@ -292,8 +289,8 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
{
if ((int)position < minchar) minchar = (int)position;
if ((int)position > maxchar) maxchar = (int)position;
auto tex = TexMan.GetTexture(lump);
tex->SetScale(Scale);
auto tex = TexMan.GetGameTexture(lump);
tex->SetScale((float)Scale.X, (float)Scale.Y);
charMap.Insert((int)position, tex);
Type = Folder;
}
@ -312,17 +309,13 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
auto lump = charMap.CheckKey(FirstChar + i);
if (lump != nullptr)
{
FTexture *pic = *lump;
auto pic = *lump;
if (pic != nullptr)
{
int height = pic->GetDisplayHeight();
int yoffs = pic->GetDisplayTopOffset();
double fheight = pic->GetDisplayHeight();
double yoffs = pic->GetDisplayTopOffset();
if (yoffs > maxyoffs)
{
maxyoffs = yoffs;
}
height += abs(yoffs);
int height = int(fheight + abs(yoffs) + 0.5);
if (height > fontheight)
{
fontheight = height;
@ -333,24 +326,24 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
}
}
Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), "");
Chars[i].OriginalPic->SetUseType(ETextureType::FontChar);
Chars[i].OriginalPic->CopySize(pic);
TexMan.AddTexture(Chars[i].OriginalPic);
auto orig = pic->GetTexture();
auto tex = MakeGameTexture(orig, nullptr, ETextureType::FontChar);
tex->CopySize(pic);
TexMan.AddGameTexture(tex);
Chars[i].OriginalPic = tex;
if (!noTranslate)
{
Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), "");
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1(orig->GetImage())), nullptr, ETextureType::FontChar);
Chars[i].TranslatedPic->CopySize(pic);
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
TexMan.AddTexture(Chars[i].TranslatedPic);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
}
else
{
Chars[i].TranslatedPic = Chars[i].OriginalPic;
Chars[i].TranslatedPic = tex;
}
Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth();
Chars[i].XMove = (int)Chars[i].TranslatedPic->GetDisplayWidth();
}
else
{
@ -388,8 +381,8 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale)
{
// all valid lumps must be named with a hex number that represents the Unicode character index for its first character,
TArray<TexPart> part(1, true);
TMap<int, FTexture*> charMap;
TArray<TexPartBuild> part(1, true);
TMap<int, FGameTexture*> charMap;
int minchar = INT_MAX;
int maxchar = INT_MIN;
for (auto &entry : folderdata)
@ -402,7 +395,7 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch);
if (lump.isValid())
{
auto tex = TexMan.GetTexture(lump);
auto tex = TexMan.GetGameTexture(lump);
int numtex_x = tex->GetTexelWidth() / width;
int numtex_y = tex->GetTexelHeight() / height;
int maxinsheet = int(position) + numtex_x * numtex_y - 1;
@ -415,25 +408,16 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
{
part[0].OriginX = -width * x;
part[0].OriginY = -height * y;
part[0].Image = tex->GetImage();
part[0].TexImage = static_cast<FImageTexture*>(tex->GetTexture());
FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false);
FImageTexture *tex = new FImageTexture(image, "");
tex->SetUseType(ETextureType::FontChar);
tex->bMultiPatch = true;
tex->Width = width;
tex->Height = height;
tex->_LeftOffset[0] =
tex->_LeftOffset[1] =
tex->_TopOffset[0] =
tex->_TopOffset[1] = 0;
tex->Scale = Scale;
tex->bMasked = true;
tex->bTranslucent = -1;
tex->bWorldPanning = true;
tex->bNoDecals = false;
tex->SourceLump = -1; // We do not really care.
TexMan.AddTexture(tex);
charMap.Insert(int(position) + x + y * numtex_x, tex);
FImageTexture *tex = new FImageTexture(image);
auto gtex = MakeGameTexture(tex, nullptr, ETextureType::FontChar);
gtex->SetWorldPanning(true);
gtex->SetOffsets(0, 0, 0);
gtex->SetOffsets(1, 0, 0);
gtex->SetScale((float)Scale.X, (float)Scale.Y);
TexMan.AddGameTexture(gtex);
charMap.Insert(int(position) + x + y * numtex_x, gtex);
}
}
}
@ -458,18 +442,18 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
auto lump = charMap.CheckKey(FirstChar + i);
if (lump != nullptr)
{
FTexture *pic = *lump;
auto pic = (*lump)->GetTexture();
auto b = pic->Get8BitPixels(false);
Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), "");
Chars[i].OriginalPic = MakeGameTexture(pic, nullptr, ETextureType::FontChar);
Chars[i].OriginalPic->SetUseType(ETextureType::FontChar);
Chars[i].OriginalPic->CopySize(pic);
Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), "");
Chars[i].TranslatedPic->CopySize(pic);
Chars[i].OriginalPic->CopySize(*lump);
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1(pic->GetImage())), nullptr, ETextureType::FontChar);
Chars[i].TranslatedPic->CopySize(*lump);
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
TexMan.AddTexture(Chars[i].OriginalPic);
TexMan.AddTexture(Chars[i].TranslatedPic);
TexMan.AddGameTexture(Chars[i].OriginalPic);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
}
Chars[i].XMove = width;
}
@ -619,7 +603,7 @@ void FFont::RecordAllTextureColors(uint32_t *usedcolors)
{
if (Chars[i].TranslatedPic)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage());
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage());
if (pic)
{
// The remap must be temporarily reset here because this can be called on an initialized font.
@ -982,7 +966,7 @@ int FFont::GetCharCode(int code, bool needpic) const
//
//==========================================================================
FTexture *FFont::GetChar (int code, int translation, int *const width, bool *redirected) const
FGameTexture *FFont::GetChar (int code, int translation, int *const width, bool *redirected) const
{
code = GetCharCode(code, true);
int xmove = SpaceWidth;
@ -1037,11 +1021,11 @@ int FFont::GetCharWidth (int code) const
double GetBottomAlignOffset(FFont *font, int c)
{
int w;
FTexture *tex_zero = font->GetChar('0', CR_UNDEFINED, &w);
FTexture *texc = font->GetChar(c, CR_UNDEFINED, &w);
auto tex_zero = font->GetChar('0', CR_UNDEFINED, &w);
auto texc = font->GetChar(c, CR_UNDEFINED, &w);
double offset = 0;
if (texc) offset += texc->GetDisplayTopOffsetDouble();
if (tex_zero) offset += -tex_zero->GetDisplayTopOffsetDouble() + tex_zero->GetDisplayHeightDouble();
if (texc) offset += texc->GetDisplayTopOffset();
if (tex_zero) offset += -tex_zero->GetDisplayTopOffset() + tex_zero->GetDisplayHeight();
return offset;
}
@ -1093,7 +1077,7 @@ bool FFont::CanPrint(const uint8_t *string) const
//
//==========================================================================
int FFont::StringWidth(const uint8_t *string) const
int FFont::StringWidth(const uint8_t *string, int spacing) const
{
int w = 0;
int maxw = 0;
@ -1123,13 +1107,17 @@ int FFont::StringWidth(const uint8_t *string) const
maxw = w;
w = 0;
}
else if (spacing >= 0)
{
w += GetCharWidth(chr) + GlobalKerning + spacing;
}
else
{
w += GetCharWidth(chr) + GlobalKerning;
w -= spacing;
}
}
return MAX(maxw, w);
return std::max(maxw, w);
}
//==========================================================================
@ -1196,7 +1184,7 @@ void FFont::LoadTranslations()
{
if (Chars[i].TranslatedPic)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage());
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage());
if (pic)
{
pic->SetSourceRemap(nullptr); // Force the FFontChar1 to return the same pixels as the base texture
@ -1210,7 +1198,7 @@ void FFont::LoadTranslations()
for (unsigned int i = 0; i < count; i++)
{
if(Chars[i].TranslatedPic)
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(PatchRemap);
}
BuildTranslations (Luminosity.Data(), identity, &TranslationParms[TranslationType][0], ActiveColors, nullptr);
@ -1286,7 +1274,7 @@ void FFont::FixXMoves()
}
if (Chars[i].OriginalPic)
{
int ofs = Chars[i].OriginalPic->GetDisplayTopOffset();
int ofs = (int)Chars[i].OriginalPic->GetDisplayTopOffset();
if (ofs > Displacement) Displacement = ofs;
}
}

View file

@ -289,10 +289,9 @@ public:
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = new FImageTexture(new FHexFontChar (&hexdata.glyphdata[offset+1], size, size * 9, 16));
Chars[i - FirstChar].TranslatedPic->SetUseType(ETextureType::FontChar);
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar (&hexdata.glyphdata[offset+1], size, size * 9, 16)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddTexture(Chars[i - FirstChar].TranslatedPic);
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;
@ -362,10 +361,9 @@ public:
{
auto offset = hexdata.glyphmap[i];
int size = hexdata.glyphdata[offset] / 16;
Chars[i - FirstChar].TranslatedPic = new FImageTexture(new FHexFontChar2(&hexdata.glyphdata[offset + 1], size, 2 + size * 8, 18));
Chars[i - FirstChar].TranslatedPic->SetUseType(ETextureType::FontChar);
Chars[i - FirstChar].TranslatedPic = MakeGameTexture(new FImageTexture(new FHexFontChar2(&hexdata.glyphdata[offset + 1], size, 2 + size * 8, 18)), nullptr, ETextureType::FontChar);
Chars[i - FirstChar].XMove = size * spacing;
TexMan.AddTexture(Chars[i - FirstChar].TranslatedPic);
TexMan.AddGameTexture(Chars[i - FirstChar].TranslatedPic);
}
else Chars[i - FirstChar].XMove = spacing;

View file

@ -167,10 +167,10 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
{
FTexture *pic = TexMan.GetTexture(picnum);
auto pic = TexMan.GetGameTexture(picnum);
FontHeight = pic->GetDisplayHeight ();
SpaceWidth = pic->GetDisplayWidth ();
FontHeight = (int)pic->GetDisplayHeight ();
SpaceWidth = (int)pic->GetDisplayWidth ();
GlobalKerning = 0;
FirstChar = LastChar = 'A';
@ -222,7 +222,7 @@ void FSingleLumpFont::LoadTranslations()
for(unsigned int i = 0;i < count;++i)
{
if(Chars[i].TranslatedPic)
static_cast<FFontChar2*>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
static_cast<FFontChar2*>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(PatchRemap);
}
BuildTranslations (luminosity, useidentity ? identity : nullptr, ranges, ActiveColors, usepalette ? local_palette : nullptr);
@ -353,9 +353,8 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
}
else
{
Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight));
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
TexMan.AddTexture(Chars[i].TranslatedPic);
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight)), nullptr, ETextureType::FontChar);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
do
{
int8_t code = *data_p++;
@ -483,15 +482,14 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
{ // Empty character: skip it.
continue;
}
auto tex = new FImageTexture(new FFontChar2(lump, int(chardata + chari + 6 - data),
auto tex = MakeGameTexture(new FImageTexture(new FFontChar2(lump, int(chardata + chari + 6 - data),
chardata[chari+1], // width
chardata[chari+2], // height
-(int8_t)chardata[chari+3], // x offset
-(int8_t)chardata[chari+4] // y offset
));
tex->SetUseType(ETextureType::FontChar);
)), nullptr, ETextureType::FontChar);
Chars[chardata[chari] - FirstChar].TranslatedPic = tex;
TexMan.AddTexture(tex);
TexMan.AddGameTexture(tex);
}
// If the font did not define a space character, determine a suitable space width now.
@ -556,10 +554,9 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity)
if(!Chars[i].TranslatedPic)
{
Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight));
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight)), nullptr, ETextureType::FontChar);
Chars[i].XMove = SpaceWidth;
TexMan.AddTexture(Chars[i].TranslatedPic);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
}
// Advance to next char's data and count the used colors.

View file

@ -45,7 +45,7 @@ public:
FSinglePicFont(const char *picname);
// FFont interface
FTexture *GetChar(int code, int translation, int *const width, bool *redirected = nullptr) const override;
FGameTexture *GetChar(int code, int translation, int *const width, bool *redirected = nullptr) const override;
int GetCharWidth (int code) const;
protected:
@ -72,11 +72,11 @@ FSinglePicFont::FSinglePicFont(const char *picname) :
I_FatalError ("%s is not a font or texture", picname);
}
FTexture *pic = TexMan.GetTexture(picnum);
auto pic = TexMan.GetGameTexture(picnum);
FontName = picname;
FontHeight = pic->GetDisplayHeight();
SpaceWidth = pic->GetDisplayWidth();
FontHeight = (int)pic->GetDisplayHeight();
SpaceWidth = (int)pic->GetDisplayWidth();
GlobalKerning = 0;
FirstChar = LastChar = 'A';
ActiveColors = 0;
@ -94,13 +94,13 @@ FSinglePicFont::FSinglePicFont(const char *picname) :
//
//==========================================================================
FTexture *FSinglePicFont::GetChar (int code, int translation, int *const width, bool *redirected) const
FGameTexture *FSinglePicFont::GetChar (int code, int translation, int *const width, bool *redirected) const
{
*width = SpaceWidth;
if (redirected) *redirected = false;
if (code == 'a' || code == 'A')
{
return TexMan.GetPalettedTexture(PicNum, true);
return TexMan.GetGameTexture(PicNum, true);
}
else
{

View file

@ -45,7 +45,7 @@
class FSpecialFont : public FFont
{
public:
FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate);
FSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate);
void LoadTranslations();
@ -60,13 +60,13 @@ protected:
//
//==========================================================================
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)
FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)
: FFont(lump)
{
int i;
TArray<FTexture *> charlumps(count, true);
TArray<FGameTexture *> charlumps(count, true);
int maxyoffs;
FTexture *pic;
FGameTexture *pic;
memcpy(this->notranslate, notranslate, 256*sizeof(bool));
@ -87,8 +87,8 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
pic = charlumps[i] = lumplist[i];
if (pic != nullptr)
{
int height = pic->GetDisplayHeight();
int yoffs = pic->GetDisplayTopOffset();
int height = (int)pic->GetDisplayHeight();
int yoffs = (int)pic->GetDisplayTopOffset();
if (yoffs > maxyoffs)
{
@ -104,20 +104,18 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
if (charlumps[i] != nullptr)
{
auto pic = charlumps[i];
Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), "");
Chars[i].OriginalPic->SetUseType(ETextureType::FontChar);
Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar);
Chars[i].OriginalPic->CopySize(pic);
TexMan.AddTexture(Chars[i].OriginalPic);
TexMan.AddGameTexture(Chars[i].OriginalPic);
if (!noTranslate)
{
Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charlumps[i]->GetImage()), "");
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1 (charlumps[i]->GetTexture()->GetImage())), nullptr, ETextureType::FontChar);
Chars[i].TranslatedPic->CopySize(charlumps[i]);
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
TexMan.AddTexture(Chars[i].TranslatedPic);
TexMan.AddGameTexture(Chars[i].TranslatedPic);
}
else Chars[i].TranslatedPic = Chars[i].OriginalPic;
Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth();
Chars[i].XMove = (int)Chars[i].TranslatedPic->GetDisplayWidth();
}
else
{
@ -167,7 +165,7 @@ void FSpecialFont::LoadTranslations()
{
if (Chars[i].TranslatedPic)
{
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage());
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage());
if (pic)
{
pic->SetSourceRemap(nullptr); // Force the FFontChar1 to return the same pixels as the base texture
@ -197,7 +195,7 @@ void FSpecialFont::LoadTranslations()
for (i = 0; i < count; i++)
{
if(Chars[i].TranslatedPic)
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetTexture()->GetImage())->SetSourceRemap(PatchRemap);
}
BuildTranslations(Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr, [=](FRemapTable* remap)
@ -217,7 +215,7 @@ void FSpecialFont::LoadTranslations()
ActiveColors = TotalColors;
}
FFont *CreateSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)
FFont *CreateSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)
{
return new FSpecialFont(name, first, count, lumplist, notranslate, lump, donttranslate);
}

View file

@ -144,7 +144,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname)
FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any);
if (picnum.isValid())
{
FTexture *tex = TexMan.GetTexture(picnum);
auto tex = TexMan.GetGameTexture(picnum);
if (tex && tex->GetSourceLump() >= folderfile)
{
FFont *CreateSinglePicFont(const char *name);
@ -170,7 +170,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname)
void V_InitCustomFonts()
{
FScanner sc;
FTexture *lumplist[256];
FGameTexture *lumplist[256];
bool notranslate[256];
bool donttranslate;
FString namebuffer, templatebuf;
@ -266,12 +266,12 @@ void V_InitCustomFonts()
else
{
if (format == 1) goto wrong;
FTexture **p = &lumplist[*(unsigned char*)sc.String];
FGameTexture **p = &lumplist[*(unsigned char*)sc.String];
sc.MustGetString();
FTextureID texid = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch);
if (texid.Exists())
{
*p = TexMan.GetTexture(texid);
*p = TexMan.GetGameTexture(texid);
}
else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetIwadNum())
{
@ -307,7 +307,7 @@ void V_InitCustomFonts()
}
if (count > 0)
{
FFont *CreateSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate);
FFont *CreateSpecialFont (const char *name, int first, int count, FGameTexture **lumplist, const bool *notranslate, int lump, bool donttranslate);
FFont *fnt = CreateSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump, donttranslate);
fnt->SetCursor(cursor);
fnt->SetKerning(kerning);

View file

@ -39,7 +39,7 @@
#include "name.h"
class DCanvas;
class FTexture;
class FGameTexture;
struct FRemapTable;
enum EColorRange : int
@ -77,7 +77,7 @@ enum EColorRange : int
extern int NumTextColors;
using GlyphSet = TMap<int, FTexture*>;
using GlyphSet = TMap<int, FGameTexture*>;
class FFont
{
@ -97,7 +97,7 @@ public:
FFont (const char *fontname, const char *nametemplate, const char *filetemplate, int first, int count, int base, int fdlump, int spacewidth=-1, bool notranslate = false, bool iwadonly = false, bool doomtemplate = false, GlyphSet *baseGlpyphs = nullptr);
virtual ~FFont ();
virtual FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const;
virtual FGameTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const;
virtual int GetCharWidth (int code) const;
int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
int GetLump() const { return Lump; }
@ -113,9 +113,9 @@ public:
static FFont *FindFont(FName fontname);
// Return width of string in pixels (unscaled)
int StringWidth (const uint8_t *str) const;
inline int StringWidth (const char *str) const { return StringWidth ((const uint8_t *)str); }
inline int StringWidth (const FString &str) const { return StringWidth ((const uint8_t *)str.GetChars()); }
int StringWidth (const uint8_t *str, int spacing = 0) const;
inline int StringWidth (const char *str, int spacing = 0) const { return StringWidth ((const uint8_t *)str, spacing); }
inline int StringWidth (const FString &str, int spacing = 0) const { return StringWidth ((const uint8_t *)str.GetChars(), spacing); }
// Checks if the font contains all characters to print this text.
bool CanPrint(const uint8_t *str) const;
@ -161,8 +161,8 @@ protected:
bool forceremap = false;
struct CharData
{
FTexture *TranslatedPic = nullptr; // Texture for use with font translations.
FTexture *OriginalPic = nullptr; // Texture for use with CR_UNTRANSLATED or font colorization.
FGameTexture *TranslatedPic = nullptr; // Texture for use with font translations.
FGameTexture *OriginalPic = nullptr; // Texture for use with CR_UNTRANSLATED or font colorization.
int XMove = INT_MIN;
};
TArray<CharData> Chars;

View file

@ -54,7 +54,7 @@ static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %0
static int CastS2So(FString *b) { return FSoundID(*b); }
static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(b); }
static void CastSID2S(FString* a, unsigned int b) { VM_CastSpriteIDToString(a, b); }
static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); }
static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetGameTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); }
void JitCompiler::EmitCAST()
{

View file

@ -1848,7 +1848,7 @@ static void DoCast(const VMRegisters &reg, const VMFrame *f, int a, int b, int c
case CAST_TID2S:
{
ASSERTS(a); ASSERTD(b);
auto tex = TexMan.GetTexture(*(FTextureID*)&(reg.d[b]));
auto tex = TexMan.GetGameTexture(*(FTextureID*)&(reg.d[b]));
reg.s[a] = tex == nullptr ? "(null)" : tex->GetName().GetChars();
break;
}

View file

@ -43,14 +43,14 @@
void AnimTexture::SetFrameSize(int width, int height)
{
FTexture::SetSize(width, height);
Image.Resize(width*height);
Image.Resize(width * height);
}
void AnimTexture::SetFrame(const uint8_t *palette, const void *data_)
void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
{
memcpy(Palette, palette, 768);
memcpy(Image.Data(), data_, Width * Height);
SystemTextures.Clean(true, true);
memcpy(Palette, palette, 768);
memcpy(Image.Data(), data_, Width * Height);
CleanHardwareTextures();
}
//===========================================================================
@ -70,10 +70,10 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
for (int i = 0; i < Width * Height; i++)
{
int p = i * 4;
int index = spix[i];
dpix[p + 0] = Palette[index*3+2];
dpix[p + 1] = Palette[index*3+1];
dpix[p + 2] = Palette[index*3];
int index = spix[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 bmp;
@ -87,30 +87,32 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
AnimTextures::AnimTextures()
{
active = 1;
tex[0] = new AnimTexture;
tex[1] = new AnimTexture;
active = 1;
tex[0] = MakeGameTexture(new AnimTexture, "", ETextureType::Special);
tex[1] = MakeGameTexture(new AnimTexture, "", ETextureType::Special);
}
AnimTextures::~AnimTextures()
{
delete tex[0];
delete tex[1];
delete tex[0];
delete tex[1];
}
void AnimTextures::SetSize(int width, int height)
{
tex[0]->SetFrameSize(width, height);
tex[1]->SetFrameSize(width, height);
}
void AnimTextures::SetFrame(const uint8_t *palette, const void* data)
{
active ^= 1;
tex[active]->SetFrame(palette, data);
static_cast<AnimTexture*>(tex[0]->GetTexture())->SetFrameSize(width, height);
static_cast<AnimTexture*>(tex[1]->GetTexture())->SetFrameSize(width, height);
tex[0]->SetSize(width, height);
tex[1]->SetSize(width, height);
}
FTexture * AnimTextures::GetFrame()
void AnimTextures::SetFrame(const uint8_t* palette, const void* data)
{
return tex[active];
active ^= 1;
static_cast<AnimTexture*>(tex[active]->GetTexture())->SetFrame(palette, data);
}
FGameTexture* AnimTextures::GetFrame()
{
return tex[active];
}

View file

@ -8,21 +8,21 @@ class AnimTexture : public FTexture
uint8_t Palette[768];
TArray<uint8_t> Image;
public:
AnimTexture() = default;
AnimTexture() = default;
void SetFrameSize(int width, int height);
void SetFrame(const uint8_t *palette, const void* data);
virtual FBitmap GetBgraBitmap(const PalEntry* remap, int* trans) override;
void SetFrame(const uint8_t* palette, const void* data);
virtual FBitmap GetBgraBitmap(const PalEntry* remap, int* trans) override;
};
class AnimTextures
{
int active;
AnimTexture *tex[2];
FGameTexture* tex[2];
public:
AnimTextures();
~AnimTextures();
void SetSize(int width, int height);
void SetFrame(const uint8_t *palette, const void* data);
FTexture *GetFrame();
void SetFrame(const uint8_t* palette, const void* data);
FGameTexture* GetFrame();
};

View file

@ -69,6 +69,11 @@ FImageSource *EmptyImage_TryCreate(FileReader & file, int lumpnum)
return new FEmptyTexture(lumpnum);
}
FImageSource* CreateEmptyTexture()
{
return new FEmptyTexture(0);
}
//==========================================================================
//
//

View file

@ -46,15 +46,19 @@
//
//==========================================================================
FMultiPatchTexture::FMultiPatchTexture(int w, int h, const TArray<TexPart> &parts, bool complex, bool textual)
FMultiPatchTexture::FMultiPatchTexture(int w, int h, const TArray<TexPartBuild> &parts, bool complex, bool textual)
{
Width = w;
Height = h;
bComplex = complex;
bTextual = textual;
bTextual = textual;
Parts = (TexPart*)ImageArena.Alloc(sizeof(TexPart) * parts.Size());
NumParts = parts.Size();
memcpy(Parts, parts.Data(), sizeof(TexPart) * parts.Size());
for (unsigned i = 0; i < parts.Size(); i++)
{
Parts[i].Image = parts[i].TexImage->GetImage();
}
bUseGamePalette = false;
if (!bComplex)
@ -67,6 +71,27 @@ FMultiPatchTexture::FMultiPatchTexture(int w, int h, const TArray<TexPart> &part
}
}
//==========================================================================
//
// sky remapping will only happen if
// - the texture was defined through a TEXTUREx lump (this implies only trivial copies)
// - all patches use the base palette.
// - all patches are in a format that allows the remap.
// All other cases would not be able to properly deal with this special case.
// For textual definitions this hack isn't necessary.
//
//==========================================================================
bool FMultiPatchTexture::SupportRemap0()
{
if (bTextual || UseGamePalette()) return false;
for (int i = 0; i < NumParts; i++)
{
if (!Parts[i].Image->SupportRemap0()) return false;
}
return true;
}
//==========================================================================
//
// GetBlendMap
@ -203,11 +228,6 @@ TArray<uint8_t> FMultiPatchTexture::CreatePalettedPixels(int conversion)
}
if (conversion == noremap0)
{
// sky remapping will only happen if
// - the texture was defined through a TEXTUREx lump (this implies only trivial copies)
// - all patches use the base palette.
// All other cases would not be able to properly deal with this special case.
// For textual definitions this hack isn't necessary.
if (bTextual || !UseGamePalette()) conversion = normal;
}

View file

@ -5,8 +5,11 @@
#include "vectors.h"
#include "bitmap.h"
#include "image.h"
#include "textures.h"
class FImageTexture;
class FTextureManager;
//==========================================================================
//
// TexPart is the data that will get passed to the final texture.
@ -25,6 +28,18 @@ struct TexPart
uint8_t op = OP_COPY;
};
struct TexPartBuild
{
FRemapTable* Translation = nullptr;
FImageTexture *TexImage = nullptr;
PalEntry Blend = 0;
blend_t Alpha = FRACUNIT;
int16_t OriginX = 0;
int16_t OriginY = 0;
uint8_t Rotate = 0;
uint8_t op = OP_COPY;
};
//==========================================================================
@ -36,8 +51,21 @@ struct TexPart
class FMultiPatchTexture : public FImageSource
{
friend class FTexture;
friend class FGameTexture;
public:
FMultiPatchTexture(int w, int h, const TArray<TexPart> &parts, bool complex, bool textual);
FMultiPatchTexture(int w, int h, const TArray<TexPartBuild> &parts, bool complex, bool textual);
int GetNumParts() const { return NumParts; }
// Query some needed info for texture hack support.
bool SupportRemap0() override;
bool IsRawCompatible() override
{
return NumParts != 1 || Parts[0].OriginY == 0 || bTextual;
}
FImageSource* GetImageForPart(int num)
{
if (num >= 0 && num < NumParts) return Parts[num].Image;
return nullptr;
}
protected:
int NumParts;
@ -64,7 +92,7 @@ struct TexInit
{
FString TexName;
ETextureType UseType = ETextureType::Null;
FTexture *Texture = nullptr;
FImageTexture *Texture = nullptr;
bool Silent = false;
bool HasLine = false;
bool UseOffsets = false;
@ -82,7 +110,7 @@ struct FPatchLookup;
struct BuildInfo
{
FString Name;
TArray<TexPart> Parts;
TArray<TexPartBuild> Parts;
TArray<TexInit> Inits;
int Width = 0;
int Height = 0;
@ -94,7 +122,7 @@ struct BuildInfo
bool bNoDecals = false;
int LeftOffset[2] = {};
int TopOffset[2] = {};
FImageTexture *tex = nullptr;
FGameTexture *texture = nullptr;
void swap(BuildInfo &other)
{
@ -113,7 +141,7 @@ struct BuildInfo
std::swap(LeftOffset[1], other.LeftOffset[1]);
std::swap(TopOffset[0], other.TopOffset[0]);
std::swap(TopOffset[1], other.TopOffset[1]);
std::swap(tex, other.tex);
std::swap(texture, other.texture);
}
};
@ -123,15 +151,17 @@ class FMultipatchTextureBuilder
{
FTextureManager &TexMan;
TArray<BuildInfo> BuiltTextures;
TMap<FGameTexture*, bool> complex;
void(*progressFunc)();
void(*checkForHacks)(BuildInfo&);
void MakeTexture(BuildInfo &buildinfo, ETextureType usetype);
void AddImageToTexture(FImageTexture* tex, BuildInfo& buildinfo);
void BuildTexture(const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum, ETextureType usetyoe);
void AddTexturesLump(const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1);
void ParsePatch(FScanner &sc, BuildInfo &info, TexPart &part, TexInit &init);
void ParsePatch(FScanner &sc, BuildInfo &info, TexPartBuild &part, TexInit &init);
void ResolvePatches(BuildInfo &buildinfo);
public:

View file

@ -63,6 +63,7 @@ public:
FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool isalphatex);
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
int CopyPixels(FBitmap *bmp, int conversion) override;
bool SupportRemap0() override { return !badflag; }
void DetectBadPatches();
};

View file

@ -41,8 +41,8 @@
#include "imagehelpers.h"
#include "image.h"
#include "printf.h"
#include "texturemanager.h"
#include "filesystem.h"
#include "colormatcher.h"
//==========================================================================
//
@ -591,7 +591,7 @@ protected:
//
//==========================================================================
FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename)
FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename)
{
if (M_FindPNGChunk(png, MAKE_ID('I','H','D','R')) == 0)
{
@ -610,7 +610,7 @@ FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename)
// Reject anything that cannot be put into a savegame picture by GZDoom itself.
if (compression != 0 || filter != 0 || interlace > 0 || bitdepth != 8 || (colortype != 2 && colortype != 3)) return nullptr;
else return new FPNGFileTexture (png->File, width, height, colortype);
else return MakeGameTexture(new FPNGFileTexture (png->File, width, height, colortype), nullptr, ETextureType::Override);
}
//==========================================================================
@ -624,6 +624,8 @@ FPNGFileTexture::FPNGFileTexture (FileReader &lump, int width, int height, uint8
{
Width = width;
Height = height;
Masked = false;
bTranslucent = false;
fr = std::move(lump);
}

View file

@ -38,6 +38,7 @@
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "textures.h"
class FBarShader : public FImageSource
@ -128,9 +129,9 @@ private:
};
FTexture *CreateShaderTexture(bool vertical, bool reverse)
FGameTexture *CreateShaderTexture(bool vertical, bool reverse)
{
FStringf name("BarShader%c%c", vertical ? 'v' : 'h', reverse ? 'r' : 'f');
return CreateImageTexture(new FBarShader(vertical, reverse), name.GetChars());
return MakeGameTexture(CreateImageTexture(new FBarShader(vertical, reverse)), name.GetChars(), ETextureType::Override);
}

View file

@ -0,0 +1,512 @@
/*
** gametexture.cpp
** The game-facing texture class.
**
**---------------------------------------------------------------------------
** Copyright 2004-2007 Randy Heit
** Copyright 2006-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 "printf.h"
#include "files.h"
#include "filesystem.h"
#include "templates.h"
#include "textures.h"
#include "bitmap.h"
#include "colormatcher.h"
#include "c_dispatch.h"
#include "m_fixed.h"
#include "imagehelpers.h"
#include "image.h"
#include "formats/multipatchtexture.h"
#include "texturemanager.h"
#include "c_cvars.h"
#include "hw_material.h"
FTexture *CreateBrightmapTexture(FImageSource*);
FGameTexture::FGameTexture(FTexture* wrap, const char* name) : Name(name)
{
if (wrap) Setup(wrap);
}
//==========================================================================
//
//
//
//==========================================================================
void FGameTexture::Setup(FTexture *wrap)
{
Base = wrap;
id.SetInvalid();
TexelWidth = Base->GetWidth();
DisplayWidth = (float)TexelWidth;
TexelHeight = Base->GetHeight();
DisplayHeight = (float)TexelHeight;
auto img = Base->GetImage();
if (img)
{
auto ofs = img->GetOffsets();
LeftOffset[0] = LeftOffset[1] = ofs.first;
TopOffset[0] = TopOffset[1] = ofs.second;
}
else
{
LeftOffset[0] = LeftOffset[1] =
TopOffset[0] = TopOffset[1] = 0;
}
ScaleX = ScaleY = 1.f;
}
//==========================================================================
//
//
//
//==========================================================================
FGameTexture::~FGameTexture()
{
FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump());
if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr);
if (SoftwareTexture != nullptr)
{
delete SoftwareTexture;
SoftwareTexture = nullptr;
}
for (auto &mat : Material)
{
if (mat != nullptr) delete mat;
mat = nullptr;
}
}
//==========================================================================
//
//
//
//==========================================================================
bool FGameTexture::isUserContent() const
{
int filenum = fileSystem.GetFileContainer(Base->GetSourceLump());
return (filenum > fileSystem.GetMaxIwadNum());
}
//==========================================================================
//
// Search auto paths for extra material textures
//
//==========================================================================
void FGameTexture::AddAutoMaterials()
{
struct AutoTextureSearchPath
{
const char* path;
RefCountedPtr<FTexture> FGameTexture::* pointer;
};
static AutoTextureSearchPath autosearchpaths[] =
{
{ "brightmaps/", &FGameTexture::Brightmap }, // For backwards compatibility, only for short names
{ "materials/brightmaps/", &FGameTexture::Brightmap },
{ "materials/normalmaps/", &FGameTexture::Normal },
{ "materials/specular/", &FGameTexture::Specular },
{ "materials/metallic/", &FGameTexture::Metallic },
{ "materials/roughness/", &FGameTexture::Roughness },
{ "materials/ao/", &FGameTexture::AmbientOcclusion }
};
bool fullname = !!(flags & GTexf_FullNameTexture);
FString searchname = GetName();
if (fullname)
{
auto dot = searchname.LastIndexOf('.');
auto slash = searchname.LastIndexOf('/');
if (dot > slash) searchname.Truncate(dot);
}
for (size_t i = 0; i < countof(autosearchpaths); i++)
{
auto& layer = autosearchpaths[i];
if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
{
FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars());
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true);
if (lump != -1)
{
auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);
if (bmtex != nullptr)
{
this->*(layer.pointer) = bmtex->GetTexture();
}
}
}
}
}
//===========================================================================
//
// Checks if the texture has a default brightmap and creates it if so
//
//===========================================================================
void FGameTexture::CreateDefaultBrightmap()
{
auto tex = GetTexture();
if (flags & GTexf_BrightmapChecked)
{
flags |= GTexf_BrightmapChecked;
// Check for brightmaps
if (tex->GetImage() && tex->GetImage()->UseGamePalette() && GPalette.HasGlobalBrightmap &&
GetUseType() != ETextureType::Decal && GetUseType() != ETextureType::MiscPatch && GetUseType() != ETextureType::FontChar &&
Brightmap == nullptr)
{
// May have one - let's check when we use this texture
auto texbuf = tex->Get8BitPixels(false);
const int white = ColorMatcher.Pick(255, 255, 255);
int size = tex->GetWidth() * tex->GetHeight();
for (int i = 0; i < size; i++)
{
if (GPalette.GlobalBrightmap.Remap[texbuf[i]] == white)
{
// Create a brightmap
DPrintf(DMSG_NOTIFY, "brightmap created for texture '%s'\n", GetName().GetChars());
Brightmap = CreateBrightmapTexture(tex->GetImage());
return;
}
}
// No bright pixels found
DPrintf(DMSG_SPAMMY, "No bright pixels found in texture '%s'\n", GetName().GetChars());
}
}
}
//==========================================================================
//
// Calculates glow color for a texture
//
//==========================================================================
void FGameTexture::GetGlowColor(float* data)
{
if (isGlowing() && GlowColor == 0)
{
auto buffer = Base->GetBgraBitmap(nullptr);
GlowColor = averageColor((uint32_t*)buffer.GetPixels(), buffer.GetWidth() * buffer.GetHeight(), 153);
// Black glow equals nothing so switch glowing off
if (GlowColor == 0) flags &= ~GTexf_Glowing;
}
data[0] = GlowColor.r * (1 / 255.0f);
data[1] = GlowColor.g * (1 / 255.0f);
data[2] = GlowColor.b * (1 / 255.0f);
}
//===========================================================================
//
//
//
//===========================================================================
int FGameTexture::GetAreas(FloatRect** pAreas) const
{
if (shaderindex == SHADER_Default) // texture splitting can only be done if there's no attached effects
{
*pAreas = Base->areas;
return Base->areacount;
}
else
{
return 0;
}
}
//===========================================================================
//
// Checks if a sprite may be expanded with an empty frame
//
//===========================================================================
bool FGameTexture::ShouldExpandSprite()
{
if (expandSprite != -1) return expandSprite;
// Only applicable to image textures with no shader effect.
if (GetShaderIndex() != SHADER_Default || !dynamic_cast<FImageTexture*>(Base.get()))
{
expandSprite = false;
return false;
}
if (Brightmap != NULL && (Base->GetWidth() != Brightmap->GetWidth() || Base->GetHeight() != Brightmap->GetHeight()))
{
// do not expand if the brightmap's physical size differs from the base.
expandSprite = false;
return false;
}
if (Glowmap != NULL && (Base->GetWidth() != Glowmap->GetWidth() || Base->GetHeight() != Glowmap->GetHeight()))
{
// same restriction for the glow map
expandSprite = false;
return false;
}
expandSprite = true;
return true;
}
//===========================================================================
//
// Sets up the sprite positioning data for this texture
//
//===========================================================================
void FGameTexture::SetupSpriteData()
{
// Since this is only needed for real sprites it gets allocated on demand.
// It also allocates from the image memory arena because it has the same lifetime and to reduce maintenance.
if (spi == nullptr) spi = (SpritePositioningInfo*)ImageArena.Alloc(2 * sizeof(SpritePositioningInfo));
for (int i = 0; i < 2; i++)
{
auto& spi = this->spi[i];
spi.mSpriteU[0] = spi.mSpriteV[0] = 0.f;
spi.mSpriteU[1] = spi.mSpriteV[1] = 1.f;
spi.spriteWidth = GetTexelWidth();
spi.spriteHeight = GetTexelHeight();
if (i == 1 && ShouldExpandSprite())
{
spi.mTrimResult = Base->TrimBorders(spi.trim); // get the trim size before adding the empty frame
spi.spriteWidth += 2;
spi.spriteHeight += 2;
}
}
SetSpriteRect();
}
//===========================================================================
//
// Set the sprite rectangle. This is separate because it may be called by a CVAR, too.
//
//===========================================================================
void FGameTexture::SetSpriteRect()
{
if (!spi) return;
auto leftOffset = GetTexelLeftOffset(r_spriteadjustHW);
auto topOffset = GetTexelTopOffset(r_spriteadjustHW);
float fxScale = GetScaleX();
float fyScale = GetScaleY();
for (int i = 0; i < 2; i++)
{
auto& spi = this->spi[i];
// mSpriteRect is for positioning the sprite in the scene.
spi.mSpriteRect.left = -leftOffset / fxScale;
spi.mSpriteRect.top = -topOffset / fyScale;
spi.mSpriteRect.width = spi.spriteWidth / fxScale;
spi.mSpriteRect.height = spi.spriteHeight / fyScale;
if (i == 1 && ShouldExpandSprite())
{
// a little adjustment to make sprites look better with texture filtering:
// create a 1 pixel wide empty frame around them.
int oldwidth = spi.spriteWidth - 2;
int oldheight = spi.spriteHeight - 2;
leftOffset += 1;
topOffset += 1;
// Reposition the sprite with the frame considered
spi.mSpriteRect.left = -(float)leftOffset / fxScale;
spi.mSpriteRect.top = -(float)topOffset / fyScale;
spi.mSpriteRect.width = (float)spi.spriteWidth / fxScale;
spi.mSpriteRect.height = (float)spi.spriteHeight / fyScale;
if (spi.mTrimResult > 0)
{
spi.mSpriteRect.left += (float)spi.trim[0] / fxScale;
spi.mSpriteRect.top += (float)spi.trim[1] / fyScale;
spi.mSpriteRect.width -= float(oldwidth - spi.trim[2]) / fxScale;
spi.mSpriteRect.height -= float(oldheight - spi.trim[3]) / fyScale;
spi.mSpriteU[0] = (float)spi.trim[0] / (float)spi.spriteWidth;
spi.mSpriteV[0] = (float)spi.trim[1] / (float)spi.spriteHeight;
spi.mSpriteU[1] -= float(oldwidth - spi.trim[0] - spi.trim[2]) / (float)spi.spriteWidth;
spi.mSpriteV[1] -= float(oldheight - spi.trim[1] - spi.trim[3]) / (float)spi.spriteHeight;
}
}
}
}
//===========================================================================
//
// Cleans the attached hardware resources.
// This should only be used on textures which alter their content at run time
//or when the engine shuts down.
//
//===========================================================================
void FGameTexture::CleanHardwareData(bool full)
{
Base->CleanHardwareTextures();
for (auto mat : Material) if (mat) mat->DeleteDescriptors();
}
//-----------------------------------------------------------------------------
//
// Make sprite offset adjustment user-configurable per renderer.
//
//-----------------------------------------------------------------------------
CUSTOM_CVAR(Int, r_spriteadjust, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
r_spriteadjustHW = !!(self & 2);
r_spriteadjustSW = !!(self & 1);
for (int i = 0; i < TexMan.NumTextures(); i++)
{
auto tex = TexMan.GetGameTexture(FSetTextureID(i));
if (tex->GetTexelLeftOffset(0) != tex->GetTexelLeftOffset(1) || tex->GetTexelTopOffset(0) != tex->GetTexelTopOffset(1))
{
tex->SetSpriteRect();
}
}
}
//===========================================================================
//
// Coordinate helper.
// The only reason this is even needed is that many years ago someone
// was convinced that having per-texel panning on walls was a good idea.
// If it wasn't for this relatively useless feature the entire positioning
// code for wall textures could be a lot simpler.
//
//===========================================================================
//===========================================================================
//
//
//
//===========================================================================
float FTexCoordInfo::RowOffset(float rowoffset) const
{
float scale = fabs(mScale.Y);
if (scale == 1.f || mWorldPanning) return rowoffset;
else return rowoffset / scale;
}
//===========================================================================
//
//
//
//===========================================================================
float FTexCoordInfo::TextureOffset(float textureoffset) const
{
float scale = fabs(mScale.X);
if (scale == 1.f || mWorldPanning) return textureoffset;
else return textureoffset / scale;
}
//===========================================================================
//
// Returns the size for which texture offset coordinates are used.
//
//===========================================================================
float FTexCoordInfo::TextureAdjustWidth() const
{
if (mWorldPanning)
{
float tscale = fabs(mTempScale.X);
if (tscale == 1.f) return (float)mRenderWidth;
else return mWidth / fabs(tscale);
}
else return (float)mWidth;
}
//===========================================================================
//
// Retrieve texture coordinate info for per-wall scaling
//
//===========================================================================
void FTexCoordInfo::GetFromTexture(FGameTexture *tex, float x, float y, bool forceworldpanning)
{
if (x == 1.f)
{
mRenderWidth = xs_RoundToInt(tex->GetDisplayWidth());
mScale.X = tex->GetScaleX();
mTempScale.X = 1.f;
}
else
{
float scale_x = x * tex->GetScaleX();
mRenderWidth = xs_CeilToInt(tex->GetTexelWidth() / scale_x);
mScale.X = scale_x;
mTempScale.X = x;
}
if (y == 1.f)
{
mRenderHeight = xs_RoundToInt(tex->GetDisplayHeight());
mScale.Y = tex->GetScaleY();
mTempScale.Y = 1.f;
}
else
{
float scale_y = y * tex->GetScaleY();
mRenderHeight = xs_CeilToInt(tex->GetTexelHeight() / scale_y);
mScale.Y = scale_y;
mTempScale.Y = y;
}
if (tex->isHardwareCanvas())
{
mScale.Y = -mScale.Y;
mRenderHeight = -mRenderHeight;
}
mWorldPanning = tex->useWorldPanning() || forceworldpanning;
mWidth = tex->GetTexelWidth();
}

View file

@ -0,0 +1,339 @@
#pragma once
#include <stdint.h>
#include "vectors.h"
#include "floatrect.h"
#include "refcounted.h"
#include "xs_Float.h"
#include "palentry.h"
#include "zstring.h"
#include "textureid.h"
// 15 because 0th texture is our texture
#define MAX_CUSTOM_HW_SHADER_TEXTURES 15
class FTexture;
class ISoftwareTexture;
class FMaterial;
struct SpritePositioningInfo
{
uint16_t trim[4];
int spriteWidth, spriteHeight;
float mSpriteU[2], mSpriteV[2];
FloatRect mSpriteRect;
uint8_t mTrimResult;
float GetSpriteUL() const { return mSpriteU[0]; }
float GetSpriteVT() const { return mSpriteV[0]; }
float GetSpriteUR() const { return mSpriteU[1]; }
float GetSpriteVB() const { return mSpriteV[1]; }
const FloatRect &GetSpriteRect() const
{
return mSpriteRect;
}
};
struct MaterialLayers
{
float Glossiness;
float SpecularLevel;
FGameTexture* Brightmap;
FGameTexture* Normal;
FGameTexture* Specular;
FGameTexture* Metallic;
FGameTexture* Roughness;
FGameTexture* AmbientOcclusion;
FGameTexture* CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES];
};
enum EGameTexFlags
{
GTexf_NoDecals = 1, // Decals should not stick to texture
GTexf_WorldPanning = 2, // Texture is panned in world units rather than texels
GTexf_FullNameTexture = 4, // Name is taken from the file system.
GTexf_Glowing = 8, // Texture emits a glow
GTexf_AutoGlowing = 16, // Glow info is determined from texture image.
GTexf_RenderFullbright = 32, // always draw fullbright
GTexf_DisableFullbrightSprites = 64, // This texture will not be displayed as fullbright sprite
GTexf_BrightmapChecked = 128, // Check for a colormap-based brightmap was already done.
};
// Refactoring helper to allow piece by piece adjustment of the API
class FGameTexture
{
friend class FMaterial;
// Material layers. These are shared so reference counting is used.
RefCountedPtr<FTexture> Base;
RefCountedPtr<FTexture> Brightmap;
RefCountedPtr<FTexture> Detailmap;
RefCountedPtr<FTexture> Glowmap;
RefCountedPtr<FTexture> Normal; // Normal map texture
RefCountedPtr<FTexture> Specular; // Specular light texture for the diffuse+normal+specular light model
RefCountedPtr<FTexture> Metallic; // Metalness texture for the physically based rendering (PBR) light model
RefCountedPtr<FTexture> Roughness; // Roughness texture for PBR
RefCountedPtr<FTexture> AmbientOcclusion; // Ambient occlusion texture for PBR
RefCountedPtr<FTexture> CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES]; // Custom texture maps for custom hardware shaders
FString Name;
FTextureID id;
uint16_t TexelWidth, TexelHeight;
int16_t LeftOffset[2], TopOffset[2];
float DisplayWidth, DisplayHeight;
float ScaleX, ScaleY;
int8_t shouldUpscaleFlag = 0; // Without explicit setup, scaling is disabled for a texture.
ETextureType UseType = ETextureType::Wall; // This texture's primary purpose
SpritePositioningInfo* spi = nullptr;
ISoftwareTexture* SoftwareTexture = nullptr;
FMaterial* Material[4] = { };
// Material properties
float Glossiness = 10.f;
float SpecularLevel = 0.1f;
float shaderspeed = 1.f;
int shaderindex = 0;
int flags = 0;
uint8_t warped = 0;
int8_t expandSprite = -1;
uint16_t GlowHeight;
PalEntry GlowColor = 0;
int16_t SkyOffset = 0;
uint16_t Rotations = 0xffff;
public:
float alphaThreshold = 0.5f;
FGameTexture(FTexture* wrap, const char *name);
~FGameTexture();
void Setup(FTexture* wrap);
FTextureID GetID() const { return id; }
void SetID(FTextureID newid) { id = newid; } // should only be called by the texture manager
const FString& GetName() const { return Name; }
void SetName(const char* name) { Name = name; } // should only be called by setup code.
float GetScaleX() { return ScaleX; }
float GetScaleY() { return ScaleY; }
float GetDisplayWidth() const { return DisplayWidth; }
float GetDisplayHeight() const { return DisplayHeight; }
int GetTexelWidth() const { return TexelWidth; }
int GetTexelHeight() const { return TexelHeight; }
void CreateDefaultBrightmap();
void AddAutoMaterials();
bool ShouldExpandSprite();
void SetupSpriteData();
void SetSpriteRect();
ETextureType GetUseType() const { return UseType; }
void SetUpscaleFlag(int what) { shouldUpscaleFlag = what; }
int GetUpscaleFlag() { return shouldUpscaleFlag; }
FTexture* GetTexture() { return Base.get(); }
int GetSourceLump() const { return Base->GetSourceLump(); }
void SetBrightmap(FGameTexture* tex) { Brightmap = tex->GetTexture(); }
int GetTexelLeftOffset(int adjusted = 0) const { return LeftOffset[adjusted]; }
int GetTexelTopOffset(int adjusted = 0) const { return TopOffset[adjusted]; }
float GetDisplayLeftOffset(int adjusted = 0) const { return LeftOffset[adjusted] / ScaleX; }
float GetDisplayTopOffset(int adjusted = 0) const { return TopOffset[adjusted] / ScaleY; }
bool isMiscPatch() const { return GetUseType() == ETextureType::MiscPatch; } // only used by the intermission screen to decide whether to tile the background image or not.
bool isFullbrightDisabled() const { return !!(flags & GTexf_DisableFullbrightSprites); }
bool isFullbright() const { return !!(flags & GTexf_RenderFullbright); }
bool isFullNameTexture() const { return !!(flags & GTexf_FullNameTexture); }
bool expandSprites() { return expandSprite == -1? ShouldExpandSprite() : !!expandSprite; }
bool useWorldPanning() const { return !!(flags & GTexf_WorldPanning); }
void SetWorldPanning(bool on) { if (on) flags |= GTexf_WorldPanning; else flags &= ~GTexf_WorldPanning; }
bool allowNoDecals() const { return !!(flags & GTexf_NoDecals); }
void SetNoDecals(bool on) { if (on) flags |= GTexf_NoDecals; else flags &= ~GTexf_NoDecals; }
bool isValid() const { return UseType != ETextureType::Null; }
int isWarped() { return warped; }
void SetWarpStyle(int style) { warped = style; }
bool isMasked() { return Base->Masked; }
bool isHardwareCanvas() const { return Base->isHardwareCanvas(); } // There's two here so that this can deal with software canvases in the hardware renderer later.
bool isSoftwareCanvas() const { return Base->isCanvas(); }
void SetTranslucent(bool on) { Base->bTranslucent = on; }
void SetUseType(ETextureType type) { UseType = type; }
int GetRotations() const { return Rotations; }
void SetRotations(int rot) { Rotations = int16_t(rot); }
void SetSkyOffset(int offs) { SkyOffset = offs; }
int GetSkyOffset() const { return SkyOffset; }
ISoftwareTexture* GetSoftwareTexture()
{
return SoftwareTexture;
}
void SetSoftwareTexture(ISoftwareTexture* swtex)
{
SoftwareTexture = swtex;
}
FMaterial* GetMaterial(int num)
{
return Material[num];
}
int GetShaderIndex() const { return shaderindex; }
float GetShaderSpeed() const { return shaderspeed; }
void SetShaderSpeed(float speed) { shaderspeed = speed; }
void SetShaderIndex(int index) { shaderindex = index; }
void SetShaderLayers(MaterialLayers& lay)
{
// Only update layers that have something defind.
if (lay.Glossiness > -1000) Glossiness = lay.Glossiness;
if (lay.SpecularLevel > -1000) SpecularLevel = lay.SpecularLevel;
if (lay.Brightmap) Brightmap = lay.Brightmap->GetTexture();
if (lay.Normal) Normal = lay.Normal->GetTexture();
if (lay.Specular) Specular = lay.Specular->GetTexture();
if (lay.Metallic) Metallic = lay.Metallic->GetTexture();
if (lay.Roughness) Roughness = lay.Roughness->GetTexture();
if (lay.AmbientOcclusion) AmbientOcclusion = lay.AmbientOcclusion->GetTexture();
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
{
if (lay.CustomShaderTextures[i]) CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture();
}
}
float GetGlossiness() const { return Glossiness; }
float GetSpecularLevel() const { return SpecularLevel; }
void CopySize(FGameTexture* BaseTexture)
{
Base->CopySize(BaseTexture->Base.get());
}
// Glowing is a pure material property that should not filter down to the actual texture objects.
void GetGlowColor(float* data);
bool isGlowing() const { return !!(flags & GTexf_Glowing); }
bool isAutoGlowing() const { return !!(flags & GTexf_AutoGlowing); }
int GetGlowHeight() const { return GlowHeight; }
void SetAutoGlowing() { flags |= (GTexf_AutoGlowing | GTexf_Glowing | GTexf_RenderFullbright); }
void SetGlowHeight(int v) { GlowHeight = v; }
void SetFullbright() { flags |= GTexf_RenderFullbright; }
void SetDisableFullbright(bool on) { if (on) flags |= GTexf_DisableFullbrightSprites; else flags &= ~GTexf_DisableFullbrightSprites; }
void SetGlowing(PalEntry color) { flags = (flags & ~GTexf_AutoGlowing) | GTexf_Glowing; GlowColor = color; }
bool isUserContent() const;
int CheckRealHeight() { return xs_RoundToInt(Base->CheckRealHeight() / ScaleY); }
void SetSize(int x, int y)
{
TexelWidth = x;
TexelHeight = y;
SetDisplaySize(float(x), float(y));
}
void SetDisplaySize(float w, float h)
{
DisplayWidth = w;
DisplayHeight = h;
ScaleX = TexelWidth / w;
ScaleY = TexelHeight / h;
// compensate for roundoff errors
if (int(ScaleX * w) != TexelWidth) ScaleX += (1 / 65536.);
if (int(ScaleY * h) != TexelHeight) ScaleY += (1 / 65536.);
}
void SetOffsets(int which, int x, int y)
{
LeftOffset[which] = x;
TopOffset[which] = y;
}
void SetOffsets(int x, int y)
{
LeftOffset[0] = x;
TopOffset[0] = y;
LeftOffset[1] = x;
TopOffset[1] = y;
}
void SetScale(float x, float y)
{
ScaleX = x;
ScaleY = y;
DisplayWidth = x * TexelWidth;
DisplayHeight = y * TexelHeight;
}
const SpritePositioningInfo& GetSpritePositioning(int which) { if (spi == nullptr) SetupSpriteData(); return spi[which]; }
int GetAreas(FloatRect** pAreas) const;
bool GetTranslucency()
{
return Base->GetTranslucency();
}
int GetClampMode(int clampmode)
{
if (GetUseType() == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER;
else if (isHardwareCanvas()) clampmode = CLAMP_CAMTEX;
else if ((isWarped() || shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
return clampmode;
}
void CleanHardwareData(bool full = true);
void GetLayers(TArray<FTexture*>& layers)
{
layers.Clear();
for (auto tex : { Base.get(), Brightmap.get(), Detailmap.get(), Glowmap.get(), Normal.get(), Specular.get(), Metallic.get(), Roughness.get(), AmbientOcclusion.get() })
{
if (tex != nullptr) layers.Push(tex);
}
for (auto& tex : CustomShaderTextures)
{
if (tex != nullptr) layers.Push(tex.get());
}
}
};
inline FGameTexture* MakeGameTexture(FTexture* tex, const char *name, ETextureType useType)
{
if (!tex) return nullptr;
auto t = new FGameTexture(tex, name);
t->SetUseType(useType);
return t;
}
enum EUpscaleFlags
{
UF_None = 0,
UF_Texture = 1,
UF_Sprite = 2,
UF_Font = 4
};
extern int upscalemask;
void UpdateUpscaleMask();
int calcShouldUpscale(FGameTexture* tex);
inline int shouldUpscale(FGameTexture* tex, EUpscaleFlags UseType)
{
// This only checks the global scale mask and the texture's validation for upscaling. Everything else has been done up front elsewhere.
if (!(upscalemask & UseType)) return 0;
return tex->GetUpscaleFlag();
}
struct FTexCoordInfo
{
int mRenderWidth;
int mRenderHeight;
int mWidth;
FVector2 mScale;
FVector2 mTempScale;
bool mWorldPanning;
float FloatToTexU(float v) const { return v / mRenderWidth; }
float FloatToTexV(float v) const { return v / mRenderHeight; }
float RowOffset(float ofs) const;
float TextureOffset(float ofs) const;
float TextureAdjustWidth() const;
void GetFromTexture(FGameTexture* tex, float x, float y, bool forceworldpanning);
};

View file

@ -46,6 +46,8 @@
#include "texturemanager.h"
#include "printf.h"
int upscalemask;
EXTERN_CVAR(Int, gl_texture_hqresizemult)
CUSTOM_CVAR(Int, gl_texture_hqresizemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
@ -54,6 +56,7 @@ CUSTOM_CVAR(Int, gl_texture_hqresizemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG |
if ((gl_texture_hqresizemult > 4) && (self < 4) && (self > 0))
gl_texture_hqresizemult = 4;
TexMan.FlushAll();
UpdateUpscaleMask();
}
CUSTOM_CVAR(Int, gl_texture_hqresizemult, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
@ -63,6 +66,7 @@ CUSTOM_CVAR(Int, gl_texture_hqresizemult, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG |
if ((self > 4) && (gl_texture_hqresizemode < 4) && (gl_texture_hqresizemode > 0))
self = 4;
TexMan.FlushAll();
UpdateUpscaleMask();
}
CUSTOM_CVAR(Int, gl_texture_hqresize_maxinputsize, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
@ -74,6 +78,7 @@ CUSTOM_CVAR(Int, gl_texture_hqresize_maxinputsize, 512, CVAR_ARCHIVE | CVAR_GLOB
CUSTOM_CVAR(Int, gl_texture_hqresize_targets, 7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
TexMan.FlushAll();
UpdateUpscaleMask();
}
CVAR (Flag, gl_texture_hqresize_textures, gl_texture_hqresize_targets, 1);
@ -96,6 +101,13 @@ CUSTOM_CVAR(Int, gl_texture_hqresize_mt_height, 4, CVAR_ARCHIVE | CVAR_GLOBALCON
CVAR(Int, xbrz_colorformat, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
void UpdateUpscaleMask()
{
if (!gl_texture_hqresizemode || gl_texture_hqresizemult == 1) upscalemask = 0;
else upscalemask = gl_texture_hqresize_targets;
}
static void xbrzApplyOptions()
{
if (gl_texture_hqresizemult != 0 && (gl_texture_hqresizemode == 4 || gl_texture_hqresizemode == 5))
@ -405,42 +417,15 @@ static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int
// the upsampled buffer.
//
//===========================================================================
void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly)
{
// [BB] Make sure that inWidth and inHeight denote the size of
// the returned buffer even if we don't upsample the input buffer.
int inWidth = texbuffer.mWidth;
int inHeight = texbuffer.mHeight;
// [BB] Don't resample if width * height of the input texture is bigger than gl_texture_hqresize_maxinputsize squared.
const int maxInputSize = gl_texture_hqresize_maxinputsize;
if (inWidth * inHeight > maxInputSize * maxInputSize)
return;
// [BB] Don't try to upsample textures based off FCanvasTexture. (This should never get here in the first place!)
if (bHasCanvas)
return;
// already scaled?
if (Scale.X >= 2 && Scale.Y >= 2)
return;
switch (UseType)
{
case ETextureType::Sprite:
case ETextureType::SkinSprite:
if (!(gl_texture_hqresize_targets & 2)) return;
break;
case ETextureType::FontChar:
if (!(gl_texture_hqresize_targets & 4)) return;
break;
default:
if (!(gl_texture_hqresize_targets & 1)) return;
break;
}
int type = gl_texture_hqresizemode;
int mult = gl_texture_hqresizemult;
#ifdef HAVE_MMX
@ -509,3 +494,28 @@ void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasA
contentId.scalefactor = mult;
texbuffer.mContentId = contentId.id;
}
//===========================================================================
//
// This was pulled out of the above function to allow running these
// checks before the texture is passed to the render state.
//
//===========================================================================
int calcShouldUpscale(FGameTexture *tex)
{
// [BB] Don't resample if width * height of the input texture is bigger than gl_texture_hqresize_maxinputsize squared.
const int maxInputSize = gl_texture_hqresize_maxinputsize;
if (tex->GetTexelWidth() * tex->GetTexelHeight() > maxInputSize * maxInputSize)
return 0;
// [BB] Don't try to upsample textures based off FCanvasTexture. (This should never get here in the first place!)
if (tex->isHardwareCanvas())
return 0;
// already scaled?
if (tex->GetDisplayWidth() >= 2* tex->GetTexelWidth() || tex->GetDisplayHeight() >= 2*tex->GetTexelHeight())
return 0;
return CTF_Upscale;
}

View file

@ -14,10 +14,8 @@ public:
MAX_TEXTURES = 16
};
IHardwareTexture() {}
virtual ~IHardwareTexture() {}
virtual void DeleteDescriptors() { }
IHardwareTexture() = default;
virtual ~IHardwareTexture() = default;
virtual void AllocateBuffer(int w, int h, int texelsize) = 0;
virtual uint8_t *MapBuffer() = 0;

View file

@ -27,8 +27,8 @@
#include "hw_material.h"
#include "texturemanager.h"
#include "c_cvars.h"
#include "v_video.h"
EXTERN_CVAR(Bool, gl_texture_usehires)
IHardwareTexture* CreateHardwareTexture();
//===========================================================================
@ -37,99 +37,100 @@ IHardwareTexture* CreateHardwareTexture();
//
//===========================================================================
FMaterial::FMaterial(FTexture * tx, bool expanded)
FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
{
mShaderIndex = SHADER_Default;
sourcetex = tex = tx;
sourcetex = tx;
auto imgtex = tx->GetTexture();
mTextureLayers.Push({ imgtex, scaleflags });
if (tx->UseType == ETextureType::SWCanvas && static_cast<FWrapperTexture*>(tx)->GetColorFormat() == 0)
if (tx->GetUseType() == ETextureType::SWCanvas && static_cast<FWrapperTexture*>(imgtex)->GetColorFormat() == 0)
{
mShaderIndex = SHADER_Paletted;
}
else if (tx->isWarped())
{
mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2
}
else if (tx->isHardwareCanvas())
{
if (tx->shaderindex >= FIRST_USER_SHADER)
if (tx->GetShaderIndex() >= FIRST_USER_SHADER)
{
mShaderIndex = tx->shaderindex;
mShaderIndex = tx->GetShaderIndex();
}
// no brightmap for cameratexture
}
else
{
if (tx->Normal && tx->Specular)
if (tx->isWarped())
{
for (auto &texture : { tx->Normal, tx->Specular })
mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2
}
// Note that the material takes no ownership of the texture!
else if (tx->Normal.get() && tx->Specular.get())
{
for (auto &texture : { tx->Normal.get(), tx->Specular.get() })
{
mTextureLayers.Push(texture);
mTextureLayers.Push({ texture, 0 });
}
mShaderIndex = SHADER_Specular;
}
else if (tx->Normal && tx->Metallic && tx->Roughness && tx->AmbientOcclusion)
else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get())
{
for (auto &texture : { tx->Normal, tx->Metallic, tx->Roughness, tx->AmbientOcclusion })
for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() })
{
mTextureLayers.Push(texture);
mTextureLayers.Push({ texture, 0 });
}
mShaderIndex = SHADER_PBR;
}
// Note that these layers must present a valid texture even if not used, because empty TMUs in the shader are an undefined condition.
tx->CreateDefaultBrightmap();
if (tx->Brightmap)
auto placeholder = TexMan.GameByIndex(1);
if (tx->Brightmap.get())
{
mTextureLayers.Push(tx->Brightmap);
if (mShaderIndex == SHADER_Specular)
mShaderIndex = SHADER_SpecularBrightmap;
else if (mShaderIndex == SHADER_PBR)
mShaderIndex = SHADER_PBRBrightmap;
else
mShaderIndex = SHADER_Brightmap;
mTextureLayers.Push({ tx->Brightmap.get(), scaleflags });
mLayerFlags |= TEXF_Brightmap;
}
else
{
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
if (tx->Detailmap.get())
{
mTextureLayers.Push({ tx->Detailmap.get(), 0 });
mLayerFlags |= TEXF_Detailmap;
}
else
{
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
if (tx->Glowmap.get())
{
mTextureLayers.Push({ tx->Glowmap.get(), scaleflags });
mLayerFlags |= TEXF_Glowmap;
}
else
{
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
if (tx->shaderindex >= FIRST_USER_SHADER)
auto index = tx->GetShaderIndex();
if (index >= FIRST_USER_SHADER)
{
const UserShaderDesc &usershader = usershaders[tx->shaderindex - FIRST_USER_SHADER];
const UserShaderDesc &usershader = usershaders[index - FIRST_USER_SHADER];
if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material
{
for (auto &texture : tx->CustomShaderTextures)
{
if (texture == nullptr) continue;
mTextureLayers.Push(texture);
mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable.
}
mShaderIndex = tx->shaderindex;
mShaderIndex = index;
}
}
}
mWidth = tx->GetTexelWidth();
mHeight = tx->GetTexelHeight();
mLeftOffset = tx->GetLeftOffset(0); // These only get used by decals and decals should not use renderer-specific offsets.
mTopOffset = tx->GetTopOffset(0);
mRenderWidth = tx->GetScaledWidth();
mRenderHeight = tx->GetScaledHeight();
mSpriteU[0] = mSpriteV[0] = 0.f;
mSpriteU[1] = mSpriteV[1] = 1.f;
mExpanded = expanded;
if (expanded)
{
int oldwidth = mWidth;
int oldheight = mHeight;
mTrimResult = TrimBorders(trim); // get the trim size before adding the empty frame
mWidth += 2;
mHeight += 2;
mRenderWidth = mRenderWidth * mWidth / oldwidth;
mRenderHeight = mRenderHeight * mHeight / oldheight;
}
SetSpriteRect();
mScaleFlags = scaleflags;
mTextureLayers.ShrinkToFit();
tx->Material[expanded] = this;
if (tx->isHardwareCanvas()) tx->bTranslucent = 0;
tx->Material[scaleflags] = this;
if (tx->isHardwareCanvas()) tx->SetTranslucent(false);
}
//===========================================================================
@ -142,193 +143,22 @@ FMaterial::~FMaterial()
{
}
//===========================================================================
//
// Set the sprite rectangle
//
//
//===========================================================================
void FMaterial::SetSpriteRect()
IHardwareTexture *FMaterial::GetLayer(int i, int translation, MaterialLayerInfo **pLayer) const
{
auto leftOffset = tex->GetLeftOffsetHW();
auto topOffset = tex->GetTopOffsetHW();
float fxScale = (float)tex->Scale.X;
float fyScale = (float)tex->Scale.Y;
// mSpriteRect is for positioning the sprite in the scene.
mSpriteRect.left = -leftOffset / fxScale;
mSpriteRect.top = -topOffset / fyScale;
mSpriteRect.width = mWidth / fxScale;
mSpriteRect.height = mHeight / fyScale;
if (mExpanded)
{
// a little adjustment to make sprites look better with texture filtering:
// create a 1 pixel wide empty frame around them.
int oldwidth = mWidth - 2;
int oldheight = mHeight - 2;
leftOffset += 1;
topOffset += 1;
// Reposition the sprite with the frame considered
mSpriteRect.left = -leftOffset / fxScale;
mSpriteRect.top = -topOffset / fyScale;
mSpriteRect.width = mWidth / fxScale;
mSpriteRect.height = mHeight / fyScale;
if (mTrimResult)
{
mSpriteRect.left += trim[0] / fxScale;
mSpriteRect.top += trim[1] / fyScale;
mSpriteRect.width -= (oldwidth - trim[2]) / fxScale;
mSpriteRect.height -= (oldheight - trim[3]) / fyScale;
mSpriteU[0] = trim[0] / (float)mWidth;
mSpriteV[0] = trim[1] / (float)mHeight;
mSpriteU[1] -= (oldwidth - trim[0] - trim[2]) / (float)mWidth;
mSpriteV[1] -= (oldheight - trim[1] - trim[3]) / (float)mHeight;
}
}
}
//===========================================================================
//
// Finds empty space around the texture.
// Used for sprites that got placed into a huge empty frame.
//
//===========================================================================
bool FMaterial::TrimBorders(uint16_t *rect)
{
auto texbuffer = sourcetex->CreateTexBuffer(0);
int w = texbuffer.mWidth;
int h = texbuffer.mHeight;
auto Buffer = texbuffer.mBuffer;
if (texbuffer.mBuffer == nullptr)
{
return false;
}
if (w != mWidth || h != mHeight)
{
// external Hires replacements cannot be trimmed.
return false;
}
int size = w*h;
if (size == 1)
{
// nothing to be done here.
rect[0] = 0;
rect[1] = 0;
rect[2] = 1;
rect[3] = 1;
return true;
}
int first, last;
for(first = 0; first < size; first++)
{
if (Buffer[first*4+3] != 0) break;
}
if (first >= size)
{
// completely empty
rect[0] = 0;
rect[1] = 0;
rect[2] = 1;
rect[3] = 1;
return true;
}
for(last = size-1; last >= first; last--)
{
if (Buffer[last*4+3] != 0) break;
}
rect[1] = first / w;
rect[3] = 1 + last/w - rect[1];
rect[0] = 0;
rect[2] = w;
unsigned char *bufferoff = Buffer + (rect[1] * w * 4);
h = rect[3];
for(int x = 0; x < w; x++)
{
for(int y = 0; y < h; y++)
{
if (bufferoff[(x+y*w)*4+3] != 0) goto outl;
}
rect[0]++;
}
outl:
rect[2] -= rect[0];
for(int x = w-1; rect[2] > 1; x--)
{
for(int y = 0; y < h; y++)
{
if (bufferoff[(x+y*w)*4+3] != 0)
{
return true;
}
}
rect[2]--;
}
return true;
}
//===========================================================================
//
//
//
//===========================================================================
IHardwareTexture *FMaterial::GetLayer(int i, int translation, FTexture **pLayer)
{
FTexture *layer = i == 0 ? tex : mTextureLayers[i - 1];
if (pLayer) *pLayer = layer;
auto &layer = mTextureLayers[i];
if (pLayer) *pLayer = &layer;
if (layer && layer->UseType!=ETextureType::Null)
{
IHardwareTexture *hwtex = layer->SystemTextures.GetHardwareTexture(translation, mExpanded);
if (hwtex == nullptr)
{
hwtex = CreateHardwareTexture();
layer->SystemTextures.AddHardwareTexture(translation, mExpanded, hwtex);
}
return hwtex;
}
if (layer.layerTexture) return layer.layerTexture->GetHardwareTexture(translation, layer.scaleFlags);
return nullptr;
}
//===========================================================================
//
//
//
//===========================================================================
int FMaterial::GetAreas(FloatRect **pAreas) const
{
if (mShaderIndex == SHADER_Default) // texture splitting can only be done if there's no attached effects
{
*pAreas = sourcetex->areas;
return sourcetex->areacount;
}
else
{
return 0;
}
}
//==========================================================================
//
// Gets a texture from the texture manager and checks its validity for
@ -336,75 +166,27 @@ int FMaterial::GetAreas(FloatRect **pAreas) const
//
//==========================================================================
FMaterial * FMaterial::ValidateTexture(FTexture * tex, bool expand, bool create)
FMaterial * FMaterial::ValidateTexture(FGameTexture * gtex, int scaleflags, bool create)
{
again:
if (tex && tex->isValid())
#if 0
if (gtex && gtex->isValid())
{
if (tex->bNoExpand) expand = false;
if (!gtex->expandSprites()) scaleflags &= ~CTF_Expand;
FMaterial *hwtex = tex->Material[expand];
FMaterial *hwtex = gtex->Material[scaleflags];
if (hwtex == NULL && create)
{
if (expand)
{
if (tex->isWarped() || tex->isHardwareCanvas() || tex->shaderindex >= FIRST_USER_SHADER || (tex->shaderindex >= SHADER_Specular && tex->shaderindex <= SHADER_PBRBrightmap))
{
tex->bNoExpand = true;
goto again;
}
if (tex->Brightmap != NULL &&
(tex->GetTexelWidth() != tex->Brightmap->GetTexelWidth() ||
tex->GetTexelHeight() != tex->Brightmap->GetTexelHeight())
)
{
// do not expand if the brightmap's size differs.
tex->bNoExpand = true;
goto again;
}
}
hwtex = new FMaterial(tex, expand);
hwtex = screen->CreateMaterial(gtex, scaleflags);
}
return hwtex;
}
#endif
return NULL;
}
FMaterial * FMaterial::ValidateTexture(FTextureID no, bool expand, bool translate, bool create)
{
return ValidateTexture(TexMan.GetTexture(no, translate), expand, create);
}
void DeleteMaterial(FMaterial* mat)
{
delete mat;
}
//-----------------------------------------------------------------------------
//
// Make sprite offset adjustment user-configurable per renderer.
//
//-----------------------------------------------------------------------------
extern int r_spriteadjustSW, r_spriteadjustHW;
CUSTOM_CVAR(Int, r_spriteadjust, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
r_spriteadjustHW = !!(self & 2);
r_spriteadjustSW = !!(self & 1);
for (int i = 0; i < TexMan.NumTextures(); i++)
{
auto tex = TexMan.GetTexture(FSetTextureID(i));
if (tex->GetTexelLeftOffset(0) != tex->GetTexelLeftOffset(1) || tex->GetTexelTopOffset(0) != tex->GetTexelTopOffset(1))
{
for (int i = 0; i < 2; i++)
{
auto mat = tex->GetMaterial(i);
if (mat != nullptr) mat->SetSpriteRect();
}
}
}
}

View file

@ -8,18 +8,12 @@
struct FRemapTable;
class IHardwareTexture;
enum
struct MaterialLayerInfo
{
CLAMP_NONE = 0,
CLAMP_X = 1,
CLAMP_Y = 2,
CLAMP_XY = 3,
CLAMP_XY_NOMIP = 4,
CLAMP_NOFILTER = 5,
CLAMP_CAMTEX = 6,
FTexture* layerTexture;
int scaleFlags;
};
//===========================================================================
//
// this is the material class for OpenGL.
@ -28,108 +22,42 @@ enum
class FMaterial
{
TArray<FTexture*> mTextureLayers;
private:
TArray<MaterialLayerInfo> mTextureLayers; // the only layers allowed to scale are the brightmap and the glowmap.
int mShaderIndex;
short mLeftOffset;
short mTopOffset;
short mWidth;
short mHeight;
short mRenderWidth;
short mRenderHeight;
bool mExpanded;
bool mTrimResult;
uint16_t trim[4];
float mSpriteU[2], mSpriteV[2];
FloatRect mSpriteRect;
bool TrimBorders(uint16_t *rect);
int mLayerFlags = 0;
int mScaleFlags;
public:
FTexture *tex;
FTexture *sourcetex; // in case of redirection this is different from tex.
FMaterial(FTexture *tex, bool forceexpand);
~FMaterial();
void SetSpriteRect();
FGameTexture *sourcetex; // the owning texture.
FMaterial(FGameTexture *tex, int scaleflags);
virtual ~FMaterial();
int GetLayerFlags() const { return mLayerFlags; }
int GetShaderIndex() const { return mShaderIndex; }
void AddTextureLayer(FTexture *tex)
int GetScaleFlags() const { return mScaleFlags; }
virtual void DeleteDescriptors() { }
FGameTexture* Source() const
{
ValidateTexture(tex, false);
mTextureLayers.Push(tex);
}
bool isMasked() const
{
return sourcetex->bMasked;
}
bool isExpanded() const
{
return mExpanded;
return sourcetex;
}
int GetLayers() const
void AddTextureLayer(FTexture *tex, bool allowscale)
{
return mTextureLayers.Size() + 1;
}
bool hasCanvas()
{
return tex->isHardwareCanvas();
mTextureLayers.Push({ tex, allowscale });
}
IHardwareTexture *GetLayer(int i, int translation, FTexture **pLayer = nullptr);
// Patch drawing utilities
void GetSpriteRect(FloatRect * r) const
int NumLayers() const
{
*r = mSpriteRect;
return mTextureLayers.Size();
}
// This is scaled size in integer units as needed by walls and flats
int TextureHeight() const { return mRenderHeight; }
int TextureWidth() const { return mRenderWidth; }
int GetAreas(FloatRect **pAreas) const;
int GetWidth() const
{
return mWidth;
}
int GetHeight() const
{
return mHeight;
}
int GetLeftOffset() const
{
return mLeftOffset;
}
int GetTopOffset() const
{
return mTopOffset;
}
// Get right/bottom UV coordinates for patch drawing
float GetUL() const { return 0; }
float GetVT() const { return 0; }
float GetUR() const { return 1; }
float GetVB() const { return 1; }
float GetU(float upix) const { return upix/(float)mWidth; }
float GetV(float vpix) const { return vpix/(float)mHeight; }
float GetSpriteUL() const { return mSpriteU[0]; }
float GetSpriteVT() const { return mSpriteV[0]; }
float GetSpriteUR() const { return mSpriteU[1]; }
float GetSpriteVB() const { return mSpriteV[1]; }
IHardwareTexture *GetLayer(int i, int translation, MaterialLayerInfo **pLayer = nullptr) const;
static FMaterial *ValidateTexture(FTexture * tex, bool expand, bool create = true);
static FMaterial *ValidateTexture(FTextureID no, bool expand, bool trans, bool create = true);
const TArray<FTexture*> &GetLayerArray() const
static FMaterial *ValidateTexture(FGameTexture * tex, int scaleflags, bool create = true);
const TArray<MaterialLayerInfo> &GetLayerArray() const
{
return mTextureLayers;
}

View file

@ -7,6 +7,15 @@
struct FTextureBuffer;
class IHardwareTexture;
enum ECreateTexBufferFlags
{
CTF_Expand = 1, // create buffer with a one-pixel wide border
CTF_Upscale = 2, // Upscale the texture
CTF_CreateMask = 3, // Flags that are relevant for hardware texture creation.
CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures.
};
class FHardwareTextureContainer
{
public:
@ -20,6 +29,7 @@ private:
{
IHardwareTexture *hwTexture = nullptr;
int translation = 0;
bool precacheMarker; // This is used to check whether a texture has been hit by the precacher, so that the cleanup code can delete the unneeded ones.
void Delete()
{
@ -27,23 +37,28 @@ private:
hwTexture = nullptr;
}
void DeleteDescriptors()
{
if (hwTexture) hwTexture->DeleteDescriptors();
}
~TranslatedTexture()
{
Delete();
}
void MarkForPrecache(bool on)
{
precacheMarker = on;
}
bool isMarkedForPreache() const
{
return precacheMarker;
}
};
private:
TranslatedTexture hwDefTex[2];
TranslatedTexture hwDefTex[4];
TArray<TranslatedTexture> hwTex_Translated;
TranslatedTexture * GetTexID(int translation, bool expanded)
TranslatedTexture * GetTexID(int translation, int scaleflags)
{
// Allow negative indices to pass through unchanged.
// This is needed for allowing the client to allocate slots that aren't matched to a palette, e.g. Build's indexed variants.
@ -54,12 +69,12 @@ private:
}
else translation &= ~0x7fffffff;
if (translation == 0)
if (translation == 0 && !(scaleflags & CTF_Upscale))
{
return &hwDefTex[expanded];
return &hwDefTex[scaleflags];
}
if (expanded) translation = -translation;
translation |= (scaleflags << 24);
// normally there aren't more than very few different
// translations here so this isn't performance critical.
unsigned index = hwTex_Translated.FindEx([=](auto &element)
@ -78,32 +93,22 @@ private:
}
public:
void Clean(bool cleannormal, bool cleanexpanded)
void Clean()
{
if (cleannormal) hwDefTex[0].Delete();
if (cleanexpanded) hwDefTex[1].Delete();
hwDefTex[0].DeleteDescriptors();
hwDefTex[1].DeleteDescriptors();
for (int i = hwTex_Translated.Size() - 1; i >= 0; i--)
{
if (cleannormal && hwTex_Translated[i].translation > 0) hwTex_Translated.Delete(i);
else if (cleanexpanded && hwTex_Translated[i].translation < 0) hwTex_Translated.Delete(i);
for (unsigned int j = 0; j < hwTex_Translated.Size(); j++)
hwTex_Translated[j].DeleteDescriptors();
}
hwDefTex[0].Delete();
hwDefTex[1].Delete();
hwTex_Translated.Clear();
}
IHardwareTexture * GetHardwareTexture(int translation, bool expanded)
IHardwareTexture * GetHardwareTexture(int translation, int scaleflags)
{
auto tt = GetTexID(translation, expanded);
auto tt = GetTexID(translation, scaleflags);
return tt->hwTexture;
}
void AddHardwareTexture(int translation, bool expanded, IHardwareTexture *tex)
void AddHardwareTexture(int translation, int scaleflags, IHardwareTexture *tex)
{
auto tt = GetTexID(translation, expanded);
auto tt = GetTexID(translation, scaleflags);
tt->Delete();
tt->hwTexture =tex;
}
@ -111,26 +116,44 @@ public:
//===========================================================================
//
// Deletes all allocated resources and considers translations
// This will only be called for sprites
//
//===========================================================================
void CleanUnused(SpriteHits &usedtranslations, bool expanded)
void CleanUnused()
{
if (usedtranslations.CheckKey(0) == nullptr)
for (auto& tt : hwDefTex)
{
hwDefTex[expanded].Delete();
if (!tt.isMarkedForPreache()) tt.Delete();
}
int fac = expanded ? -1 : 1;
for (int i = hwTex_Translated.Size()-1; i>= 0; i--)
{
if (usedtranslations.CheckKey(hwTex_Translated[i].translation * fac) == nullptr)
auto& tt = hwTex_Translated[i];
if (!tt.isMarkedForPreache())
{
hwTex_Translated.Delete(i);
}
}
}
void UnmarkAll()
{
for (auto& tt : hwDefTex)
{
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
}
for (auto& tt : hwTex_Translated)
{
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
}
}
void MarkForPrecache(int translation, int scaleflags)
{
auto tt = GetTexID(translation, scaleflags);
tt->MarkForPrecache(true);
}
template<class T>
void Iterate(T callback)
{

View file

@ -41,7 +41,7 @@
#include "cmdlib.h"
#include "palettecontainer.h"
FMemArena FImageSource::ImageArena(32768);
FMemArena ImageArena(32768);
TArray<FImageSource *>FImageSource::ImageForLump;
int FImageSource::NextID;
static PrecacheInfo precacheInfo;

View file

@ -7,6 +7,7 @@
class FImageSource;
using PrecacheInfo = TMap<int, std::pair<int, int>>;
extern FMemArena ImageArena;
// Doom patch format header
struct patch_t
@ -38,7 +39,6 @@ class FImageSource
friend class FBrightmapTexture;
protected:
static FMemArena ImageArena;
static TArray<FImageSource *>ImageForLump;
static int NextID;
@ -57,6 +57,8 @@ protected:
public:
virtual bool SupportRemap0() { return false; } // Unfortunate hackery that's needed for Hexen's skies. Only the image can know about the needed parameters
virtual bool IsRawCompatible() { return true; } // Same thing for mid texture compatibility handling. Can only be determined by looking at the composition data which is private to the image.
void CopySize(FImageSource &other)
{
@ -169,4 +171,4 @@ protected:
class FTexture;
FTexture* CreateImageTexture(FImageSource* img, const char *name = nullptr) noexcept;
FTexture* CreateImageTexture(FImageSource* img) noexcept;

View file

@ -47,25 +47,25 @@
//
//==========================================================================
FImageTexture::FImageTexture(FImageSource* img, const char* name) noexcept
: FTexture(name, img ? img->LumpNum() : 0)
FImageTexture::FImageTexture(FImageSource *img) noexcept
: FTexture(img? img->LumpNum() : 0)
{
mImage = img;
if (img != nullptr)
{
if (name == nullptr) fileSystem.GetFileShortName(Name, img->LumpNum());
Width = img->GetWidth();
Height = img->GetHeight();
auto offsets = img->GetOffsets();
_LeftOffset[1] = _LeftOffset[0] = offsets.first;
_TopOffset[1] = _TopOffset[0] = offsets.second;
bMasked = img->bMasked;
bTranslucent = img->bTranslucent;
SetFromImage();
}
}
void FImageTexture::SetFromImage()
{
auto img = mImage;
Width = img->GetWidth();
Height = img->GetHeight();
Masked = img->bMasked;
bTranslucent = img->bTranslucent;
}
//===========================================================================
//
//
@ -108,8 +108,8 @@ bool FImageTexture::DetermineTranslucency()
}
FTexture* CreateImageTexture(FImageSource* img, const char* name) noexcept
FTexture* CreateImageTexture(FImageSource* img) noexcept
{
return new FImageTexture(img, name);
return new FImageTexture(img);
}

View file

@ -119,8 +119,8 @@ bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int p
uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int idatlen);
class FTexture;
class FGameTexture;
FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename);
FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename);
#endif

View file

@ -57,7 +57,6 @@
#endif
//--------------------------------------------------------------------------
//
// Data structures for the TEXTUREx lumps
@ -85,7 +84,7 @@ struct mappatch_t
struct maptexture_t
{
uint8_t name[8];
uint16_t Flags; // [RH] Was unused
uint16_t Flags; // [RH] Was unused
uint8_t ScaleX; // [RH] Scaling (8 is normal)
uint8_t ScaleY; // [RH] Same as above
int16_t width;
@ -113,7 +112,7 @@ struct strifemappatch_t
struct strifemaptexture_t
{
uint8_t name[8];
uint16_t Flags; // [RH] Was unused
uint16_t Flags; // [RH] Was unused
uint8_t ScaleX; // [RH] Scaling (8 is normal)
uint8_t ScaleY; // [RH] Same as above
int16_t width;
@ -137,25 +136,23 @@ struct FPatchLookup
void FMultipatchTextureBuilder::MakeTexture(BuildInfo &buildinfo, ETextureType usetype)
{
FImageTexture *tex = new FImageTexture(nullptr, buildinfo.Name);
tex->SetUseType(usetype);
tex->bMultiPatch = true;
tex->Width = buildinfo.Width;
tex->Height = buildinfo.Height;
tex->_LeftOffset[0] = buildinfo.LeftOffset[0];
tex->_LeftOffset[1] = buildinfo.LeftOffset[1];
tex->_TopOffset[0] = buildinfo.TopOffset[0];
tex->_TopOffset[1] = buildinfo.TopOffset[1];
tex->Scale = buildinfo.Scale;
tex->bMasked = true; // we do not really know yet.
tex->bTranslucent = -1;
tex->bWorldPanning = buildinfo.bWorldPanning;
tex->bNoDecals = buildinfo.bNoDecals;
tex->SourceLump = buildinfo.DefinitionLump;
buildinfo.tex = tex;
TexMan.AddTexture(tex);
buildinfo.texture = new FGameTexture(nullptr, buildinfo.Name);
buildinfo.texture->SetUseType(usetype);
TexMan.AddGameTexture(buildinfo.texture);
}
void FMultipatchTextureBuilder::AddImageToTexture(FImageTexture *tex, BuildInfo& buildinfo)
{
buildinfo.texture->Setup(tex);
buildinfo.texture->SetOffsets(0, buildinfo.LeftOffset[0], buildinfo.TopOffset[0]);
buildinfo.texture->SetOffsets(1, buildinfo.LeftOffset[1], buildinfo.TopOffset[1]);
buildinfo.texture->SetScale((float)buildinfo.Scale.X, (float)buildinfo.Scale.X);
buildinfo.texture->SetWorldPanning(buildinfo.bWorldPanning);
buildinfo.texture->SetNoDecals(buildinfo.bNoDecals);
calcShouldUpscale(buildinfo.texture); // calculate this once at insertion
}
//==========================================================================
//
// The reader for TEXTUREx
@ -238,7 +235,7 @@ void FMultipatchTextureBuilder::BuildTexture(const void *texdef, FPatchLookup *p
}
buildinfo.Parts[i].OriginX = LittleShort(mpatch.d->originx);
buildinfo.Parts[i].OriginY = LittleShort(mpatch.d->originy);
buildinfo.Parts[i].Image = nullptr;
buildinfo.Parts[i].TexImage = nullptr;
buildinfo.Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name;
buildinfo.Inits[i].UseType = ETextureType::WallPatch;
if (strife)
@ -356,7 +353,7 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi
// It still needs to be created in case someone uses it by name.
offset = LittleLong(directory[1]);
const maptexture_t *tex = (const maptexture_t *)((const uint8_t *)maptex + offset);
FTexture *tex0 = TexMan.ByIndex(0);
auto tex0 = TexMan.GameByIndex(0);
tex0->SetSize(SAFESHORT(tex->width), SAFESHORT(tex->height));
}
@ -373,7 +370,7 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi
int j;
for (j = (int)TexMan.NumTextures() - 1; j >= firstdup; --j)
{
if (strnicmp(TexMan.ByIndex(j)->GetName(), (const char *)maptex + offset, 8) == 0)
if (strnicmp(TexMan.GameByIndex(j)->GetName(), (const char *)maptex + offset, 8) == 0)
break;
}
if (j + 1 == firstdup)
@ -420,7 +417,7 @@ void FMultipatchTextureBuilder::AddTexturesLumps(int lump1, int lump2, int patch
//
//==========================================================================
void FMultipatchTextureBuilder::ParsePatch(FScanner &sc, BuildInfo &info, TexPart & part, TexInit &init)
void FMultipatchTextureBuilder::ParsePatch(FScanner &sc, BuildInfo &info, TexPartBuild & part, TexInit &init)
{
FString patchname;
int Mirror = 0;
@ -672,7 +669,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
}
else if (sc.Compare("Patch"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -684,12 +681,12 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Sprite"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -701,12 +698,12 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Graphic"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -718,7 +715,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Offset"))
@ -774,19 +771,23 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo)
for (unsigned i = 0; i < buildinfo.Inits.Size(); i++)
{
FTextureID texno = TexMan.CheckForTexture(buildinfo.Inits[i].TexName, buildinfo.Inits[i].UseType);
if (texno == buildinfo.tex->id) // we found ourselves. Try looking for another one with the same name which is not a multipatch texture itself.
if (texno == buildinfo.texture->GetID()) // we found ourselves. Try looking for another one with the same name which is not a multipatch texture itself.
{
TArray<FTextureID> list;
TexMan.ListTextures(buildinfo.Inits[i].TexName, list, true);
for (int i = list.Size() - 1; i >= 0; i--)
{
if (list[i] != buildinfo.tex->id && !TexMan.GetTexture(list[i])->bMultiPatch)
if (list[i] != buildinfo.texture->GetID())
{
texno = list[i];
auto gtex = TexMan.GetGameTexture(list[i]);
if (gtex && !dynamic_cast<FMultiPatchTexture*>(gtex->GetTexture()))
{
texno = list[i];
}
break;
}
}
if (texno == buildinfo.tex->id)
if (texno == buildinfo.texture->GetID())
{
if (buildinfo.Inits[i].HasLine) buildinfo.Inits[i].sc.Message(MSG_WARNING, "Texture '%s' references itself as patch\n", buildinfo.Inits[i].TexName.GetChars());
else Printf(TEXTCOLOR_YELLOW "Texture '%s' references itself as patch\n", buildinfo.Inits[i].TexName.GetChars());
@ -809,18 +810,19 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo)
}
else
{
FTexture *tex = TexMan.GetTexture(texno);
FGameTexture *tex = TexMan.GetGameTexture(texno);
if (tex != nullptr && tex->isValid())
if (tex != nullptr && tex->isValid() && dynamic_cast<FImageTexture*>(tex->GetTexture()))
{
//We cannot set the image source yet. First all textures need to be resolved.
buildinfo.Inits[i].Texture = tex;
buildinfo.tex->bComplex |= tex->bComplex;
buildinfo.bComplex |= tex->bComplex;
buildinfo.Inits[i].Texture = static_cast<FImageTexture*>(tex->GetTexture());
bool iscomplex = !!complex.CheckKey(tex);
if (iscomplex) complex.Insert(buildinfo.texture, true);
buildinfo.bComplex |= iscomplex;
if (buildinfo.Inits[i].UseOffsets)
{
buildinfo.Parts[i].OriginX -= tex->GetLeftOffset(0);
buildinfo.Parts[i].OriginY -= tex->GetTopOffset(0);
buildinfo.Parts[i].OriginX -= tex->GetTexelLeftOffset(0);
buildinfo.Parts[i].OriginY -= tex->GetTexelTopOffset(0);
}
}
else
@ -841,8 +843,6 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo)
i--;
}
}
checkForHacks(buildinfo);
}
void FMultipatchTextureBuilder::ResolveAllPatches()
@ -874,12 +874,12 @@ void FMultipatchTextureBuilder::ResolveAllPatches()
for (unsigned j = 0; j < buildinfo.Inits.Size(); j++)
{
if (buildinfo.Parts[j].Image == nullptr)
if (buildinfo.Parts[j].TexImage == nullptr)
{
auto image = buildinfo.Inits[j].Texture->GetImage();
if (image != nullptr)
auto image = buildinfo.Inits[j].Texture;
if (image->GetImage() != nullptr)
{
buildinfo.Parts[j].Image = image;
buildinfo.Parts[j].TexImage = image;
donesomething = true;
}
else hasEmpty = true;
@ -889,26 +889,28 @@ void FMultipatchTextureBuilder::ResolveAllPatches()
{
// If this texture is just a wrapper around a single patch, we can simply
// use that patch's image directly here.
checkForHacks(buildinfo);
bool done = false;
if (buildinfo.Parts.Size() == 1)
{
if (buildinfo.Parts[0].OriginX == 0 && buildinfo.Parts[0].OriginY == 0 &&
buildinfo.Parts[0].Image->GetWidth() == buildinfo.Width &&
buildinfo.Parts[0].Image->GetHeight() == buildinfo.Height &&
buildinfo.Parts[0].TexImage->GetWidth() == buildinfo.Width &&
buildinfo.Parts[0].TexImage->GetHeight() == buildinfo.Height &&
buildinfo.Parts[0].Rotate == 0 &&
!buildinfo.bComplex)
{
buildinfo.tex->SetImage(buildinfo.Parts[0].Image);
AddImageToTexture(buildinfo.Parts[0].TexImage, buildinfo);
buildinfo.texture->Setup(buildinfo.Parts[0].TexImage);
done = true;
}
}
if (!done)
{
auto img = new FMultiPatchTexture(buildinfo.Width, buildinfo.Height, buildinfo.Parts, buildinfo.bComplex, buildinfo.textual);
buildinfo.tex->SetImage(img);
auto itex = new FImageTexture(img);
AddImageToTexture(itex, buildinfo);
}
BuiltTextures.Delete(i);
donesomething = true;
}
@ -919,7 +921,7 @@ void FMultipatchTextureBuilder::ResolveAllPatches()
for (auto &b : BuiltTextures)
{
Printf("%s\n", b.Name.GetChars());
b.tex->SetUseType(ETextureType::Null);
b.texture->SetUseType(ETextureType::Null);
}
break;
}

View file

@ -47,18 +47,15 @@
//-----------------------------------------------------------------------------
FSkyBox::FSkyBox(const char *name)
: FTexture(name)
: FImageTexture(nullptr)
{
FTextureID texid = TexMan.CheckForTexture(name, ETextureType::Wall);
previous = nullptr;
if (texid.isValid())
{
previous = TexMan.GetTexture(texid);
CopySize(previous);
previous = TexMan.GetGameTexture(texid);
}
else previous = nullptr;
faces[0]=faces[1]=faces[2]=faces[3]=faces[4]=faces[5] = nullptr;
UseType = ETextureType::Override;
bSkybox = true;
fliptop = false;
}
@ -68,29 +65,11 @@ FSkyBox::FSkyBox(const char *name)
//
//-----------------------------------------------------------------------------
TArray<uint8_t> FSkyBox::Get8BitPixels(bool alphatex)
void FSkyBox::SetSize()
{
return previous->Get8BitPixels(alphatex);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
FBitmap FSkyBox::GetBgraBitmap(const PalEntry *p, int *trans)
{
return previous->GetBgraBitmap(p, trans);
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
FImageSource *FSkyBox::GetImage() const
{
return previous->GetImage();
if (!previous && faces[0]) previous = faces[0];
if (previous && previous->GetTexture()->GetImage())
{
SetImage(previous->GetTexture()->GetImage());
}
}

View file

@ -1,35 +1,24 @@
#pragma once
#include "textures.h"
//-----------------------------------------------------------------------------
//
// This is not a real texture but will be added to the texture manager
// so that it can be handled like any other sky.
// Todo: Get rid of this
// The faces can easily be stored in the material layer array
//
//-----------------------------------------------------------------------------
class FSkyBox : public FTexture
class FSkyBox : public FImageTexture
{
public:
FTexture *previous;
FTexture * faces[6];
FGameTexture* previous;
FGameTexture* faces[6]; // the faces need to be full materials as they can have all supported effects.
bool fliptop;
FSkyBox(const char *name);
TArray<uint8_t> Get8BitPixels(bool alphatex);
FBitmap GetBgraBitmap(const PalEntry *, int *trans) override;
FImageSource *GetImage() const override;
void SetSize()
{
if (!previous && faces[0]) previous = faces[0];
if (previous)
{
CopySize(previous);
}
}
FSkyBox(const char* name);
void SetSize();
bool Is3Face() const
{
@ -40,4 +29,14 @@ public:
{
return fliptop;
}
FGameTexture* GetSkyFace(int num) const
{
return faces[num];
}
bool GetSkyFlip() const
{
return fliptop;
}
};

View file

@ -47,123 +47,24 @@
#include "image.h"
#include "formats/multipatchtexture.h"
#include "texturemanager.h"
#include "c_cvars.h"
// Wrappers to keep the definitions of these classes out of here.
void DeleteMaterial(FMaterial* mat);
void DeleteSoftwareTexture(FSoftwareTexture* swtex);
IHardwareTexture* CreateHardwareTexture();
FTexture* CreateBrightmapTexture(FImageSource*);
// Make sprite offset adjustment user-configurable per renderer.
int r_spriteadjustSW, r_spriteadjustHW;
//==========================================================================
//
//
//
//==========================================================================
// Examines the lump contents to decide what type of texture to create,
// and creates the texture.
FTexture* FTexture::CreateTexture(const char* name, int lumpnum, ETextureType usetype)
{
if (lumpnum == -1) return nullptr;
auto image = FImageSource::GetImage(lumpnum, usetype == ETextureType::Flat);
if (image != nullptr)
{
FTexture* tex = new FImageTexture(image);
if (tex != nullptr)
{
tex->UseType = usetype;
if (usetype == ETextureType::Flat)
{
int w = tex->GetTexelWidth();
int h = tex->GetTexelHeight();
// Auto-scale flats with dimensions 128x128 and 256x256.
// In hindsight, a bad idea, but RandomLag made it sound better than it really is.
// Now we're stuck with this stupid behaviour.
if (w == 128 && h == 128)
{
tex->Scale.X = tex->Scale.Y = 2;
tex->bWorldPanning = true;
}
else if (w == 256 && h == 256)
{
tex->Scale.X = tex->Scale.Y = 4;
tex->bWorldPanning = true;
}
}
tex->Name = name;
tex->Name.ToUpper();
return tex;
}
}
return nullptr;
}
//==========================================================================
//
//
//
//==========================================================================
FTexture::FTexture(const char* name, int lumpnum)
:
Scale(1, 1), SourceLump(lumpnum),
UseType(ETextureType::Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false),
bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), bFullNameTexture(false),
Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0)
FTexture::FTexture (int lumpnum)
: SourceLump(lumpnum), bHasCanvas(false)
{
bBrightmapChecked = false;
bGlowing = false;
bAutoGlowing = false;
bFullbright = false;
bDisableFullbright = false;
bSkybox = false;
bNoCompress = false;
bNoExpand = false;
bTranslucent = -1;
_LeftOffset[0] = _LeftOffset[1] = _TopOffset[0] = _TopOffset[1] = 0;
id.SetInvalid();
if (name != NULL)
{
Name = name;
Name.ToUpper();
}
else if (lumpnum < 0)
{
Name = FString();
}
else
{
fileSystem.GetFileShortName(Name, lumpnum);
}
}
FTexture::~FTexture()
{
FTexture* link = fileSystem.GetLinkedTexture(SourceLump);
if (link == this) fileSystem.SetLinkedTexture(SourceLump, nullptr);
if (areas != nullptr) delete[] areas;
areas = nullptr;
for (int i = 0; i < 2; i++)
{
if (Material[i] != nullptr) DeleteMaterial(Material[i]);
Material[i] = nullptr;
}
if (SoftwareTexture != nullptr)
{
DeleteSoftwareTexture(SoftwareTexture);
SoftwareTexture = nullptr;
}
}
//===========================================================================
@ -182,111 +83,6 @@ FBitmap FTexture::GetBgraBitmap(const PalEntry* remap, int* ptrans)
return bmp;
}
//==========================================================================
//
//
//
//==========================================================================
FTexture* FTexture::GetRawTexture()
{
if (OffsetLess) return OffsetLess;
// Reject anything that cannot have been a single-patch multipatch texture in vanilla.
auto image = static_cast<FMultiPatchTexture*>(GetImage());
if (bMultiPatch != 1 || UseType != ETextureType::Wall || Scale.X != 1 || Scale.Y != 1 || bWorldPanning || image == nullptr || image->NumParts != 1 || _TopOffset[0] == 0)
{
OffsetLess = this;
return this;
}
// Set up a new texture that directly references the underlying patch.
// From here we cannot retrieve the original texture made for it, so just create a new one.
FImageSource* source = image->Parts[0].Image;
// Size must match for this to work as intended
if (source->GetWidth() != Width || source->GetHeight() != Height)
{
OffsetLess = this;
return this;
}
OffsetLess = new FImageTexture(source, "");
TexMan.AddTexture(OffsetLess);
return OffsetLess;
}
void FTexture::SetDisplaySize(int fitwidth, int fitheight)
{
Scale.X = double(Width) / fitwidth;
Scale.Y = double(Height) / fitheight;
// compensate for roundoff errors
if (int(Scale.X * fitwidth) != Width) Scale.X += (1 / 65536.);
if (int(Scale.Y * fitheight) != Height) Scale.Y += (1 / 65536.);
}
//===========================================================================
//
// Gets the average color of a texture for use as a sky cap color
//
//===========================================================================
PalEntry FTexture::averageColor(const uint32_t* data, int size, int maxout)
{
int i;
unsigned int r, g, b;
// First clear them.
r = g = b = 0;
if (size == 0)
{
return PalEntry(255, 255, 255);
}
for (i = 0; i < size; i++)
{
b += BPART(data[i]);
g += GPART(data[i]);
r += RPART(data[i]);
}
r = r / size;
g = g / size;
b = b / size;
int maxv = MAX(MAX(r, g), b);
if (maxv && maxout)
{
r = ::Scale(r, maxout, maxv);
g = ::Scale(g, maxout, maxv);
b = ::Scale(b, maxout, maxv);
}
return PalEntry(255, r, g, b);
}
PalEntry FTexture::GetSkyCapColor(bool bottom)
{
if (!bSWSkyColorDone)
{
bSWSkyColorDone = true;
FBitmap bitmap = GetBgraBitmap(nullptr);
int w = bitmap.GetWidth();
int h = bitmap.GetHeight();
const uint32_t* buffer = (const uint32_t*)bitmap.GetPixels();
if (buffer)
{
CeilingSkyColor = averageColor((uint32_t*)buffer, w * MIN(30, h), 0);
if (h > 30)
{
FloorSkyColor = averageColor(((uint32_t*)buffer) + (h - 30) * w, w * 30, 0);
}
else FloorSkyColor = CeilingSkyColor;
}
}
return bottom ? FloorSkyColor : CeilingSkyColor;
}
//====================================================================
//
// CheckRealHeight
@ -299,16 +95,13 @@ PalEntry FTexture::GetSkyCapColor(bool bottom)
int FTexture::CheckRealHeight()
{
auto pixels = Get8BitPixels(false);
for (int h = GetTexelHeight() - 1; h >= 0; h--)
for(int h = GetHeight()-1; h>= 0; h--)
{
for (int w = 0; w < GetTexelWidth(); w++)
for(int w = 0; w < GetWidth(); w++)
{
if (pixels[h + w * GetTexelHeight()] != 0)
if (pixels[h + w * GetHeight()] != 0)
{
// Scale maxy before returning it
h = int((h * 2) / Scale.Y);
h = (h >> 1) + (h & 1);
return h;
}
}
@ -316,127 +109,6 @@ int FTexture::CheckRealHeight()
return 0;
}
//==========================================================================
//
// Search auto paths for extra material textures
//
//==========================================================================
void FTexture::AddAutoMaterials()
{
struct AutoTextureSearchPath
{
const char* path;
FTexture* FTexture::* pointer;
};
static AutoTextureSearchPath autosearchpaths[] =
{
{ "brightmaps/", &FTexture::Brightmap }, // For backwards compatibility, only for short names
{ "materials/brightmaps/", &FTexture::Brightmap },
{ "materials/normalmaps/", &FTexture::Normal },
{ "materials/specular/", &FTexture::Specular },
{ "materials/metallic/", &FTexture::Metallic },
{ "materials/roughness/", &FTexture::Roughness },
{ "materials/ao/", &FTexture::AmbientOcclusion }
};
int startindex = bFullNameTexture ? 1 : 0;
FString searchname = Name;
if (bFullNameTexture)
{
auto dot = searchname.LastIndexOf('.');
auto slash = searchname.LastIndexOf('/');
if (dot > slash) searchname.Truncate(dot);
}
for (size_t i = 0; i < countof(autosearchpaths); i++)
{
auto& layer = autosearchpaths[i];
if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
{
FStringf lookup("%s%s%s", layer.path, bFullNameTexture ? "" : "auto/", searchname.GetChars());
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true);
if (lump != -1)
{
auto bmtex = TexMan.FindTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);
if (bmtex != nullptr)
{
bmtex->bMasked = false;
this->*(layer.pointer) = bmtex;
}
}
}
}
}
//===========================================================================
//
// Checks if the texture has a default brightmap and creates it if so
//
//===========================================================================
void FTexture::CreateDefaultBrightmap()
{
if (!bBrightmapChecked)
{
// Check for brightmaps
if (GetImage() && GetImage()->UseGamePalette() && GPalette.HasGlobalBrightmap &&
UseType != ETextureType::Decal && UseType != ETextureType::MiscPatch && UseType != ETextureType::FontChar &&
Brightmap == NULL && bWarped == 0)
{
// May have one - let's check when we use this texture
auto texbuf = Get8BitPixels(false);
const int white = ColorMatcher.Pick(255, 255, 255);
int size = GetTexelWidth() * GetTexelHeight();
for (int i = 0; i < size; i++)
{
if (GPalette.GlobalBrightmap.Remap[texbuf[i]] == white)
{
// Create a brightmap
DPrintf(DMSG_NOTIFY, "brightmap created for texture '%s'\n", Name.GetChars());
Brightmap = CreateBrightmapTexture(static_cast<FImageTexture*>(this)->GetImage());
bBrightmapChecked = true;
TexMan.AddTexture(Brightmap);
return;
}
}
// No bright pixels found
DPrintf(DMSG_SPAMMY, "No bright pixels found in texture '%s'\n", Name.GetChars());
bBrightmapChecked = true;
}
else
{
// does not have one so set the flag to 'done'
bBrightmapChecked = true;
}
}
}
//==========================================================================
//
// Calculates glow color for a texture
//
//==========================================================================
void FTexture::GetGlowColor(float* data)
{
if (bGlowing && GlowColor == 0)
{
auto buffer = GetBgraBitmap(nullptr);
GlowColor = averageColor((uint32_t*)buffer.GetPixels(), buffer.GetWidth() * buffer.GetHeight(), 153);
// Black glow equals nothing so switch glowing off
if (GlowColor == 0) bGlowing = false;
}
data[0] = GlowColor.r / 255.0f;
data[1] = GlowColor.g / 255.0f;
data[2] = GlowColor.b / 255.0f;
}
//===========================================================================
//
// Finds gaps in the texture which can be skipped by the renderer
@ -455,11 +127,10 @@ bool FTexture::FindHoles(const unsigned char* buffer, int w, int h)
// already done!
if (areacount) return false;
if (UseType == ETextureType::Flat) return false; // flats don't have transparent parts
areacount = -1; //whatever happens next, it shouldn't be done twice!
// large textures are excluded for performance reasons
if (h > 512) return false;
// large textures and non-images are excluded for performance reasons
if (h>512 || !GetImage()) return false;
startdraw = -1;
lendraw = 0;
@ -510,7 +181,7 @@ bool FTexture::FindHoles(const unsigned char* buffer, int w, int h)
if (gapc > 0)
{
FloatRect* rcs = new FloatRect[gapc];
FloatRect* rcs = (FloatRect*)ImageArena.Alloc(gapc * sizeof(FloatRect)); // allocate this on the image arena
for (x = 0; x < gapc; x++)
{
@ -635,10 +306,10 @@ bool FTexture::SmoothEdges(unsigned char* buffer, int w, int h)
bool FTexture::ProcessData(unsigned char* buffer, int w, int h, bool ispatch)
{
if (bMasked)
if (Masked)
{
bMasked = SmoothEdges(buffer, w, h);
if (bMasked && !ispatch) FindHoles(buffer, w, h);
Masked = SmoothEdges(buffer, w, h);
if (Masked && !ispatch) FindHoles(buffer, w, h);
}
return true;
}
@ -660,8 +331,8 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
int exx = !!(flags & CTF_Expand);
W = GetTexelWidth() + 2 * exx;
H = GetTexelHeight() + 2 * exx;
W = GetWidth() + 2 * exx;
H = GetHeight() + 2 * exx;
if (!checkonly)
{
@ -669,6 +340,7 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
memset(buffer, 0, W * (H + 1) * 4);
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
if (remap) translation = remap->Index;
FBitmap bmp(buffer, W * 4, W, H);
int trans;
@ -705,10 +377,8 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
// Only do postprocessing for image-backed textures. (i.e. not for the burn texture which can also pass through here.)
if (GetImage() && flags & CTF_ProcessData)
{
#pragma message("Activate me")
#if 0
CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly);
#endif
if (flags & CTF_Upscale) CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly);
if (!checkonly) ProcessData(result.mBuffer, result.mWidth, result.mHeight, false);
}
@ -723,15 +393,8 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
bool FTexture::DetermineTranslucency()
{
if (!bHasCanvas)
{
// This will calculate all we need, so just discard the result.
CreateTexBuffer(0);
}
else
{
bTranslucent = 0;
}
return !!bTranslucent;
}
@ -749,101 +412,114 @@ TArray<uint8_t> FTexture::Get8BitPixels(bool alphatex)
}
//===========================================================================
//
// Coordinate helper.
// The only reason this is even needed is that many years ago someone
// was convinced that having per-texel panning on walls was a good idea.
// If it wasn't for this relatively useless feature the entire positioning
// code for wall textures could be a lot simpler.
//
//===========================================================================
//===========================================================================
//
//
// Finds empty space around the texture.
// Used for sprites that got placed into a huge empty frame.
//
//===========================================================================
float FTexCoordInfo::RowOffset(float rowoffset) const
bool FTexture::TrimBorders(uint16_t* rect)
{
float scale = fabs(mScale.Y);
if (scale == 1.f || mWorldPanning) return rowoffset;
else return rowoffset / scale;
auto texbuffer = CreateTexBuffer(0);
int w = texbuffer.mWidth;
int h = texbuffer.mHeight;
auto Buffer = texbuffer.mBuffer;
if (texbuffer.mBuffer == nullptr)
{
return false;
}
if (w != Width || h != Height)
{
// external Hires replacements cannot be trimmed.
return false;
}
int size = w * h;
if (size == 1)
{
// nothing to be done here.
rect[0] = 0;
rect[1] = 0;
rect[2] = 1;
rect[3] = 1;
return true;
}
int first, last;
for (first = 0; first < size; first++)
{
if (Buffer[first * 4 + 3] != 0) break;
}
if (first >= size)
{
// completely empty
rect[0] = 0;
rect[1] = 0;
rect[2] = 1;
rect[3] = 1;
return true;
}
for (last = size - 1; last >= first; last--)
{
if (Buffer[last * 4 + 3] != 0) break;
}
rect[1] = first / w;
rect[3] = 1 + last / w - rect[1];
rect[0] = 0;
rect[2] = w;
unsigned char* bufferoff = Buffer + (rect[1] * w * 4);
h = rect[3];
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
if (bufferoff[(x + y * w) * 4 + 3] != 0) goto outl;
}
rect[0]++;
}
outl:
rect[2] -= rect[0];
for (int x = w - 1; rect[2] > 1; x--)
{
for (int y = 0; y < h; y++)
{
if (bufferoff[(x + y * w) * 4 + 3] != 0)
{
return true;
}
}
rect[2]--;
}
return true;
}
//===========================================================================
//
//
// Create a hardware texture for this texture image.
//
//===========================================================================
float FTexCoordInfo::TextureOffset(float textureoffset) const
IHardwareTexture* FTexture::GetHardwareTexture(int translation, int scaleflags)
{
float scale = fabs(mScale.X);
if (scale == 1.f || mWorldPanning) return textureoffset;
else return textureoffset / scale;
}
//===========================================================================
//
// Returns the size for which texture offset coordinates are used.
//
//===========================================================================
float FTexCoordInfo::TextureAdjustWidth() const
{
if (mWorldPanning)
//if (UseType != ETextureType::Null)
{
float tscale = fabs(mTempScale.X);
if (tscale == 1.f) return (float)mRenderWidth;
else return mWidth / fabs(tscale);
}
else return (float)mWidth;
}
//===========================================================================
//
// Retrieve texture coordinate info for per-wall scaling
//
//===========================================================================
void FTexCoordInfo::GetFromTexture(FTexture* tex, float x, float y, bool forceworldpanning)
{
if (x == 1.f)
IHardwareTexture* hwtex = SystemTextures.GetHardwareTexture(translation, scaleflags);
if (hwtex == nullptr)
{
mRenderWidth = tex->GetScaledWidth();
mScale.X = (float)tex->Scale.X;
mTempScale.X = 1.f;
hwtex = CreateHardwareTexture();
SystemTextures.AddHardwareTexture(translation, scaleflags, hwtex);
}
else
{
float scale_x = x * (float)tex->Scale.X;
mRenderWidth = xs_CeilToInt(tex->GetTexelWidth() / scale_x);
mScale.X = scale_x;
mTempScale.X = x;
return hwtex;
}
if (y == 1.f)
{
mRenderHeight = tex->GetScaledHeight();
mScale.Y = (float)tex->Scale.Y;
mTempScale.Y = 1.f;
}
else
{
float scale_y = y * (float)tex->Scale.Y;
mRenderHeight = xs_CeilToInt(tex->GetTexelHeight() / scale_y);
mScale.Y = scale_y;
mTempScale.Y = y;
}
if (tex->bHasCanvas)
{
mScale.Y = -mScale.Y;
mRenderHeight = -mRenderHeight;
}
mWorldPanning = tex->bWorldPanning || forceworldpanning;
mWidth = tex->GetTexelWidth();
return nullptr;
}
@ -858,8 +534,7 @@ FWrapperTexture::FWrapperTexture(int w, int h, int bits)
Width = w;
Height = h;
Format = bits;
UseType = ETextureType::SWCanvas;
bNoCompress = true;
//bNoCompress = true;
auto hwtex = CreateHardwareTexture();
// todo: Initialize here.
SystemTextures.AddHardwareTexture(0, false, hwtex);

View file

@ -17,7 +17,7 @@ enum class ETextureType : uint8_t
SkinGraphic,
Null,
FirstDefined,
Canvas,
Special,
SWCanvas,
};

View file

@ -103,15 +103,14 @@ void FTextureManager::DeleteAll()
//==========================================================================
//
// Flushes all hardware dependent data.
// Thia must not, under any circumstances, delete the wipe textures, because
// This must not, under any circumstances, delete the wipe textures, because
// all CCMDs triggering a flush can be executed while a wipe is in progress
//
// This now also deletes the software textures because having the software
// renderer use the texture scalers is a planned feature and that is the
// renderer can also use the texture scalers and that is the
// main reason to call this outside of the destruction code.
//
//==========================================================================
void DeleteSoftwareTexture(FSoftwareTexture* swtex);
void FTextureManager::FlushAll()
{
@ -119,13 +118,33 @@ void FTextureManager::FlushAll()
{
for (int j = 0; j < 2; j++)
{
Textures[i].Texture->SystemTextures.Clean(true, true);
DeleteSoftwareTexture(Textures[i].Texture->SoftwareTexture);
Textures[i].Texture->SoftwareTexture = nullptr;
Textures[i].Texture->CleanHardwareData();
delete Textures[i].Texture->GetSoftwareTexture();
Textures[i].Texture->SetSoftwareTexture(nullptr);
calcShouldUpscale(Textures[i].Texture);
}
}
}
//==========================================================================
//
// Examines the lump contents to decide what type of texture to create,
// and creates the texture.
//
//==========================================================================
static FTexture* CreateTextureFromLump(int lumpnum, bool allowflats = false)
{
if (lumpnum == -1) return nullptr;
auto image = FImageSource::GetImage(lumpnum, allowflats);
if (image != nullptr)
{
return new FImageTexture(image);
}
return nullptr;
}
//==========================================================================
//
// FTextureManager :: CheckForTexture
@ -152,38 +171,39 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
for(i = HashFirst[MakeKey(name) % HASH_SIZE]; i != HASH_END; i = Textures[i].HashNext)
{
const FTexture *tex = Textures[i].Texture;
auto tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0 )
if (stricmp (tex->GetName(), name) == 0 )
{
// If we look for short names, we must ignore any long name texture.
if ((flags & TEXMAN_ShortNameOnly) && tex->bFullNameTexture)
if ((flags & TEXMAN_ShortNameOnly) && tex->isFullNameTexture())
{
continue;
}
auto texUseType = tex->GetUseType();
// The name matches, so check the texture type
if (usetype == ETextureType::Any)
{
// All NULL textures should actually return 0
if (tex->UseType == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0;
if (tex->UseType == ETextureType::SkinGraphic && !(flags & TEXMAN_AllowSkins)) return 0;
return FTextureID(tex->UseType==ETextureType::Null ? 0 : i);
if (texUseType == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0;
if (texUseType == ETextureType::SkinGraphic && !(flags & TEXMAN_AllowSkins)) return 0;
return FTextureID(texUseType==ETextureType::Null ? 0 : i);
}
else if ((flags & TEXMAN_Overridable) && tex->UseType == ETextureType::Override)
else if ((flags & TEXMAN_Overridable) && texUseType == ETextureType::Override)
{
return FTextureID(i);
}
else if (tex->UseType == usetype)
else if (texUseType == usetype)
{
return FTextureID(i);
}
else if (tex->UseType == ETextureType::FirstDefined && usetype == ETextureType::Wall)
else if (texUseType == ETextureType::FirstDefined && usetype == ETextureType::Wall)
{
if (!(flags & TEXMAN_ReturnFirst)) return FTextureID(0);
else return FTextureID(i);
}
else if (tex->UseType == ETextureType::Null && usetype == ETextureType::Wall)
else if (texUseType == ETextureType::Null && usetype == ETextureType::Wall)
{
// We found a NULL texture on a wall -> return 0
return FTextureID(0);
@ -192,12 +212,12 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
{
if (firsttype == ETextureType::Null ||
(firsttype == ETextureType::MiscPatch &&
tex->UseType != firsttype &&
tex->UseType != ETextureType::Null)
texUseType != firsttype &&
texUseType != ETextureType::Null)
)
{
firstfound = i;
firsttype = tex->UseType;
firsttype = texUseType;
}
}
}
@ -221,20 +241,20 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
// Any graphic being placed in the zip's root directory can not be found by this.
if (strchr(name, '/'))
{
FTexture *const NO_TEXTURE = (FTexture*)-1;
FGameTexture *const NO_TEXTURE = (FGameTexture*)-1;
int lump = fileSystem.CheckNumForFullName(name);
if (lump >= 0)
{
FTexture *tex = fileSystem.GetLinkedTexture(lump);
FGameTexture *tex = fileSystem.GetLinkedTexture(lump);
if (tex == NO_TEXTURE) return FTextureID(-1);
if (tex != NULL) return tex->id;
if (tex != NULL) return tex->GetID();
if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet.
tex = FTexture::CreateTexture("", lump, ETextureType::Override);
tex = MakeGameTexture(CreateTextureFromLump(lump), nullptr, ETextureType::Override);
if (tex != NULL)
{
tex->AddAutoMaterials();
fileSystem.SetLinkedTexture(lump, tex);
return AddTexture(tex);
return AddGameTexture(tex);
}
else
{
@ -273,12 +293,13 @@ int FTextureManager::ListTextures (const char *name, TArray<FTextureID> &list, b
while (i != HASH_END)
{
const FTexture *tex = Textures[i].Texture;
auto tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0)
if (stricmp (tex->GetName(), name) == 0)
{
auto texUseType = tex->GetUseType();
// NULL textures must be ignored.
if (tex->UseType!=ETextureType::Null)
if (texUseType!=ETextureType::Null)
{
unsigned int j = list.Size();
if (!listall)
@ -286,7 +307,7 @@ int FTextureManager::ListTextures (const char *name, TArray<FTextureID> &list, b
for (j = 0; j < list.Size(); j++)
{
// Check for overriding definitions from newer WADs
if (Textures[list[j].GetIndex()].Texture->UseType == tex->UseType) break;
if (Textures[list[j].GetIndex()].Texture->GetUseType() == texUseType) break;
}
}
if (j==list.Size()) list.Push(FTextureID(i));
@ -331,10 +352,10 @@ FTextureID FTextureManager::GetTextureID (const char *name, ETextureType usetype
//
//==========================================================================
FTexture *FTextureManager::FindTexture(const char *texname, ETextureType usetype, BITFIELD flags)
FGameTexture *FTextureManager::FindGameTexture(const char *texname, ETextureType usetype, BITFIELD flags)
{
FTextureID texnum = CheckForTexture (texname, usetype, flags);
return GetTexture(texnum.GetIndex());
return GetGameTexture(texnum.GetIndex());
}
//==========================================================================
@ -362,7 +383,7 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut
if (locmode == 2) return false;
// Mode 3 must also reject substitutions for non-IWAD content.
int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->SourceLump);
int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->GetSourceLump());
if (file > fileSystem.GetMaxIwadNum()) return true;
return false;
@ -374,19 +395,23 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut
//
//==========================================================================
FTextureID FTextureManager::AddTexture (FTexture *texture)
FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohash)
{
int bucket;
int hash;
if (texture == NULL) return FTextureID(-1);
// Later textures take precedence over earlier ones
if (texture->GetTexture())
{
// Later textures take precedence over earlier ones
calcShouldUpscale(texture); // calculate this once at insertion
}
// Textures without name can't be looked for
if (texture->Name[0] != '\0')
if (addtohash && texture->GetName().IsNotEmpty())
{
bucket = int(MakeKey (texture->Name) % HASH_SIZE);
bucket = int(MakeKey (texture->GetName()) % HASH_SIZE);
hash = HashFirst[bucket];
}
else
@ -395,11 +420,13 @@ FTextureID FTextureManager::AddTexture (FTexture *texture)
hash = -1;
}
TextureHash hasher = { texture, hash };
TextureHash hasher = { texture, -1, -1, -1, hash };
int trans = Textures.Push (hasher);
Translation.Push (trans);
if (bucket >= 0) HashFirst[bucket] = trans;
return (texture->id = FTextureID(trans));
auto id = FTextureID(trans);
texture->SetID(id);
return id;
}
//==========================================================================
@ -416,9 +443,32 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype)
{
FString str;
fileSystem.GetFileShortName(str, lumpnum);
FTexture *out = FTexture::CreateTexture(str, lumpnum, usetype);
auto out = MakeGameTexture(CreateTextureFromLump(lumpnum, usetype == ETextureType::Flat), str, usetype);
if (out != NULL) return AddTexture (out);
if (out != NULL)
{
if (usetype == ETextureType::Flat)
{
int w = out->GetTexelWidth();
int h = out->GetTexelHeight();
// Auto-scale flats with dimensions 128x128 and 256x256.
// In hindsight, a bad idea, but RandomLag made it sound better than it really is.
// Now we're stuck with this stupid behaviour.
if (w == 128 && h == 128)
{
out->SetScale(2, 2);
out->SetWorldPanning(true);
}
else if (w == 256 && h == 256)
{
out->SetScale(4, 4);
out->SetWorldPanning(true);
}
}
return AddGameTexture(out);
}
else
{
Printf (TEXTCOLOR_ORANGE "Invalid data encountered for texture %s\n", fileSystem.GetFileFullPath(lumpnum).GetChars());
@ -434,20 +484,20 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype)
//
//==========================================================================
void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, bool free)
void FTextureManager::ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free)
{
int index = picnum.GetIndex();
if (unsigned(index) >= Textures.Size())
return;
FTexture *oldtexture = Textures[index].Texture;
auto oldtexture = Textures[index].Texture;
newtexture->Name = oldtexture->Name;
newtexture->UseType = oldtexture->UseType;
newtexture->SetName(oldtexture->GetName());
newtexture->SetUseType(oldtexture->GetUseType());
Textures[index].Texture = newtexture;
newtexture->id = oldtexture->id;
oldtexture->Name = "";
AddTexture(oldtexture);
newtexture->SetID(oldtexture->GetID());
oldtexture->SetName("");
AddGameTexture(oldtexture);
}
//==========================================================================
@ -465,11 +515,11 @@ bool FTextureManager::AreTexturesCompatible (FTextureID picnum1, FTextureID picn
if (unsigned(index1) >= Textures.Size() || unsigned(index2) >= Textures.Size())
return false;
FTexture *texture1 = Textures[index1].Texture;
FTexture *texture2 = Textures[index2].Texture;
auto texture1 = Textures[index1].Texture;
auto texture2 = Textures[index2].Texture;
// both textures must be the same type.
if (texture1 == NULL || texture2 == NULL || texture1->UseType != texture2->UseType)
if (texture1 == NULL || texture2 == NULL || texture1->GetUseType() != texture2->GetUseType())
return false;
// both textures must be from the same file
@ -556,30 +606,28 @@ void FTextureManager::AddHiresTextures (int wadnum)
if (amount == 0)
{
// A texture with this name does not yet exist
FTexture * newtex = FTexture::CreateTexture (Name, firsttx, ETextureType::Any);
auto newtex = MakeGameTexture(CreateTextureFromLump(firsttx), Name, ETextureType::Override);
if (newtex != NULL)
{
newtex->UseType=ETextureType::Override;
AddTexture(newtex);
AddGameTexture(newtex);
}
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * newtex = FTexture::CreateTexture ("", firsttx, ETextureType::Any);
FTexture * newtex = CreateTextureFromLump(firsttx);
if (newtex != NULL)
{
FTexture * oldtex = Textures[tlist[i].GetIndex()].Texture;
auto oldtex = Textures[tlist[i].GetIndex()].Texture;
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetDisplaySize(oldtex->GetDisplayWidth(), oldtex->GetDisplayHeight());
newtex->_LeftOffset[0] = int(oldtex->GetScaledLeftOffset(0) * newtex->Scale.X);
newtex->_LeftOffset[1] = int(oldtex->GetScaledLeftOffset(1) * newtex->Scale.X);
newtex->_TopOffset[0] = int(oldtex->GetScaledTopOffset(0) * newtex->Scale.Y);
newtex->_TopOffset[1] = int(oldtex->GetScaledTopOffset(1) * newtex->Scale.Y);
ReplaceTexture(tlist[i], newtex, true);
auto gtex = MakeGameTexture(newtex, nullptr, ETextureType::Override);
gtex->SetWorldPanning(true);
gtex->SetDisplaySize(oldtex->GetDisplayWidth(), oldtex->GetDisplayHeight());
gtex->SetOffsets(0, xs_RoundToInt(oldtex->GetDisplayLeftOffset(0) * gtex->GetScaleX()), xs_RoundToInt(oldtex->GetDisplayTopOffset(0) * gtex->GetScaleY()));
gtex->SetOffsets(1, xs_RoundToInt(oldtex->GetDisplayLeftOffset(1) * gtex->GetScaleX()), xs_RoundToInt(oldtex->GetDisplayTopOffset(1) * gtex->GetScaleY()));
ReplaceTexture(tlist[i], gtex, true);
}
}
}
@ -655,28 +703,27 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * oldtex = Textures[tlist[i].GetIndex()].Texture;
auto oldtex = Textures[tlist[i].GetIndex()].Texture;
int sl;
// only replace matching types. For sprites also replace any MiscPatches
// based on the same lump. These can be created for icons.
if (oldtex->UseType == type || type == ETextureType::Any ||
(mode == TEXMAN_Overridable && oldtex->UseType == ETextureType::Override) ||
(type == ETextureType::Sprite && oldtex->UseType == ETextureType::MiscPatch &&
if (oldtex->GetUseType() == type || type == ETextureType::Any ||
(mode == TEXMAN_Overridable && oldtex->GetUseType() == ETextureType::Override) ||
(type == ETextureType::Sprite && oldtex->GetUseType() == ETextureType::MiscPatch &&
(sl=oldtex->GetSourceLump()) >= 0 && fileSystem.GetFileNamespace(sl) == ns_sprites)
)
{
FTexture * newtex = FTexture::CreateTexture ("", lumpnum, ETextureType::Any);
FTexture * newtex = CreateTextureFromLump(lumpnum);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetDisplaySize(oldtex->GetDisplayWidth(), oldtex->GetDisplayHeight());
newtex->_LeftOffset[0] = int(oldtex->GetScaledLeftOffset(0) * newtex->Scale.X);
newtex->_LeftOffset[1] = int(oldtex->GetScaledLeftOffset(1) * newtex->Scale.X);
newtex->_TopOffset[0] = int(oldtex->GetScaledTopOffset(0) * newtex->Scale.Y);
newtex->_TopOffset[1] = int(oldtex->GetScaledTopOffset(1) * newtex->Scale.Y);
ReplaceTexture(tlist[i], newtex, true);
auto gtex = MakeGameTexture(newtex, nullptr, ETextureType::Override);
gtex->SetWorldPanning(true);
gtex->SetDisplaySize(oldtex->GetDisplayWidth(), oldtex->GetDisplayHeight());
gtex->SetOffsets(0, xs_RoundToInt(oldtex->GetDisplayLeftOffset(0) * gtex->GetScaleX()), xs_RoundToInt(oldtex->GetDisplayTopOffset(0) * gtex->GetScaleY()));
gtex->SetOffsets(1, xs_RoundToInt(oldtex->GetDisplayLeftOffset(1) * gtex->GetScaleX()), xs_RoundToInt(oldtex->GetDisplayTopOffset(1) * gtex->GetScaleY()));
ReplaceTexture(tlist[i], gtex, true);
}
}
}
@ -705,21 +752,21 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build
if (lumpnum>=0)
{
FTexture *newtex = FTexture::CreateTexture(src, lumpnum, ETextureType::Override);
auto newtex = MakeGameTexture(CreateTextureFromLump(lumpnum), src, ETextureType::Override);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetDisplaySize(width, height);
newtex->SetWorldPanning(true);
newtex->SetDisplaySize((float)width, (float)height);
FTextureID oldtex = TexMan.CheckForTexture(src, ETextureType::MiscPatch);
if (oldtex.isValid())
{
ReplaceTexture(oldtex, newtex, true);
newtex->UseType = ETextureType::Override;
newtex->SetUseType(ETextureType::Override);
}
else AddTexture(newtex);
else AddGameTexture(newtex);
}
}
}
@ -925,11 +972,11 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b
// 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(Name, i, skin ? ETextureType::SkinGraphic : ETextureType::MiscPatch);
auto out = MakeGameTexture(CreateTextureFromLump(i), Name, skin ? ETextureType::SkinGraphic : ETextureType::MiscPatch);
if (out != NULL)
{
AddTexture (out);
AddGameTexture (out);
}
}
@ -953,7 +1000,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b
void FTextureManager::SortTexturesByType(int start, int end)
{
TArray<FTexture *> newtextures;
TArray<FGameTexture *> newtextures;
// First unlink all newly added textures from the hash chain
for (int i = 0; i < HASH_SIZE; i++)
@ -981,9 +1028,9 @@ void FTextureManager::SortTexturesByType(int start, int end)
{
for(unsigned j = 0; j<newtextures.Size(); j++)
{
if (newtextures[j] != NULL && newtextures[j]->UseType == texturetypes[i])
if (newtextures[j] != NULL && newtextures[j]->GetUseType() == texturetypes[i])
{
AddTexture(newtextures[j]);
AddGameTexture(newtextures[j]);
newtextures[j] = NULL;
}
}
@ -993,8 +1040,8 @@ void FTextureManager::SortTexturesByType(int start, int end)
{
if (newtextures[j] != NULL)
{
Printf("Texture %s has unknown type!\n", newtextures[j]->Name.GetChars());
AddTexture(newtextures[j]);
Printf("Texture %s has unknown type!\n", newtextures[j]->GetName().GetChars());
AddGameTexture(newtextures[j]);
}
}
}
@ -1032,8 +1079,8 @@ void FTextureManager::AddLocalizedVariants()
FTextureID tex = CheckForTexture(entry.name, ETextureType::MiscPatch);
if (tex.isValid())
{
FTexture *otex = GetTexture(origTex);
FTexture *ntex = GetTexture(tex);
auto otex = GetGameTexture(origTex);
auto ntex = GetGameTexture(tex);
if (otex->GetDisplayWidth() != ntex->GetDisplayWidth() || otex->GetDisplayHeight() != ntex->GetDisplayHeight())
{
Printf("Localized texture %s must be the same size as the one it replaces\n", entry.name);
@ -1081,8 +1128,9 @@ void FTextureManager::AddLocalizedVariants()
// FTextureManager :: Init
//
//==========================================================================
FTexture *CreateShaderTexture(bool, bool);
FGameTexture *CreateShaderTexture(bool, bool);
void InitBuildTiles();
FImageSource* CreateEmptyTexture();
void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&))
{
@ -1090,15 +1138,18 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI
DeleteAll();
//if (BuildTileFiles.Size() == 0) CountBuildTiles ();
// Texture 0 is a dummy texture used to indicate "no texture"
auto nulltex = new FImageTexture(nullptr, "");
nulltex->SetUseType(ETextureType::Null);
AddTexture (nulltex);
auto nulltex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Null);
AddGameTexture(nulltex);
// This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture.
auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Override);
emptytex->SetSize(1, 1);
AddGameTexture(emptytex);
// some special textures used in the game.
AddTexture(CreateShaderTexture(false, false));
AddTexture(CreateShaderTexture(false, true));
AddTexture(CreateShaderTexture(true, false));
AddTexture(CreateShaderTexture(true, true));
AddGameTexture(CreateShaderTexture(false, false));
AddGameTexture(CreateShaderTexture(false, true));
AddGameTexture(CreateShaderTexture(true, false));
AddGameTexture(CreateShaderTexture(true, true));
int wadcnt = fileSystem.GetNumWads();
@ -1133,6 +1184,13 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI
glPart = TexMan.CheckForTexture("glstuff/glpart.png", ETextureType::MiscPatch);
mirrorTexture = TexMan.CheckForTexture("glstuff/mirror.png", ETextureType::MiscPatch);
AddLocalizedVariants();
// Make sure all ID's are correct by resetting them here to the proper index.
for (unsigned int i = 0, count = Textures.Size(); i < count; ++i)
{
Textures[i].Texture->SetID(i);
}
}
//==========================================================================
@ -1160,19 +1218,95 @@ void FTextureManager::InitPalettedVersions()
FTextureID pic2 = CheckForTexture(sc.String, ETextureType::Any);
if (!pic2.isValid())
{
sc.ScriptMessage("Unknown texture %s to use as replacement", sc.String);
sc.ScriptMessage("Unknown texture %s to use as paletted replacement", sc.String);
}
if (pic1.isValid() && pic2.isValid())
{
FTexture *owner = GetTexture(pic1);
FTexture *owned = GetTexture(pic2);
if (owner && owned) owner->PalVersion = owned;
Textures[pic1.GetIndex()].Paletted = pic2.GetIndex();
}
}
}
}
//==========================================================================
//
//
//
//==========================================================================
FTextureID FTextureManager::GetRawTexture(FTextureID texid)
{
int texidx = texid.GetIndex();
if ((unsigned)texidx >= Textures.Size()) return texid;
if (Textures[texidx].FrontSkyLayer != -1) return FSetTextureID(Textures[texidx].FrontSkyLayer);
// Reject anything that cannot have been a front layer for the sky in original Hexen, i.e. it needs to be an unscaled wall texture only using Doom patches.
auto tex = Textures[texidx].Texture;
auto ttex = tex->GetTexture();
auto image = ttex->GetImage();
// Reject anything that cannot have been a single-patch multipatch texture in vanilla.
if (image == nullptr || image->IsRawCompatible() || tex->GetUseType() != ETextureType::Wall || ttex->GetWidth() != tex->GetDisplayWidth() ||
ttex->GetHeight() != tex->GetDisplayHeight())
{
Textures[texidx].RawTexture = texidx;
return texid;
}
// Let the hackery begin
auto mptimage = static_cast<FMultiPatchTexture*>(image);
auto source = mptimage->GetImageForPart(0);
// Size must match for this to work as intended
if (source->GetWidth() != ttex->GetWidth() || source->GetHeight() != ttex->GetHeight())
{
Textures[texidx].RawTexture = texidx;
return texid;
}
// Todo: later this can just link to the already existing texture for this source graphic, once it can be retrieved through the image's SourceLump index
auto RawTexture = MakeGameTexture(new FImageTexture(source), nullptr, ETextureType::Wall);
texid = TexMan.AddGameTexture(RawTexture);
Textures[texidx].RawTexture = texid.GetIndex();
Textures[texid.GetIndex()].RawTexture = texid.GetIndex();
return texid;
}
//==========================================================================
//
// Same shit for a different hack, this time Hexen's front sky layers.
//
//==========================================================================
FTextureID FTextureManager::GetFrontSkyLayer(FTextureID texid)
{
int texidx = texid.GetIndex();
if ((unsigned)texidx >= Textures.Size()) return texid;
if (Textures[texidx].FrontSkyLayer != -1) return FSetTextureID(Textures[texidx].FrontSkyLayer);
// Reject anything that cannot have been a front layer for the sky in original Hexen, i.e. it needs to be an unscaled wall texture only using Doom patches.
auto tex = Textures[texidx].Texture;
auto ttex = tex->GetTexture();
auto image = ttex->GetImage();
if (image == nullptr || !image->SupportRemap0() || tex->GetUseType() != ETextureType::Wall || tex->useWorldPanning() || tex->GetTexelTopOffset() != 0 ||
ttex->GetWidth() != tex->GetDisplayWidth() || ttex->GetHeight() != tex->GetDisplayHeight())
{
Textures[texidx].FrontSkyLayer = texidx;
return texid;
}
// Set this up so that it serializes to the same info as the base texture - this is needed to restore it on load.
// But do not link the new texture into the hash chain!
auto itex = new FImageTexture(image);
itex->SetNoRemap0();
auto FrontSkyLayer = MakeGameTexture(itex, tex->GetName(), ETextureType::Wall);
FrontSkyLayer->SetUseType(tex->GetUseType());
texid = TexMan.AddGameTexture(FrontSkyLayer, false);
Textures[texidx].FrontSkyLayer = texid.GetIndex();
Textures[texid.GetIndex()].FrontSkyLayer = texid.GetIndex(); // also let it refer to itself as its front sky layer, in case for repeated InitSkyMap calls.
return texid;
}
//==========================================================================
//
//
@ -1314,7 +1448,7 @@ void FTextureManager::AdjustSpriteOffsets()
fileSystem.GetFileShortName(str, i);
str[8] = 0;
FTextureID texid = TexMan.CheckForTexture(str, ETextureType::Sprite, 0);
if (texid.isValid() && fileSystem.GetFileContainer(GetTexture(texid)->SourceLump) > fileSystem.GetMaxIwadNum())
if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxIwadNum())
{
// This texture has been replaced by some PWAD.
memcpy(&sprid, str, 4);
@ -1349,7 +1483,7 @@ void FTextureManager::AdjustSpriteOffsets()
}
if (texno.isValid())
{
FTexture * tex = GetTexture(texno);
auto tex = GetGameTexture(texno);
int lumpnum = tex->GetSourceLump();
// We only want to change texture offsets for sprites in the IWAD or the file this lump originated from.
@ -1360,11 +1494,10 @@ void FTextureManager::AdjustSpriteOffsets()
{
if (wadno >= fileSystem.GetIwadNum() && wadno <= fileSystem.GetMaxIwadNum() && !forced && iwadonly)
{
memcpy(&sprid, &tex->Name[0], 4);
memcpy(&sprid, tex->GetName().GetChars(), 4);
if (donotprocess.CheckKey(sprid)) continue; // do not alter sprites that only get partially replaced.
}
tex->_LeftOffset[1] = x;
tex->_TopOffset[1] = y;
tex->SetOffsets(1, x, y);
}
}
}

View file

@ -9,8 +9,8 @@
#include "name.h"
class FxAddSub;
class FTexture;
struct BuildInfo;
class FMultipatchTextureBuilder;
int PalCheck(int tex);
// Texture manager
@ -25,42 +25,59 @@ public:
private:
int ResolveLocalizedTexture(int texnum);
FTexture *InternalGetTexture(int texnum, bool animate, bool localize, bool palettesubst)
int ResolveTextureIndex(int texnum, bool animate, bool localize)
{
if ((unsigned)texnum >= Textures.Size()) return nullptr;
if ((unsigned)texnum >= Textures.Size()) return -1;
if (animate) texnum = Translation[texnum];
if (localize && Textures[texnum].HasLocalization) texnum = ResolveLocalizedTexture(texnum);
if (palettesubst) texnum = PalCheck(texnum);
return texnum;
}
FGameTexture *InternalGetTexture(int texnum, bool animate, bool localize)
{
texnum = ResolveTextureIndex(texnum, animate, localize);
if (texnum == -1) return nullptr;
return Textures[texnum].Texture;
}
public:
FTextureID ResolveTextureIndex(FTextureID texid, bool animate, bool localize)
{
return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate, localize));
}
// This only gets used in UI code so we do not need PALVERS handling.
FTexture *GetTextureByName(const char *name, bool animate = false)
FGameTexture* GetGameTextureByName(const char *name, bool animate = false)
{
FTextureID texnum = GetTextureID (name, ETextureType::MiscPatch);
return InternalGetTexture(texnum.GetIndex(), animate, true, false);
FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch);
return InternalGetTexture(texnum.GetIndex(), animate, true);
}
FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false)
{
return InternalGetTexture(texnum.GetIndex(), animate, true);
}
FTexture *GetTexture(FTextureID texnum, bool animate = false)
FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true)
{
return InternalGetTexture(texnum.GetIndex(), animate, true, false);
auto texid = ResolveTextureIndex(texnum.GetIndex(), animate, true);
if (texid == -1) return nullptr;
if (allowsubstitute && Textures[texid].Paletted > 0) texid = Textures[texid].Paletted;
return Textures[texid].Texture;
}
// This is the only access function that should be used inside the software renderer.
FTexture *GetPalettedTexture(FTextureID texnum, bool animate)
FGameTexture* GameByIndex(int i, bool animate = false)
{
return InternalGetTexture(texnum.GetIndex(), animate, true, true);
return InternalGetTexture(i, animate, true);
}
FTexture *ByIndex(int i, bool animate = false)
{
return InternalGetTexture(i, animate, true, false);
}
FTexture *FindTexture(const char *texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny);
FGameTexture* FindGameTexture(const char* texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny);
bool OkForLocalization(FTextureID texnum, const char *substitute, int locnum);
void FlushAll();
FTextureID GetFrontSkyLayer(FTextureID);
FTextureID GetRawTexture(FTextureID);
enum
@ -99,7 +116,7 @@ public:
void AddLocalizedVariants();
FTextureID CreateTexture (int lumpnum, ETextureType usetype=ETextureType::Any); // Also calls AddTexture
FTextureID AddTexture (FTexture *texture);
FTextureID AddGameTexture(FGameTexture* texture, bool addtohash = true);
FTextureID GetDefaultTexture() const { return DefaultTexture; }
void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build);
@ -107,7 +124,7 @@ public:
void Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo &));
void DeleteAll();
void ReplaceTexture (FTextureID picnum, FTexture *newtexture, bool free);
void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free);
int NumTextures () const { return (int)Textures.Size(); }
@ -144,7 +161,7 @@ public:
return BuildTileData.Last();
}
FTexture* Texture(FTextureID id) { return Textures[id.GetIndex()].Texture; }
FGameTexture* GameTexture(FTextureID id) { return Textures[id.GetIndex()].Texture; }
void SetTranslation(FTextureID fromtexnum, FTextureID totexnum);
private:
@ -155,7 +172,10 @@ private:
struct TextureHash
{
FTexture *Texture;
FGameTexture* Texture;
int Paletted; // redirection to paletted variant
int FrontSkyLayer; // and front sky layer,
int RawTexture;
int HashNext;
bool HasLocalization;
};
@ -185,3 +205,4 @@ public:
};
extern FTextureManager TexMan;

View file

@ -42,23 +42,33 @@
#include "textureid.h"
#include <vector>
#include "hw_texcontainer.h"
// 15 because 0th texture is our texture
#define MAX_CUSTOM_HW_SHADER_TEXTURES 15
#include "floatrect.h"
#include "refcounted.h"
typedef TMap<int, bool> SpriteHits;
class FImageSource;
class FGameTexture;
class IHardwareTexture;
enum
{
CLAMP_NONE = 0,
CLAMP_X = 1,
CLAMP_Y = 2,
CLAMP_XY = 3,
CLAMP_XY_NOMIP = 4,
CLAMP_NOFILTER = 5,
CLAMP_CAMTEX = 6,
};
enum MaterialShaderIndex
{
SHADER_Default,
SHADER_Warp1,
SHADER_Warp2,
SHADER_Brightmap,
SHADER_Specular,
SHADER_SpecularBrightmap,
SHADER_PBR,
SHADER_PBRBrightmap,
SHADER_Paletted,
SHADER_NoTexture,
SHADER_BasicFuzz,
@ -72,46 +82,34 @@ enum MaterialShaderIndex
FIRST_USER_SHADER
};
enum texflags
{
// These get Or'ed into uTextureMode because it only uses its 3 lowermost bits.
TEXF_Brightmap = 0x10000,
TEXF_Detailmap = 0x20000,
TEXF_Glowmap = 0x40000,
};
enum
{
SFlag_Brightmap = 1,
SFlag_Detailmap = 2,
SFlag_Glowmap = 4,
};
struct UserShaderDesc
{
FString shader;
MaterialShaderIndex shaderType;
FString defines;
bool disablealphatest = false;
uint8_t shaderFlags = 0;
};
extern TArray<UserShaderDesc> usershaders;
struct FloatRect
{
float left,top;
float width,height;
void Offset(float xofs,float yofs)
{
left+=xofs;
top+=yofs;
}
void Scale(float xfac,float yfac)
{
left*=xfac;
width*=xfac;
top*=yfac;
height*=yfac;
}
};
enum ECreateTexBufferFlags
{
CTF_Expand = 2, // create buffer with a one-pixel wide border
CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture.
CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures.
};
class FBitmap;
struct FRemapTable;
struct FCopyInfo;
@ -141,7 +139,12 @@ enum FTextureFormat : uint32_t
TEX_Count
};
class FSoftwareTexture;
class ISoftwareTexture
{
public:
virtual ~ISoftwareTexture() = default;
};
class FGLRenderState;
struct spriteframewithrotate;
@ -202,115 +205,62 @@ struct FTextureBuffer
};
// Base texture class
class FTexture
class FTexture : public RefCountedBase
{
friend class GLDefsParser;
friend class FMultipatchTextureBuilder;
// The serializer also needs access to more specific info that shouldn't be accessible through the interface.
friend FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTextureID *defval);
friend class FGameTexture; // only for the porting work
// For now only give access to classes which cannot be reworked yet. None of these should remain here when all is done.
friend class FSoftwareTexture;
friend class FWarpTexture;
friend class FMaterial;
friend class OpenGLRenderer::FGLRenderState; // For now this needs access to some fields in ApplyMaterial. This should be rerouted through the Material class
friend class VkRenderState;
friend class PolyRenderState;
friend struct FTexCoordInfo;
friend class OpenGLRenderer::FHardwareTexture;
friend class VkHardwareTexture;
friend class PolyHardwareTexture;
friend class FMultiPatchTexture;
friend class FSkyBox;
friend class FBrightmapTexture;
friend class FFont;
public:
FHardwareTextureContainer SystemTextures;
protected:
FloatRect* areas = nullptr;
int SourceLump;
uint16_t Width = 0, Height = 0;
bool Masked = false; // Texture (might) have holes
bool bHasCanvas = false;
int8_t bTranslucent = -1;
int8_t areacount = 0; // this is capped at 4 sections.
public:
static FTexture *CreateTexture(const char *name, int lumpnum, ETextureType usetype);
virtual ~FTexture ();
IHardwareTexture* GetHardwareTexture(int translation, int scaleflags);
virtual FImageSource *GetImage() const { return nullptr; }
void AddAutoMaterials();
void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly);
// These are mainly meant for 2D code which only needs logical information about the texture to position it properly.
int GetDisplayWidth() { int foo = int((Width * 2) / Scale.X); return (foo >> 1) + (foo & 1); }
int GetDisplayHeight() { int foo = int((Height * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
double GetDisplayWidthDouble() { return Width / Scale.X; }
double GetDisplayHeightDouble() { return Height / Scale.Y; }
int GetDisplayLeftOffset() { return GetScaledLeftOffset(0); }
int GetDisplayTopOffset() { return GetScaledTopOffset(0); }
double GetDisplayLeftOffsetDouble() { return GetScaledLeftOffsetDouble(0); }
double GetDisplayTopOffsetDouble() { return GetScaledTopOffsetDouble(0); }
void SetOffsets(int l, int t)
void CleanHardwareTextures()
{
_LeftOffset[0] = _LeftOffset[1] = l;
_TopOffset[0] = _TopOffset[1] = t;
SystemTextures.Clean();
}
int GetTexelWidth() { return Width; }
int GetTexelHeight() { return Height; }
int GetTexelLeftOffset(int adjusted) { return _LeftOffset[adjusted]; }
int GetTexelTopOffset(int adjusted) { return _TopOffset[adjusted]; }
void CleanPrecacheMarker()
{
SystemTextures.UnmarkAll();
}
void MarkForPrecache(int translation, int scaleflags)
{
SystemTextures.MarkForPrecache(translation, scaleflags);
}
void CleanUnused()
{
SystemTextures.CleanUnused();
}
int GetWidth() { return Width; }
int GetHeight() { return Height; }
bool isValid() const { return UseType != ETextureType::Null; }
bool isSWCanvas() const { return UseType == ETextureType::SWCanvas; }
bool isSkybox() const { return bSkybox; }
bool isFullbrightDisabled() const { return bDisableFullbright; }
bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later.
bool isCanvas() const { return bHasCanvas; }
bool isMiscPatch() const { return UseType == ETextureType::MiscPatch; } // only used by the intermission screen to decide whether to tile the background image or not.
int isWarped() const { return bWarped; }
int GetRotations() const { return Rotations; }
void SetRotations(int rot) { Rotations = int16_t(rot); }
bool isSprite() const { return UseType == ETextureType::Sprite || UseType == ETextureType::SkinSprite || UseType == ETextureType::Decal; }
const FString &GetName() const { return Name; }
void SetNoDecals(bool on) { bNoDecals = on; }
void SetWarpStyle(int style) { bWarped = style; }
bool allowNoDecals() const { return bNoDecals; }
bool isScaled() const { return Scale.X != 1 || Scale.Y != 1; }
bool isMasked() const { return bMasked; }
void SetSkyOffset(int offs) { SkyOffset = offs; }
int GetSkyOffset() const { return SkyOffset; }
FTextureID GetID() const { return id; }
PalEntry GetSkyCapColor(bool bottom);
FTexture *GetRawTexture();
virtual int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method.
void GetGlowColor(float *data);
bool isGlowing() const { return bGlowing; }
bool isAutoGlowing() const { return bAutoGlowing; }
int GetGlowHeight() const { return GlowHeight; }
bool isFullbright() const { return bFullbright; }
void CreateDefaultBrightmap();
int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method.
bool FindHoles(const unsigned char * buffer, int w, int h);
void SetUseType(ETextureType type) { UseType = type; }
int GetSourceLump() const { return SourceLump; }
ETextureType GetUseType() const { return UseType; }
void SetSpeed(float fac) { shaderspeed = fac; }
void SetWorldPanning(bool on) { bWorldPanning = on; }
void SetDisplaySize(int fitwidth, int fitheight);
void SetFrontSkyLayer(bool on = true) { bNoRemap0 = on; }
bool IsFrontSkyLayer() { return bNoRemap0; }
FTexture* GetBrightmap()
{
if (!bBrightmapChecked)
CreateDefaultBrightmap();
return Brightmap;
}
void CopySize(FTexture* BaseTexture)
{
Width = BaseTexture->GetTexelWidth();
Height = BaseTexture->GetTexelHeight();
_TopOffset[0] = BaseTexture->_TopOffset[0];
_TopOffset[1] = BaseTexture->_TopOffset[1];
_LeftOffset[0] = BaseTexture->_LeftOffset[0];
_LeftOffset[1] = BaseTexture->_LeftOffset[1];
Scale = BaseTexture->Scale;
Width = BaseTexture->GetWidth();
Height = BaseTexture->GetHeight();
}
// This is only used for the null texture and for Heretic's skies.
@ -320,119 +270,20 @@ public:
Height = h;
}
bool TrimBorders(uint16_t* rect);
int GetAreas(FloatRect** pAreas) const;
// Returns the whole texture, stored in column-major order
virtual TArray<uint8_t> Get8BitPixels(bool alphatex);
virtual FBitmap GetBgraBitmap(const PalEntry *remap, int *trans = nullptr);
static bool SmoothEdges(unsigned char * buffer,int w, int h);
static PalEntry averageColor(const uint32_t *data, int size, int maxout);
FSoftwareTexture *GetSoftwareTexture();
protected:
DVector2 Scale;
int SourceLump;
FTextureID id;
FMaterial *Material[2] = { nullptr, nullptr };
public:
FHardwareTextureContainer SystemTextures;
int alphaThreshold = 0.5;
FixedBitArray<256> NoBrightmapFlag = false;
protected:
FSoftwareTexture *SoftwareTexture = nullptr;
// None of the following pointers are owned by this texture, they are all controlled by the texture manager.
// Offset-less version for COMPATF_MASKEDMIDTEX
FTexture *OffsetLess = nullptr;
// Paletted variant
FTexture *PalVersion = nullptr;
// Material layers
FTexture *Brightmap = nullptr;
FTexture *Normal = nullptr; // Normal map texture
FTexture *Specular = nullptr; // Specular light texture for the diffuse+normal+specular light model
FTexture *Metallic = nullptr; // Metalness texture for the physically based rendering (PBR) light model
FTexture *Roughness = nullptr; // Roughness texture for PBR
FTexture *AmbientOcclusion = nullptr; // Ambient occlusion texture for PBR
FTexture *CustomShaderTextures[MAX_CUSTOM_HW_SHADER_TEXTURES] = { nullptr }; // Custom texture maps for custom hardware shaders
FString Name;
ETextureType UseType; // This texture's primary purpose
uint8_t bNoDecals:1; // Decals should not stick to texture
uint8_t bNoRemap0:1; // Do not remap color 0 (used by front layer of parallax skies)
uint8_t bWorldPanning:1; // Texture is panned in world units rather than texels
uint8_t bMasked:1; // Texture (might) have holes
uint8_t bAlphaTexture:1; // Texture is an alpha channel without color information
uint8_t bHasCanvas:1; // Texture is based off FCanvasTexture
uint8_t bWarped:2; // This is a warped texture. Used to avoid multiple warps on one texture
uint8_t bComplex:1; // Will be used to mark extended MultipatchTextures that have to be
// fully composited before subjected to any kind of postprocessing instead of
// doing it per patch.
uint8_t bMultiPatch:2; // This is a multipatch texture (we really could use real type info for textures...)
uint8_t bFullNameTexture : 1;
uint8_t bBrightmapChecked : 1; // Set to 1 if brightmap has been checked
uint8_t bGlowing : 1; // Texture glow color
uint8_t bAutoGlowing : 1; // Glow info is determined from texture image.
uint8_t bFullbright : 1; // always draw fullbright
uint8_t bDisableFullbright : 1; // This texture will not be displayed as fullbright sprite
uint8_t bSkybox : 1; // is a cubic skybox
uint8_t bNoCompress : 1;
uint8_t bNoExpand : 1;
int8_t bTranslucent : 2;
bool bHiresHasColorKey = false; // Support for old color-keyed Doomsday textures
uint16_t Rotations;
int16_t SkyOffset;
FloatRect *areas = nullptr;
int areacount = 0;
int GlowHeight = 128;
PalEntry GlowColor = 0;
int HiresLump = -1; // For external hires textures.
float Glossiness = 10.f;
float SpecularLevel = 0.1f;
float shaderspeed = 1.f;
int shaderindex = 0;
int GetScaledWidth () { int foo = int((Width * 2) / Scale.X); return (foo >> 1) + (foo & 1); }
int GetScaledHeight () { int foo = int((Height * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
double GetScaledWidthDouble () { return Width / Scale.X; }
double GetScaledHeightDouble () { return Height / Scale.Y; }
double GetScaleY() const { return Scale.Y; }
// Now with improved offset adjustment.
int GetLeftOffset(int adjusted) { return _LeftOffset[adjusted]; }
int GetTopOffset(int adjusted) { return _TopOffset[adjusted]; }
int GetScaledLeftOffset (int adjusted) { int foo = int((_LeftOffset[adjusted] * 2) / Scale.X); return (foo >> 1) + (foo & 1); }
int GetScaledTopOffset (int adjusted) { int foo = int((_TopOffset[adjusted] * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
double GetScaledLeftOffsetDouble(int adjusted) { return _LeftOffset[adjusted] / Scale.X; }
double GetScaledTopOffsetDouble(int adjusted) { return _TopOffset[adjusted] / Scale.Y; }
// Interfaces for the different renderers. Everything that needs to check renderer-dependent offsets
// should use these, so that if changes are needed, this is the only place to edit.
// For the hardware renderer. The software renderer's have been offloaded to FSoftwareTexture
int GetLeftOffsetHW() { return _LeftOffset[r_spriteadjustHW]; }
int GetTopOffsetHW() { return _TopOffset[r_spriteadjustHW]; }
virtual void ResolvePatches() {}
void SetScale(const DVector2 &scale)
{
Scale = scale;
}
protected:
uint16_t Width, Height;
int16_t _LeftOffset[2], _TopOffset[2];
FTexture (const char *name = NULL, int lumpnum = -1);
FTexture (int lumpnum = -1);
public:
FTextureBuffer CreateTexBuffer(int translation, int flags = 0);
@ -442,27 +293,6 @@ public:
{
return bTranslucent != -1 ? bTranslucent : DetermineTranslucency();
}
FMaterial* GetMaterial(int num)
{
return Material[num];
}
FTexture* GetPalVersion()
{
return PalVersion;
}
void DeleteHardwareTextures()
{
SystemTextures.Clean(true, true);
}
private:
int CheckDDPK3();
int CheckExternalFile(bool & hascolorkey);
bool bSWSkyColorDone = false;
PalEntry FloorSkyColor;
PalEntry CeilingSkyColor;
public:
@ -479,17 +309,13 @@ public:
class FCanvasTexture : public FTexture
{
public:
FCanvasTexture(const char* name, int width, int height)
FCanvasTexture(int width, int height)
{
Name = name;
Width = width;
Height = height;
bMasked = false;
bHasCanvas = true;
bTranslucent = false;
bNoExpand = true;
UseType = ETextureType::Wall;
aspectRatio = (float)width / height;
}
void NeedUpdate() { bNeedsUpdate = true; }
@ -501,6 +327,7 @@ protected:
bool bNeedsUpdate = true;
public:
bool bFirstUpdate = true;
float aspectRatio;
friend struct FCanvasTextureInfo;
};
@ -514,7 +341,7 @@ public:
FWrapperTexture(int w, int h, int bits = 1);
IHardwareTexture *GetSystemTexture()
{
return SystemTextures.GetHardwareTexture(0, false);
return SystemTextures.GetHardwareTexture(0, 0);
}
int GetColorFormat() const
@ -527,14 +354,19 @@ public:
class FImageTexture : public FTexture
{
FImageSource* mImage;
bool bNoRemap0 = false;
protected:
void SetFromImage();
public:
FImageTexture(FImageSource* image, const char* name = nullptr) noexcept;
FImageTexture(FImageSource* image) noexcept;
virtual TArray<uint8_t> Get8BitPixels(bool alphatex);
void SetImage(FImageSource* img) // This is only for the multipatch texture builder!
void SetImage(FImageSource* img)
{
mImage = img;
SetFromImage();
}
void SetNoRemap0() { bNoRemap0 = true; }
FImageSource* GetImage() const override { return mImage; }
FBitmap GetBgraBitmap(const PalEntry* p, int* trans) override;
@ -542,24 +374,8 @@ public:
};
struct FTexCoordInfo
{
int mRenderWidth;
int mRenderHeight;
int mWidth;
FVector2 mScale;
FVector2 mTempScale;
bool mWorldPanning;
float FloatToTexU(float v) const { return v / mRenderWidth; }
float FloatToTexV(float v) const { return v / mRenderHeight; }
float RowOffset(float ofs) const;
float TextureOffset(float ofs) const;
float TextureAdjustWidth() const;
void GetFromTexture(FTexture *tex, float x, float y, bool forceworldpanning);
};
#include "gametexture.h"
#endif

View file

@ -86,7 +86,7 @@ static bool TabbedList; // True if tab list was shown
CVAR(Bool, con_notablist, false, CVAR_ARCHIVE)
static FTexture* conback;
static FGameTexture* conback;
static uint32_t conshade;
static bool conline;

View file

@ -316,7 +316,7 @@ bool FListMenuItem::Selectable()
return false;
}
void FListMenuItem::DrawSelector(int xofs, int yofs, FTexture *tex)
void FListMenuItem::DrawSelector(int xofs, int yofs, FGameTexture *tex)
{
if (!tex)
{
@ -399,7 +399,7 @@ int FListMenuItem::GetWidth()
//
//=============================================================================
FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FTexture *patch, bool centered)
FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FGameTexture *patch, bool centered)
: FListMenuItem(x, y)
{
mTexture = patch;
@ -414,7 +414,7 @@ void FListMenuItemStaticPatch::Drawer(DListMenu* menu, const DVector2& origin, b
}
int x = mXpos;
FTexture *tex = mTexture;
FGameTexture *tex = mTexture;
if (mYpos >= 0)
{
if (mCentered) x -= tex->GetDisplayWidth()/2;
@ -631,7 +631,7 @@ int FListMenuItemNativeText::GetWidth()
//
//=============================================================================
FListMenuItemPatch::FListMenuItemPatch(int x, int y, int height, int hotkey, FTexture *patch, FName child, int param)
FListMenuItemPatch::FListMenuItemPatch(int x, int y, int height, int hotkey, FGameTexture *patch, FName child, int param)
: FListMenuItemSelectable(x, y, height, child, param)
{
mHotkey = hotkey;

View file

@ -270,7 +270,7 @@ bool DMenu::MouseEventBack(int type, int x, int y)
auto texid = TexMan.CheckForTexture("engine/graphics/m_back.png", ETextureType::Any);
if (texid.isValid())
{
auto tex = TexMan.GetTexture(texid);
auto tex = TexMan.GetGameTexture(texid);
if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetDisplayWidth() * CleanXfac;
if (m_show_backbutton&2) y -= screen->GetHeight() - tex->GetDisplayHeight() * CleanYfac;
mBackbuttonSelected = ( x >= 0 && x < tex->GetDisplayWidth() * CleanXfac &&
@ -327,7 +327,7 @@ void DMenu::Drawer ()
auto texid = TexMan.CheckForTexture("engine/graphics/m_back.png", ETextureType::Any);
if (texid.isValid())
{
auto tex = TexMan.GetTexture(texid);
auto tex = TexMan.GetGameTexture(texid);
int w = tex->GetDisplayWidth() * CleanXfac;
int h = tex->GetDisplayHeight() * CleanYfac;
int x = (!(m_show_backbutton & 1)) ? 0 : screen->GetWidth() - w;

View file

@ -107,7 +107,7 @@ enum EMenuSounds : int
EXTERN_CVAR(Bool, menu_sounds)
struct event_t;
class FTexture;
class FGameTexture;
class FFont;
enum EColorRange : int;
class FPlayerClass;
@ -196,7 +196,7 @@ struct FListMenuDescriptor : public FMenuDescriptor
int mSelectedItem;
int mSelectOfsX;
int mSelectOfsY;
FTexture *mSelector;
FGameTexture *mSelector;
int mDisplayTop;
int mXpos, mYpos, mYbotton;
int mWLeft, mWRight;
@ -401,7 +401,7 @@ public:
virtual bool MouseEvent(int type, int x, int y);
virtual bool CheckHotkey(int c);
virtual int GetWidth();
virtual void DrawSelector(int xofs, int yofs, FTexture *tex);
virtual void DrawSelector(int xofs, int yofs, FGameTexture *tex);
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
int GetY() { return mYpos; }
int GetX() { return mXpos; }
@ -414,11 +414,11 @@ public:
class FListMenuItemStaticPatch : public FListMenuItem
{
protected:
FTexture *mTexture;
FGameTexture *mTexture;
bool mCentered;
public:
FListMenuItemStaticPatch(int x, int y, FTexture *patch, bool centered);
FListMenuItemStaticPatch(int x, int y, FGameTexture *patch, bool centered);
void Drawer(DListMenu* menu, const DVector2& origin, bool selected);
};
@ -496,15 +496,15 @@ public:
~FListMenuItemNativeText();
void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override;
int GetWidth() override;
void DrawSelector(int xofs, int yofs, FTexture* tex) override { } // The text drawer handles this itself.
void DrawSelector(int xofs, int yofs, FGameTexture* tex) override { } // The text drawer handles this itself.
};
class FListMenuItemPatch : public FListMenuItemSelectable
{
FTexture* mTexture;
FGameTexture* mTexture;
public:
FListMenuItemPatch(int x, int y, int height, int hotkey, FTexture* patch, FName child, int param = 0);
FListMenuItemPatch(int x, int y, int height, int hotkey, FGameTexture* patch, FName child, int param = 0);
void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override;
int GetWidth() override;
};
@ -806,7 +806,7 @@ private:
int LastSaved = -1;
int LastAccessed = -1;
TArray<char> SavePicData;
FTexture *SavePic = nullptr;
FGameTexture *SavePic = nullptr;
public:
int WindowSize = 0;

View file

@ -104,7 +104,7 @@ void M_DeinitMenus()
DefaultListMenuSettings.mItems.Clear();
}
static FTexture* GetMenuTexture(const char* const name)
static FGameTexture* GetMenuTexture(const char* const name)
{
auto texid = TexMan.CheckForTexture(name, ETextureType::Any);
if (!texid.isValid())
@ -112,7 +112,7 @@ static FTexture* GetMenuTexture(const char* const name)
Printf("Missing menu texture: \"%s\"\n", name);
}
return TexMan.GetTexture(texid);
return TexMan.GetGameTexture(texid);
}
//=============================================================================
@ -370,7 +370,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
int y = sc.Number;
sc.MustGetStringName(",");
sc.MustGetString();
FTexture* tex = GetMenuTexture(sc.String);
auto tex = GetMenuTexture(sc.String);
FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered);
desc->mItems.Push(it);
@ -401,7 +401,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc)
else if (sc.Compare("PatchItem"))
{
sc.MustGetString();
FTexture* tex = GetMenuTexture(sc.String);
auto tex = GetMenuTexture(sc.String);
sc.MustGetStringName(",");
sc.MustGetString();
int hotkey = sc.String[0];

View file

@ -330,7 +330,7 @@ void DTextEnterMenu::Drawer ()
int width;
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
FTexture *pic = displayFont->GetChar(ch, CR_DARKGRAY, &width);
auto pic = displayFont->GetChar(ch, CR_DARKGRAY, &width);
EColorRange color;
int remap;

View file

@ -169,9 +169,9 @@ void FGLRenderer::EndOffscreen()
//
//===========================================================================
void FGLRenderer::BindToFrameBuffer(FTexture *mat)
void FGLRenderer::BindToFrameBuffer(FGameTexture *mat)
{
auto pBaseLayer = mat->SystemTextures.GetHardwareTexture(0, false);
auto pBaseLayer = mat->GetTexture()->SystemTextures.GetHardwareTexture(0, false);
auto BaseLayer = pBaseLayer ? (::FHardwareTexture*)pBaseLayer : nullptr;
if (BaseLayer == nullptr)
@ -179,7 +179,7 @@ void FGLRenderer::BindToFrameBuffer(FTexture *mat)
// must create the hardware texture first
BaseLayer = new ::FHardwareTexture;
BaseLayer->CreateTexture(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4, ::FHardwareTexture::TrueColor, false);
mat->SystemTextures.AddHardwareTexture(0, false, BaseLayer);
mat->GetTexture()->SystemTextures.AddHardwareTexture(0, false, BaseLayer);
}
BaseLayer->BindToFrameBuffer(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4);
}

View file

@ -88,7 +88,7 @@ public:
bool StartOffscreen();
void EndOffscreen();
void BindToFrameBuffer(FTexture* tex);
void BindToFrameBuffer(FGameTexture* tex);
private:

View file

@ -108,7 +108,7 @@ TArray<uint8_t> FTileTexture::CreatePalettedPixels(int conversion)
//
//==========================================================================
static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
static FGameTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
{
auto tex = new FArtTile(backingstore, offset, width, height);
auto p = &backingstore[offset];
@ -122,7 +122,7 @@ static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backing
if (tex)
{
return new FImageTexture(tex, name);
return MakeGameTexture(new FImageTexture(tex), name, ETextureType::Any);
}
return nullptr;
}
@ -130,7 +130,7 @@ static FTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backing
void BuildTiles::Init()
{
Placeholder = TexMan.ByIndex(0);
Placeholder = TexMan.GameByIndex(0);
for (auto& tile : tiledata)
{
tile.texture = Placeholder;
@ -138,6 +138,7 @@ void BuildTiles::Init()
tile.picanm = {};
tile.RotTile = { -1,-1 };
tile.replacement = ReplacementType::Art;
tile.NoBrightmapFlag.Zero();
}
}
@ -147,10 +148,10 @@ void BuildTiles::Init()
//
//==========================================================================
void BuildTiles::AddTile(int tilenum, FTexture* tex, bool permap)
void BuildTiles::AddTile(int tilenum, FGameTexture* tex, bool permap)
{
assert(!tex->GetID().isValid()); // must not be added yet.
TexMan.AddTexture(tex);
TexMan.AddGameTexture(tex);
tiledata[tilenum].texture = tex;
if (!permap) tiledata[tilenum].backup = tex;
}
@ -300,12 +301,12 @@ void BuildTiles::InvalidateTile(int num)
if ((unsigned) num < MAXTILES)
{
auto tex = tiledata[num].texture;
tex->SystemTextures.Clean(true, true);
tex->GetTexture()->SystemTextures.Clean();
for (auto &rep : tiledata[num].Hightiles)
{
for (auto &reptex : rep.faces)
{
if (reptex) reptex->SystemTextures.Clean(true, true);
if (reptex) reptex->GetTexture()->SystemTextures.Clean();
}
}
tiledata[num].rawCache.data.Clear();
@ -404,7 +405,7 @@ void BuildTiles::LoadArtSet(const char* filename)
//
//==========================================================================
FTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
FGameTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
{
if (tilenum < 0 || tilenum >= MAXTILES) return nullptr;
auto &td = tiledata[tilenum];
@ -435,15 +436,16 @@ FTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
// All of these effects should probably be redone without actual texture hacking...
if (tile->GetTexelWidth() == 0 || tile->GetTexelHeight() == 0) return nullptr; // The base must have a size for this to work.
// todo: invalidate hardware textures for tile.
replacement = new FImageTexture(new FRestorableTile(tile->GetImage()));
replacement = new FImageTexture(new FRestorableTile(tile->GetTexture()->GetImage()));
}
else if (type == ReplacementType::Canvas)
{
replacement = new FCanvasTexture("camera", 0, 0);
replacement = new FCanvasTexture(0, 0);
}
else return nullptr;
AddTile(tilenum, replacement);
return replacement;
auto reptex = MakeGameTexture(replacement, "", ETextureType::Any);
AddTile(tilenum, reptex);
return reptex;
}
//==========================================================================
@ -470,7 +472,7 @@ uint8_t* BuildTiles::tileCreate(int tilenum, int width, int height)
if (width <= 0 || height <= 0) return nullptr;
auto tex = ValidateCustomTile(tilenum, ReplacementType::Writable);
if (tex == nullptr) return nullptr;
auto wtex = static_cast<FWritableTile*>(tex->GetImage());
auto wtex = static_cast<FWritableTile*>(tex->GetTexture()->GetImage());
if (!wtex->ResizeImage(width, height)) return nullptr;
tex->SetSize(width, height);
return wtex->GetRawData();
@ -486,7 +488,7 @@ uint8_t* BuildTiles::tileCreate(int tilenum, int width, int height)
uint8_t* BuildTiles::tileMakeWritable(int num)
{
auto tex = ValidateCustomTile(num, ReplacementType::Restorable);
auto wtex = static_cast<FWritableTile*>(tex->GetImage());
auto wtex = static_cast<FWritableTile*>(tex->GetTexture()->GetImage());
return wtex ? wtex->GetRawData() : nullptr;
}
@ -499,7 +501,7 @@ uint8_t* BuildTiles::tileMakeWritable(int num)
int32_t tileGetCRC32(int tileNum)
{
if ((unsigned)tileNum >= (unsigned)MAXTILES) return 0;
auto tile = dynamic_cast<FArtTile*>(TileFiles.tiledata[tileNum].texture->GetImage()); // only consider original ART tiles.
auto tile = dynamic_cast<FArtTile*>(TileFiles.tiledata[tileNum].texture->GetTexture()->GetImage()); // only consider original ART tiles.
if (!tile) return 0;
auto pixels = tile->GetRawData();
if (!pixels) return 0;
@ -541,7 +543,7 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu
{
FTextureID texid = TexMan.CheckForTexture(fn, ETextureType::Any);
if (!texid.isValid()) return -1;
auto tex = TexMan.GetTexture(texid);
auto tex = TexMan.GetGameTexture(texid);
//tex->alphaThreshold = 255 - alphacut;
int32_t xsiz = tex->GetTexelWidth(), ysiz = tex->GetTexelHeight();
@ -573,7 +575,7 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
picanm_t* picanm = nullptr;
picanm_t* sourceanm = nullptr;
int srcxo, srcyo;
FTexture* tex;
FGameTexture* tex;
if (pal == -1 && tile == source)
{
@ -594,7 +596,7 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
srcxo = tex->GetTexelLeftOffset(0);
srcyo = tex->GetTexelTopOffset(0);
TArray<uint8_t> buffer = tex->Get8BitPixels(false);
TArray<uint8_t> buffer = tex->GetTexture()->Get8BitPixels(false);
if (pal != -1)
{
@ -604,7 +606,7 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
pixel = remap[pixel];
}
}
tex = new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight()));
tex = MakeGameTexture(new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight())), "", ETextureType::Any);
picanm = &TileFiles.tiledata[tile].picanm;
TileFiles.AddTile(tile, tex);
}
@ -656,7 +658,7 @@ void artSetupMapArt(const char* filename)
auto texid = TexMan.CheckForTexture(name, ETextureType::Any);
if (texid.isValid())
{
TileFiles.tiledata[i].texture = TexMan.GetTexture(texid);
TileFiles.tiledata[i].texture = TexMan.GetGameTexture(texid);
}
}
return;
@ -691,7 +693,7 @@ void artSetupMapArt(const char* filename)
void tileDelete(int tile)
{
TileFiles.TextureToTile.Remove(tileGetTexture(tile));
TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.ByIndex(0);
TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.GameByIndex(0);
vox_undefine(tile);
md_undefinetile(tile);
tileRemoveReplacement(tile);
@ -723,7 +725,7 @@ void tileSetDummy(int tile, int width, int height)
}
else if (width > 0 && height > 0)
{
auto dtile = new FImageTexture(new FDummyTile(width, height));
auto dtile = MakeGameTexture(new FImageTexture(new FDummyTile(width, height)), "", ETextureType::Any);
TileFiles.AddTile(tile, dtile);
}
}
@ -760,7 +762,7 @@ int BuildTiles::tileCreateRotated(int tileNum)
if ((unsigned)tileNum >= MAXTILES) return tileNum;
auto tex = tileGetTexture(tileNum);
if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return tileNum;
TArray<uint8_t> buffer = tex->Get8BitPixels(false);
TArray<uint8_t> buffer = tex->GetTexture()->Get8BitPixels(false);
TArray<uint8_t> dbuffer(tex->GetTexelWidth() * tex->GetTexelHeight(), true);
auto src = buffer.Data();
@ -777,7 +779,7 @@ int BuildTiles::tileCreateRotated(int tileNum)
*(dst + y * width + xofs) = *(src + y + yofs);
}
auto dtex = new FImageTexture(new FLooseTile(dbuffer, tex->GetTexelHeight(), tex->GetTexelWidth()));
auto dtex = MakeGameTexture(new FImageTexture(new FLooseTile(dbuffer, tex->GetTexelHeight(), tex->GetTexelWidth())), "", ETextureType::Any);
int index = findUnusedTile();
bool mapart = TileFiles.tiledata[tileNum].texture != TileFiles.tiledata[tileNum].backup;
TileFiles.AddTile(index, dtex, mapart);
@ -821,7 +823,7 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo
return -1;
}
replace.faces[0] = TexMan.GetTexture(texid);
replace.faces[0] = TexMan.GetGameTexture(texid);
if (replace.faces[0] == nullptr)
replace.alphacut = min(alphacut,1.f);
replace.scale = { xscale, yscale };
@ -861,7 +863,7 @@ int tileSetSkybox(int picnum, int palnum, const char **facenames, int flags )
Printf("%s: Skybox image for tile %d does not exist or is invalid\n", *facenames, picnum);
return -1;
}
face = TexMan.GetTexture(texid);
face = TexMan.GetGameTexture(texid);
}
replace.flags = flags;
replace.palnum = (uint16_t)palnum;

View file

@ -62,7 +62,7 @@ struct rottile_t
struct HightileReplacement
{
FTexture* faces[6]; // only one gets used by a texture, the other 5 are for skyboxes only
FGameTexture* faces[6]; // only one gets used by a texture, the other 5 are for skyboxes only
vec2f_t scale;
float alphacut, specpower, specfactor;
uint16_t palnum, flags;
@ -257,23 +257,24 @@ struct RawCacheNode
struct TileDesc
{
FTexture* texture; // the currently active tile
FTexture* backup; // original backup for map tiles
FGameTexture* texture; // the currently active tile
FGameTexture* backup; // original backup for map tiles
RawCacheNode rawCache; // this is needed for hitscan testing to avoid reloading the texture each time.
picanm_t picanm; // animation descriptor
picanm_t picanmbackup; // animation descriptor backup when using map tiles
rottile_t RotTile;// = { -1,-1 };
TArray<HightileReplacement> Hightiles;
ReplacementType replacement;
FixedBitArray<256> NoBrightmapFlag;
};
struct BuildTiles
{
FTexture* Placeholder;
FGameTexture* Placeholder;
TDeletingArray<BuildArtFile*> ArtFiles;
TileDesc tiledata[MAXTILES];
TArray<FString> addedArt;
TMap<FTexture*, int> TextureToTile;
TMap<FGameTexture*, int> TextureToTile;
TArray<FString> maptilesadded;
void Init(); // This cannot be a constructor because it needs the texture manager running.
@ -284,7 +285,7 @@ struct BuildTiles
void CloseAll();
void AddTile(int tilenum, FTexture* tex, bool permap = false);
void AddTile(int tilenum, FGameTexture* tex, bool permap = false);
void AddTiles(int firsttile, TArray<uint8_t>& store, const char* mapname);
@ -302,7 +303,7 @@ struct BuildTiles
{
addedArt = std::move(art);
}
int GetTileIndex(FTexture* tex)
int GetTileIndex(FGameTexture* tex)
{
auto p = TextureToTile.CheckKey(tex);
return p ? *p : -1;
@ -317,14 +318,12 @@ struct BuildTiles
}
}
FTexture* ValidateCustomTile(int tilenum, ReplacementType type);
FGameTexture* ValidateCustomTile(int tilenum, ReplacementType type);
int32_t artLoadFiles(const char* filename);
uint8_t* tileMakeWritable(int num);
uint8_t* tileCreate(int tilenum, int width, int height);
void tileSetExternal(int tilenum, int width, int height, uint8_t* data);
int findUnusedTile(void);
int tileCreateRotated(int owner);
void ClearTextureCache(bool artonly = false);
void InvalidateTile(int num);
void MakeCanvas(int tilenum, int width, int height);
HightileReplacement* FindReplacement(int picnum, int palnum, bool skybox = false);
@ -367,7 +366,7 @@ inline const uint8_t* tilePtr(int num)
{
auto tex = TileFiles.tiledata[num].texture;
if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return nullptr;
TileFiles.tiledata[num].rawCache.data = std::move(tex->Get8BitPixels(false));
TileFiles.tiledata[num].rawCache.data = std::move(tex->GetTexture()->Get8BitPixels(false));
}
TileFiles.tiledata[num].rawCache.lastUseTime = I_nsTime();
return TileFiles.tiledata[num].rawCache.data.Data();
@ -381,7 +380,7 @@ inline bool tileLoad(int tileNum)
inline uint8_t* tileData(int num)
{
auto tex = TileFiles.tiledata[num].texture;
auto p = dynamic_cast<FWritableTile*>(tex);
auto p = dynamic_cast<FWritableTile*>(tex->GetTexture());
return p ? p->GetRawData() : nullptr;
}
@ -464,7 +463,7 @@ inline void tileInvalidate(int tilenume, int32_t, int32_t)
TileFiles.InvalidateTile(tilenume);
}
inline FTexture* tileGetTexture(int tile)
inline FGameTexture* tileGetTexture(int tile)
{
assert(tile < MAXTILES);
return TileFiles.tiledata[tile].texture;

View file

@ -66,11 +66,11 @@ void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch)
//
//===========================================================================
FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex)
FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex)
{
vec2_t siz = { tex->GetTexelWidth(), tex->GetTexelHeight() };
auto store = tex->Get8BitPixels(false);
auto store = tex->GetTexture()->Get8BitPixels(false);
const uint8_t* p = store.Data();
auto glpic = GLInterface.NewTexture();
@ -88,9 +88,9 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex)
//
//===========================================================================
FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
{
auto texbuffer = tex->CreateTexBuffer(palid, checkfulltransparency? 0: CTF_ProcessData);
auto texbuffer = tex->GetTexture()->CreateTexBuffer(palid, checkfulltransparency? 0: CTF_ProcessData);
// Check if the texture is fully transparent. When creating a brightmap such textures can be discarded.
if (checkfulltransparency)
{
@ -122,21 +122,21 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, b
//
//===========================================================================
FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid)
{
if (textype == TT_INDEXED) palid = -1;
auto phwtex = tex->SystemTextures.GetHardwareTexture(palid, false);
auto phwtex = tex->GetTexture()->SystemTextures.GetHardwareTexture(palid, false);
if (phwtex) return (FHardwareTexture*)phwtex;
FHardwareTexture *hwtex = nullptr;
if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex);
else if (tex->GetUseType() != ETextureType::Canvas)
else if (!tex->GetTexture()->isHardwareCanvas())
hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP);
else
hwtex = nullptr;
if (hwtex) tex->SystemTextures.AddHardwareTexture(palid, false, hwtex);
if (hwtex) tex->GetTexture()->SystemTextures.AddHardwareTexture(palid, false, hwtex);
return hwtex;
}
@ -148,7 +148,7 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
struct TexturePick
{
FTexture* texture; // which texture to use
FGameTexture* texture; // which texture to use
int translation; // which translation table to use
int tintFlags; // which shader tinting options to use
PalEntry tintColor; // Tint color
@ -165,7 +165,7 @@ TexturePick PickTexture(int tilenum, int basepal, int palette)
auto tex = TileFiles.tiles[tilenum];
auto rep = (hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? TileFiles.FindReplacement(tilenum, usepalswap) : nullptr;
// Canvas textures must be treated like hightile replacements in the following code.
bool truecolor = rep || tex->GetUseType() == FTexture::Canvas;
bool truecolor = rep || tex->GetUseType() == FGameTexture::Canvas;
bool applytint = false;
if (truecolor)
{
@ -203,7 +203,7 @@ TexturePick PickTexture(int tilenum, int basepal, int palette)
}
#endif
bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int method, int sampleroverride, FTexture *det, float detscale, FTexture *glow)
bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int palette, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow)
{
if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false;
int usepalette = fixpalette >= 0 ? fixpalette : curbasepal;
@ -225,7 +225,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
// Canvas textures must be treated like hightile replacements in the following code.
if (picnum < 0) picnum = TileFiles.GetTileIndex(tex); // Allow getting replacements also when the texture is not passed by its tile number.
auto rep = (picnum >= 0 && hw_hightile && !(h.f & HICTINT_ALWAYSUSEART)) ? TileFiles.FindReplacement(picnum, palette) : nullptr;
if (rep || tex->GetUseType() == ETextureType::Canvas)
if (rep || tex->GetTexture()->isHardwareCanvas())
{
if (usepalette != 0)
{
@ -338,7 +338,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
}
}
#if 1
if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT) && !tex->NoBrightmapFlag[usepalswap])
if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT) && !TileFiles.tiledata[picnum].NoBrightmapFlag[usepalswap])
{
if (TextureType == TT_HICREPLACE)
{
@ -364,7 +364,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
if (htex == nullptr)
{
// Flag the texture as not being brightmapped for the given palette
tex->NoBrightmapFlag.Set(usepalswap);
TileFiles.tiledata[picnum].NoBrightmapFlag.Set(usepalswap);
}
else
{
@ -400,7 +400,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
//
//===========================================================================
bool GLInstance::SetNamedTexture(FTexture* tex, int palette, int sampler)
bool GLInstance::SetNamedTexture(FGameTexture* tex, int palette, int sampler)
{
auto mtex = LoadTexture(tex, palette>= 0? TT_TRUECOLOR : TT_HICREPLACE, palette);
if (!mtex) return false;
@ -417,11 +417,6 @@ int PalCheck(int tex)
return tex;
}
void DeleteSoftwareTexture(FSoftwareTexture *)
{
}
void InitBuildTiles()
{

View file

@ -14,7 +14,7 @@ class FSamplerManager;
class FShader;
class PolymostShader;
class SurfaceShader;
class FTexture;
class FGameTexture;
class GLInstance;
class F2DDrawer;
struct palette_t;
@ -115,7 +115,7 @@ class GLInstance
PaletteManager palmanager;
int lastPalswapIndex = -1;
FHardwareTexture* texv;
FTexture* currentTexture = nullptr;
FGameTexture* currentTexture = nullptr;
int TextureType;
int MatrixChange = 0;
@ -474,19 +474,19 @@ public:
renderState.AlphaThreshold = al;
}
FHardwareTexture* CreateIndexedTexture(FTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride, FTexture *det, float detscale, FTexture *glow);
FHardwareTexture* CreateIndexedTexture(FGameTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow);
bool SetNamedTexture(FTexture* tex, int palette, int sampleroverride);
bool SetNamedTexture(FGameTexture* tex, int palette, int sampleroverride);
bool SetTexture(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride)
bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride)
{
return SetTextureInternal(globalpicnum, tex, palette, method, sampleroverride, nullptr, 1, nullptr);
}
bool SetModelTexture(FTexture *tex, int palette, FTexture *det, float detscale, FTexture *glow)
bool SetModelTexture(FGameTexture *tex, int palette, FGameTexture *det, float detscale, FGameTexture *glow)
{
return SetTextureInternal(-1, tex, palette, 8/*DAMETH_MODEL*/, -1, det, detscale, glow);
}

View file

@ -63,8 +63,8 @@ TArray<FString> I_GetGogPaths();
// The ini could not be saved at exit
bool I_WriteIniFailed ();
class FTexture;
bool I_SetCursor(FTexture *);
class FGameTexture;
bool I_SetCursor(FGameTexture *);
static inline char *strlwr(char *str)
{

View file

@ -38,14 +38,14 @@
#include "bitmap.h"
#include "textures.h"
bool I_SetCursor(FTexture *cursorpic)
bool I_SetCursor(FGameTexture *cursorpic)
{
static SDL_Cursor *cursor;
static SDL_Surface *cursorSurface;
if (cursorpic != NULL)
{
auto src = cursorpic->GetBgraBitmap(nullptr);
auto src = cursorpic->GetTexture()->GetBgraBitmap(nullptr);
// Must be no larger than 32x32.
if (src.GetWidth() > 32 || src.GetHeight() > 32)
{

View file

@ -646,13 +646,13 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad)
//
//==========================================================================
bool I_SetCursor(FTexture *cursorpic)
bool I_SetCursor(FGameTexture *cursorpic)
{
HCURSOR cursor;
if (cursorpic != NULL)
{
auto image = cursorpic->GetBgraBitmap(nullptr);
auto image = cursorpic->GetTexture()->GetBgraBitmap(nullptr);
// Must be no larger than 32x32. (is this still necessary?
if (image.GetWidth() > 32 || image.GetHeight() > 32)
{

View file

@ -62,8 +62,8 @@ void I_Quit (void);
void I_Tactile (int on, int off, int total);
// Set the mouse cursor. The texture must be 32x32.
class FTexture;
bool I_SetCursor(FTexture *cursor);
class FGameTexture;
bool I_SetCursor(FGameTexture *cursor);
// Repaint the pre-game console
void I_PaintConsole (void);