- 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,213 +383,11 @@ static int32_t defsparser(scriptfile *script)
break; break;
case T_TILEFROMTEXTURE: case T_TILEFROMTEXTURE:
{ parseTileFromTexture(*script, pos);
auto texturepos = scriptfile_getposition(script); break;
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);
}
break;
case T_COPYTILE: case T_COPYTILE:
{ parseCopyTile(*script, pos);
FScanner::SavedPos blockend; break;
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);
}
break;
case T_IMPORTTILE: case T_IMPORTTILE:
{ {
int32_t tile; int32_t tile;

View file

@ -122,6 +122,13 @@ public:
return true; return true;
} }
bool GetNumber(int64_t& var, bool evaluate = false)
{
if (!GetNumber(evaluate)) return false;
var = BigNumber;
return true;
}
bool GetString(FString& var) bool GetString(FString& var)
{ {
if (!GetString()) return false; 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) void parseDefineSkybox(FScanner& sc, FScriptPosition& pos)
{ {
int tile, palette; 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) 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* picanm = nullptr;
picanm_t* sourceanm = nullptr; picanm_t* sourceanm = nullptr;
int srcxo, srcyo; 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) if (imp.sizex != INT_MAX && tileWidth(imp.tile) != imp.sizex && tileHeight(imp.tile) != imp.sizey)
return; return;
imp.alphacut = clamp(imp.alphacut, 0, 255);
gi->SetTileProps(imp.tile, imp.surface, imp.vox, imp.shade); 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; 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. // 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. // 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); 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); if (imp.yoffset == INT_MAX) imp.yoffset = tileTopOffset(imp.tile);
else imp.yoffset = clamp(imp.yoffset, -128, 127);
auto tex = tileGetTexture(imp.tile); 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; if (imp.extra != INT_MAX) TileFiles.tiledata[imp.tile].picanm.extra = imp.extra;
} }