diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 3dd43706e..00769d57c 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -142,14 +142,6 @@ enum scripttoken_t T_SURFACE, T_VIEW, }; -static int32_t lastmodelid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0; - -static const char *skyfaces[6] = -{ - "front face", "right face", "back face", - "left face", "top face", "bottom face" -}; - static int32_t defsparser(scriptfile *script); static void defsparser_include(const char *fn, scriptfile *script, FScriptPosition *pos) @@ -433,416 +425,7 @@ static int32_t defsparser(scriptfile *script) // NEW (ENCOURAGED) DEFINITION SYNTAX case T_MODEL: - { - FScanner::SavedPos modelend; - FString modelfn; - double scale=1.0, mzadd=0.0, myoffset=0.0; - int32_t shadeoffs=0, pal=0, flags=0; - uint8_t usedframebitmap[(1024+7)>>3]; - - int32_t model_ok = 1; - - static const tokenlist modeltokens[] = - { - { "scale", T_SCALE }, - { "shade", T_SHADE }, - { "zadd", T_ZADD }, - { "yoffset", T_YOFFSET }, - { "frame", T_FRAME }, - { "anim", T_ANIM }, - { "skin", T_SKIN }, - { "detail", T_DETAIL }, - { "glow", T_GLOW }, - { "specular", T_SPECULAR }, - { "normal", T_NORMAL }, - { "hud", T_HUD }, - { "flags", T_FLAGS }, - }; - - memset(usedframebitmap, 0, sizeof(usedframebitmap)); - - modelskin = lastmodelskin = 0; - seenframe = 0; - - if (scriptfile_getstring(script,&modelfn)) break; - if (scriptfile_getbraces(script,&modelend)) break; - - lastmodelid = md_loadmodel(modelfn); - if (lastmodelid < 0) - { - Printf("Warning: Failed loading MD2/MD3 model \"%s\"\n", modelfn.GetChars()); - scriptfile_setposition(script, modelend); - break; - } - while (!scriptfile_endofblock(script, modelend)) - { - int32_t token = getatoken(script,modeltokens,countof(modeltokens)); - switch (token) - { - //case T_ERROR: Printf("Error on line %s:%d in model tokens\n", script->filename,script->linenum); break; - case T_SCALE: - scriptfile_getdouble(script,&scale); break; - case T_SHADE: - scriptfile_getnumber(script,&shadeoffs); break; - case T_ZADD: - scriptfile_getdouble(script,&mzadd); break; - case T_YOFFSET: - scriptfile_getdouble(script,&myoffset); break; - case T_FLAGS: - scriptfile_getnumber(script,&flags); break; - case T_FRAME: - { - auto framepos = scriptfile_getposition(script); - FScanner::SavedPos frameend; - FString framename; - char happy=1; - int32_t tilex = 0, framei; - int32_t ftilenume = -1, ltilenume = -1; - double smoothduration = 0.1f; - - static const tokenlist modelframetokens[] = - { - { "pal", T_PAL }, - { "frame", T_FRAME }, - { "name", T_FRAME }, - { "tile", T_TILE }, - { "tile0", T_TILE0 }, - { "tile1", T_TILE1 }, - { "smoothduration", T_SMOOTHDURATION }, - }; - - if (scriptfile_getbraces(script,&frameend)) break; - while (!scriptfile_endofblock(script, frameend)) - { - switch (getatoken(script,modelframetokens,countof(modelframetokens))) - { - case T_PAL: - scriptfile_getsymbol(script,&pal); break; - case T_FRAME: - scriptfile_getstring(script,&framename); break; - case T_TILE: - scriptfile_getsymbol(script,&ftilenume); ltilenume = ftilenume; break; - case T_TILE0: - scriptfile_getsymbol(script,&ftilenume); break; //first tile number - case T_TILE1: - scriptfile_getsymbol(script,<ilenume); break; //last tile number (inclusive) - case T_SMOOTHDURATION: - scriptfile_getdouble(script,&smoothduration); break; - } - } - - if (check_tile_range("model: frame", &ftilenume, <ilenume, script, pos)) - { - model_ok = 0; - break; - } - - if (lastmodelid < 0) - { - framepos.Message(MSG_WARNING, "ignoring frame definition"); - break; - } - - if (smoothduration > 1.0) - { - framepos.Message(MSG_WARNING, "smoothduration out of range"); - smoothduration = 1.0; - } - for (tilex = ftilenume; tilex <= ltilenume && happy; tilex++) - { - framei = md_defineframe(lastmodelid, framename, tilex, max(0,modelskin), smoothduration,pal); - switch (framei) - { - case -1: - happy = 0; break; // invalid model id!? - case -2: - framepos.Message(MSG_WARNING, "Invalid tile number"); - happy = 0; - break; - case -3: - framepos.Message(MSG_WARNING, "%s: Invalid frame name", framename.GetChars()); - happy = 0; - break; - default: - if (framei >= 0 && framei<1024) - usedframebitmap[framei>>3] |= (1 << (framei&7)); - } - model_ok &= happy; - } - seenframe = 1; - } - break; - case T_ANIM: - { - auto animpos = scriptfile_getposition(script); - FScanner::SavedPos animend; - FString startframe, endframe; - int happy=1; - int32_t flags = 0; - double dfps = 1.0; - - static const tokenlist modelanimtokens[] = - { - { "frame0", T_FRAME0 }, - { "frame1", T_FRAME1 }, - { "fps", T_FPS }, - { "flags", T_FLAGS }, - }; - - if (scriptfile_getbraces(script,&animend)) break; - while (!scriptfile_endofblock(script, animend)) - { - switch (getatoken(script,modelanimtokens,countof(modelanimtokens))) - { - case T_FRAME0: - scriptfile_getstring(script,&startframe); break; - case T_FRAME1: - scriptfile_getstring(script,&endframe); break; - case T_FPS: - scriptfile_getdouble(script,&dfps); break; //animation frame rate - case T_FLAGS: - scriptfile_getsymbol(script,&flags); break; - } - } - - if (startframe.IsEmpty()) animpos.Message(MSG_ERROR, "missing 'start frame' for anim definition"), happy = 0; - if (endframe.IsEmpty()) animpos.Message(MSG_ERROR, "missing 'end frame' for anim definition"), happy = 0; - model_ok &= happy; - if (!happy) break; - - if (lastmodelid < 0) - { - Printf("Warning: Ignoring animation definition.\n"); - break; - } - switch (md_defineanimation(lastmodelid, startframe, endframe, (int32_t)(dfps*(65536.0*.001)), flags)) - { - case 0: - break; - case -1: - break; // invalid model id!? - case -2: - pos.Message(MSG_ERROR, "Invalid starting frame name"); - model_ok = 0; - break; - case -3: - pos.Message(MSG_ERROR, "Invalid ending frame name"); - model_ok = 0; - break; - case -4: - pos.Message(MSG_ERROR, "Out of memory"); - model_ok = 0; - break; - } - } - break; - case T_SKIN: case T_DETAIL: case T_GLOW: case T_SPECULAR: case T_NORMAL: - { - auto skinpos = scriptfile_getposition(script); - FScanner::SavedPos skinend; - FString skinfn; - int32_t palnum = 0, surfnum = 0; - double param = 1.0, specpower = 1.0, specfactor = 1.0; - int32_t flags = 0; - - static const tokenlist modelskintokens[] = - { - { "pal", T_PAL }, - { "file", T_FILE }, - { "surf", T_SURF }, - { "surface", T_SURF }, - { "intensity", T_PARAM }, - { "scale", T_PARAM }, - { "detailscale", T_PARAM }, - { "specpower", T_SPECPOWER }, { "specularpower", T_SPECPOWER }, { "parallaxscale", T_SPECPOWER }, - { "specfactor", T_SPECFACTOR }, { "specularfactor", T_SPECFACTOR }, { "parallaxbias", T_SPECFACTOR }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - }; - - if (scriptfile_getbraces(script,&skinend)) break; - while (!scriptfile_endofblock(script, skinend)) - { - switch (getatoken(script,modelskintokens,countof(modelskintokens))) - { - case T_PAL: - scriptfile_getsymbol(script,&palnum); break; - case T_PARAM: - scriptfile_getdouble(script,¶m); break; - case T_SPECPOWER: - scriptfile_getdouble(script,&specpower); break; - case T_SPECFACTOR: - scriptfile_getdouble(script,&specfactor); break; - case T_FILE: - scriptfile_getstring(script,&skinfn); break; //skin filename - case T_SURF: - scriptfile_getnumber(script,&surfnum); break; - } - } - - if (skinfn.IsEmpty()) - { - skinpos.Message(MSG_ERROR, "missing 'skin filename' for skin definition"); - model_ok = 0; - break; - } - - if (seenframe) { modelskin = ++lastmodelskin; } - seenframe = 0; - - switch (token) - { - case T_DETAIL: - palnum = DETAILPAL; - param = 1.0f / param; - break; - case T_GLOW: - palnum = GLOWPAL; - break; - case T_SPECULAR: - palnum = SPECULARPAL; - break; - case T_NORMAL: - palnum = NORMALPAL; - break; - } - - if (!fileSystem.FileExists(skinfn)) - break; - - switch (md_defineskin(lastmodelid, skinfn, palnum, max(0,modelskin), surfnum, param, specpower, specfactor, flags)) - { - case 0: - break; - case -1: - break; // invalid model id!? - case -2: - skinpos.Message(MSG_ERROR, "Invalid skin filename"); - model_ok = 0; - break; - case -3: - skinpos.Message(MSG_ERROR, "Invalid palette number"); - model_ok = 0; - break; - case -4: - skinpos.Message(MSG_ERROR, "Out of memory"); - model_ok = 0; - break; - } - } - break; - case T_HUD: - { - auto hudpos = scriptfile_getposition(script); - FScanner::SavedPos frameend; - char happy=1; - int32_t tilex = 0; - int32_t ftilenume = -1, ltilenume = -1, flags = 0, fov = -1, angadd = 0; - double xadd = 0.0, yadd = 0.0, zadd = 0.0; - - static const tokenlist modelhudtokens[] = - { - { "tile", T_TILE }, - { "tile0", T_TILE0 }, - { "tile1", T_TILE1 }, - { "xadd", T_XADD }, - { "yadd", T_YADD }, - { "zadd", T_ZADD }, - { "angadd", T_ANGADD }, - { "fov", T_FOV }, - { "hide", T_HIDE }, - { "nobob", T_NOBOB }, - { "flipped",T_FLIPPED}, - { "nodepth",T_NODEPTH}, - }; - - if (scriptfile_getbraces(script,&frameend)) break; - while (!scriptfile_endofblock(script, frameend)) - { - switch (getatoken(script,modelhudtokens,countof(modelhudtokens))) - { - case T_TILE: - scriptfile_getsymbol(script,&ftilenume); ltilenume = ftilenume; break; - case T_TILE0: - scriptfile_getsymbol(script,&ftilenume); break; //first tile number - case T_TILE1: - scriptfile_getsymbol(script,<ilenume); break; //last tile number (inclusive) - case T_XADD: - scriptfile_getdouble(script,&xadd); break; - case T_YADD: - scriptfile_getdouble(script,&yadd); break; - case T_ZADD: - scriptfile_getdouble(script,&zadd); break; - case T_ANGADD: - scriptfile_getsymbol(script,&angadd); break; - case T_FOV: - scriptfile_getsymbol(script,&fov); break; - case T_HIDE: - flags |= HUDFLAG_HIDE; break; - case T_NOBOB: - flags |= HUDFLAG_NOBOB; break; - case T_FLIPPED: - flags |= HUDFLAG_FLIPPED; break; - case T_NODEPTH: - flags |= HUDFLAG_NODEPTH; break; - } - } - - if (check_tile_range("hud", &ftilenume, <ilenume, script, hudpos)) - { - model_ok = 0; - break; - } - - if (lastmodelid < 0) - { - hudpos.Message(MSG_WARNING, "Ignoring frame definition."); - break; - } - for (tilex = ftilenume; tilex <= ltilenume && happy; tilex++) - { - vec3f_t const add = { (float)xadd, (float)yadd, (float)zadd }; - switch (md_definehud(lastmodelid, tilex, add, angadd, flags, fov)) - { - case 0: - break; - case -1: - happy = 0; break; // invalid model id!? - case -2: - hudpos.Message(MSG_ERROR, "Invalid tile number"); - happy = 0; - break; - case -3: - hudpos.Message(MSG_ERROR, "Invalid frame name"); - happy = 0; - break; - } - - model_ok &= happy; - } - } - break; - } - } - - if (!model_ok) - { - if (lastmodelid >= 0) - { - pos.Message(MSG_ERROR, "Removing model %d due to errors.", lastmodelid); - md_undefinemodel(lastmodelid); - nextmodelid--; - } - break; - } - - md_setmisc(lastmodelid,(float)scale,shadeoffs,(float)mzadd,(float)myoffset,flags); - modelskin = lastmodelskin = 0; - seenframe = 0; - - } + parseModel(*script, pos); break; case T_VOXEL: parseVoxel(*script, pos); diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 7da21adc3..b80fd93ae 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -1745,3 +1745,247 @@ void parseUndefModelOf(FScanner& sc, FScriptPosition& pos) if (!ValidateTilenum("undefmodelof", tile, pos)) return; pos.Message(MSG_WARNING, "undefmodelof: currently non-functional."); } + +//=========================================================================== +// +// +// +//=========================================================================== + +static bool parseModelFrameBlock(FScanner& sc, FixedBitArray<1024>& usedframes) +{ + FScanner::SavedPos blockend; + FScriptPosition pos = sc; + + FString framename; + bool ok = true; + int pal = -1; + int starttile = -1, endtile = -1; + double smoothduration = 0.1f; + + if (sc.StartBraces(&blockend)) return false; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("pal")) sc.GetNumber(pal, true); + else if (sc.Compare({ "name", "frame" })) sc.GetString(framename); + else if (sc.Compare("tile")) { sc.GetNumber(starttile, true); endtile = starttile; } + else if (sc.Compare("tile0")) sc.GetNumber(starttile, true); + else if (sc.Compare("tile1")) sc.GetNumber(endtile, true); + else if (sc.Compare("smoothduration")) sc.GetFloat(smoothduration, true); + } + + if (!ValidateTileRange("model: frame", starttile, endtile, pos)) return false; + + if (smoothduration > 1.0) + { + pos.Message(MSG_WARNING, "smoothduration out of range"); + smoothduration = 1.0; + } + for (int i = starttile; i <= endtile && ok; i++) + { + int res = md_defineframe(mdglobal.lastmodelid, framename, i, max(0, mdglobal.modelskin), smoothduration, pal); + if (res < 0) + { + ok = false; + if (res == -2) pos.Message(MSG_WARNING, "Invalid tile number %d", i); + else if (res == -3) pos.Message(MSG_WARNING, "%s: Invalid frame name", framename.GetChars()); + } + else if (res < 1024) usedframes.Set(res); + } + mdglobal.seenframe = 1; + return ok; +} + +static bool parseModelAnimBlock(FScanner& sc) +{ + FScanner::SavedPos blockend; + FScriptPosition pos = sc; + + FString startframe, endframe; + int flags = 0; + double fps = 1.0; + + if (sc.StartBraces(&blockend)) return false; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("frame0")) sc.GetString(startframe); + else if (sc.Compare("frame1")) sc.GetString(endframe); + else if (sc.Compare("fps")) sc.GetFloat(fps, true); + else if (sc.Compare("flags")) sc.GetNumber(flags, true); + } + + if (startframe.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing start frame for anim definition"); + return false; + } + if (endframe.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing end frame for anim definition"); + return false; + } + + int res = md_defineanimation(mdglobal.lastmodelid, startframe, endframe, (int)(fps * (65536.0 * .001)), flags); + if (res < 0) + { + if (res == -2) pos.Message(MSG_ERROR, "Invalid starting frame name %s", startframe.GetChars()); + else if (res == -3) pos.Message(MSG_ERROR, "Invalid ending frame name %s", endframe.GetChars()); + return false; + } + return true; +} + +static bool parseModelSkinBlock(FScanner& sc, int whichpal) +{ + FScanner::SavedPos blockend; + FScriptPosition pos = sc; + + FString filename; + int pal = 0, surface = 0; + double param = 1.0, specpower = 1.0, specfactor = 1.0; + int flags = 0; + + if (sc.StartBraces(&blockend)) return false; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("pal")) sc.GetNumber(pal, true); + else if (sc.Compare("file")) sc.GetString(filename); + else if (sc.Compare({ "surface", "surf" })) sc.GetNumber(surface, true); + else if (sc.Compare({ "intensity", "scale", "detailscale" })) sc.GetFloat(param, true); + else if (sc.Compare({ "specpower", "specularpower", "parallaxscale" })) sc.GetFloat(specpower, true); + else if (sc.Compare({ "specfactor", "specularfactor", "parallaxbias" })) sc.GetFloat(specfactor, true); + else if (sc.Compare("forcefilter")) { /* not suppoted yet*/ } + } + + + if (filename.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing 'skin filename' for skin definition"); + return false; + } + + if (mdglobal.seenframe) mdglobal.modelskin = ++mdglobal.lastmodelskin; + mdglobal.seenframe = 0; + + if (!fileSystem.FileExists(filename)) + { + pos.Message(MSG_ERROR, "%s: file not found", filename.GetChars()); + return false; + } + + if (whichpal == DETAILPAL) param = 1. / param; + int res = md_defineskin(mdglobal.lastmodelid, filename, pal, max(0, mdglobal.modelskin), surface, param, specpower, specfactor, flags); + if (res < 0) + { + if (res == -2) pos.Message(MSG_ERROR, "Invalid skin filename %s", filename.GetChars()); + else if (res == -3) pos.Message(MSG_ERROR, "Invalid palette number %d", pal); + return false; + } + return true; +} + +static bool parseModelHudBlock(FScanner& sc) +{ + FScanner::SavedPos blockend; + FScriptPosition pos = sc; + + int starttile = -1, endtile = -1, flags = 0, fov = -1, angadd = 0; + DVector3 add{}; + + if (sc.StartBraces(&blockend)) return false; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("tile")) { sc.GetNumber(starttile, true); endtile = starttile; } + else if (sc.Compare("tile0")) sc.GetNumber(starttile, true); + else if (sc.Compare("tile1")) sc.GetNumber(endtile, true); + else if (sc.Compare("xadd")) sc.GetFloat(add.X, true); + else if (sc.Compare("yadd")) sc.GetFloat(add.Y, true); + else if (sc.Compare("zadd")) sc.GetFloat(add.Z, true); + else if (sc.Compare("angadd")) sc.GetNumber(angadd, true); + else if (sc.Compare("fov")) sc.GetNumber(fov, true); + else if (sc.Compare("hide")) flags |= HUDFLAG_HIDE; + else if (sc.Compare("nobob")) flags |= HUDFLAG_NOBOB; + else if (sc.Compare("flipped")) flags |= HUDFLAG_FLIPPED; + else if (sc.Compare("nodepth")) flags |= HUDFLAG_NODEPTH; + } + + if (!ValidateTileRange("hud", starttile, endtile, pos)) return false; + + for (int i = starttile; i <= endtile; i++) + { + vec3f_t addf = { (float)add.X, (float)add.Y, (float)add.Z }; + int res = md_definehud(mdglobal.lastmodelid, i, addf, angadd, flags, fov); + if (res < 0) + { + if (res == -2) pos.Message(MSG_ERROR, "Invalid tile number %d", i); + return false; + } + } + return true; +} + +void parseModel(FScanner& sc, FScriptPosition& pos) +{ + FScanner::SavedPos blockend; + + FString modelfn; + double scale = 1.0, mzadd = 0.0, myoffset = 0.0; + int32_t shadeoffs = 0, pal = 0, flags = 0; + FixedBitArray<1024> usedframes; + + usedframes.Zero(); + mdglobal.modelskin = mdglobal.lastmodelskin = 0; + mdglobal.seenframe = 0; + + if (!sc.GetString(modelfn)) return; + + if (sc.StartBraces(&blockend)) return; + + mdglobal.lastmodelid = md_loadmodel(modelfn); + if (mdglobal.lastmodelid < 0) + { + pos.Message(MSG_WARNING, "Unable to load model file \"%s\"\n", modelfn.GetChars()); + sc.RestorePos(blockend); + sc.CheckString("}"); + return; + } + + bool ok = true; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("scale")) sc.GetFloat(scale, true); + else if (sc.Compare("shade")) sc.GetNumber(shadeoffs, true); + else if (sc.Compare("zadd")) sc.GetFloat(mzadd, true); + else if (sc.Compare("yoffset")) sc.GetFloat(myoffset, true); + else if (sc.Compare("frame")) ok &= parseModelFrameBlock(sc, usedframes); + else if (sc.Compare("anim")) ok &= parseModelAnimBlock(sc); + else if (sc.Compare("skin")) ok &= parseModelSkinBlock(sc, 0); + else if (sc.Compare("detail")) ok &= parseModelSkinBlock(sc, DETAILPAL); + else if (sc.Compare("glow")) ok &= parseModelSkinBlock(sc, GLOWPAL); + else if (sc.Compare("specular")) ok &= parseModelSkinBlock(sc, SPECULARPAL); + else if (sc.Compare("normal")) ok &= parseModelSkinBlock(sc, NORMALPAL); + else if (sc.Compare("hud")) ok &= parseModelHudBlock(sc); + else if (sc.Compare("flags")) sc.GetNumber(flags, true); + } + + if (!ok) + { + if (mdglobal.lastmodelid >= 0) + { + pos.Message(MSG_ERROR, "Removing model %d due to errors.", mdglobal.lastmodelid); + md_undefinemodel(mdglobal.lastmodelid); + nextmodelid--; + } + } + else + { + md_setmisc(mdglobal.lastmodelid, (float)scale, shadeoffs, (float)mzadd, (float)myoffset, flags); + mdglobal.modelskin = mdglobal.lastmodelskin = 0; + mdglobal.seenframe = 0; + } +}