mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-16 01:11:28 +00:00
2044 lines
51 KiB
C++
2044 lines
51 KiB
C++
/*
|
|
** gldefs.cpp
|
|
** GLDEFS parser
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2003 Timothy Stump
|
|
** Copyright 2005-2018 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 <ctype.h>
|
|
|
|
#include "sc_man.h"
|
|
|
|
#include "filesystem.h"
|
|
#include "gi.h"
|
|
//#include "r_state.h"
|
|
#include "stats.h"
|
|
#include "v_text.h"
|
|
//#include "g_levellocals.h"
|
|
#include "a_dynlight.h"
|
|
#include "v_video.h"
|
|
#include "skyboxtexture.h"
|
|
#include "hwrenderer/postprocessing/hw_postprocessshader.h"
|
|
#include "hw_material.h"
|
|
#include "texturemanager.h"
|
|
#include "gameconfigfile.h"
|
|
#include "m_argv.h"
|
|
|
|
#if 0
|
|
void AddLightDefaults(FLightDefaults *defaults, double attnFactor);
|
|
void AddLightAssociation(const char *actor, const char *frame, const char *light);
|
|
void InitializeActorLights(TArray<FLightAssociation> &LightAssociations);
|
|
void ParseColorization(FScanner& sc);
|
|
|
|
extern TDeletingArray<FLightDefaults *> LightDefaults;
|
|
extern int AttenuationIsSet;
|
|
#endif
|
|
|
|
bool addedcvars = false;
|
|
|
|
struct ExtraUniformCVARData
|
|
{
|
|
FString Shader;
|
|
FString Uniform;
|
|
double* vec4 = nullptr;
|
|
ExtraUniformCVARData* Next;
|
|
};
|
|
|
|
static void do_uniform_set(float value, ExtraUniformCVARData* data)
|
|
{
|
|
if (!(data->vec4))
|
|
{
|
|
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
|
{
|
|
PostProcessShader& shader = PostProcessShaders[i];
|
|
if (strcmp(shader.Name, data->Shader) == 0)
|
|
{
|
|
data->vec4 = shader.Uniforms[data->Uniform].Values;
|
|
}
|
|
}
|
|
}
|
|
double* vec4 = data->vec4;
|
|
if (vec4)
|
|
{
|
|
vec4[0] = value;
|
|
vec4[1] = 0.0;
|
|
vec4[2] = 0.0;
|
|
vec4[3] = 1.0;
|
|
}
|
|
if (data->Next)
|
|
do_uniform_set(value, data->Next);
|
|
}
|
|
|
|
void uniform_callback_int(FIntCVar &self)
|
|
{
|
|
do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer());
|
|
}
|
|
|
|
void uniform_callback_float(FFloatCVar &self)
|
|
{
|
|
do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// ParseVavoomSkybox
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
static void ParseVavoomSkybox()
|
|
{
|
|
int lump = fileSystem.CheckNumForName("SKYBOXES");
|
|
|
|
if (lump < 0) return;
|
|
|
|
FScanner sc(lump);
|
|
while (sc.GetString())
|
|
{
|
|
int facecount=0;
|
|
int maplump = -1;
|
|
bool error = false;
|
|
FString s = sc.String;
|
|
FSkyBox * sb = new FSkyBox(sc.String);
|
|
sb->fliptop = true;
|
|
sc.MustGetStringName("{");
|
|
while (!sc.CheckString("}"))
|
|
{
|
|
if (facecount<6)
|
|
{
|
|
sc.MustGetStringName("{");
|
|
sc.MustGetStringName("map");
|
|
sc.MustGetString();
|
|
|
|
maplump = fileSystem.CheckNumForFullName(sc.String, true);
|
|
|
|
auto tex = TexMan.FindGameTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny);
|
|
if (tex == NULL)
|
|
{
|
|
sc.ScriptMessage("Texture '%s' not found in Vavoom skybox '%s'\n", sc.String, s.GetChars());
|
|
error = true;
|
|
}
|
|
sb->faces[facecount] = tex;
|
|
sc.MustGetStringName("}");
|
|
}
|
|
facecount++;
|
|
}
|
|
if (facecount != 6)
|
|
{
|
|
sc.ScriptError("%s: Skybox definition requires 6 faces", s.GetChars());
|
|
}
|
|
sb->SetSize();
|
|
if (!error)
|
|
{
|
|
TexMan.AddGameTexture(MakeGameTexture(sb, s, ETextureType::Override));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// light definition keywords
|
|
//
|
|
//==========================================================================
|
|
|
|
|
|
static const char *LightTags[]=
|
|
{
|
|
"color",
|
|
"size",
|
|
"secondarySize",
|
|
"offset",
|
|
"chance",
|
|
"interval",
|
|
"scale",
|
|
"frame",
|
|
"light",
|
|
"{",
|
|
"}",
|
|
"subtractive",
|
|
"additive",
|
|
"halo",
|
|
"dontlightself",
|
|
"attenuate",
|
|
"dontlightactors",
|
|
"spot",
|
|
"noshadowmap",
|
|
nullptr
|
|
};
|
|
|
|
|
|
enum {
|
|
LIGHTTAG_COLOR,
|
|
LIGHTTAG_SIZE,
|
|
LIGHTTAG_SECSIZE,
|
|
LIGHTTAG_OFFSET,
|
|
LIGHTTAG_CHANCE,
|
|
LIGHTTAG_INTERVAL,
|
|
LIGHTTAG_SCALE,
|
|
LIGHTTAG_FRAME,
|
|
LIGHTTAG_LIGHT,
|
|
LIGHTTAG_OPENBRACE,
|
|
LIGHTTAG_CLOSEBRACE,
|
|
LIGHTTAG_SUBTRACTIVE,
|
|
LIGHTTAG_ADDITIVE,
|
|
LIGHTTAG_HALO,
|
|
LIGHTTAG_DONTLIGHTSELF,
|
|
LIGHTTAG_ATTENUATE,
|
|
LIGHTTAG_DONTLIGHTACTORS,
|
|
LIGHTTAG_SPOT,
|
|
LIGHTTAG_NOSHADOWMAP,
|
|
};
|
|
|
|
//==========================================================================
|
|
//
|
|
// Top level keywords
|
|
//
|
|
//==========================================================================
|
|
|
|
// these are the core types available in the *DEFS lump
|
|
static const char *CoreKeywords[]=
|
|
{
|
|
"pointlight",
|
|
"pulselight",
|
|
"flickerlight",
|
|
"flickerlight2",
|
|
"sectorlight",
|
|
"object",
|
|
"clearlights",
|
|
"shader",
|
|
"clearshaders",
|
|
"skybox",
|
|
"glow",
|
|
"brightmap",
|
|
"disable_fullbright",
|
|
"hardwareshader",
|
|
"detail",
|
|
"#include",
|
|
"material",
|
|
"lightsizefactor",
|
|
"colorization",
|
|
nullptr
|
|
};
|
|
|
|
|
|
enum
|
|
{
|
|
LIGHT_POINT,
|
|
LIGHT_PULSE,
|
|
LIGHT_FLICKER,
|
|
LIGHT_FLICKER2,
|
|
LIGHT_SECTOR,
|
|
LIGHT_OBJECT,
|
|
LIGHT_CLEAR,
|
|
TAG_SHADER,
|
|
TAG_CLEARSHADERS,
|
|
TAG_SKYBOX,
|
|
TAG_GLOW,
|
|
TAG_BRIGHTMAP,
|
|
TAG_DISABLE_FB,
|
|
TAG_HARDWARESHADER,
|
|
TAG_DETAIL,
|
|
TAG_INCLUDE,
|
|
TAG_MATERIAL,
|
|
TAG_LIGHTSIZEFACTOR,
|
|
TAG_COLORIZATION,
|
|
};
|
|
|
|
//==========================================================================
|
|
//
|
|
// GLDEFS parser
|
|
//
|
|
//==========================================================================
|
|
|
|
class GLDefsParser
|
|
{
|
|
FScanner sc;
|
|
int workingLump;
|
|
int ScriptDepth = 0;
|
|
TArray<FLightAssociation> &LightAssociations;
|
|
double lightSizeFactor = 1.;
|
|
|
|
//==========================================================================
|
|
//
|
|
// This is only here so any shader definition for ZDoomGL can be skipped
|
|
// There is no functionality for this stuff!
|
|
//
|
|
//==========================================================================
|
|
|
|
bool ParseShader()
|
|
{
|
|
int ShaderDepth = 0;
|
|
|
|
if (sc.GetString())
|
|
{
|
|
char *tmp;
|
|
|
|
tmp = strstr(sc.String, "{");
|
|
while (tmp)
|
|
{
|
|
ShaderDepth++;
|
|
tmp++;
|
|
tmp = strstr(tmp, "{");
|
|
}
|
|
|
|
tmp = strstr(sc.String, "}");
|
|
while (tmp)
|
|
{
|
|
ShaderDepth--;
|
|
tmp++;
|
|
tmp = strstr(tmp, "}");
|
|
}
|
|
|
|
if (ShaderDepth == 0) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// Parses a GLBoom+ detail texture definition
|
|
//
|
|
// Syntax is this:
|
|
// detail
|
|
// {
|
|
// (walls | flats) [default_detail_name [width [height [offset_x [offset_y]]]]]
|
|
// {
|
|
// texture_name [detail_name [width [height [offset_x [offset_y]]]]]
|
|
// }
|
|
// }
|
|
// This merely parses the block and returns no error if valid. The feature
|
|
// is not actually implemented, so nothing else happens.
|
|
//
|
|
// The semantics of this are too horrible to comprehend (default detail texture???)
|
|
// so if this ever gets done, the parser will look different.
|
|
//==========================================================================
|
|
#if 0
|
|
void ParseDetailTexture()
|
|
{
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("walls") || sc.Compare("flats"))
|
|
{
|
|
if (!sc.CheckToken('{'))
|
|
{
|
|
sc.MustGetString(); // Default detail texture
|
|
if (sc.CheckFloat()) // Width
|
|
if (sc.CheckFloat()) // Height
|
|
if (sc.CheckFloat()) // OffsX
|
|
if (sc.CheckFloat()) // OffsY
|
|
{
|
|
// Nothing
|
|
}
|
|
}
|
|
else sc.UnGet();
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString(); // Texture
|
|
if (sc.GetString()) // Detail texture
|
|
{
|
|
if (sc.CheckFloat()) // Width
|
|
if (sc.CheckFloat()) // Height
|
|
if (sc.CheckFloat()) // OffsX
|
|
if (sc.CheckFloat()) // OffsY
|
|
{
|
|
// Nothing
|
|
}
|
|
}
|
|
else sc.UnGet();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
float ParseFloat(FScanner &sc)
|
|
{
|
|
sc.MustGetFloat();
|
|
return float(sc.Float);
|
|
}
|
|
|
|
|
|
int ParseInt(FScanner &sc)
|
|
{
|
|
sc.MustGetNumber();
|
|
return sc.Number;
|
|
}
|
|
|
|
|
|
char *ParseString(FScanner &sc)
|
|
{
|
|
sc.GetString();
|
|
return sc.String;
|
|
}
|
|
|
|
|
|
void ParseTriple(FScanner &sc, float floatVal[3])
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
floatVal[i] = ParseFloat(sc);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void AddLightAssociation(const char *actor, const char *frame, const char *light)
|
|
{
|
|
FLightAssociation *temp;
|
|
unsigned int i;
|
|
FLightAssociation assoc(actor, frame, light);
|
|
|
|
for (i = 0; i < LightAssociations.Size(); i++)
|
|
{
|
|
temp = &LightAssociations[i];
|
|
if (temp->ActorName() == assoc.ActorName())
|
|
{
|
|
if (strcmp(temp->FrameName(), assoc.FrameName()) == 0)
|
|
{
|
|
temp->ReplaceLightName(assoc.Light());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
LightAssociations.Push(assoc);
|
|
}
|
|
#endif
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Note: The different light type parsers really could use some consolidation...
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParsePointLight()
|
|
{
|
|
int type;
|
|
float floatTriple[3];
|
|
int intVal;
|
|
FLightDefaults *defaults;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
FName name = sc.String;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
defaults = new FLightDefaults(name, PointLight);
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_COLOR:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetArg(LIGHT_RED, clamp<int>((int)(floatTriple[0] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_GREEN, clamp<int>((int)(floatTriple[1] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_BLUE, clamp<int>((int)(floatTriple[2] * 255), 0, 255));
|
|
break;
|
|
case LIGHTTAG_OFFSET:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetOffset(floatTriple);
|
|
break;
|
|
case LIGHTTAG_SIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_SUBTRACTIVE:
|
|
defaults->SetSubtractive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ADDITIVE:
|
|
defaults->SetAdditive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_HALO: // old development garbage
|
|
ParseInt(sc);
|
|
break;
|
|
case LIGHTTAG_NOSHADOWMAP:
|
|
defaults->SetNoShadowmap(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTSELF:
|
|
defaults->SetDontLightSelf(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ATTENUATE:
|
|
defaults->SetAttenuate(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTACTORS:
|
|
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_SPOT:
|
|
{
|
|
float innerAngle = ParseFloat(sc);
|
|
float outerAngle = ParseFloat(sc);
|
|
defaults->SetSpot(true);
|
|
defaults->SetSpotInnerAngle(innerAngle);
|
|
defaults->SetSpotOuterAngle(outerAngle);
|
|
}
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
#if 0
|
|
AddLightDefaults(defaults, lightSizeFactor);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParsePulseLight()
|
|
{
|
|
int type;
|
|
float floatVal, floatTriple[3];
|
|
int intVal;
|
|
FLightDefaults *defaults;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
FName name = sc.String;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
defaults = new FLightDefaults(name, PulseLight);
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_COLOR:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetArg(LIGHT_RED, clamp<int>((int)(floatTriple[0] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_GREEN, clamp<int>((int)(floatTriple[1] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_BLUE, clamp<int>((int)(floatTriple[2] * 255), 0, 255));
|
|
break;
|
|
case LIGHTTAG_OFFSET:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetOffset(floatTriple);
|
|
break;
|
|
case LIGHTTAG_SIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_SECSIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_INTERVAL:
|
|
floatVal = ParseFloat(sc);
|
|
defaults->SetParameter(floatVal * TICRATE);
|
|
break;
|
|
case LIGHTTAG_SUBTRACTIVE:
|
|
defaults->SetSubtractive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_HALO: // old development garbage
|
|
ParseInt(sc);
|
|
break;
|
|
case LIGHTTAG_NOSHADOWMAP:
|
|
defaults->SetNoShadowmap(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTSELF:
|
|
defaults->SetDontLightSelf(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ATTENUATE:
|
|
defaults->SetAttenuate(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTACTORS:
|
|
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_SPOT:
|
|
{
|
|
float innerAngle = ParseFloat(sc);
|
|
float outerAngle = ParseFloat(sc);
|
|
defaults->SetSpot(true);
|
|
defaults->SetSpotInnerAngle(innerAngle);
|
|
defaults->SetSpotOuterAngle(outerAngle);
|
|
}
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
defaults->OrderIntensities();
|
|
|
|
AddLightDefaults(defaults, lightSizeFactor);
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseFlickerLight()
|
|
{
|
|
int type;
|
|
float floatVal, floatTriple[3];
|
|
int intVal;
|
|
FLightDefaults *defaults;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
FName name = sc.String;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
defaults = new FLightDefaults(name, FlickerLight);
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_COLOR:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetArg(LIGHT_RED, clamp<int>((int)(floatTriple[0] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_GREEN, clamp<int>((int)(floatTriple[1] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_BLUE, clamp<int>((int)(floatTriple[2] * 255), 0, 255));
|
|
break;
|
|
case LIGHTTAG_OFFSET:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetOffset(floatTriple);
|
|
break;
|
|
case LIGHTTAG_SIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_SECSIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_CHANCE:
|
|
floatVal = ParseFloat(sc);
|
|
defaults->SetParameter(floatVal*360.);
|
|
break;
|
|
case LIGHTTAG_SUBTRACTIVE:
|
|
defaults->SetSubtractive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_HALO: // old development garbage
|
|
ParseInt(sc);
|
|
break;
|
|
case LIGHTTAG_NOSHADOWMAP:
|
|
defaults->SetNoShadowmap(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTSELF:
|
|
defaults->SetDontLightSelf(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ATTENUATE:
|
|
defaults->SetAttenuate(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTACTORS:
|
|
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_SPOT:
|
|
{
|
|
float innerAngle = ParseFloat(sc);
|
|
float outerAngle = ParseFloat(sc);
|
|
defaults->SetSpot(true);
|
|
defaults->SetSpotInnerAngle(innerAngle);
|
|
defaults->SetSpotOuterAngle(outerAngle);
|
|
}
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
defaults->OrderIntensities();
|
|
AddLightDefaults(defaults, lightSizeFactor);
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseFlickerLight2()
|
|
{
|
|
int type;
|
|
float floatVal, floatTriple[3];
|
|
int intVal;
|
|
FLightDefaults *defaults;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
FName name = sc.String;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
defaults = new FLightDefaults(name, RandomFlickerLight);
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_COLOR:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetArg(LIGHT_RED, clamp<int>((int)(floatTriple[0] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_GREEN, clamp<int>((int)(floatTriple[1] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_BLUE, clamp<int>((int)(floatTriple[2] * 255), 0, 255));
|
|
break;
|
|
case LIGHTTAG_OFFSET:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetOffset(floatTriple);
|
|
break;
|
|
case LIGHTTAG_SIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_SECSIZE:
|
|
intVal = clamp<int>(ParseInt(sc), 1, 1024);
|
|
defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal);
|
|
break;
|
|
case LIGHTTAG_INTERVAL:
|
|
floatVal = ParseFloat(sc);
|
|
defaults->SetParameter(floatVal * 360.);
|
|
break;
|
|
case LIGHTTAG_SUBTRACTIVE:
|
|
defaults->SetSubtractive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_HALO: // old development garbage
|
|
ParseInt(sc);
|
|
break;
|
|
case LIGHTTAG_NOSHADOWMAP:
|
|
defaults->SetNoShadowmap(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTSELF:
|
|
defaults->SetDontLightSelf(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ATTENUATE:
|
|
defaults->SetAttenuate(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTACTORS:
|
|
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_SPOT:
|
|
{
|
|
float innerAngle = ParseFloat(sc);
|
|
float outerAngle = ParseFloat(sc);
|
|
defaults->SetSpot(true);
|
|
defaults->SetSpotInnerAngle(innerAngle);
|
|
defaults->SetSpotOuterAngle(outerAngle);
|
|
}
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
if (defaults->GetArg(LIGHT_SECONDARY_INTENSITY) < defaults->GetArg(LIGHT_INTENSITY))
|
|
{
|
|
int v = defaults->GetArg(LIGHT_SECONDARY_INTENSITY);
|
|
defaults->SetArg(LIGHT_SECONDARY_INTENSITY, defaults->GetArg(LIGHT_INTENSITY));
|
|
defaults->SetArg(LIGHT_INTENSITY, v);
|
|
}
|
|
AddLightDefaults(defaults, lightSizeFactor);
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseSectorLight()
|
|
{
|
|
int type;
|
|
float floatVal;
|
|
float floatTriple[3];
|
|
FLightDefaults *defaults;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
FName name = sc.String;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
defaults = new FLightDefaults(name, SectorLight);
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_COLOR:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetArg(LIGHT_RED, clamp<int>((int)(floatTriple[0] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_GREEN, clamp<int>((int)(floatTriple[1] * 255), 0, 255));
|
|
defaults->SetArg(LIGHT_BLUE, clamp<int>((int)(floatTriple[2] * 255), 0, 255));
|
|
break;
|
|
case LIGHTTAG_OFFSET:
|
|
ParseTriple(sc, floatTriple);
|
|
defaults->SetOffset(floatTriple);
|
|
break;
|
|
case LIGHTTAG_SCALE:
|
|
floatVal = ParseFloat(sc);
|
|
defaults->SetArg(LIGHT_INTENSITY, clamp((int)(floatVal * 255), 1, 1024));
|
|
break;
|
|
case LIGHTTAG_SUBTRACTIVE:
|
|
defaults->SetSubtractive(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_HALO: // old development garbage
|
|
ParseInt(sc);
|
|
break;
|
|
case LIGHTTAG_NOSHADOWMAP:
|
|
defaults->SetNoShadowmap(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTSELF:
|
|
defaults->SetDontLightSelf(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_ATTENUATE:
|
|
defaults->SetAttenuate(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_DONTLIGHTACTORS:
|
|
defaults->SetDontLightActors(ParseInt(sc) != 0);
|
|
break;
|
|
case LIGHTTAG_SPOT:
|
|
{
|
|
float innerAngle = ParseFloat(sc);
|
|
float outerAngle = ParseFloat(sc);
|
|
defaults->SetSpot(true);
|
|
defaults->SetSpotInnerAngle(innerAngle);
|
|
defaults->SetSpotOuterAngle(outerAngle);
|
|
}
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
AddLightDefaults(defaults, lightSizeFactor);
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseFrame(const FString &name)
|
|
{
|
|
int type, startDepth;
|
|
FString frameName;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
if (strlen(sc.String) > 8)
|
|
{
|
|
sc.ScriptError("Name longer than 8 characters: %s\n", sc.String);
|
|
}
|
|
frameName = sc.String;
|
|
frameName.ToUpper();
|
|
|
|
startDepth = ScriptDepth;
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
ScriptDepth++;
|
|
while (ScriptDepth > startDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_LIGHT:
|
|
ParseString(sc);
|
|
AddLightAssociation(name, frameName, sc.String);
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseObject()
|
|
{
|
|
int type;
|
|
FString name;
|
|
|
|
// get name
|
|
sc.GetString();
|
|
name = sc.String;
|
|
if (!PClass::FindActor(name))
|
|
sc.ScriptMessage("Warning: dynamic lights attached to non-existent actor %s\n", name.GetChars());
|
|
|
|
// check for opening brace
|
|
sc.GetString();
|
|
if (sc.Compare("{"))
|
|
{
|
|
ScriptDepth++;
|
|
while (ScriptDepth)
|
|
{
|
|
sc.GetString();
|
|
type = sc.MatchString(LightTags);
|
|
switch (type)
|
|
{
|
|
case LIGHTTAG_OPENBRACE:
|
|
ScriptDepth++;
|
|
break;
|
|
case LIGHTTAG_CLOSEBRACE:
|
|
ScriptDepth--;
|
|
break;
|
|
case LIGHTTAG_FRAME:
|
|
ParseFrame(name);
|
|
break;
|
|
default:
|
|
sc.ScriptError("Unknown tag: %s\n", sc.String);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Expected '{'.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#if 0
|
|
void ParseGldefSkybox()
|
|
{
|
|
int facecount=0;
|
|
|
|
sc.MustGetString();
|
|
|
|
FString s = sc.String;
|
|
FSkyBox * sb = new FSkyBox(s);
|
|
if (sc.CheckString("fliptop"))
|
|
{
|
|
sb->fliptop = true;
|
|
}
|
|
sc.MustGetStringName("{");
|
|
while (!sc.CheckString("}"))
|
|
{
|
|
sc.MustGetString();
|
|
if (facecount<6)
|
|
{
|
|
sb->faces[facecount] = TexMan.GetGameTexture(TexMan.GetTextureID(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_Overridable));
|
|
}
|
|
facecount++;
|
|
}
|
|
if (facecount != 3 && facecount != 6)
|
|
{
|
|
sc.ScriptError("%s: Skybox definition requires either 3 or 6 faces", s.GetChars());
|
|
}
|
|
sb->SetSize();
|
|
TexMan.AddGameTexture(MakeGameTexture(sb, s, ETextureType::Override));
|
|
}
|
|
#endif
|
|
//===========================================================================
|
|
//
|
|
// Reads glow definitions from GLDEFS
|
|
//
|
|
//===========================================================================
|
|
#if 0
|
|
void ParseGlow()
|
|
{
|
|
sc.MustGetStringName("{");
|
|
while (!sc.CheckString("}"))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("FLATS"))
|
|
{
|
|
sc.MustGetStringName("{");
|
|
while (!sc.CheckString("}"))
|
|
{
|
|
sc.MustGetString();
|
|
FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny);
|
|
auto tex = TexMan.GetGameTexture(flump);
|
|
if (tex) tex->SetAutoGlowing();
|
|
}
|
|
}
|
|
else if (sc.Compare("WALLS"))
|
|
{
|
|
sc.MustGetStringName("{");
|
|
while (!sc.CheckString("}"))
|
|
{
|
|
sc.MustGetString();
|
|
FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Wall,FTextureManager::TEXMAN_TryAny);
|
|
auto tex = TexMan.GetGameTexture(flump);
|
|
if (tex) tex->SetAutoGlowing();
|
|
}
|
|
}
|
|
else if (sc.Compare("TEXTURE"))
|
|
{
|
|
sc.SetCMode(true);
|
|
sc.MustGetString();
|
|
FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny);
|
|
auto tex = TexMan.GetGameTexture(flump);
|
|
sc.MustGetStringName(",");
|
|
sc.MustGetString();
|
|
PalEntry color = V_GetColor(sc.String);
|
|
//sc.MustGetStringName(",");
|
|
//sc.MustGetNumber();
|
|
if (sc.CheckString(","))
|
|
{
|
|
if (sc.CheckNumber())
|
|
{
|
|
if (tex) tex->SetGlowHeight(sc.Number);
|
|
if (!sc.CheckString(",")) goto skip_fb;
|
|
}
|
|
|
|
sc.MustGetStringName("fullbright");
|
|
if (tex) tex->SetFullbright();
|
|
}
|
|
skip_fb:
|
|
sc.SetCMode(false);
|
|
|
|
if (tex && color != 0)
|
|
{
|
|
tex->SetGlowing(color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//==========================================================================
|
|
//
|
|
// Parses a brightmap definition
|
|
//
|
|
//==========================================================================
|
|
#if 0
|
|
void ParseBrightmap()
|
|
{
|
|
ETextureType type = ETextureType::Any;
|
|
bool disable_fullbright=false;
|
|
bool thiswad = false;
|
|
bool iwad = false;
|
|
FGameTexture *bmtex = NULL;
|
|
|
|
sc.MustGetString();
|
|
if (sc.Compare("texture")) type = ETextureType::Wall;
|
|
else if (sc.Compare("flat")) type = ETextureType::Flat;
|
|
else if (sc.Compare("sprite")) type = ETextureType::Sprite;
|
|
else sc.UnGet();
|
|
|
|
sc.MustGetString();
|
|
FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable);
|
|
auto tex = TexMan.GetGameTexture(no);
|
|
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("disablefullbright"))
|
|
{
|
|
// This can also be used without a brightness map to disable
|
|
// fullbright in rotations that only use brightness maps on
|
|
// other angles.
|
|
disable_fullbright = true;
|
|
}
|
|
else if (sc.Compare("thiswad"))
|
|
{
|
|
// only affects textures defined in the WAD containing the definition file.
|
|
thiswad = true;
|
|
}
|
|
else if (sc.Compare ("iwad"))
|
|
{
|
|
// only affects textures defined in the IWAD.
|
|
iwad = true;
|
|
}
|
|
else if (sc.Compare ("map"))
|
|
{
|
|
sc.MustGetString();
|
|
|
|
if (bmtex != NULL)
|
|
{
|
|
Printf("Multiple brightmap definitions in texture %s\n", tex? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
|
|
bmtex = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
|
|
|
if (bmtex == NULL)
|
|
Printf("Brightmap '%s' not found in texture '%s'\n", sc.String, tex? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
}
|
|
if (!tex)
|
|
{
|
|
return;
|
|
}
|
|
if (thiswad || iwad)
|
|
{
|
|
bool useme = false;
|
|
int lumpnum = tex->GetSourceLump();
|
|
|
|
if (lumpnum != -1)
|
|
{
|
|
if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxIwadNum()) useme = true;
|
|
if (thiswad && fileSystem.GetFileContainer(lumpnum) == fileSystem.GetFileContainer(workingLump)) useme = true;
|
|
}
|
|
if (!useme) return;
|
|
}
|
|
|
|
if (bmtex != NULL)
|
|
{
|
|
tex->SetBrightmap(bmtex);
|
|
}
|
|
tex->SetDisableFullbright(disable_fullbright);
|
|
}
|
|
#endif
|
|
#if 0
|
|
void SetShaderIndex(FGameTexture *tex, unsigned index)
|
|
{
|
|
auto desc = usershaders[index - FIRST_USER_SHADER];
|
|
if (desc.disablealphatest)
|
|
{
|
|
tex->SetTranslucent(true);
|
|
}
|
|
tex->SetShaderIndex(index);
|
|
}
|
|
#endif
|
|
//==========================================================================
|
|
//
|
|
// Parses a material definition
|
|
//
|
|
//==========================================================================
|
|
#if 0
|
|
void ParseMaterial()
|
|
{
|
|
ETextureType type = ETextureType::Any;
|
|
bool disable_fullbright = false;
|
|
bool disable_fullbright_specified = false;
|
|
bool thiswad = false;
|
|
bool iwad = false;
|
|
|
|
UserShaderDesc usershader;
|
|
TArray<FString> texNameList;
|
|
TArray<int> texNameIndex;
|
|
float speed = 1.f;
|
|
|
|
MaterialLayers mlay = { -1000, -1000 };
|
|
FGameTexture* textures[6] = {};
|
|
const char *keywords[7] = { "brightmap", "normal", "specular", "metallic", "roughness", "ao", nullptr };
|
|
const char *notFound[6] = { "Brightmap", "Normalmap", "Specular texture", "Metallic texture", "Roughness texture", "Ambient occlusion texture" };
|
|
|
|
sc.MustGetString();
|
|
if (sc.Compare("texture")) type = ETextureType::Wall;
|
|
else if (sc.Compare("flat")) type = ETextureType::Flat;
|
|
else if (sc.Compare("sprite")) type = ETextureType::Sprite;
|
|
else sc.UnGet();
|
|
|
|
sc.MustGetString();
|
|
FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable);
|
|
auto tex = TexMan.GetGameTexture(no);
|
|
|
|
if (tex == nullptr)
|
|
{
|
|
sc.ScriptMessage("Material definition refers nonexistent texture '%s'\n", sc.String);
|
|
}
|
|
else tex->AddAutoMaterials(); // We need these before setting up the texture.
|
|
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("disablefullbright"))
|
|
{
|
|
// This can also be used without a brightness map to disable
|
|
// fullbright in rotations that only use brightness maps on
|
|
// other angles.
|
|
disable_fullbright = true;
|
|
disable_fullbright_specified = true;
|
|
}
|
|
else if (sc.Compare("thiswad"))
|
|
{
|
|
// only affects textures defined in the WAD containing the definition file.
|
|
thiswad = true;
|
|
}
|
|
else if (sc.Compare ("iwad"))
|
|
{
|
|
// only affects textures defined in the IWAD.
|
|
iwad = true;
|
|
}
|
|
else if (sc.Compare("glossiness"))
|
|
{
|
|
sc.MustGetFloat();
|
|
mlay.Glossiness = (float)sc.Float;
|
|
}
|
|
else if (sc.Compare("specularlevel"))
|
|
{
|
|
sc.MustGetFloat();
|
|
mlay.SpecularLevel = (float)sc.Float;
|
|
}
|
|
else if (sc.Compare("speed"))
|
|
{
|
|
sc.MustGetFloat();
|
|
speed = float(sc.Float);
|
|
}
|
|
else if (sc.Compare("shader"))
|
|
{
|
|
sc.MustGetString();
|
|
usershader.shader = sc.String;
|
|
}
|
|
else if (sc.Compare("texture"))
|
|
{
|
|
sc.MustGetString();
|
|
FString textureName = sc.String;
|
|
for (FString &texName : texNameList)
|
|
{
|
|
if (!texName.Compare(textureName))
|
|
{
|
|
sc.ScriptError("Trying to redefine custom hardware shader texture '%s' in texture '%s'\n", textureName.GetChars(), tex ? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
}
|
|
sc.MustGetString();
|
|
if (tex)
|
|
{
|
|
bool okay = false;
|
|
for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++)
|
|
{
|
|
if (!mlay.CustomShaderTextures[i])
|
|
{
|
|
mlay.CustomShaderTextures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
|
if (!mlay.CustomShaderTextures[i])
|
|
{
|
|
sc.ScriptError("Custom hardware shader texture '%s' not found in texture '%s'\n", sc.String, tex->GetName().GetChars());
|
|
}
|
|
|
|
texNameList.Push(textureName);
|
|
texNameIndex.Push((int)i);
|
|
okay = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!okay)
|
|
{
|
|
sc.ScriptError("Error: out of texture units in texture '%s'", tex->GetName().GetChars());
|
|
}
|
|
}
|
|
}
|
|
else if (sc.Compare("define"))
|
|
{
|
|
sc.MustGetString();
|
|
FString defineName = sc.String;
|
|
FString defineValue = "";
|
|
if (sc.CheckToken('='))
|
|
{
|
|
sc.MustGetString();
|
|
defineValue = sc.String;
|
|
}
|
|
usershader.defines.AppendFormat("#define %s %s\n", defineName.GetChars(), defineValue.GetChars());
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; keywords[i] != nullptr; i++)
|
|
{
|
|
if (sc.Compare (keywords[i]))
|
|
{
|
|
sc.MustGetString();
|
|
if (textures[i])
|
|
Printf("Multiple %s definitions in texture %s\n", keywords[i], tex? tex->GetName().GetChars() : "(null)");
|
|
textures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
|
if (!textures[i])
|
|
Printf("%s '%s' not found in texture '%s'\n", notFound[i], sc.String, tex? tex->GetName().GetChars() : "(null)");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!tex)
|
|
{
|
|
return;
|
|
}
|
|
if (thiswad || iwad)
|
|
{
|
|
bool useme = false;
|
|
int lumpnum = tex->GetSourceLump();
|
|
|
|
if (lumpnum != -1)
|
|
{
|
|
if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxIwadNum()) useme = true;
|
|
if (thiswad && fileSystem.GetFileContainer(lumpnum) == fileSystem.GetFileContainer(workingLump)) useme = true;
|
|
}
|
|
if (!useme) return;
|
|
}
|
|
|
|
FGameTexture **bindings[6] =
|
|
{
|
|
&mlay.Brightmap,
|
|
&mlay.Normal,
|
|
&mlay.Specular,
|
|
&mlay.Metallic,
|
|
&mlay.Roughness,
|
|
&mlay.AmbientOcclusion
|
|
};
|
|
for (int i = 0; keywords[i] != nullptr; i++)
|
|
{
|
|
if (textures[i])
|
|
{
|
|
*bindings[i] = textures[i];
|
|
}
|
|
}
|
|
|
|
if (disable_fullbright_specified)
|
|
tex->SetDisableFullbright(disable_fullbright);
|
|
|
|
if (usershader.shader.IsNotEmpty())
|
|
{
|
|
int firstUserTexture;
|
|
if ((mlay.Normal || tex->Normal.get()) && (mlay.Specular || tex->Specular.get()))
|
|
{
|
|
usershader.shaderType = SHADER_Specular;
|
|
firstUserTexture = 7;
|
|
}
|
|
else if ((mlay.Normal || tex->Normal.get()) && (mlay.Metallic || tex->Metallic.get()) && (mlay.Roughness || tex->Roughness.get()) && (mlay.AmbientOcclusion || tex->AmbientOcclusion.get()))
|
|
{
|
|
usershader.shaderType = SHADER_PBR;
|
|
firstUserTexture = 9;
|
|
}
|
|
else
|
|
{
|
|
usershader.shaderType = SHADER_Default;
|
|
firstUserTexture = 5;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < texNameList.Size(); i++)
|
|
{
|
|
usershader.defines.AppendFormat("#define %s texture%d\n", texNameList[i].GetChars(), texNameIndex[i] + firstUserTexture);
|
|
}
|
|
|
|
if (tex->isWarped() != 0)
|
|
{
|
|
Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->GetName().GetChars());
|
|
return;
|
|
}
|
|
tex->SetShaderSpeed(speed);
|
|
for (unsigned i = 0; i < usershaders.Size(); i++)
|
|
{
|
|
if (!usershaders[i].shader.CompareNoCase(usershader.shader) &&
|
|
usershaders[i].shaderType == usershader.shaderType &&
|
|
!usershaders[i].defines.Compare(usershader.defines))
|
|
{
|
|
SetShaderIndex(tex, i + FIRST_USER_SHADER);
|
|
tex->SetShaderLayers(mlay);
|
|
return;
|
|
}
|
|
}
|
|
SetShaderIndex(tex, usershaders.Push(usershader) + FIRST_USER_SHADER);
|
|
}
|
|
tex->SetShaderLayers(mlay);
|
|
}
|
|
#endif
|
|
|
|
//==========================================================================
|
|
//
|
|
// Parses a shader definition
|
|
//
|
|
//==========================================================================
|
|
|
|
void ParseHardwareShader()
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("postprocess"))
|
|
{
|
|
sc.MustGetString();
|
|
|
|
PostProcessShader shaderdesc;
|
|
shaderdesc.Target = sc.String;
|
|
shaderdesc.Target.ToLower();
|
|
|
|
bool validTarget = false;
|
|
if (sc.Compare("beforebloom")) validTarget = true;
|
|
if (sc.Compare("scene")) validTarget = true;
|
|
if (sc.Compare("screen")) validTarget = true;
|
|
if (!validTarget)
|
|
sc.ScriptError("Invalid target '%s' for postprocess shader",sc.String);
|
|
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("shader"))
|
|
{
|
|
sc.MustGetString();
|
|
shaderdesc.ShaderLumpName = sc.String;
|
|
|
|
sc.MustGetNumber();
|
|
shaderdesc.ShaderVersion = sc.Number;
|
|
if (sc.Number > 450 || sc.Number < 330)
|
|
sc.ScriptError("Shader version must be in range 330 to 450!");
|
|
}
|
|
else if (sc.Compare("name"))
|
|
{
|
|
sc.MustGetString();
|
|
shaderdesc.Name = sc.String;
|
|
}
|
|
else if (sc.Compare("uniform") || sc.Compare("cvar_uniform"))
|
|
{
|
|
bool is_cvar = sc.Compare("cvar_uniform");
|
|
|
|
sc.MustGetString();
|
|
FString uniformType = sc.String;
|
|
uniformType.ToLower();
|
|
|
|
sc.MustGetString();
|
|
FString uniformName = sc.String;
|
|
|
|
PostProcessUniformType parsedType = PostProcessUniformType::Undefined;
|
|
|
|
if (uniformType.Compare("int") == 0)
|
|
parsedType = PostProcessUniformType::Int;
|
|
else if (uniformType.Compare("float") == 0)
|
|
parsedType = PostProcessUniformType::Float;
|
|
else if (uniformType.Compare("vec2") == 0)
|
|
parsedType = PostProcessUniformType::Vec2;
|
|
else if (uniformType.Compare("vec3") == 0)
|
|
parsedType = PostProcessUniformType::Vec3;
|
|
else
|
|
sc.ScriptError("Unrecognized uniform type '%s'", sc.String);
|
|
|
|
auto strUniformType = sc.String;
|
|
|
|
if (parsedType != PostProcessUniformType::Undefined)
|
|
shaderdesc.Uniforms[uniformName].Type = parsedType;
|
|
|
|
if (is_cvar)
|
|
{
|
|
addedcvars = true;
|
|
if (!shaderdesc.Name.GetChars())
|
|
sc.ScriptError("Shader must have a name to use cvar uniforms");
|
|
|
|
ECVarType cvartype = CVAR_Dummy;
|
|
int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL;
|
|
FBaseCVar *cvar;
|
|
void (*callback)(FBaseCVar&) = NULL;
|
|
FString cvarname;
|
|
switch (parsedType)
|
|
{
|
|
case PostProcessUniformType::Int:
|
|
cvartype = CVAR_Int;
|
|
callback = (void (*)(FBaseCVar&))uniform_callback_int;
|
|
break;
|
|
case PostProcessUniformType::Float:
|
|
cvartype = CVAR_Float;
|
|
callback = (void (*)(FBaseCVar&))uniform_callback_float;
|
|
break;
|
|
default:
|
|
sc.ScriptError("'%s' not supported for CVAR uniforms!", strUniformType);
|
|
break;
|
|
}
|
|
sc.MustGetString();
|
|
cvarname = sc.String;
|
|
cvar = FindCVar(cvarname, NULL);
|
|
|
|
UCVarValue oldval;
|
|
UCVarValue val;
|
|
ExtraUniformCVARData* oldextra = nullptr;
|
|
sc.MustGetFloat();
|
|
|
|
val.Float = oldval.Float = sc.Float;
|
|
|
|
if (!Args->CheckParm ("-shaderuniformtest"))
|
|
{
|
|
// these aren't really release-ready, so lock them behind a command-line argument for now.
|
|
sc.ScriptMessage("Warning - Use -shaderuniformtest to enable shader uniforms!");
|
|
}
|
|
else
|
|
{
|
|
if (!cvar)
|
|
{
|
|
cvar = C_CreateCVar(cvarname, cvartype, cvarflags);
|
|
}
|
|
else if (cvar && (((cvar->GetFlags()) & CVAR_MOD) == CVAR_MOD))
|
|
{
|
|
// this value may have been previously loaded
|
|
oldval.Float = cvar->GetGenericRep(CVAR_Float).Float;
|
|
oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer();
|
|
}
|
|
|
|
if (!(cvar->GetFlags() & CVAR_MOD))
|
|
{
|
|
if (!((cvar->GetFlags() & (CVAR_AUTO | CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE)))
|
|
sc.ScriptError("CVAR '%s' already in use!", cvarname.GetChars());
|
|
}
|
|
|
|
// must've picked this up from an autoexec.cfg, handle accordingly
|
|
if (cvar && ((cvar->GetFlags() & (CVAR_MOD|CVAR_AUTO|CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE)))
|
|
{
|
|
oldval.Float = cvar->GetGenericRep(CVAR_Float).Float;
|
|
oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer();
|
|
delete cvar;
|
|
cvar = C_CreateCVar(cvarname, cvartype, cvarflags);
|
|
}
|
|
|
|
shaderdesc.Uniforms[uniformName].Values[0] = oldval.Float;
|
|
|
|
cvar->SetGenericRepDefault(val, CVAR_Float);
|
|
|
|
if (val.Float != oldval.Float) // it's not default anymore
|
|
cvar->SetGenericRep(oldval.Float, CVAR_Float);
|
|
|
|
if (callback)
|
|
cvar->SetCallback(callback);
|
|
ExtraUniformCVARData* extra = new ExtraUniformCVARData;
|
|
extra->Shader = shaderdesc.Name.GetChars();
|
|
extra->Uniform = uniformName.GetChars();
|
|
extra->Next = oldextra;
|
|
cvar->SetExtraDataPointer(extra);
|
|
}
|
|
}
|
|
}
|
|
else if (sc.Compare("texture"))
|
|
{
|
|
sc.MustGetString();
|
|
FString textureName = sc.String;
|
|
|
|
sc.MustGetString();
|
|
FString textureSource = sc.String;
|
|
|
|
shaderdesc.Textures[textureName] = textureSource;
|
|
}
|
|
else if (sc.Compare("enabled"))
|
|
{
|
|
shaderdesc.Enabled = true;
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
|
}
|
|
}
|
|
|
|
PostProcessShaders.Push(shaderdesc);
|
|
}
|
|
else
|
|
{
|
|
#if 0 // not ready for this yet
|
|
ETextureType type = ETextureType::Any;
|
|
|
|
if (sc.Compare("texture")) type = ETextureType::Wall;
|
|
else if (sc.Compare("flat")) type = ETextureType::Flat;
|
|
else if (sc.Compare("sprite")) type = ETextureType::Sprite;
|
|
else sc.UnGet();
|
|
|
|
bool disable_fullbright = false;
|
|
bool thiswad = false;
|
|
bool iwad = false;
|
|
int maplump = -1;
|
|
UserShaderDesc desc;
|
|
desc.shaderType = SHADER_Default;
|
|
TArray<FString> texNameList;
|
|
TArray<int> texNameIndex;
|
|
float speed = 1.f;
|
|
|
|
sc.MustGetString();
|
|
FTextureID no = TexMan.CheckForTexture(sc.String, type);
|
|
auto tex = TexMan.GetGameTexture(no);
|
|
if (tex) tex->AddAutoMaterials();
|
|
MaterialLayers mlay = { -1000, -1000 };
|
|
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("shader"))
|
|
{
|
|
sc.MustGetString();
|
|
desc.shader = sc.String;
|
|
}
|
|
else if (sc.Compare("material"))
|
|
{
|
|
sc.MustGetString();
|
|
static MaterialShaderIndex typeIndex[6] = { SHADER_Default, SHADER_Default, SHADER_Specular, SHADER_Specular, SHADER_PBR, SHADER_PBR };
|
|
static bool usesBrightmap[6] = { false, true, false, true, false, true };
|
|
static const char *typeName[6] = { "normal", "brightmap", "specular", "specularbrightmap", "pbr", "pbrbrightmap" };
|
|
bool found = false;
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
if (sc.Compare(typeName[i]))
|
|
{
|
|
desc.shaderType = typeIndex[i];
|
|
if (usesBrightmap[i]) desc.shaderFlags |= SFlag_Brightmap;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
sc.ScriptError("Unknown material type '%s' specified\n", sc.String);
|
|
}
|
|
else if (sc.Compare("speed"))
|
|
{
|
|
sc.MustGetFloat();
|
|
speed = float(sc.Float);
|
|
}
|
|
else if (sc.Compare("texture"))
|
|
{
|
|
sc.MustGetString();
|
|
FString textureName = sc.String;
|
|
for(FString &texName : texNameList)
|
|
{
|
|
if(!texName.Compare(textureName))
|
|
{
|
|
sc.ScriptError("Trying to redefine custom hardware shader texture '%s' in texture '%s'\n", textureName.GetChars(), tex? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
}
|
|
sc.MustGetString();
|
|
bool okay = false;
|
|
for (size_t i = 0; i < countof(mlay.CustomShaderTextures); i++)
|
|
{
|
|
if (!mlay.CustomShaderTextures[i])
|
|
{
|
|
mlay.CustomShaderTextures[i] = TexMan.FindGameTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny);
|
|
if (!mlay.CustomShaderTextures[i])
|
|
{
|
|
sc.ScriptError("Custom hardware shader texture '%s' not found in texture '%s'\n", sc.String, tex? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
|
|
texNameList.Push(textureName);
|
|
texNameIndex.Push((int)i);
|
|
okay = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!okay)
|
|
{
|
|
sc.ScriptError("Error: out of texture units in texture '%s'", tex? tex->GetName().GetChars() : "(null)");
|
|
}
|
|
}
|
|
else if(sc.Compare("define"))
|
|
{
|
|
sc.MustGetString();
|
|
FString defineName = sc.String;
|
|
FString defineValue = "";
|
|
if(sc.CheckToken('='))
|
|
{
|
|
sc.MustGetString();
|
|
defineValue = sc.String;
|
|
}
|
|
desc.defines.AppendFormat("#define %s %s\n", defineName.GetChars(), defineValue.GetChars());
|
|
}
|
|
else if (sc.Compare("disablealphatest"))
|
|
{
|
|
desc.disablealphatest = true;
|
|
}
|
|
}
|
|
if (!tex)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int firstUserTexture;
|
|
switch (desc.shaderType)
|
|
{
|
|
default:
|
|
case SHADER_Default: firstUserTexture = 5; break;
|
|
case SHADER_Specular: firstUserTexture = 7; break;
|
|
case SHADER_PBR: firstUserTexture = 9; break;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < texNameList.Size(); i++)
|
|
{
|
|
desc.defines.AppendFormat("#define %s texture%d\n", texNameList[i].GetChars(), texNameIndex[i] + firstUserTexture);
|
|
}
|
|
|
|
if (desc.shader.IsNotEmpty())
|
|
{
|
|
if (tex->isWarped() != 0)
|
|
{
|
|
Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->GetName().GetChars());
|
|
return;
|
|
}
|
|
tex->SetShaderSpeed(speed);
|
|
for (unsigned i = 0; i < usershaders.Size(); i++)
|
|
{
|
|
if (!usershaders[i].shader.CompareNoCase(desc.shader) &&
|
|
usershaders[i].shaderType == desc.shaderType &&
|
|
!usershaders[i].defines.Compare(desc.defines))
|
|
{
|
|
SetShaderIndex(tex, i + FIRST_USER_SHADER);
|
|
tex->SetShaderLayers(mlay);
|
|
return;
|
|
}
|
|
}
|
|
SetShaderIndex(tex, usershaders.Push(desc) + FIRST_USER_SHADER);
|
|
}
|
|
tex->SetShaderLayers(mlay);
|
|
#endif
|
|
}
|
|
}
|
|
#if 0
|
|
void ParseColorization(FScanner& sc)
|
|
{
|
|
TextureManipulation tm = {};
|
|
tm.ModulateColor = 0x01ffffff;
|
|
sc.MustGetString();
|
|
FName cname = sc.String;
|
|
sc.MustGetToken('{');
|
|
while (!sc.CheckToken('}'))
|
|
{
|
|
sc.MustGetString();
|
|
if (sc.Compare("DesaturationFactor"))
|
|
{
|
|
sc.MustGetFloat();
|
|
tm.DesaturationFactor = (float)sc.Float;
|
|
}
|
|
else if (sc.Compare("AddColor"))
|
|
{
|
|
sc.MustGetString();
|
|
tm.AddColor = (tm.AddColor & 0xff000000) | (V_GetColor(sc) & 0xffffff);
|
|
}
|
|
else if (sc.Compare("ModulateColor"))
|
|
{
|
|
sc.MustGetString();
|
|
tm.ModulateColor = V_GetColor(sc) & 0xffffff;
|
|
if (sc.CheckToken(','))
|
|
{
|
|
sc.MustGetNumber();
|
|
tm.ModulateColor.a = sc.Number;
|
|
}
|
|
else tm.ModulateColor.a = 1;
|
|
}
|
|
else if (sc.Compare("BlendColor"))
|
|
{
|
|
sc.MustGetString();
|
|
tm.BlendColor = V_GetColor(sc) & 0xffffff;
|
|
sc.MustGetToken(',');
|
|
sc.MustGetString();
|
|
static const char* opts[] = { "none", "alpha", "screen", "overlay", "hardlight", nullptr };
|
|
tm.AddColor.a = (tm.AddColor.a & ~TextureManipulation::BlendMask) | sc.MustMatchString(opts);
|
|
if (sc.Compare("alpha"))
|
|
{
|
|
sc.MustGetToken(',');
|
|
sc.MustGetFloat();
|
|
tm.BlendColor.a = (uint8_t)(clamp(sc.Float, 0., 1.) * 255);
|
|
}
|
|
}
|
|
else if (sc.Compare("invert"))
|
|
{
|
|
tm.AddColor.a |= TextureManipulation::InvertBit;
|
|
}
|
|
else sc.ScriptError("Unknown token '%s'", sc.String);
|
|
}
|
|
if (tm.CheckIfEnabled())
|
|
{
|
|
TexMan.InsertTextureManipulation(cname, tm);
|
|
}
|
|
else
|
|
{
|
|
TexMan.RemoveTextureManipulation(cname);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
public:
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
void DoParseDefs()
|
|
{
|
|
int recursion=0;
|
|
int lump, type;
|
|
|
|
// Get actor class name.
|
|
while (true)
|
|
{
|
|
sc.SavePos();
|
|
if (!sc.GetToken ())
|
|
{
|
|
// *** fixme! need to load from config file
|
|
//if (addedcvars)
|
|
// GameConfig->DoModSetup (gameinfo.ConfigName);
|
|
return;
|
|
}
|
|
type = sc.MatchString(CoreKeywords);
|
|
switch (type)
|
|
{
|
|
case TAG_INCLUDE:
|
|
{
|
|
sc.MustGetString();
|
|
// This is not using sc.Open because it can print a more useful error message when done here
|
|
lump = fileSystem.CheckNumForFullName(sc.String, true);
|
|
if (lump==-1)
|
|
sc.ScriptError("Lump '%s' not found", sc.String);
|
|
|
|
GLDefsParser newscanner(lump, LightAssociations);
|
|
newscanner.lightSizeFactor = lightSizeFactor;
|
|
newscanner.DoParseDefs();
|
|
break;
|
|
}
|
|
#if 0
|
|
case LIGHT_POINT:
|
|
ParsePointLight();
|
|
break;
|
|
case LIGHT_PULSE:
|
|
ParsePulseLight();
|
|
break;
|
|
case LIGHT_FLICKER:
|
|
ParseFlickerLight();
|
|
break;
|
|
case LIGHT_FLICKER2:
|
|
ParseFlickerLight2();
|
|
break;
|
|
case LIGHT_SECTOR:
|
|
ParseSectorLight();
|
|
break;
|
|
case LIGHT_OBJECT:
|
|
ParseObject();
|
|
break;
|
|
case LIGHT_CLEAR:
|
|
// This has been intentionally removed
|
|
break;
|
|
#endif
|
|
case TAG_SHADER:
|
|
ParseShader();
|
|
break;
|
|
case TAG_CLEARSHADERS:
|
|
break;
|
|
#if 0
|
|
case TAG_SKYBOX:
|
|
ParseGldefSkybox();
|
|
break;
|
|
case TAG_GLOW:
|
|
ParseGlow();
|
|
break;
|
|
case TAG_BRIGHTMAP:
|
|
ParseBrightmap();
|
|
break;
|
|
case TAG_MATERIAL:
|
|
ParseMaterial();
|
|
break;
|
|
#endif
|
|
case TAG_HARDWARESHADER:
|
|
ParseHardwareShader();
|
|
break;
|
|
#if 0
|
|
case TAG_DETAIL:
|
|
ParseDetailTexture();
|
|
break;
|
|
case TAG_LIGHTSIZEFACTOR:
|
|
lightSizeFactor = ParseFloat(sc);
|
|
break;
|
|
case TAG_DISABLE_FB:
|
|
{
|
|
/* not implemented.
|
|
sc.MustGetString();
|
|
const PClass *cls = PClass::FindClass(sc.String);
|
|
if (cls) GetDefaultByType(cls)->renderflags |= RF_NEVERFULLBRIGHT;
|
|
*/
|
|
}
|
|
break;
|
|
case TAG_COLORIZATION:
|
|
ParseColorization(sc);
|
|
break;
|
|
#endif
|
|
default:
|
|
sc.ScriptError("Error parsing defs. Unknown tag: %s.\n", sc.String);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
GLDefsParser(int lumpnum, TArray<FLightAssociation> &la)
|
|
: sc(lumpnum), workingLump(lumpnum), LightAssociations(la)
|
|
{
|
|
}
|
|
};
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
void LoadGLDefs(const char *defsLump)
|
|
{
|
|
TArray<FLightAssociation> LightAssociations;
|
|
int workingLump, lastLump;
|
|
static const char *gldefsnames[] = { "GLDEFS", defsLump, nullptr };
|
|
|
|
lastLump = 0;
|
|
while ((workingLump = fileSystem.FindLumpMulti(gldefsnames, &lastLump)) != -1)
|
|
{
|
|
GLDefsParser sc(workingLump, LightAssociations);
|
|
sc.DoParseDefs();
|
|
}
|
|
#if 0
|
|
InitializeActorLights(LightAssociations);
|
|
#endif
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
void ParseGLDefs()
|
|
{
|
|
const char *defsLump = NULL;
|
|
|
|
#if 0
|
|
LightDefaults.DeleteAndClear();
|
|
AttenuationIsSet = -1;
|
|
#endif
|
|
//gl_DestroyUserShaders(); function says 'todo'
|
|
#if 0
|
|
// should we really use a system like this anymore with the advent of filter folders?
|
|
switch (gameinfo.gametype)
|
|
{
|
|
case GAME_Heretic:
|
|
defsLump = "HTICDEFS";
|
|
break;
|
|
case GAME_Hexen:
|
|
defsLump = "HEXNDEFS";
|
|
break;
|
|
case GAME_Strife:
|
|
defsLump = "STRFDEFS";
|
|
break;
|
|
case GAME_Doom:
|
|
defsLump = "DOOMDEFS";
|
|
break;
|
|
case GAME_Chex:
|
|
defsLump = "CHEXDEFS";
|
|
break;
|
|
default: // silence GCC
|
|
break;
|
|
}
|
|
#endif
|
|
#if 0
|
|
ParseVavoomSkybox();
|
|
#endif
|
|
LoadGLDefs(defsLump);
|
|
}
|