- tileimportfromtexture and copytile.

This commit is contained in:
Christoph Oelckers 2021-04-13 18:17:28 +02:00
parent 97637e4d2d
commit 8c5a9c23c3
4 changed files with 133 additions and 209 deletions

View file

@ -383,212 +383,10 @@ static int32_t defsparser(scriptfile *script)
break;
case T_TILEFROMTEXTURE:
{
auto texturepos = scriptfile_getposition(script);
FScanner::SavedPos textureend;
TileImport imp;
static const tokenlist tilefromtexturetokens[] =
{
{ "file", T_FILE },
{ "name", T_FILE },
{ "alphacut", T_ALPHACUT },
{ "xoffset", T_XOFFSET },
{ "xoff", T_XOFFSET },
{ "yoffset", T_YOFFSET },
{ "yoff", T_YOFFSET },
{ "texhitscan", T_TEXHITSCAN },
{ "nofullbright", T_NOFULLBRIGHT },
{ "texture", T_TEXTURE },
{ "ifcrc", T_IFCRC },
{ "ifmatch", T_IFMATCH },
{ "extra", T_EXTRA },
// Blood also defines these.
{ "surface", T_SURFACE },
{ "voxel", T_VOXEL },
{ "view", T_VIEW },
{ "shade", T_SHADE },
};
if (scriptfile_getsymbol(script,&imp.tile)) break;
if (scriptfile_getbraces(script,&textureend)) break;
while (!scriptfile_endofblock(script, textureend))
{
int32_t token = getatoken(script,tilefromtexturetokens,countof(tilefromtexturetokens));
switch (token)
{
case T_FILE:
scriptfile_getstring(script,&imp.fn);
break;
case T_ALPHACUT:
scriptfile_getsymbol(script,&imp.alphacut);
imp.alphacut = clamp(imp.alphacut, 0, 255);
break;
case T_XOFFSET:
scriptfile_getsymbol(script,&imp.xoffset);
imp.xoffset = clamp(imp.xoffset, -128, 127);
break;
case T_YOFFSET:
scriptfile_getsymbol(script,&imp.yoffset);
imp.yoffset = clamp(imp.yoffset, -128, 127);
break;
case T_IFCRC:
scriptfile_getsymbol(script, &imp.crc32);
break;
case T_IFMATCH:
{
FScanner::SavedPos ifmatchend;
static const tokenlist ifmatchtokens[] =
{
{ "crc32", T_CRC32 },
{ "size", T_SIZE },
};
if (scriptfile_getbraces(script,&ifmatchend)) break;
while (!scriptfile_endofblock(script, ifmatchend))
{
int32_t token = getatoken(script,ifmatchtokens,countof(ifmatchtokens));
switch (token)
{
case T_CRC32:
scriptfile_getsymbol(script, &imp.crc32);
break;
case T_SIZE:
scriptfile_getsymbol(script, &imp.sizex);
scriptfile_getsymbol(script, &imp.sizey);
break;
default:
break;
}
}
break;
}
case T_TEXHITSCAN:
imp.flags |= PICANM_TEXHITSCAN_BIT;
break;
case T_NOFULLBRIGHT:
imp.flags |= PICANM_NOFULLBRIGHT_BIT;
break;
case T_TEXTURE:
imp.istexture = 1;
break;
case T_EXTRA:
scriptfile_getsymbol(script, &imp.extra);
break;
case T_SURFACE:
scriptfile_getsymbol(script, &imp.surface);
break;
case T_VOXEL:
scriptfile_getsymbol(script, &imp.vox);
break;
case T_VIEW:
scriptfile_getsymbol(script, &imp.extra);
imp.extra &= 7;
break;
case T_SHADE:
scriptfile_getsymbol(script, &imp.shade);
break;
default:
break;
}
}
processTileImport("tileimporttexture", pos, imp);
}
parseTileFromTexture(*script, pos);
break;
case T_COPYTILE:
{
FScanner::SavedPos blockend;
int32_t tile = -1, source;
int32_t havetile = 0, havexoffset = 0, haveyoffset = 0;
int32_t xoffset = -1024, yoffset = -1024;
int32_t flags = 0;
int32_t tsiz = 0;
int32_t temppal = -1;
int32_t tempsource = -1;
static const tokenlist copytiletokens[] =
{
{ "tile", T_TILE },
{ "pal", T_PAL },
{ "xoffset", T_XOFFSET },
{ "xoff", T_XOFFSET },
{ "yoffset", T_YOFFSET },
{ "yoff", T_YOFFSET },
{ "texhitscan", T_TEXHITSCAN },
{ "nofullbright", T_NOFULLBRIGHT },
};
if (scriptfile_getsymbol(script,&tile)) break;
source = tile; // without a "tile" token, we still palettize self by default
if (scriptfile_getbraces(script,&blockend)) break;
while (!scriptfile_endofblock(script, blockend))
{
int32_t token = getatoken(script,copytiletokens,countof(copytiletokens));
switch (token)
{
case T_TILE:
{
scriptfile_getsymbol(script,&tempsource);
if (check_tile("copytile", tempsource, script, pos))
break;
source = tempsource;
havetile = 1;
break;
}
case T_PAL:
{
scriptfile_getsymbol(script,&temppal);
// palettize self case
if (!havetile)
{
if (check_tile("copytile", source, script, pos))
break;
havetile = 1;
}
if ((unsigned)temppal >= MAXPALOOKUPS-RESERVEDPALS)
{
pos.Message(MSG_ERROR, "copytile 'palette number' out of range (max=%d)\n",
MAXPALOOKUPS-RESERVEDPALS-1);
break;
}
break;
}
case T_XOFFSET:
havexoffset = 1;
scriptfile_getsymbol(script,&xoffset); break;
case T_YOFFSET:
haveyoffset = 1;
scriptfile_getsymbol(script,&yoffset); break;
case T_TEXHITSCAN:
flags |= PICANM_TEXHITSCAN_BIT;
break;
case T_NOFULLBRIGHT:
flags |= PICANM_NOFULLBRIGHT_BIT;
break;
default:
break;
}
}
if (check_tile("copytile", tile, script, pos))
break;
if (!havetile)
{
// if !havetile, we have never confirmed a valid source
if (check_tile("copytile", source, script, pos))
break;
}
tileCopy(tile, tempsource, temppal, xoffset, yoffset, flags);
}
parseCopyTile(*script, pos);
break;
case T_IMPORTTILE:
{

View file

@ -122,6 +122,13 @@ public:
return true;
}
bool GetNumber(int64_t& var, bool evaluate = false)
{
if (!GetNumber(evaluate)) return false;
var = BigNumber;
return true;
}
bool GetString(FString& var)
{
if (!GetString()) return false;

View file

@ -207,6 +207,116 @@ void parseTexture(FScanner& sc, FScriptPosition& pos)
//
//===========================================================================
void parseTileFromTexture(FScanner& sc, FScriptPosition& pos)
{
FScanner::SavedPos blockend;
TileImport imp;
if (!sc.GetNumber(imp.tile, true)) return;
if (sc.StartBraces(&blockend)) return;
while (!sc.FoundEndBrace(blockend))
{
sc.MustGetString();
if (sc.Compare({ "file", "name" })) sc.GetString(imp.fn);
else if (sc.Compare("alphacut")) sc.GetNumber(imp.alphacut, true);
else if (sc.Compare({ "xoff", "xoffset" })) sc.GetNumber(imp.xoffset, true);
else if (sc.Compare({ "yoff", "yoffset" })) sc.GetNumber(imp.yoffset, true);
else if (sc.Compare("texhitscan")) imp.flags |= PICANM_TEXHITSCAN_BIT;
else if (sc.Compare("nofullbright")) imp.flags |= PICANM_NOFULLBRIGHT_BIT;
else if (sc.Compare("texture")) imp.istexture = 1;
else if (sc.Compare("ifcrc")) sc.GetNumber(imp.crc32, true);
else if (sc.Compare("extra")) sc.GetNumber(imp.extra, true);
else if (sc.Compare("surface")) sc.GetNumber(imp.surface, true);
else if (sc.Compare("voxel")) sc.GetNumber(imp.vox, true);
else if (sc.Compare("shade")) sc.GetNumber(imp.shade, true);
else if (sc.Compare("view")) { sc.GetNumber(imp.extra, true); imp.extra &= 7; }
else if (sc.Compare("ifmatch"))
{
FScanner::SavedPos blockend2;
if (sc.StartBraces(&blockend2)) return;
while (!sc.FoundEndBrace(blockend2))
{
sc.MustGetString();
if (sc.Compare("size"))
{
sc.GetNumber(imp.sizex, true);
sc.GetNumber(imp.sizey, true);
}
else if (sc.Compare("crc32")) sc.GetNumber(imp.crc32, true);
}
}
}
processTileImport("tilefromtexture", pos, imp);
}
//===========================================================================
//
//
//
//===========================================================================
void parseCopyTile(FScanner& sc, FScriptPosition& pos)
{
FScanner::SavedPos blockend;
int tile = -1, source = -1;
int havetile = 0, xoffset = -1024, yoffset = -1024;
int flags = 0, tsiz = 0, temppal = -1, tempsource = -1;
if (!sc.GetNumber(tile, true)) return;
if (sc.StartBraces(&blockend)) return;
while (!sc.FoundEndBrace(blockend))
{
sc.MustGetString();
if (sc.Compare("tile"))
{
if (sc.GetNumber(tempsource, true))
{
if (ValidateTilenum("copytile", tempsource, pos))
{
source = tempsource;
havetile = true;
}
}
}
else if (sc.Compare("pal"))
{
// This is a bit messy because it doesn't wait until everything is parsed. Sadly that quirk needs to be replicated...
if (sc.GetNumber(temppal, true))
{
// palettize self case
if (!havetile)
{
if (ValidateTilenum("copytile", tile, pos)) havetile = true;
}
if ((unsigned)temppal >= MAXPALOOKUPS - RESERVEDPALS)
{
pos.Message(MSG_ERROR, "copytile 'palette number' out of range (max=%d)\n", MAXPALOOKUPS - RESERVEDPALS - 1);
break;
}
}
}
else if (sc.Compare({ "xoff", "xoffset" })) sc.GetNumber(xoffset, true);
else if (sc.Compare({ "yoff", "yoffset" })) sc.GetNumber(yoffset, true);
else if (sc.Compare("texhitscan")) flags |= PICANM_TEXHITSCAN_BIT;
else if (sc.Compare("nofullbright")) flags |= PICANM_NOFULLBRIGHT_BIT;
}
if (!ValidateTilenum("copytile", tile, pos)) return;
// if !havetile, we have never confirmed a valid source
if (!havetile && !ValidateTilenum("copytile", source, pos)) return;
tileCopy(tile, source, temppal, xoffset, yoffset, flags);
}
//===========================================================================
//
//
//
//===========================================================================
void parseDefineSkybox(FScanner& sc, FScriptPosition& pos)
{
int tile, palette;

View file

@ -527,8 +527,6 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu
void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags)
{
// Todo. Since I do not know if some mod needs this it's of low priority now.
// Let's get things working first.
picanm_t* picanm = nullptr;
picanm_t* sourceanm = nullptr;
int srcxo, srcyo;
@ -889,6 +887,8 @@ void processTileImport(const char *cmd, FScriptPosition& pos, TileImport& imp)
if (imp.sizex != INT_MAX && tileWidth(imp.tile) != imp.sizex && tileHeight(imp.tile) != imp.sizey)
return;
imp.alphacut = clamp(imp.alphacut, 0, 255);
gi->SetTileProps(imp.tile, imp.surface, imp.vox, imp.shade);
if (imp.fn.IsNotEmpty() && tileImportFromTexture(imp.fn, imp.tile, imp.alphacut, imp.istexture) < 0) return;
@ -898,10 +898,19 @@ void processTileImport(const char *cmd, FScriptPosition& pos, TileImport& imp)
// 1: Since these are texture properties now, there's no need to clear them.
// 2: The original code assumed that an imported texture cannot have an offset. But this can import Doom patches and PNGs with grAb, so the situation is very different.
if (imp.xoffset == INT_MAX) imp.xoffset = tileLeftOffset(imp.tile);
else imp.xoffset = clamp(imp.xoffset, -128, 127);
if (imp.yoffset == INT_MAX) imp.yoffset = tileTopOffset(imp.tile);
else imp.yoffset = clamp(imp.yoffset, -128, 127);
auto tex = tileGetTexture(imp.tile);
if (tex) tex->SetOffsets(imp.xoffset, imp.yoffset);
if (tex)
{
tex->SetOffsets(imp.xoffset, imp.yoffset);
if (imp.flags & PICANM_NOFULLBRIGHT_BIT)
{
tex->SetDisableBrightmap();
}
}
if (imp.extra != INT_MAX) TileFiles.tiledata[imp.tile].picanm.extra = imp.extra;
}