diff --git a/.travis.yml b/.travis.yml
index 956ed21cf..6962cbaff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,7 @@ matrix:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9"
- os: osx
- osx_image: xcode9.4
+ osx_image: xcode10
env:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9"
diff --git a/src/posix/osx/zdoom-info.plist b/src/posix/osx/zdoom-info.plist
index f0bbbf3d9..341a061d7 100644
--- a/src/posix/osx/zdoom-info.plist
+++ b/src/posix/osx/zdoom-info.plist
@@ -48,5 +48,7 @@
NSApplication
NSSupportsAutomaticGraphicsSwitching
+ NSRequiresAquaSystemAppearance
+
diff --git a/src/r_data/models/models_obj.cpp b/src/r_data/models/models_obj.cpp
index 4cc5ffa17..035efd4d4 100644
--- a/src/r_data/models/models_obj.cpp
+++ b/src/r_data/models/models_obj.cpp
@@ -101,8 +101,9 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
FTextureID curMtl = FNullTextureID();
OBJSurface *curSurface = nullptr;
- int aggSurfFaceCount = 0;
- int curSurfFaceCount = 0;
+ unsigned int aggSurfFaceCount = 0;
+ unsigned int curSurfFaceCount = 0;
+ unsigned int curSmoothGroup = 0;
while(sc.GetString())
{
@@ -186,9 +187,25 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
sc.UnGet(); // No 4th side, move back
}
}
+ face.smoothGroup = curSmoothGroup;
faces.Push(face);
curSurfFaceCount += 1;
}
+ else if (sc.Compare("s"))
+ {
+ sc.MustGetString();
+ if (sc.Compare("off"))
+ {
+ curSmoothGroup = 0;
+ }
+ else
+ {
+ sc.UnGet();
+ sc.MustGetNumber();
+ curSmoothGroup = sc.Number;
+ hasSmoothGroups = hasSmoothGroups || curSmoothGroup > 0;
+ }
+ }
}
sc.Close();
@@ -277,11 +294,13 @@ bool FOBJModel::ParseFaceSide(const FString &sideStr, OBJFace &face, int sidx)
else
{
side.normref = -1;
+ hasMissingNormals = true;
}
}
else
{
side.normref = -1;
+ hasMissingNormals = true;
}
}
else
@@ -289,6 +308,7 @@ bool FOBJModel::ParseFaceSide(const FString &sideStr, OBJFace &face, int sidx)
origIdx = atoi(sideStr.GetChars());
side.vertref = ResolveIndex(origIdx, FaceElement::VertexIndex);
side.normref = -1;
+ hasMissingNormals = true;
side.uvref = -1;
}
face.sides[sidx] = side;
@@ -348,15 +368,20 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
surfaces[i].vbStart = vbufsize;
vbufsize += surfaces[i].numTris * 3;
}
+ // Initialize/populate vertFaces
+ if (hasMissingNormals && hasSmoothGroups)
+ {
+ AddVertFaces();
+ }
auto vbuf = renderer->CreateVertexBuffer(false,true);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(vbufsize);
- for (size_t i = 0; i < surfaces.Size(); i++)
+ for (unsigned int i = 0; i < surfaces.Size(); i++)
{
- for (size_t j = 0; j < surfaces[i].numTris; j++)
+ for (unsigned int j = 0; j < surfaces[i].numTris; j++)
{
for (size_t side = 0; side < 3; side++)
{
@@ -372,39 +397,40 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
FVector3 curVvec = RealignVector(verts[vidx]);
FVector2 curUvec = FixUV(uvs[uvidx]);
- FVector3 *nvec = nullptr;
+ FVector3 nvec;
mdv->Set(curVvec.X, curVvec.Y, curVvec.Z, curUvec.X, curUvec.Y);
if (nidx >= 0 && (unsigned int)nidx < norms.Size())
{
- nvec = new FVector3(RealignVector(norms[nidx]));
+ nvec = RealignVector(norms[nidx]);
}
else
{
- // https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
- // Find other sides of triangle
- auto nextSidx = side + 2;
- if (nextSidx >= 3) nextSidx -= 3;
-
- auto lastSidx = side + 1;
- if (lastSidx >= 3) lastSidx -= 3;
-
- OBJFaceSide &nextSide = surfaces[i].tris[j].sides[nextSidx];
- OBJFaceSide &lastSide = surfaces[i].tris[j].sides[lastSidx];
-
- // Cross-multiply the U-vector and V-vector
- FVector3 uvec = RealignVector(verts[nextSide.vertref]) - curVvec;
- FVector3 vvec = RealignVector(verts[lastSide.vertref]) - curVvec;
-
- nvec = new FVector3(uvec ^ vvec);
+ if (surfaces[i].tris[j].smoothGroup == 0)
+ {
+ nvec = CalculateNormalFlat(i, j);
+ }
+ else
+ {
+ nvec = CalculateNormalSmooth(vidx, surfaces[i].tris[j].smoothGroup);
+ }
}
- mdv->SetNormal(nvec->X, nvec->Y, nvec->Z);
- delete nvec;
+ mdv->SetNormal(nvec.X, nvec.Y, nvec.Z);
}
}
delete[] surfaces[i].tris;
}
+
+ // Destroy vertFaces
+ if (hasMissingNormals && hasSmoothGroups)
+ {
+ for (size_t i = 0; i < verts.Size(); i++)
+ {
+ vertFaces[i].Clear();
+ }
+ delete[] vertFaces;
+ }
vbuf->UnlockVertexBuffer();
}
@@ -432,6 +458,7 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
surf.tris[triIdx].sideCount = 3;
if (faces[i].sideCount == 3)
{
+ surf.tris[triIdx].smoothGroup = faces[i].smoothGroup;
memcpy(surf.tris[triIdx].sides, faces[i].sides, sizeof(OBJFaceSide) * 3);
}
else if (faces[i].sideCount == 4) // Triangulate face
@@ -443,6 +470,7 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
delete[] triangulated;
triIdx += 1; // Filling out two faces
}
+ DPrintf(DMSG_SPAMMY, "Smooth group: %d\n", surf.tris[triIdx].smoothGroup);
}
}
@@ -455,7 +483,9 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
void FOBJModel::TriangulateQuad(const OBJFace &quad, OBJFace *tris)
{
tris[0].sideCount = 3;
+ tris[0].smoothGroup = quad.smoothGroup;
tris[1].sideCount = 3;
+ tris[1].smoothGroup = quad.smoothGroup;
int tsidx[2][3] = {{0, 1, 3}, {1, 2, 3}};
@@ -470,6 +500,26 @@ void FOBJModel::TriangulateQuad(const OBJFace &quad, OBJFace *tris)
}
}
+/**
+ * Add the vertices of all surfaces' triangles to the array of vertex->triangle references
+ */
+void FOBJModel::AddVertFaces() {
+ // Initialize and populate vertFaces - this array stores references to triangles per vertex
+ vertFaces = new TArray[verts.Size()];
+ for (unsigned int i = 0; i < surfaces.Size(); i++)
+ {
+ for (unsigned int j = 0; j < surfaces[i].numTris; j++)
+ {
+ OBJTriRef otr = OBJTriRef(i, j);
+ for (size_t k = 0; k < surfaces[i].tris[j].sideCount; k++)
+ {
+ int vidx = surfaces[i].tris[j].sides[k].vertref;
+ vertFaces[vidx].Push(otr);
+ }
+ }
+ }
+}
+
/**
* Re-align a vector to match MD3 alignment
*
@@ -494,6 +544,65 @@ inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
return vecToRealign;
}
+/**
+ * Calculate the surface normal for a triangle
+ *
+ * @param surfIdx The surface index
+ * @param triIdx The triangle Index
+ * @return The surface normal vector
+ */
+FVector3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
+{
+ // https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
+ int curVert = surfaces[surfIdx].tris[triIdx].sides[0].vertref;
+ int nextVert = surfaces[surfIdx].tris[triIdx].sides[2].vertref;
+ int lastVert = surfaces[surfIdx].tris[triIdx].sides[1].vertref;
+
+ // Cross-multiply the U-vector and V-vector
+ FVector3 curVvec = RealignVector(verts[curVert]);
+ FVector3 uvec = RealignVector(verts[nextVert]) - curVvec;
+ FVector3 vvec = RealignVector(verts[lastVert]) - curVvec;
+
+ return uvec ^ vvec;
+}
+
+/**
+ * Calculate the surface normal for a triangle
+ *
+ * @param otr A reference to the surface, and a triangle within that surface, as an OBJTriRef
+ * @return The surface normal vector
+ */
+FVector3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
+{
+ return CalculateNormalFlat(otr.surf, otr.tri);
+}
+
+/**
+ * Calculate the normal of a vertex in a specific smooth group
+ *
+ * @param vidx The index of the vertex in the array of vertices
+ * @param smoothGroup The smooth group number
+ */
+FVector3 FOBJModel::CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup)
+{
+ unsigned int connectedFaces = 0;
+ TArray& vTris = vertFaces[vidx];
+
+ FVector3 vNormal(0,0,0);
+ for (size_t face = 0; face < vTris.Size(); face++)
+ {
+ OBJFace& tri = surfaces[vTris[face].surf].tris[vTris[face].tri];
+ if (tri.smoothGroup == smoothGroup)
+ {
+ FVector3 fNormal = CalculateNormalFlat(vTris[face]);
+ connectedFaces += 1;
+ vNormal += fNormal;
+ }
+ }
+ vNormal /= (float)connectedFaces;
+ return vNormal;
+}
+
/**
* Find the index of the frame with the given name
*
diff --git a/src/r_data/models/models_obj.h b/src/r_data/models/models_obj.h
index d6d68a58e..01a6e03cf 100644
--- a/src/r_data/models/models_obj.h
+++ b/src/r_data/models/models_obj.h
@@ -30,6 +30,8 @@ class FOBJModel : public FModel
{
private:
const char *newSideSep = "$"; // OBJ side separator is /, which is parsed as a line comment by FScanner if two of them are next to each other.
+ bool hasMissingNormals;
+ bool hasSmoothGroups;
enum class FaceElement
{
@@ -38,6 +40,14 @@ private:
VNormalIndex
};
+ struct OBJTriRef
+ {
+ unsigned int surf;
+ unsigned int tri;
+ OBJTriRef(): surf(0), tri(0) {}
+ OBJTriRef(unsigned int surf, unsigned int tri): surf(surf), tri(tri) {}
+ bool operator== (OBJTriRef other) { return surf == other.surf && tri == other.tri; }
+ };
struct OBJFaceSide
{
int vertref;
@@ -47,7 +57,9 @@ private:
struct OBJFace
{
unsigned int sideCount;
+ unsigned int smoothGroup;
OBJFaceSide sides[4];
+ OBJFace(): sideCount(0), smoothGroup(0) {}
};
struct OBJSurface // 1 surface per 'usemtl'
{
@@ -66,16 +78,21 @@ private:
TArray faces;
TArray surfaces;
FScanner sc;
+ TArray* vertFaces;
+ int ResolveIndex(int origIndex, FaceElement el);
template void ParseVector(TArray &array);
bool ParseFaceSide(const FString &side, OBJFace &face, int sidx);
void ConstructSurfaceTris(OBJSurface &surf);
- int ResolveIndex(int origIndex, FaceElement el);
+ void AddVertFaces();
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
FVector3 RealignVector(FVector3 vecToRealign);
FVector2 FixUV(FVector2 vecToRealign);
+ FVector3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
+ FVector3 CalculateNormalFlat(OBJTriRef otr);
+ FVector3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
public:
- FOBJModel() {}
+ FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {}
~FOBJModel();
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
int FindFrame(const char* name) override;
diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu
index 6ce6fcf23..6a58cb0cf 100644
--- a/wadsrc/static/language.enu
+++ b/wadsrc/static/language.enu
@@ -2442,7 +2442,9 @@ OPTVAL_FOO_DUMB = "foo_dumb";
OPTVAL_ALIASING = "Aliasing";
OPTVAL_LINEAR = "Linear";
OPTVAL_NEAREST = "Nearest";
-OPTVAL_PCF = "PCF";
+OPTVAL_PCF_LOW = "PCF (Low)";
+OPTVAL_PCF_MEDIUM = "PCF (Medium)";
+OPTVAL_PCF_HIGH = "PCF (High)";
OPTVAL_CUBIC = "Cubic";
OPTVAL_BLEP = "Band-limited step";
OPTVAL_LINEARSLOW = "Linear (Slower)";
diff --git a/wadsrc/static/language.fr b/wadsrc/static/language.fr
index c43a3c222..22cd852d8 100644
--- a/wadsrc/static/language.fr
+++ b/wadsrc/static/language.fr
@@ -2419,7 +2419,9 @@ OPTVAL_DEFAULT = "Défaut";
OPTVAL_SOUNDSYSTEM = "Système Sonore";
OPTVAL_LINEAR = "Linéaire";
OPTVAL_NEAREST = "Nearest";
-OPTVAL_PCF = "PCF";
+OPTVAL_PCF_LOW = "PCF (Low)";
+OPTVAL_PCF_MEDIUM = "PCF (Medium)";
+OPTVAL_PCF_HIGH = "PCF (High)";
OPTVAL_CUBIC = "Cubique";
OPTVAL_BLEP = "Step limité sur bande";
OPTVAL_LINEARSLOW = "Linéaire (Lent)";
diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt
index f210af477..640b6186c 100644
--- a/wadsrc/static/menudef.txt
+++ b/wadsrc/static/menudef.txt
@@ -2261,7 +2261,9 @@ OptionValue ShadowMapQuality
OptionValue ShadowMapFilter
{
0, "$OPTVAL_NEAREST"
- 1, "$OPTVAL_PCF"
+ 1, "$OPTVAL_PCF_LOW"
+ 2, "$OPTVAL_PCF_MEDIUM"
+ 3, "$OPTVAL_PCF_HIGH"
}
diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp
index c8ad439cb..228d7b02d 100644
--- a/wadsrc/static/shaders/glsl/main.fp
+++ b/wadsrc/static/shaders/glsl/main.fp
@@ -178,47 +178,26 @@ float shadowDirToU(vec2 dir)
}
}
-float sampleShadowmap(vec2 dir, float v)
+vec2 shadowUToDir(float u)
{
- float u = shadowDirToU(dir);
- float dist2 = dot(dir, dir);
- return step(dist2, texture(ShadowMap, vec2(u, v)).x);
+ u *= 4.0;
+ vec2 raydir;
+ switch (int(u))
+ {
+ case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break;
+ case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
+ case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
+ case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
+ }
+ return raydir;
}
-float sampleShadowmapLinear(vec2 dir, float v)
+float sampleShadowmap(vec3 planePoint, float v)
{
- float u = shadowDirToU(dir);
- float dist2 = dot(dir, dir);
+ float bias = 1.0;
+ float negD = dot(vWorldNormal.xyz, planePoint);
- vec2 isize = textureSize(ShadowMap, 0);
- vec2 size = vec2(isize);
-
- vec2 fetchPos = vec2(u, v) * size - vec2(0.5, 0.0);
- if (fetchPos.x < 0.0)
- fetchPos.x += size.x;
-
- ivec2 ifetchPos = ivec2(fetchPos);
- int y = ifetchPos.y;
-
- float t = fract(fetchPos.x);
- int x0 = ifetchPos.x;
- int x1 = ifetchPos.x + 1;
- if (x1 == isize.x)
- x1 = 0;
-
- float depth0 = texelFetch(ShadowMap, ivec2(x0, y), 0).x;
- float depth1 = texelFetch(ShadowMap, ivec2(x1, y), 0).x;
- return mix(step(dist2, depth0), step(dist2, depth1), t);
-}
-
-vec2 shadowmapAdjustedRay(vec4 lightpos)
-{
- vec3 planePoint = pixelpos.xyz - lightpos.xyz;
-
- if (dot(planePoint.xz, planePoint.xz) < 1.0)
- return planePoint.xz * 0.5;
-
- vec3 ray = normalize(planePoint);
+ vec3 ray = planePoint;
vec2 isize = textureSize(ShadowMap, 0);
float scale = float(isize.x) * 0.25;
@@ -239,51 +218,70 @@ vec2 shadowmapAdjustedRay(vec4 lightpos)
ray.x = sign(ray.x);
}
- float bias = 1.0;
- float negD = dot(vWorldNormal.xyz, planePoint);
float t = negD / dot(vWorldNormal.xyz, ray) - bias;
- return ray.xz * t;
+ vec2 dir = ray.xz * t;
+
+ float u = shadowDirToU(dir);
+ float dist2 = dot(dir, dir);
+ return step(dist2, texture(ShadowMap, vec2(u, v)).x);
}
-//===========================================================================
-//
-// Check if light is in shadow using Percentage Closer Filtering (PCF)
-//
-//===========================================================================
+float sampleShadowmapPCF(vec3 planePoint, float v)
+{
+ float bias = 1.0;
+ float negD = dot(vWorldNormal.xyz, planePoint);
+
+ vec3 ray = planePoint;
+
+ if (abs(ray.z) > abs(ray.x))
+ ray.y = ray.y / abs(ray.z);
+ else
+ ray.y = ray.y / abs(ray.x);
+
+ vec2 isize = textureSize(ShadowMap, 0);
+ float scale = float(isize.x);
+ float texelPos = floor(shadowDirToU(ray.xz) * scale);
+
+ float sum = 0.0;
+ float step_count = uShadowmapFilter;
+
+ texelPos -= step_count + 0.5;
+ for (float x = -step_count; x <= step_count; x++)
+ {
+ float u = fract(texelPos / scale);
+ vec2 dir = shadowUToDir(u);
+
+ ray.x = dir.x;
+ ray.z = dir.y;
+ float t = negD / dot(vWorldNormal.xyz, ray) - bias;
+ dir = ray.xz * t;
+
+ float dist2 = dot(dir, dir);
+ sum += step(dist2, texture(ShadowMap, vec2(u, v)).x);
+ texelPos++;
+ }
+ return sum / (uShadowmapFilter * 2.0 + 1.0);
+}
float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
{
if (shadowIndex >= 1024.0)
return 1.0; // No shadowmap available for this light
- float v = (shadowIndex + 0.5) / 1024.0;
+ vec3 planePoint = pixelpos.xyz - lightpos.xyz;
- vec2 ray = shadowmapAdjustedRay(lightpos);
+ if (dot(planePoint.xz, planePoint.xz) < 1.0)
+ return 1.0; // Light is too close
+
+ float v = (shadowIndex + 0.5) / 1024.0;
if (uShadowmapFilter <= 0)
{
- return sampleShadowmap(ray, v);
- //return sampleShadowmapLinear(ray, v);
+ return sampleShadowmap(planePoint, v);
}
else
{
- float length = length(ray);
- if (length < 3.0)
- return 1.0;
-
- vec2 dir = ray / length * min(length / 50.0, 1.0); // avoid sampling behind light
-
- vec2 normal = vec2(-dir.y, dir.x);
- vec2 bias = dir * 10.0;
-
- float sum = 0.0;
- float step_count = ((uShadowmapFilter - 1) / 2.);
-
- for (float x = -step_count; x <= step_count; x++)
- {
- sum += sampleShadowmap(ray + normal * x /*- bias * abs(x)*/, v);
- }
- return sum / uShadowmapFilter;
+ return sampleShadowmapPCF(planePoint, v);
}
}
diff --git a/wadsrc/static/zscript/hexen/spike.txt b/wadsrc/static/zscript/hexen/spike.txt
index cb8df17e2..a411dbf3f 100644
--- a/wadsrc/static/zscript/hexen/spike.txt
+++ b/wadsrc/static/zscript/hexen/spike.txt
@@ -179,26 +179,29 @@ class ThrustFloor : Actor
while (it.Next())
{
let targ = it.thing;
- double blockdist = radius + it.thing.radius;
- if (abs(targ.pos.x - it.Position.X) >= blockdist || abs(targ.pos.y - it.Position.Y) >= blockdist)
- continue;
-
- // Q: Make this z-aware for everything? It never was before.
- if (targ.pos.z + targ.height < pos.z || targ.pos.z > pos.z + height)
+ if (targ != null)
{
- if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
+ double blockdist = radius + targ.radius;
+ if (abs(targ.pos.x - it.Position.X) >= blockdist || abs(targ.pos.y - it.Position.Y) >= blockdist)
continue;
+
+ // Q: Make this z-aware for everything? It never was before.
+ if (targ.pos.z + targ.height < pos.z || targ.pos.z > pos.z + height)
+ {
+ if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
+ continue;
+ }
+
+ if (!targ.bShootable)
+ continue;
+
+ if (targ == self)
+ continue; // don't clip against self
+
+ int newdam = targ.DamageMobj (self, self, 10001, 'Crush');
+ targ.TraceBleed (newdam > 0 ? newdam : 10001, null);
+ args[1] = 1; // Mark thrust thing as bloody
}
-
- if (!targ.bShootable)
- continue;
-
- if (targ == self)
- continue; // don't clip against self
-
- int newdam = targ.DamageMobj (self, self, 10001, 'Crush');
- targ.TraceBleed (newdam > 0 ? newdam : 10001, null);
- args[1] = 1; // Mark thrust thing as bloody
}
}
}
diff --git a/wadsrc/static/zscript/menu/optionmenu.txt b/wadsrc/static/zscript/menu/optionmenu.txt
index 3e1853735..f73035ab0 100644
--- a/wadsrc/static/zscript/menu/optionmenu.txt
+++ b/wadsrc/static/zscript/menu/optionmenu.txt
@@ -540,14 +540,19 @@ class CompatibilityMenu : OptionMenu
class GLTextureGLOptions : OptionMenu
{
private int mWarningIndex;
+ private string mWarningLabel;
override void Init(Menu parent, OptionMenuDescriptor desc)
{
super.Init(parent, desc);
+ // Find index of warning item placeholder
+ mWarningIndex = -1;
+ mWarningLabel = "!HQRESIZE_WARNING!";
+
for (int i=0; i < mDesc.mItems.Size(); ++i)
{
- if (mDesc.mItems[i].mLabel == "!HQRESIZE_WARNING!")
+ if (mDesc.mItems[i].mLabel == mWarningLabel)
{
mWarningIndex = i;
break;
@@ -555,11 +560,22 @@ class GLTextureGLOptions : OptionMenu
}
}
+ override void OnDestroy()
+ {
+ // Restore warning item placeholder
+ if (mWarningIndex >= 0)
+ {
+ mDesc.mItems[mWarningIndex].mLabel = mWarningLabel;
+ }
+
+ Super.OnDestroy();
+ }
+
override void Ticker()
{
Super.Ticker();
- if (mWarningIndex > 0)
+ if (mWarningIndex >= 0)
{
string message;
diff --git a/wadsrc_lights/static/filter/hexen/gldefs.txt b/wadsrc_lights/static/filter/hexen/gldefs.txt
index cc9513d97..fb6cb49c3 100644
--- a/wadsrc_lights/static/filter/hexen/gldefs.txt
+++ b/wadsrc_lights/static/filter/hexen/gldefs.txt
@@ -1545,11 +1545,6 @@ pointlight MANA1
offset 0 36 0
}
-object Mana1
-{
- frame MAN1 { light MANA1 }
-}
-
// Green mana
pointlight MANA2
{
@@ -1559,11 +1554,6 @@ pointlight MANA2
offset 0 36 0
}
-object Mana2
-{
- frame MAN2 { light MANA2 }
-}
-
// Combined mana
pointlight MANA3
{