Merge remote-tracking branch 'origin/master' into asmjit

This commit is contained in:
Magnus Norddahl 2018-11-14 01:23:17 +01:00
commit 99849bc0c5
66 changed files with 1042 additions and 601 deletions

View file

@ -154,31 +154,52 @@ Note: All <bool> fields default to false unless mentioned otherwise.
sidedef
{
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
// When global texture offsets are used they will
// be added on top of these values.
light = <integer>; // This side's light level. Default is 0.
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
// relative to the owning sector's light level.
lightfog = <bool>; // true = This side's relative lighting is used even in
// foggy sectors. Default is to disable relative
// lighting in foggy sectors.
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
smoothlighting = <bool>; // Use smooth fake contrast.
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
wrapmidtex = <bool>; // Side's mid textures are wrapped.
nodecals = <bool>; // Disables decals on the sidedef.
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
// When global texture offsets are used they will
// be added on top of these values.
light = <integer>; // This side's light level. Default is 0.
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
// relative to the owning sector's light level.
lightfog = <bool>; // true = This side's relative lighting is used even in
// foggy sectors. Default is to disable relative
// lighting in foggy sectors.
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
smoothlighting = <bool>; // Use smooth fake contrast.
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
wrapmidtex = <bool>; // Side's mid textures are wrapped.
nodecals = <bool>; // Disables decals on the sidedef.
nogradient_top = <bool>; // disables color gradient on upper tier. (Hardware rendering only.)
flipgradient_top = <bool>; // flips gradient colors on upper tier. (Hardware rendering only.)
clampgradient_top = <bool>; // clamps gradient on upper tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_top = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_top = <int>; // Material color of the top of the upper tier.
lowercolor_top = <int>; // Material color of the bottom of the upper tier. (Hardware rendering only.)
nogradient_mid = <bool>; // disables color gradient on middle tier. (Hardware rendering only.)
flipgradient_mid = <bool>; // flips gradient colors on middle tier. (Hardware rendering only.)
clampgradient_mid = <bool>; // clamps gradient on middle tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_mid = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_mid = <int>; // Material color of the top of the middle tier.
lowercolor_mid = <int>; // Material color of the bottom of the middle tier. (Hardware rendering only.)
nogradient_bottom = <bool>; // disables color gradient on lower tier. (Hardware rendering only.)
flipgradient_bottom = <bool>; // flips gradient colors on lower tier. (Hardware rendering only.)
clampgradient_bottom = <bool>;// clamps gradient on lower tier to actual bounds (default is the entire front sector height, hardware rendering only.)
useowncolors_bottom = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
uppercolor_bottom = <int>; // Material color of the top of the lower tier.
lowercolor_bottom = <int>; // Material color of the bottom of the lower tier. (Hardware rendering only.)
}
sector
@ -300,8 +321,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scalex = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scaley = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).

View file

@ -62,6 +62,7 @@
#include "a_keys.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "earcut.hpp"
//=============================================================================
@ -2054,6 +2055,7 @@ sector_t * AM_FakeFlat(AActor *viewer, sector_t * sec, sector_t * dest)
void AM_drawSubsectors()
{
static TArray<FVector2> points;
std::vector<uint32_t> indices;
double scale = scale_mtof;
DAngle rotation;
sector_t tempsec;
@ -2067,27 +2069,28 @@ void AM_drawSubsectors()
auto &subsectors = level.subsectors;
for (unsigned i = 0; i < subsectors.Size(); ++i)
{
if (subsectors[i].flags & SSECF_POLYORG)
auto sub = &subsectors[i];
if (sub->flags & SSECF_POLYORG)
{
continue;
}
if ((!(subsectors[i].flags & SSECMF_DRAWN) || (subsectors[i].flags & SSECF_HOLE) || (subsectors[i].render_sector->MoreFlags & SECMF_HIDDEN)) && am_cheat == 0)
if ((!(sub->flags & SSECMF_DRAWN) || (sub->flags & SSECF_HOLE) || (sub->render_sector->MoreFlags & SECMF_HIDDEN)) && am_cheat == 0)
{
continue;
}
if (am_portaloverlay && subsectors[i].render_sector->PortalGroup != MapPortalGroup && subsectors[i].render_sector->PortalGroup != 0)
if (am_portaloverlay && sub->render_sector->PortalGroup != MapPortalGroup && sub->render_sector->PortalGroup != 0)
{
continue;
}
// Fill the points array from the subsector.
points.Resize(subsectors[i].numlines);
for (uint32_t j = 0; j < subsectors[i].numlines; ++j)
points.Resize(sub->numlines);
for (uint32_t j = 0; j < sub->numlines; ++j)
{
mpoint_t pt = { subsectors[i].firstline[j].v1->fX(),
subsectors[i].firstline[j].v1->fY() };
mpoint_t pt = { sub->firstline[j].v1->fX(),
sub->firstline[j].v1->fY() };
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
{
AM_rotatePoint(&pt.x, &pt.y);
@ -2096,7 +2099,7 @@ void AM_drawSubsectors()
points[j].Y = float(f_y + (f_h - (pt.y - m_y) * scale));
}
// For lighting and texture determination
sector_t *sec = AM_FakeFlat(players[consoleplayer].camera, subsectors[i].render_sector, &tempsec);
sector_t *sec = AM_FakeFlat(players[consoleplayer].camera, sub->render_sector, &tempsec);
floorlight = sec->GetFloorLight();
// Find texture origin.
originpt.x = -sec->GetXOffset(sector_t::floor);
@ -2123,7 +2126,7 @@ void AM_drawSubsectors()
double secx;
double secy;
double seczb, seczt;
auto &vp = r_viewpoint;
auto &vp = r_viewpoint;
double cmpz = vp.Pos.Z;
if (players[consoleplayer].camera && sec == players[consoleplayer].camera->Sector)
@ -2144,7 +2147,7 @@ void AM_drawSubsectors()
{
F3DFloor *rover = sec->e->XFloor.ffloors[i];
if (!(rover->flags & FF_EXISTS)) continue;
if (rover->flags & (FF_FOG|FF_THISINSIDE)) continue;
if (rover->flags & (FF_FOG | FF_THISINSIDE)) continue;
if (!(rover->flags & FF_RENDERPLANES)) continue;
if (rover->alpha == 0) continue;
double roverz = rover->top.plane->ZatPoint(secx, secy);
@ -2194,7 +2197,7 @@ void AM_drawSubsectors()
// If this subsector has not actually been seen yet (because you are cheating
// to see it on the map), tint and desaturate it.
if (!(subsectors[i].flags & SSECMF_DRAWN))
if (!(sub->flags & SSECMF_DRAWN))
{
colormap.LightColor = PalEntry(
(colormap.LightColor.r + 255) / 2,
@ -2210,8 +2213,28 @@ void AM_drawSubsectors()
// Draw the polygon.
FTexture *pic = TexMan(maptex);
if (pic != NULL && pic->UseType != ETextureType::Null)
if (pic != nullptr && pic->UseType != ETextureType::Null)
{
// Hole filling "subsectors" are not necessarily convex so they require real triangulation.
// These things are extremely rare so performance is secondary here.
if (sub->flags & SSECF_HOLE && sub->numlines > 3)
{
using Point = std::pair<double, double>;
std::vector<std::vector<Point>> polygon;
std::vector<Point> *curPoly;
polygon.resize(1);
curPoly = &polygon.back();
curPoly->resize(points.Size());
for (unsigned i = 0; i < points.Size(); i++)
{
(*curPoly)[i] = { points[i].X, points[i].Y };
}
indices = mapbox::earcut(polygon);
}
else indices.clear();
screen->FillSimplePoly(TexMan(maptex),
&points[0], points.Size(),
originx, originy,
@ -2221,8 +2244,8 @@ void AM_drawSubsectors()
colormap,
flatcolor,
floorlight,
f_y + f_h
);
f_y + f_h,
indices.data(), indices.size());
}
}
}

View file

@ -150,9 +150,9 @@ void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile)
void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline)
{
// Strip out any color escape sequences before writing to the log file
char * copy = new char[strlen(outline)+1];
TArray<char> copy(strlen(outline)+1);
const char * srcp = outline;
char * dstp = copy;
char * dstp = copy.Data();
while (*srcp != 0)
{
@ -193,8 +193,7 @@ void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline)
}
*dstp=0;
fputs (copy, LogFile);
delete [] copy;
fputs (copy.Data(), LogFile);
fflush (LogFile);
}

View file

@ -257,7 +257,7 @@ FIWadManager::FIWadManager(const char *fn)
if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "IWADINFO"))
{
// Found one!
ParseIWadInfo(resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize);
ParseIWadInfo(resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize);
break;
}
}
@ -349,7 +349,7 @@ int FIWadManager::CheckIWADInfo(const char *fn)
try
{
FIWADInfo result;
ParseIWadInfo(resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize, &result);
ParseIWadInfo(resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize, &result);
delete resfile;
for (unsigned i = 0, count = mIWadInfos.Size(); i < count; ++i)

View file

@ -1905,7 +1905,7 @@ static FString CheckGameInfo(TArray<FString> & pwads)
if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "GAMEINFO"))
{
// Found one!
FString iwad = ParseGameInfo(pwads, resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize);
FString iwad = ParseGameInfo(pwads, resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize);
delete resfile;
return iwad;
}

View file

@ -32,29 +32,24 @@
class FBurnTexture : public FTexture
{
uint32_t *WorkBuffer;
TArray<uint32_t> WorkBuffer;
public:
FBurnTexture(int w, int h)
: WorkBuffer(w*h, true)
{
Width = w;
Height = h;
WorkBuffer = new uint32_t[w * h];
}
~FBurnTexture()
{
delete [] WorkBuffer;
}
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override
{
bmp->CopyPixelDataRGB(x, y, (uint8_t*)WorkBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
bmp->CopyPixelDataRGB(x, y, (uint8_t*)WorkBuffer.Data(), Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
return 0;
}
uint32_t *GetBuffer()
{
return WorkBuffer;
return WorkBuffer.Data();
}
};

View file

@ -184,6 +184,14 @@ public:
return mReader->Read(buffer, (long)len);
}
TArray<uint8_t> Read(size_t len)
{
TArray<uint8_t> buffer((int)len, true);
Size length = mReader->Read(&buffer[0], (long)len);
buffer.Clamp((int)length);
return buffer;
}
TArray<uint8_t> Read()
{
TArray<uint8_t> buffer(mReader->Length, true);

View file

@ -53,6 +53,7 @@
#include "hwrenderer/postprocessing/hw_shadowmapshader.h"
#include "hwrenderer/data/flatvertices.h"
#include "hwrenderer/scene/hw_skydome.h"
#include "hwrenderer/scene/hw_fakeflat.h"
#include "gl/shaders/gl_postprocessshaderinstance.h"
#include "gl/textures/gl_samplers.h"
#include "hwrenderer/dynlights/hw_lightbuffer.h"
@ -231,6 +232,8 @@ sector_t *FGLRenderer::RenderView(player_t* player)
}
else
{
hw_ClearFakeFlat();
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
checkBenchActive();
@ -302,6 +305,7 @@ void FGLRenderer::BindToFrameBuffer(FMaterial *mat)
void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
{
// This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene.
FMaterial * gltex = FMaterial::ValidateTexture(tex, false);
int width = gltex->TextureWidth();
@ -343,7 +347,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
// Switch to render buffers dimensioned for the savepic
mBuffers = mSaveBuffers;
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
hw_ClearFakeFlat();
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
gl_RenderState.SetVertexBuffer(screen->mVertexData);
screen->mVertexData->Reset();
screen->mLights->Clear();

View file

@ -122,8 +122,6 @@ private:
};
#include "hwrenderer/scene/hw_fakeflat.h"
struct TexFilter_s
{
int minfilter;

View file

@ -138,7 +138,6 @@ bool FGLRenderState::ApplyShader()
activeShader->muLightParms.Set(mLightParms);
activeShader->muFogColor.Set(mFogColor);
activeShader->muObjectColor.Set(mObjectColor);
activeShader->muObjectColor2.Set(mObjectColor2);
activeShader->muDynLightColor.Set(mDynColor.vec);
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
@ -151,6 +150,8 @@ bool FGLRenderState::ApplyShader()
{
activeShader->muGlowTopColor.Set(mGlowTop.vec);
activeShader->muGlowBottomColor.Set(mGlowBottom.vec);
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
activeShader->currentglowstate = 1;
}
else if (activeShader->currentglowstate)
@ -160,10 +161,18 @@ bool FGLRenderState::ApplyShader()
activeShader->muGlowBottomColor.Set(nulvec);
activeShader->currentglowstate = 0;
}
if (mGlowEnabled || mObjectColor2.a != 0)
if (mGradientEnabled)
{
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
activeShader->muObjectColor2.Set(mObjectColor2);
activeShader->muGradientTopPlane.Set(mGradientTopPlane.vec);
activeShader->muGradientBottomPlane.Set(mGradientBottomPlane.vec);
activeShader->currentgradientstate = 1;
}
else if (activeShader->currentgradientstate)
{
activeShader->muObjectColor2.Set(0);
activeShader->currentgradientstate = 0;
}
if (mSplitEnabled)

View file

@ -93,6 +93,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
i_data += "uniform vec4 uGlowBottomPlane;\n";
i_data += "uniform vec4 uGlowBottomColor;\n";
i_data += "uniform vec4 uGradientTopPlane;\n";
i_data += "uniform vec4 uGradientBottomPlane;\n";
i_data += "uniform vec4 uSplitTopPlane;\n";
i_data += "uniform vec4 uSplitBottomPlane;\n";
@ -335,6 +338,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
muGlowTopColor.Init(hShader, "uGlowTopColor");
muGlowBottomPlane.Init(hShader, "uGlowBottomPlane");
muGlowTopPlane.Init(hShader, "uGlowTopPlane");
muGradientBottomPlane.Init(hShader, "uGradientBottomPlane");
muGradientTopPlane.Init(hShader, "uGradientTopPlane");
muSplitBottomPlane.Init(hShader, "uSplitBottomPlane");
muSplitTopPlane.Init(hShader, "uSplitTopPlane");
muInterpolationFactor.Init(hShader, "uInterpolationFactor");

View file

@ -249,6 +249,8 @@ class FShader
FUniform4f muGlowTopColor;
FUniform4f muGlowBottomPlane;
FUniform4f muGlowTopPlane;
FUniform4f muGradientBottomPlane;
FUniform4f muGradientTopPlane;
FUniform4f muSplitBottomPlane;
FUniform4f muSplitTopPlane;
FBufferedUniform1f muInterpolationFactor;
@ -266,6 +268,7 @@ public:
int fakevb_index;
private:
int currentglowstate = 0;
int currentgradientstate = 0;
int currentsplitstate = 0;
int currentcliplinestate = 0;
int currentfixedcolormap = 0;

View file

@ -53,12 +53,14 @@ static void CreateVerticesForSubsector(subsector_t *sub, VertexContainer &gen, i
using Point = std::pair<double, double>;
std::vector<std::vector<Point>> polygon;
std::vector<Point> *curPoly;
polygon.resize(1);
curPoly = &polygon.back();
curPoly->resize(sub->numlines);
for (unsigned i = 0; i < sub->numlines; i++)
{
polygon.resize(1);
curPoly = &polygon.back();
curPoly->push_back({ sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() });
(*curPoly)[i] = { sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() };
}
auto indices = mapbox::earcut(polygon);
for (auto vti : indices)

View file

@ -96,7 +96,7 @@ static RenderJobQueue jobQueue; // One static queue is sufficient here. This cod
void HWDrawInfo::WorkerThread()
{
sector_t fakefront, fakeback, *front, *back;
sector_t *front, *back;
WTTotal.Clock();
isWorkerThread = true; // for adding asserts in GL API code. The worker thread may never call any GL API.
@ -118,6 +118,8 @@ void HWDrawInfo::WorkerThread()
_mm_pause();
_mm_pause();
}
// Note that the main thread MUST have prepared the fake sectors that get used below!
// This worker thread cannot prepare them itself without costly synchronization.
else switch (job->type)
{
case RenderJob::TerminateJob:
@ -130,7 +132,7 @@ void HWDrawInfo::WorkerThread()
SetupWall.Clock();
wall.sub = job->sub;
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
front = hw_FakeFlat(job->sub->sector, in_area, false);
auto seg = job->seg;
if (seg->backsector)
{
@ -140,7 +142,7 @@ void HWDrawInfo::WorkerThread()
}
else
{
back = hw_FakeFlat(seg->backsector, &fakeback, in_area, true);
back = hw_FakeFlat(seg->backsector, in_area, true);
}
}
else back = nullptr;
@ -156,7 +158,7 @@ void HWDrawInfo::WorkerThread()
GLFlat flat;
SetupFlat.Clock();
flat.section = job->sub->section;
front = hw_FakeFlat(job->sub->render_sector, &fakefront, in_area, false);
front = hw_FakeFlat(job->sub->render_sector, in_area, false);
flat.ProcessSector(this, front);
SetupFlat.Unclock();
break;
@ -164,14 +166,14 @@ void HWDrawInfo::WorkerThread()
case RenderJob::SpriteJob:
SetupSprite.Clock();
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
front = hw_FakeFlat(job->sub->sector, in_area, false);
RenderThings(job->sub, front);
SetupSprite.Unclock();
break;
case RenderJob::ParticleJob:
SetupSprite.Clock();
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
front = hw_FakeFlat(job->sub->sector, in_area, false);
RenderParticles(job->sub, front);
SetupSprite.Unclock();
break;
@ -228,7 +230,6 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
#endif
sector_t * backsector = nullptr;
sector_t bs;
if (portalclip)
{
@ -291,7 +292,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
// clipping checks are only needed when the backsector is not the same as the front sector
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
backsector = hw_FakeFlat(seg->backsector, &bs, in_area, true);
backsector = hw_FakeFlat(seg->backsector, in_area, true);
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
{
@ -575,7 +576,6 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
{
sector_t * sector;
sector_t * fakesector;
sector_t fake;
#ifdef _DEBUG
if (sub->sector->sectornum==931)
@ -600,7 +600,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
}
if (mClipper->IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
fakesector=hw_FakeFlat(sector, &fake, in_area, false);
fakesector=hw_FakeFlat(sector, in_area, false);
if (mClipPortal)
{
@ -677,7 +677,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
sector = sub->render_sector;
// the planes of this subsector are faked to belong to another sector
// This means we need the heightsec parts and light info of the render sector, not the actual one.
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
fakesector = hw_FakeFlat(sector, in_area, false);
}
uint8_t &srf = section_renderflags[level.sections.SectionIndex(sub->section)];

View file

@ -95,7 +95,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
for (unsigned k = 0; k < lightlist.Size(); k++)
{
secplane_t &lowplane = k == lightlist.Size() - 1 ? bottomplane : lightlist[k + 1].plane;
secplane_t &lowplane = k == lightlist.Size() - 1 ? frontsector->floorplane : lightlist[k + 1].plane;
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
@ -404,7 +404,7 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
gldecal->alpha = decal->Alpha;
gldecal->zcenter = zpos - decalheight * 0.5f;
gldecal->bottomplane = bottomplane;
gldecal->frontsector = frontsector;
gldecal->Normal = normal;
gldecal->lightlist = lightlist;
memcpy(gldecal->dv, dv, sizeof(dv));

View file

@ -193,8 +193,6 @@ private:
subsector_t *currentsubsector; // used by the line processing code.
sector_t *currentsector;
sector_t fakesec; // this is a struct member because it gets used in recursively called functions so it cannot be put on the stack.
void WorkerThread();
void UnclipSubsector(subsector_t *sub);

View file

@ -36,6 +36,7 @@
#include "hwrenderer/utility/hw_clock.h"
#include "hw_renderstate.h"
#include "hw_drawinfo.h"
#include "hw_fakeflat.h"
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.

View file

@ -186,7 +186,6 @@ public:
};
secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows.
// these are not the same as ytop and ybottom!!!
float zceil[2];
@ -198,6 +197,7 @@ public:
public:
seg_t * seg; // this gives the easiest access to all other structs involved
subsector_t * sub; // For polyobjects
sector_t *frontsector, *backsector;
//private:
void PutWall(HWDrawInfo *di, bool translucent);
@ -411,7 +411,7 @@ struct GLDecal
int rellight;
float alpha;
FColormap Colormap;
secplane_t bottomplane;
sector_t *frontsector;
FVector3 Normal;
void DrawDecal(HWDrawInfo *di, FRenderState &state);

View file

@ -36,6 +36,9 @@
#include "hwrenderer/utility/hw_cvars.h"
#include "r_utility.h"
static sector_t **fakesectorbuffer;
extern thread_local bool isWorkerThread;
//==========================================================================
//
@ -182,6 +185,24 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto
return area_default;
}
//==========================================================================
//
//
//
//==========================================================================
static FMemArena FakeSectorAllocator(20 * sizeof(sector_t));
static sector_t *allocateSector(sector_t *sec)
{
if (fakesectorbuffer == nullptr)
{
fakesectorbuffer = (sector_t**)FakeSectorAllocator.Alloc(level.sectors.Size() * sizeof(sector_t*));
memset(fakesectorbuffer, 0, level.sectors.Size() * sizeof(sector_t*));
}
auto sectornum = sec->sectornum;
fakesectorbuffer[sectornum] = (sector_t*)FakeSectorAllocator.Alloc(sizeof(sector_t));
return fakesectorbuffer[sectornum];
}
//==========================================================================
//
@ -189,7 +210,8 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto
// by hardware rendering
//
//==========================================================================
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back)
sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy)
{
if (!sec->GetHeightSec() || sec->heightsec==sec)
{
@ -197,6 +219,8 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
// visual glitches because upper amd lower textures overlap.
if (back && (sec->MoreFlags & SECMF_OVERLAPPING))
{
if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) return fakesectorbuffer[sec->sectornum];
auto dest = localcopy? localcopy : allocateSector(sec);
*dest = *sec;
dest->ceilingplane = sec->floorplane;
dest->ceilingplane.FlipVert();
@ -215,6 +239,12 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
}
#endif
if (fakesectorbuffer && fakesectorbuffer[sec->sectornum])
{
return fakesectorbuffer[sec->sectornum];
}
assert(!(isWorkerThread && localcopy == nullptr));
if (in_area==area_above)
{
if (sec->heightsec->MoreFlags&SECMF_FAKEFLOORONLY /*|| sec->GetTexture(sector_t::ceiling)==skyflatnum*/) in_area=area_normal;
@ -223,11 +253,8 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
int diffTex = (sec->heightsec->MoreFlags & SECMF_CLIPFAKEPLANES);
sector_t * s = sec->heightsec;
#if 0
*dest=*sec; // This will invoke the copy operator which isn't really needed here. Memcpy is faster.
#else
memcpy(dest, sec, sizeof(sector_t));
#endif
auto dest = localcopy ? localcopy : allocateSector(sec);
*dest = *sec;
// Replace floor and ceiling height with control sector's heights.
if (diffTex)
@ -309,7 +336,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
dest->lightlevel = s->lightlevel;
}
if (!back)
//if (!back)
{
dest->SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false);
dest->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;
@ -362,7 +389,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
dest->lightlevel = s->lightlevel;
}
if (!back)
//if (!back)
{
dest->SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false);
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false);
@ -386,3 +413,10 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
}
return dest;
}
void hw_ClearFakeFlat()
{
FakeSectorAllocator.FreeAll();
fakesectorbuffer = nullptr;
}

View file

@ -11,6 +11,7 @@ enum area_t : int
// Global functions.
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
void hw_ClearFakeFlat();
sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr);
area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);

View file

@ -38,8 +38,7 @@
#include "hwrenderer/data/flatvertices.h"
#include "hwrenderer/dynlights/hw_lightbuffer.h"
#include "hwrenderer/scene/hw_portal.h"
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
#include "hw_fakeflat.h"
//==========================================================================
//
@ -53,32 +52,31 @@ void HWDrawInfo::DispatchRenderHacks()
TMap<int, gl_floodrendernode*>::Pair *fpair;
TMap<int, gl_subsectorrendernode*>::Iterator ofi(otherFloorPlanes);
GLFlat glflat;
sector_t fakesec;
glflat.section = nullptr;
while (ofi.NextPair(pair))
{
auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false);
auto sec = hw_FakeFlat(&level.sectors[pair->Key], in_area, false);
glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK);
}
TMap<int, gl_subsectorrendernode*>::Iterator oci(otherCeilingPlanes);
while (ofi.NextPair(pair))
while (oci.NextPair(pair))
{
auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false);
auto sec = hw_FakeFlat(&level.sectors[pair->Key], in_area, false);
glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK);
}
TMap<int, gl_floodrendernode*>::Iterator ffi(floodFloorSegs);
while (ffi.NextPair(fpair))
{
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false);
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], in_area, false);
glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK);
}
TMap<int, gl_floodrendernode*>::Iterator fci(floodCeilingSegs);
while (fci.NextPair(fpair))
{
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false);
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], in_area, false);
glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK);
}
}
@ -336,7 +334,7 @@ bool HWDrawInfo::DoOneSectorUpper(subsector_t * subsec, float Planez, area_t in_
// Note: if this is a real line between sectors
// we can be sure that render_sector is the real sector!
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
// Don't bother with slopes
if (sec->ceilingplane.isSlope()) return false;
@ -394,7 +392,7 @@ bool HWDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez, area_t in_
// Note: if this is a real line between sectors
// we can be sure that render_sector is the real sector!
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
// Don't bother with slopes
if (sec->floorplane.isSlope()) return false;
@ -453,7 +451,7 @@ bool HWDrawInfo::DoFakeBridge(subsector_t * subsec, float Planez, area_t in_area
// Note: if this is a real line between sectors
// we can be sure that render_sector is the real sector!
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
// Don't bother with slopes
if (sec->floorplane.isSlope()) return false;
@ -506,7 +504,7 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t
// Note: if this is a real line between sectors
// we can be sure that render_sector is the real sector!
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
// Don't bother with slopes
if (sec->ceilingplane.isSlope()) return false;
@ -538,8 +536,6 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t
//==========================================================================
void HWDrawInfo::HandleMissingTextures(area_t in_area)
{
sector_t fake;
for (unsigned int i = 0; i < MissingUpperTextures.Size(); i++)
{
if (!MissingUpperTextures[i].seg) continue;
@ -589,7 +585,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
{
// It isn't a hole. Now check whether it might be a fake bridge
sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, &fake, in_area, false);
sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, in_area, false);
float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling);
backsub->validcount = validcount;
@ -655,7 +651,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
{
// It isn't a hole. Now check whether it might be a fake bridge
sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, &fake, in_area, false);
sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, in_area, false);
float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor);
backsub->validcount = validcount;
@ -729,9 +725,8 @@ void HWDrawInfo::CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float plan
void HWDrawInfo::PrepareUpperGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true);
vertex_t * v1, *v2;
@ -786,9 +781,8 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg)
void HWDrawInfo::PrepareLowerGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true);
vertex_t * v1, *v2;
@ -826,13 +820,13 @@ void HWDrawInfo::PrepareLowerGap(seg_t * seg)
CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false);
gl_floodrendernode *node = NewFloodRenderNode();
auto pNode = floodCeilingSegs.CheckKey(fakebsector->sectornum);
auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum);
node->next = pNode? *pNode : nullptr;
node->seg = seg;
node->vertexindex = vertices.second;
floodCeilingSegs[fakebsector->sectornum] = node;
floodFloorSegs[fakebsector->sectornum] = node;
}
//==========================================================================
@ -1220,7 +1214,7 @@ void HWDrawInfo::CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = hw_FakeFlat(sub->render_sector, &fakesec, in_area, false);
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
if (me->GetTexture(sector_t::ceiling) != anchor->GetTexture(sector_t::ceiling) ||
me->ceilingplane != anchor->ceilingplane ||
me->GetCeilingLight() != anchor->GetCeilingLight() ||
@ -1264,7 +1258,7 @@ void HWDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor,
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = hw_FakeFlat(sub->render_sector, &fakesec, in_area, false);
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
if (me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
me->floorplane != anchor->floorplane ||
me->GetFloorLight() != anchor->GetFloorLight() ||
@ -1303,7 +1297,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
validcount++;
for (i=0;i<CeilingStacks.Size (); i++)
{
sector_t *sec = hw_FakeFlat(CeilingStacks[i], &fakesec, in_area, false);
sector_t *sec = hw_FakeFlat(CeilingStacks[i], in_area, false);
auto portal = sec->GetPortalGroup(sector_t::ceiling);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{
@ -1347,7 +1341,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
validcount++;
for (i=0;i<FloorStacks.Size (); i++)
{
sector_t *sec = hw_FakeFlat(FloorStacks[i], &fakesec, in_area, false);
sector_t *sec = hw_FakeFlat(FloorStacks[i], in_area, false);
auto portal = sec->GetPortalGroup(sector_t::floor);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{

View file

@ -127,6 +127,7 @@ protected:
uint8_t mFogEnabled;
uint8_t mTextureEnabled:1;
uint8_t mGlowEnabled : 1;
uint8_t mGradientEnabled : 1;
uint8_t mBrightmapEnabled : 1;
uint8_t mModelMatrixEnabled : 1;
uint8_t mTextureMatrixEnabled : 1;
@ -147,6 +148,7 @@ protected:
FStateVec4 mColor;
FStateVec4 mGlowTop, mGlowBottom;
FStateVec4 mGlowTopPlane, mGlowBottomPlane;
FStateVec4 mGradientTopPlane, mGradientBottomPlane;
FStateVec4 mSplitTopPlane, mSplitBottomPlane;
PalEntry mFogColor;
PalEntry mObjectColor;
@ -172,7 +174,7 @@ public:
void Reset()
{
mTextureEnabled = true;
mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mGradientEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mFogColor.d = -1;
mTextureMode = -1;
mDesaturation = 0;
@ -201,6 +203,8 @@ public:
mGlowBottom.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGlowTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGlowBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGradientTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mGradientBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mSplitTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
mDynColor.Set(0.0f, 0.0f, 0.0f, 0.0f);
@ -290,6 +294,11 @@ public:
mGlowEnabled = on;
}
void EnableGradient(bool on)
{
mGradientEnabled = on;
}
void EnableBrightmap(bool on)
{
mBrightmapEnabled = on;
@ -324,18 +333,26 @@ public:
void SetGlowPlanes(const secplane_t &top, const secplane_t &bottom)
{
DVector3 tn = top.Normal();
DVector3 bn = bottom.Normal();
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
auto &tn = top.Normal();
auto &bn = bottom.Normal();
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
}
void SetGradientPlanes(const secplane_t &top, const secplane_t &bottom)
{
auto &tn = top.Normal();
auto &bn = bottom.Normal();
mGradientTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
mGradientBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
}
void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom)
{
DVector3 tn = top.Normal();
DVector3 bn = bottom.Normal();
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
auto &tn = top.Normal();
auto &bn = bottom.Normal();
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
}
void SetDynLight(float r, float g, float b)

View file

@ -207,8 +207,8 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
state.EnableSplit(true);
}
secplane_t bottomp = { { 0, 0, -1. }, bottomclip };
secplane_t topp = { { 0, 0, -1. }, topclip };
secplane_t bottomp = { { 0, 0, -1. }, bottomclip, 1. };
secplane_t topp = { { 0, 0, -1. }, topclip, 1. };
for (unsigned i = 0; i < iter; i++)
{
if (lightlist)
@ -755,7 +755,9 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
if (sector->sectornum != thing->Sector->sectornum && !thruportal)
{
rendersector = hw_FakeFlat(thing->Sector, &rs, in_area, false);
// This cannot create a copy in the fake sector cache because it'd interfere with the main thread, so provide a local buffer for the copy.
// Adding synchronization for this one case would cost more than it might save if the result here could be cached.
rendersector = hw_FakeFlat(thing->Sector, in_area, false, &rs);
}
else
{
@ -1287,7 +1289,8 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
th->Prev += newpos - savedpos;
GLSprite spr;
spr.Process(this, th, hw_FakeFlat(th->Sector, &fakesector, in_area, false), in_area, 2);
// This is called from the worker thread and must not alter the fake sector cache.
spr.Process(this, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2);
th->Angles.Yaw = savedangle;
th->SetXYZ(savedpos);
th->Prev -= newpos - savedpos;

View file

@ -130,6 +130,20 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
//
//==========================================================================
static const uint8_t renderwalltotier[] =
{
side_t::none,
side_t::top,
side_t::mid,
side_t::mid,
side_t::bottom,
side_t::none,
side_t::none,
side_t::mid,
side_t::none,
side_t::mid,
};
void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
{
int tmode = state.GetTextureMode();
@ -139,8 +153,8 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
{
state.EnableGlow(true);
state.SetGlowParams(topglowcolor, bottomglowcolor);
state.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane);
}
state.SetGlowPlanes(topplane, bottomplane);
state.SetMaterial(gltexture, flags & 3, 0, -1);
if (type == RENDERWALL_M2SNF)
@ -151,8 +165,41 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
}
state.SetFog(255, 0, di->isFullbrightScene(), nullptr, false);
}
state.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000);
state.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000);
if (type != RENDERWALL_COLOR)
{
auto side = seg->sidedef;
auto tierndx = renderwalltotier[type];
auto &tier = side->textures[tierndx];
PalEntry color1 = side->GetSpecialColor(tierndx, side_t::walltop, frontsector);
PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector);
state.SetObjectColor(color1);
state.SetObjectColor2(color2);
if (color1 != color2)
{
// Do gradient setup only if there actually is a gradient.
state.EnableGradient(true);
if ((tier.flags & side_t::part::ClampGradient) && backsector)
{
if (tierndx == side_t::top)
{
state.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane);
}
else if (tierndx == side_t::mid)
{
state.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane);
}
else // side_t::bottom:
{
state.SetGradientPlanes(backsector->floorplane, frontsector->floorplane);
}
}
else
{
state.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane);
}
}
}
float absalpha = fabsf(alpha);
if (lightlist == nullptr)
@ -167,14 +214,14 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
for (unsigned i = 0; i < lightlist->Size(); i++)
{
secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane;
secplane_t &lowplane = i == (*lightlist).Size() - 1 ? frontsector->floorplane : (*lightlist)[i + 1].plane;
// this must use the exact same calculation method as GLWall::Process etc.
float low1 = lowplane.ZatPoint(vertexes[0]);
float low2 = lowplane.ZatPoint(vertexes[1]);
if (low1 < ztop[0] || low2 < ztop[1])
{
int thisll = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
int thisll = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
FColormap thiscm;
thiscm.FadeColor = Colormap.FadeColor;
thiscm.FogDensity = Colormap.FogDensity;
@ -193,6 +240,7 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
state.SetObjectColor2(0);
state.SetTextureMode(tmode);
state.EnableGlow(false);
state.EnableGradient(false);
}
//==========================================================================
@ -1799,6 +1847,8 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
// note: we always have a valid sidedef and linedef reference when getting here.
this->seg = seg;
this->frontsector = frontsector;
this->backsector = backsector;
vertindex = 0;
vertcount = 0;
@ -1893,8 +1943,6 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
if (frontsector->GetWallGlow(topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
topplane = frontsector->ceilingplane;
bottomplane = frontsector->floorplane;
zfloor[0] = ffh1 = segfront->floorplane.ZatPoint(v1);
zfloor[1] = ffh2 = segfront->floorplane.ZatPoint(v2);
@ -2104,6 +2152,8 @@ void GLWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec
if (bfh > ffh)
{
this->seg = seg;
this->frontsector = frontsector;
this->backsector = backsector;
this->sub = NULL;
vertex_t * v1 = seg->v1;
@ -2129,8 +2179,6 @@ void GLWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec
Colormap = frontsector->Colormap;
if (frontsector->GetWallGlow(topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
topplane = frontsector->ceilingplane;
bottomplane = frontsector->floorplane;
dynlightindex = -1;
zfloor[0] = zfloor[1] = ffh;

View file

@ -222,8 +222,7 @@ static WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &po
}
else
{
sector_t fs;
auto fakesec = hw_FakeFlat(viewsector, &fs, in_area, false);
auto fakesec = hw_FakeFlat(viewsector, in_area, false);
// calculate light level for weapon sprites
l.lightlevel = hw_ClampLight(fakesec->lightlevel);

View file

@ -630,6 +630,26 @@ xx(hidden)
xx(blocksight)
xx(blockhitscan)
xx(nogradient_top)
xx(flipgradient_top)
xx(clampgradient_top)
xx(useowncolors_top)
xx(uppercolor_top)
xx(lowercolor_top)
xx(nogradient_mid)
xx(flipgradient_mid)
xx(clampgradient_mid)
xx(useowncolors_mid)
xx(uppercolor_mid)
xx(lowercolor_mid)
xx(nogradient_bottom)
xx(flipgradient_bottom)
xx(clampgradient_bottom)
xx(useowncolors_bottom)
xx(uppercolor_bottom)
xx(lowercolor_bottom)
xx(Renderstyle)
xx(ceilingplane_a)

View file

@ -4564,6 +4564,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSelf)
ACTION_RETURN_BOOL(P_Thing_Raise(self, NULL, (flags & RF_NOCHECKPOSITION)));
}
//===========================================================================
//
// RaiseActor
//
// Generalized version that allows passing pointers for ZScript's sake.
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, RaiseActor)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(other, AActor);
PARAM_INT_DEF(flags);
ACTION_RETURN_BOOL(P_Thing_Raise(other, self, (flags & RF_NOCHECKPOSITION)));
}
//===========================================================================
//
// CanRaise

View file

@ -2757,11 +2757,63 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
actor->flags &= ~MF_INCHASE;
}
//==========================================================================
//
// CanResurrect
//
// Checks if an actor can resurrect with another one, calling virtual script
// functions to check.
//
//==========================================================================
// [MC] Code is almost a duplicate of CanCollideWith but with changes to
// accommodate checking of just one actor.
bool P_CanResurrect(AActor *tmthing, AActor *thing)
{
if (tmthing == nullptr)
return false;
static unsigned VIndex = ~0u;
if (VIndex == ~0u)
{
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanResurrect");
assert(VIndex != ~0u);
}
VMValue params[3] = { tmthing, thing, false };
VMReturn ret;
int retval;
ret.IntAt(&retval);
auto clss = tmthing->GetClass();
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
VMCall(func, params, 3, &ret, 1);
if (!retval) return false;
}
// Pointless to be running it again if it's just self.
if (thing == nullptr || thing == tmthing)
return true;
std::swap(params[0].a, params[1].a);
params[2].i = true;
// re-get for the other actor.
clss = thing->GetClass();
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
VMCall(func, params, 3, &ret, 1);
if (!retval) return false;
}
return true;
}
//==========================================================================
//
// P_CheckForResurrection (formerly part of A_VileChase)
// Check for ressurecting a body
// Check for resurrecting a body
//
//==========================================================================
@ -2834,7 +2886,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
corpsehit->flags = oldflags;
corpsehit->radius = oldradius;
corpsehit->Height = oldheight;
if (!check) continue;
if (!check || !P_CanResurrect(self, corpsehit)) continue;
// got one!
temp = self->target;

View file

@ -210,16 +210,14 @@ static bool format5;
static bool LoadGLVertexes(FileReader &lump)
{
uint8_t *gldata;
int i;
firstglvertex = level.vertexes.Size();
auto gllen=lump.GetLength();
gldata = new uint8_t[gllen];
lump.Seek(0, FileReader::SeekSet);
lump.Read(gldata, gllen);
auto glbuf = lump.Read();
auto gllen=lump.GetLength();
auto gldata = glbuf.Data();
if (*(int *)gldata == gNd5)
{
@ -233,7 +231,6 @@ static bool LoadGLVertexes(FileReader &lump)
Printf("GL nodes v%d found. This format is not supported by " GAMENAME "\n",
(*(int *)gldata == gNd4)? 4:1);
delete [] gldata;
return false;
}
else format5=false;
@ -256,7 +253,6 @@ static bool LoadGLVertexes(FileReader &lump)
level.vertexes[i].set(LittleLong(mgl->x)/65536., LittleLong(mgl->y)/65536.);
mgl++;
}
delete[] gldata;
return true;
}
@ -288,139 +284,119 @@ static inline int checkGLVertex3(int num)
static bool LoadGLSegs(FileReader &lump)
{
char *data;
int i;
line_t *ldef=NULL;
int numsegs = (int)lump.GetLength();
data= new char[numsegs];
lump.Seek(0, FileReader::SeekSet);
lump.Read(data, numsegs);
auto data = lump.Read();
int numsegs = (int)lump.GetLength();
auto &segs = level.segs;
#ifdef _MSC_VER
__try
#endif
if (!format5 && memcmp(data.Data(), "gNd3", 4))
{
if (!format5 && memcmp(data, "gNd3", 4))
{
numsegs/=sizeof(glseg_t);
level.segs.Alloc(numsegs);
memset(&segs[0],0,sizeof(seg_t)*numsegs);
numsegs/=sizeof(glseg_t);
level.segs.Alloc(numsegs);
memset(&segs[0],0,sizeof(seg_t)*numsegs);
glseg_t * ml = (glseg_t*)data;
for(i = 0; i < numsegs; i++)
{
// check for gl-vertices
segs[i].v1 = &level.vertexes[checkGLVertex(LittleShort(ml->v1))];
segs[i].v2 = &level.vertexes[checkGLVertex(LittleShort(ml->v2))];
segs[i].PartnerSeg = ml->partner == 0xFFFF ? nullptr : &segs[LittleShort(ml->partner)];
if(ml->linedef != 0xffff)
{
ldef = &level.lines[LittleShort(ml->linedef)];
segs[i].linedef = ldef;
glseg_t * ml = (glseg_t*)data.Data();
for(i = 0; i < numsegs; i++)
{
// check for gl-vertices
segs[i].v1 = &level.vertexes[checkGLVertex(LittleShort(ml->v1))];
segs[i].v2 = &level.vertexes[checkGLVertex(LittleShort(ml->v2))];
segs[i].PartnerSeg = ml->partner == 0xFFFF ? nullptr : &segs[LittleShort(ml->partner)];
if(ml->linedef != 0xffff)
{
ldef = &level.lines[LittleShort(ml->linedef)];
segs[i].linedef = ldef;
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].frontsector = NULL;
}
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
}
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = NULL;
}
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].linedef = NULL;
segs[i].sidedef = NULL;
segs[i].frontsector = NULL;
segs[i].backsector = NULL;
}
ml++;
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
}
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = NULL;
}
}
else
{
segs[i].linedef = NULL;
segs[i].sidedef = NULL;
segs[i].frontsector = NULL;
segs[i].backsector = NULL;
}
ml++;
}
else
{
if (!format5) numsegs-=4;
numsegs/=sizeof(glseg3_t);
level.segs.Alloc(numsegs);
memset(&segs[0],0,sizeof(seg_t)*numsegs);
}
else
{
if (!format5) numsegs-=4;
numsegs/=sizeof(glseg3_t);
level.segs.Alloc(numsegs);
memset(&segs[0],0,sizeof(seg_t)*numsegs);
glseg3_t * ml = (glseg3_t*)(data+ (format5? 0:4));
for(i = 0; i < numsegs; i++)
{ // check for gl-vertices
segs[i].v1 = &level.vertexes[checkGLVertex3(LittleLong(ml->v1))];
segs[i].v2 = &level.vertexes[checkGLVertex3(LittleLong(ml->v2))];
glseg3_t * ml = (glseg3_t*)(data.Data() + (format5? 0:4));
for(i = 0; i < numsegs; i++)
{ // check for gl-vertices
segs[i].v1 = &level.vertexes[checkGLVertex3(LittleLong(ml->v1))];
segs[i].v2 = &level.vertexes[checkGLVertex3(LittleLong(ml->v2))];
const uint32_t partner = LittleLong(ml->partner);
segs[i].PartnerSeg = DWORD_MAX == partner ? nullptr : &segs[partner];
const uint32_t partner = LittleLong(ml->partner);
segs[i].PartnerSeg = DWORD_MAX == partner ? nullptr : &segs[partner];
if(ml->linedef != 0xffff) // skip minisegs
{
ldef = &level.lines[LittleLong(ml->linedef)];
segs[i].linedef = ldef;
if(ml->linedef != 0xffff) // skip minisegs
{
ldef = &level.lines[LittleLong(ml->linedef)];
segs[i].linedef = ldef;
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].frontsector = NULL;
}
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
}
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = NULL;
}
ml->side=LittleShort(ml->side);
segs[i].sidedef = ldef->sidedef[ml->side];
if (ldef->sidedef[ml->side] != NULL)
{
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
}
else
{
segs[i].linedef = NULL;
segs[i].sidedef = NULL;
segs[i].frontsector = NULL;
segs[i].backsector = NULL;
}
ml++;
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
{
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
}
else
{
ldef->flags &= ~ML_TWOSIDED;
segs[i].backsector = NULL;
}
}
else
{
segs[i].linedef = NULL;
segs[i].sidedef = NULL;
segs[i].frontsector = NULL;
segs[i].backsector = NULL;
}
ml++;
}
delete [] data;
return true;
}
#ifdef _MSC_VER
__except(1)
{
// Invalid data has the bad habit of requiring extensive checks here
// so let's just catch anything invalid and output a message.
// (at least under MSVC. GCC can't do SEH even for Windows... :( )
Printf("Invalid GL segs. The BSP will have to be rebuilt.\n");
delete [] data;
level.segs.Clear();
return false;
}
#endif
return true;
}
@ -432,23 +408,20 @@ static bool LoadGLSegs(FileReader &lump)
static bool LoadGLSubsectors(FileReader &lump)
{
char * datab;
int i;
int numsubsectors = (int)lump.GetLength();
datab = new char[numsubsectors];
lump.Seek(0, FileReader::SeekSet);
lump.Read(datab, numsubsectors);
auto datab = lump.Read();
if (numsubsectors == 0)
{
delete [] datab;
return false;
}
if (!format5 && memcmp(datab, "gNd3", 4))
if (!format5 && memcmp(datab.Data(), "gNd3", 4))
{
mapsubsector_t * data = (mapsubsector_t*) datab;
mapsubsector_t * data = (mapsubsector_t*) datab.Data();
numsubsectors /= sizeof(mapsubsector_t);
level.subsectors.Alloc(numsubsectors);
auto &subsectors = level.subsectors;
@ -461,14 +434,13 @@ static bool LoadGLSubsectors(FileReader &lump)
if (subsectors[i].numlines == 0)
{
delete [] datab;
return false;
}
}
}
else
{
gl3_mapsubsector_t * data = (gl3_mapsubsector_t*) (datab+(format5? 0:4));
gl3_mapsubsector_t * data = (gl3_mapsubsector_t*) (datab.Data()+(format5? 0:4));
numsubsectors /= sizeof(gl3_mapsubsector_t);
level.subsectors.Alloc(numsubsectors);
auto &subsectors = level.subsectors;
@ -481,7 +453,6 @@ static bool LoadGLSubsectors(FileReader &lump)
if (subsectors[i].numlines == 0)
{
delete [] datab;
return false;
}
}
@ -499,12 +470,10 @@ static bool LoadGLSubsectors(FileReader &lump)
// The subsector must be closed. If it isn't we can't use these nodes and have to do a rebuild.
if (lastseg->v2 != firstseg->v1)
{
delete [] datab;
return false;
}
}
delete [] datab;
return true;
}
@ -522,7 +491,7 @@ static bool LoadNodes (FileReader &lump)
int j;
int k;
node_t* no;
uint16_t* used;
TArray<uint16_t> used;
if (!format5)
{
@ -534,11 +503,11 @@ static bool LoadNodes (FileReader &lump)
level.nodes.Alloc(numnodes);
lump.Seek(0, FileReader::SeekSet);
basemn = mn = new mapnode_t[numnodes];
lump.Read(mn, lump.GetLength());
auto buf = lump.Read();
basemn = mn = (mapnode_t*)buf.Data();
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
memset (used, 0, sizeof(uint16_t)*numnodes);
used.Resize(numnodes);
memset (used.Data(), 0, sizeof(uint16_t)*numnodes);
no = &level.nodes[0];
@ -556,19 +525,16 @@ static bool LoadNodes (FileReader &lump)
child &= ~NF_SUBSECTOR;
if (child >= level.subsectors.Size())
{
delete [] basemn;
return false;
}
no->children[j] = (uint8_t *)&level.subsectors[child] + 1;
}
else if (child >= numnodes)
{
delete [] basemn;
return false;
}
else if (used[child])
{
delete [] basemn;
return false;
}
else
@ -582,7 +548,6 @@ static bool LoadNodes (FileReader &lump)
}
}
}
delete [] basemn;
}
else
{
@ -594,11 +559,11 @@ static bool LoadNodes (FileReader &lump)
level.nodes.Alloc(numnodes);
lump.Seek(0, FileReader::SeekSet);
basemn = mn = new gl5_mapnode_t[numnodes];
lump.Read(mn, lump.GetLength());
auto buf = lump.Read();
basemn = mn = (gl5_mapnode_t*)buf.Data();
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
memset (used, 0, sizeof(uint16_t)*numnodes);
used.Resize(numnodes);
memset(used.Data(), 0, sizeof(uint16_t)*numnodes);
no = &level.nodes[0];
@ -616,19 +581,16 @@ static bool LoadNodes (FileReader &lump)
child &= ~GL5_NF_SUBSECTOR;
if ((unsigned)child >= level.subsectors.Size())
{
delete [] basemn;
return false;
}
no->children[j] = (uint8_t *)&level.subsectors[child] + 1;
}
else if ((unsigned)child >= numnodes)
{
delete [] basemn;
return false;
}
else if (used[child])
{
delete [] basemn;
return false;
}
else
@ -642,7 +604,6 @@ static bool LoadNodes (FileReader &lump)
}
}
}
delete [] basemn;
}
return true;
}
@ -1097,31 +1058,30 @@ static void CreateCachedNodes(MapData *map)
}
uLongf outlen = ZNodes.Size();
uint8_t *compressed;
TArray<Bytef> compressed;
int offset = level.lines.Size() * 8 + 12 + 16;
int r;
do
{
compressed = new Bytef[outlen + offset];
r = compress (compressed + offset, &outlen, &ZNodes[0], ZNodes.Size());
compressed.Resize(outlen + offset);
r = compress (compressed.Data() + offset, &outlen, &ZNodes[0], ZNodes.Size());
if (r == Z_BUF_ERROR)
{
delete[] compressed;
outlen += 1024;
}
}
while (r == Z_BUF_ERROR);
memcpy(compressed, "CACH", 4);
memcpy(compressed.Data(), "CACH", 4);
uint32_t len = LittleLong(level.lines.Size());
memcpy(compressed+4, &len, 4);
map->GetChecksum(compressed+8);
memcpy(&compressed[4], &len, 4);
map->GetChecksum(&compressed[8]);
for (unsigned i = 0; i < level.lines.Size(); i++)
{
uint32_t ndx[2] = { LittleLong(uint32_t(level.lines[i].v1->Index())), LittleLong(uint32_t(level.lines[i].v2->Index())) };
memcpy(compressed + 8 + 16 + 8 * i, ndx, 8);
memcpy(&compressed[8 + 16 + 8 * i], ndx, 8);
}
memcpy(compressed + offset - 4, "ZGL3", 4);
memcpy(&compressed[offset - 4], "ZGL3", 4);
FString path = CreateCacheName(map, true);
FileWriter *fw = FileWriter::Open(path);
@ -1129,7 +1089,7 @@ static void CreateCachedNodes(MapData *map)
if (fw != nullptr)
{
const size_t length = outlen + offset;
if (fw->Write(compressed, length) != length)
if (fw->Write(compressed.Data(), length) != length)
{
Printf("Error saving nodes to file %s\n", path.GetChars());
}
@ -1139,8 +1099,6 @@ static void CreateCachedNodes(MapData *map)
{
Printf("Cannot open nodes file %s for writing\n", path.GetChars());
}
delete [] compressed;
}
@ -1150,29 +1108,29 @@ static bool CheckCachedNodes(MapData *map)
uint8_t md5[16];
uint8_t md5map[16];
uint32_t numlin;
uint32_t *verts = NULL;
TArray<uint32_t> verts;
FString path = CreateCacheName(map, false);
FileReader fr;
if (!fr.OpenFile(path)) return false;
if (fr.Read(magic, 4) != 4) goto errorout;
if (memcmp(magic, "CACH", 4)) goto errorout;
if (fr.Read(magic, 4) != 4) return false;
if (memcmp(magic, "CACH", 4)) return false;
if (fr.Read(&numlin, 4) != 4) goto errorout;
if (fr.Read(&numlin, 4) != 4) return false;
numlin = LittleLong(numlin);
if (numlin != level.lines.Size()) goto errorout;
if (numlin != level.lines.Size()) return false;
if (fr.Read(md5, 16) != 16) goto errorout;
if (fr.Read(md5, 16) != 16) return false;
map->GetChecksum(md5map);
if (memcmp(md5, md5map, 16)) goto errorout;
if (memcmp(md5, md5map, 16)) return false;
verts = new uint32_t[numlin * 8];
if (fr.Read(verts, 8 * numlin) != 8 * numlin) goto errorout;
verts.Resize(numlin * 2);
if (fr.Read(verts.Data(), 8 * numlin) != 8 * numlin) return false;
if (fr.Read(magic, 4) != 4) goto errorout;
if (memcmp(magic, "ZGL2", 4) && memcmp(magic, "ZGL3", 4)) goto errorout;
if (fr.Read(magic, 4) != 4) return false;
if (memcmp(magic, "ZGL2", 4) && memcmp(magic, "ZGL3", 4)) return false;
try
@ -1186,7 +1144,7 @@ static bool CheckCachedNodes(MapData *map)
level.subsectors.Clear();
level.segs.Clear();
level.nodes.Clear();
goto errorout;
return false;
}
for(auto &line : level.lines)
@ -1195,16 +1153,7 @@ static bool CheckCachedNodes(MapData *map)
line.v1 = &level.vertexes[LittleLong(verts[i*2])];
line.v2 = &level.vertexes[LittleLong(verts[i*2+1])];
}
delete [] verts;
return true;
errorout:
if (verts != NULL)
{
delete[] verts;
}
return false;
}
UNSAFE_CCMD(clearnodecache)
@ -1308,32 +1257,6 @@ void P_SetRenderSector()
TArray<subsector_t *> undetermined;
subsector_t * ss;
#if 0 // doesn't work as expected :(
// hide all sectors on textured automap that only have hidden lines.
bool *hidesec = new bool[numsectors];
for(i = 0; i < numsectors; i++)
{
hidesec[i] = true;
}
for(i = 0; i < numlines; i++)
{
if (!(lines[i].flags & ML_DONTDRAW))
{
hidesec[lines[i].frontsector - sectors] = false;
if (lines[i].backsector != NULL)
{
hidesec[lines[i].backsector - sectors] = false;
}
}
}
for(i = 0; i < numsectors; i++)
{
if (hidesec[i]) sectors[i].MoreFlags |= SECMF_HIDDEN;
}
delete [] hidesec;
#endif
// Check for incorrect partner seg info so that the following code does not crash.
for (auto &seg : level.segs)

View file

@ -1086,7 +1086,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
damage = int(damage * source->DamageMultiply);
// Handle active damage modifiers (e.g. PowerDamage)
if (damage > 0)
if (damage > 0 && !(flags & DMG_NO_ENHANCE))
{
damage = source->GetModifiedDamage(mod, damage, false);
}

View file

@ -162,6 +162,7 @@ void P_Thing_SetVelocity(AActor *actor, const DVector3 &vec, bool add, bool setb
void P_RemoveThing(AActor * actor);
bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck = false);
bool P_Thing_CanRaise(AActor *thing);
bool P_CanResurrect(AActor *ththing, AActor *thing);
PClassActor *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo();
int P_Thing_CheckInputNum(player_t *p, int inputnum);
@ -454,6 +455,7 @@ enum EDmgFlags
DMG_USEANGLE = 512,
DMG_NO_PAIN = 1024,
DMG_EXPLOSION = 2048,
DMG_NO_ENHANCE = 4096,
};

View file

@ -7063,7 +7063,7 @@ void SpawnShootDecal(AActor *t1, const FTraceResults &trace)
if (t1->player != NULL && t1->player->ReadyWeapon != NULL)
{
decalbase = t1->player->ReadyWeapon->GetDefault()->DecalGenerator;
decalbase = t1->player->ReadyWeapon->DecalGenerator;
}
else
{

View file

@ -105,6 +105,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
("yscale", part.yScale, def->yScale)
("texture", part.texture, def->texture)
("interpolation", part.interpolation)
("flags", part.flags, def->flags)
("color1", part.SpecialColors[0], def->SpecialColors[0])
("color2", part.SpecialColors[1], def->SpecialColors[1])
.EndObject();
}
return arc;

View file

@ -878,17 +878,6 @@ DEFINE_ACTION_FUNCTION(_Sector, SetFade)
//
//=====================================================================================
void sector_t::SetSpecialColor(int slot, int r, int g, int b)
{
SpecialColors[slot] = PalEntry(255, r, g, b);
}
void sector_t::SetSpecialColor(int slot, PalEntry rgb)
{
rgb.a = 255;
SpecialColors[slot] = rgb;
}
DEFINE_ACTION_FUNCTION(_Sector, SetSpecialColor)
{
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
@ -2241,6 +2230,26 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
ACTION_RETURN_INT(self->Index());
}
//=====================================================================================
//
//
//=====================================================================================
DEFINE_ACTION_FUNCTION(_Side, SetSpecialColor)
{
PARAM_SELF_STRUCT_PROLOGUE(side_t);
PARAM_INT(tier);
PARAM_INT(position);
PARAM_COLOR(color);
if (tier >= 0 && tier < 3 && position >= 0 && position < 2)
{
color.a = 255;
self->SetSpecialColor(tier, position, color);
}
return 0;
}
DEFINE_ACTION_FUNCTION(_Vertex, Index)
{
PARAM_SELF_STRUCT_PROLOGUE(vertex_t);

View file

@ -1691,15 +1691,10 @@ uint16_t MakeSkill(int flags)
void P_LoadThings (MapData * map)
{
int lumplen = map->Size(ML_THINGS);
int numthings = lumplen / sizeof(mapthing_t);
char *mtp;
mapthing_t *mt;
mtp = new char[lumplen];
map->Read(ML_THINGS, mtp);
mt = (mapthing_t*)mtp;
auto mtp = map->Read(ML_THINGS);
int numthings = mtp.Size() / sizeof(mapthing_t);
mt = (mapthing_t*)mtp.Data();
MapThingsConverted.Resize(numthings);
FMapThing *mti = &MapThingsConverted[0];
@ -1767,7 +1762,6 @@ void P_LoadThings (MapData * map)
if (flags & BTF_NOTSINGLE) mti[i].flags &= ~MTF_SINGLE;
}
}
delete [] mtp;
}
//===========================================================================
@ -2109,29 +2103,24 @@ void P_LoadLineDefs (MapData * map)
{
int i, skipped;
line_t *ld;
int lumplen = map->Size(ML_LINEDEFS);
char * mldf;
maplinedef_t *mld;
int numlines = lumplen / sizeof(maplinedef_t);
auto mldf = map->Read(ML_LINEDEFS);
int numlines = mldf.Size() / sizeof(maplinedef_t);
linemap.Resize(numlines);
mldf = new char[lumplen];
map->Read(ML_LINEDEFS, mldf);
// [RH] Count the number of sidedef references. This is the number of
// sidedefs we need. The actual number in the SIDEDEFS lump might be less.
// Lines with 0 length are also removed.
for (skipped = sidecount = i = 0; i < numlines; )
{
mld = ((maplinedef_t*)mldf) + i;
mld = ((maplinedef_t*)mldf.Data()) + i;
unsigned v1 = LittleShort(mld->v1);
unsigned v2 = LittleShort(mld->v2);
if (v1 >= level.vertexes.Size() || v2 >= level.vertexes.Size())
{
delete [] mldf;
I_Error ("Line %d has invalid vertices: %d and/or %d.\nThe map only contains %u vertices.", i+skipped, v1, v2, level.vertexes.Size());
}
else if (v1 == v2 ||
@ -2164,7 +2153,7 @@ void P_LoadLineDefs (MapData * map)
P_AllocateSideDefs (map, sidecount);
mld = (maplinedef_t *)mldf;
mld = (maplinedef_t *)mldf.Data();
ld = &level.lines[0];
for (i = 0; i < numlines; i++, mld++, ld++)
{
@ -2203,7 +2192,6 @@ void P_LoadLineDefs (MapData * map)
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
if (level.flags2 & LEVEL2_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE;
}
delete[] mldf;
}
//===========================================================================
@ -3644,7 +3632,7 @@ void P_FreeExtraLevelData()
//
//===========================================================================
void P_SetupLevel (const char *lumpname, int position, bool newGame)
void P_SetupLevel(const char *lumpname, int position, bool newGame)
{
cycle_t times[20];
#if 0
@ -3674,7 +3662,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
level.SetMusicVolume(level.MusicVolume);
for (i = 0; i < MAXPLAYERS; ++i)
{
players[i].killcount = players[i].secretcount
players[i].killcount = players[i].secretcount
= players[i].itemcount = 0;
}
}
@ -3695,16 +3683,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
translationtables[TRANSLATION_LevelScripted].Clear();
// Initial height of PointOfView will be set by player think.
players[consoleplayer].viewz = NO_VALUE;
players[consoleplayer].viewz = NO_VALUE;
// Make sure all sounds are stopped before Z_FreeTags.
S_Start ();
S_Start();
// [RH] clear out the mid-screen message
C_MidPrint (NULL, NULL);
C_MidPrint(NULL, NULL);
// Free all level data from the previous map
P_FreeLevelData ();
P_FreeLevelData();
MapData *map = P_OpenMapData(lumpname, true);
if (map == NULL)
@ -3736,7 +3724,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
uint8_t *mapdata = new uint8_t[map->Size(0)];
map->Read(0, mapdata);
times[0].Clock();
buildmap = P_LoadBuildMap (mapdata, map->Size(0), &buildthings, &numbuildthings);
buildmap = P_LoadBuildMap(mapdata, map->Size(0), &buildthings, &numbuildthings);
times[0].Unclock();
delete[] mapdata;
}
@ -3748,10 +3736,10 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
ForceNodeBuild = gennodes;
// [RH] Load in the BEHAVIOR lump
FBehavior::StaticUnloadModules ();
FBehavior::StaticUnloadModules();
if (map->HasBehavior)
{
P_LoadBehavior (map);
P_LoadBehavior(map);
level.maptype = MAPTYPE_HEXEN;
}
else
@ -3768,7 +3756,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
{
// Has the user overridden the game's default translator with a commandline parameter?
translator = Args->CheckValue("-xlat");
if (translator == NULL)
if (translator == NULL)
{
// Use the game's default.
translator = gameinfo.translator.GetChars();
@ -3808,25 +3796,25 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
level.flags2 |= LEVEL2_DUMMYSWITCHES;
}
FBehavior::StaticLoadDefaultModules ();
FBehavior::StaticLoadDefaultModules();
#ifndef NO_EDATA
LoadMapinfoACSLump();
#endif
P_LoadStrifeConversations (map, lumpname);
P_LoadStrifeConversations(map, lumpname);
FMissingTextureTracker missingtex;
if (!map->isText)
{
times[0].Clock();
P_LoadVertexes (map);
P_LoadVertexes(map);
times[0].Unclock();
// Check for maps without any BSP data at all (e.g. SLIGE)
times[1].Clock();
P_LoadSectors (map, missingtex);
P_LoadSectors(map, missingtex);
times[1].Unclock();
times[2].Clock();
@ -3834,23 +3822,23 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
times[3].Clock();
if (!map->HasBehavior)
P_LoadLineDefs (map);
P_LoadLineDefs(map);
else
P_LoadLineDefs2 (map); // [RH] Load Hexen-style linedefs
P_LoadLineDefs2(map); // [RH] Load Hexen-style linedefs
times[3].Unclock();
times[4].Clock();
P_LoadSideDefs2 (map, missingtex);
P_LoadSideDefs2(map, missingtex);
times[4].Unclock();
times[5].Clock();
P_FinishLoadingLineDefs ();
P_FinishLoadingLineDefs();
times[5].Unclock();
if (!map->HasBehavior)
P_LoadThings (map);
P_LoadThings(map);
else
P_LoadThings2 (map); // [RH] Load Hexen-style things
P_LoadThings2(map); // [RH] Load Hexen-style things
}
else
{
@ -3862,7 +3850,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
SetCompatibilityParams(checksum);
times[6].Clock();
P_LoopSidedefs (true);
P_LoopSidedefs(true);
times[6].Unclock();
linemap.Clear();
@ -3881,36 +3869,36 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
{
// Check for compressed nodes first, then uncompressed nodes
FileReader *fr = nullptr;
uint32_t id = MAKE_ID('X','x','X','x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
uint32_t id = MAKE_ID('X', 'x', 'X', 'x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
if (map->Size(ML_ZNODES) != 0)
{
// Test normal nodes first
fr = &map->Reader(ML_ZNODES);
idcheck = MAKE_ID('Z','N','O','D');
idcheck2 = MAKE_ID('X','N','O','D');
idcheck = MAKE_ID('Z', 'N', 'O', 'D');
idcheck2 = MAKE_ID('X', 'N', 'O', 'D');
}
else if (map->Size(ML_GLZNODES) != 0)
{
fr = &map->Reader(ML_GLZNODES);
idcheck = MAKE_ID('Z','G','L','N');
idcheck2 = MAKE_ID('Z','G','L','2');
idcheck3 = MAKE_ID('Z','G','L','3');
idcheck4 = MAKE_ID('X','G','L','N');
idcheck5 = MAKE_ID('X','G','L','2');
idcheck6 = MAKE_ID('X','G','L','3');
idcheck = MAKE_ID('Z', 'G', 'L', 'N');
idcheck2 = MAKE_ID('Z', 'G', 'L', '2');
idcheck3 = MAKE_ID('Z', 'G', 'L', '3');
idcheck4 = MAKE_ID('X', 'G', 'L', 'N');
idcheck5 = MAKE_ID('X', 'G', 'L', '2');
idcheck6 = MAKE_ID('X', 'G', 'L', '3');
}
if (fr != nullptr && fr->isOpen()) fr->Read (&id, 4);
if (fr != nullptr && fr->isOpen()) fr->Read(&id, 4);
if (id != 0 && (id == idcheck || id == idcheck2 || id == idcheck3 || id == idcheck4 || id == idcheck5 || id == idcheck6))
{
try
{
P_LoadZNodes (*fr, id);
P_LoadZNodes(*fr, id);
}
catch (CRecoverableError &error)
{
Printf ("Error loading nodes: %s\n", error.GetMessage());
Printf("Error loading nodes: %s\n", error.GetMessage());
ForceNodeBuild = true;
level.subsectors.Clear();
@ -3927,29 +3915,29 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
if (!P_CheckV4Nodes(map))
{
times[7].Clock();
P_LoadSubsectors<mapsubsector_t, mapseg_t> (map);
P_LoadSubsectors<mapsubsector_t, mapseg_t>(map);
times[7].Unclock();
times[8].Clock();
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t> (map);
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t>(map);
times[8].Unclock();
times[9].Clock();
if (!ForceNodeBuild) P_LoadSegs<mapseg_t> (map);
if (!ForceNodeBuild) P_LoadSegs<mapseg_t>(map);
times[9].Unclock();
}
else
{
times[7].Clock();
P_LoadSubsectors<mapsubsector4_t, mapseg4_t> (map);
P_LoadSubsectors<mapsubsector4_t, mapseg4_t>(map);
times[7].Unclock();
times[8].Clock();
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t> (map);
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t>(map);
times[8].Unclock();
times[9].Clock();
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t> (map);
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t>(map);
times[9].Unclock();
}
}
@ -3960,7 +3948,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
// If loading the regular nodes failed try GL nodes before considering a rebuild
if (ForceNodeBuild)
{
if (P_LoadGLNodes(map))
if (P_LoadGLNodes(map))
{
ForceNodeBuild = false;
reloop = true;
@ -3969,16 +3957,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
}
else reloop = true;
uint64_t startTime=0, endTime=0;
uint64_t startTime = 0, endTime = 0;
bool BuildGLNodes;
if (ForceNodeBuild)
{
BuildGLNodes = RequireGLNodes || multiplayer || demoplayback || demorecording || genglnodes;
startTime = I_msTime ();
startTime = I_msTime();
TArray<FNodeBuilder::FPolyStart> polyspots, anchors;
P_GetPolySpots (map, polyspots, anchors);
P_GetPolySpots(map, polyspots, anchors);
FNodeBuilder::FLevel leveldata =
{
&level.vertexes[0], (int)level.vertexes.Size(),
@ -3986,14 +3974,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
&level.lines[0], (int)level.lines.Size(),
0, 0, 0, 0
};
leveldata.FindMapBounds ();
leveldata.FindMapBounds();
// We need GL nodes if am_textured is on.
// In case a sync critical game mode is started, also build GL nodes to avoid problems
// if the different machines' am_textured setting differs.
FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes);
builder.Extract (level);
endTime = I_msTime ();
DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
FNodeBuilder builder(leveldata, polyspots, anchors, BuildGLNodes);
builder.Extract(level);
endTime = I_msTime();
DPrintf(DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
oldvertextable = builder.GetOldVertexTable();
reloop = true;
}
@ -4001,14 +3989,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
{
BuildGLNodes = false;
// Older ZDBSPs had problems with compressed sidedefs and assigned wrong sides to the segs if both sides were the same sidedef.
for(auto &seg : level.segs)
for (auto &seg : level.segs)
{
if (seg.backsector == seg.frontsector && seg.linedef)
{
double d1 = (seg.v1->fPos() - seg.linedef->v1->fPos()).LengthSquared();
double d2 = (seg.v2->fPos() - seg.linedef->v1->fPos()).LengthSquared();
if (d2<d1) // backside
if (d2 < d1) // backside
{
seg.sidedef = seg.linedef->sidedef[1];
}
@ -4035,22 +4023,22 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
}
// set the head node for gameplay purposes. If the separate gamenodes array is not empty, use that, otherwise use the render nodes.
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size()? &level.nodes[level.nodes.Size() - 1] : nullptr;
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size() ? &level.nodes[level.nodes.Size() - 1] : nullptr;
times[10].Clock();
P_LoadBlockMap (map);
P_LoadBlockMap(map);
times[10].Unclock();
times[11].Clock();
P_LoadReject (map, buildmap);
P_LoadReject(map, buildmap);
times[11].Unclock();
times[12].Clock();
P_GroupLines (buildmap);
P_GroupLines(buildmap);
times[12].Unclock();
times[13].Clock();
P_FloodZones ();
P_FloodZones();
times[13].Unclock();
if (hasglnodes)
@ -4061,8 +4049,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
}
bodyqueslot = 0;
// phares 8/10/98: Clear body queue so the corpses from previous games are
// not assumed to be from this one.
// phares 8/10/98: Clear body queue so the corpses from previous games are
// not assumed to be from this one.
for (i = 0; i < BODYQUESIZE; i++)
bodyque[i] = NULL;
@ -4072,7 +4060,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
if (!buildmap)
{
// [RH] Spawn slope creating things first.
P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
P_SpawnSlopeMakers(&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
P_CopySlopes();
// Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials
@ -4090,7 +4078,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
times[15].Clock();
if (!map->HasBehavior && !map->isText)
P_TranslateTeleportThings (); // [RH] Assign teleport destination TIDs
P_TranslateTeleportThings(); // [RH] Assign teleport destination TIDs
times[15].Unclock();
}
#if 0 // There is no such thing as a build map.
@ -4098,7 +4086,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
{
for (i = 0; i < numbuildthings; ++i)
{
SpawnMapThing (i, &buildthings[i], 0);
SpawnMapThing(i, &buildthings[i], 0);
}
delete[] buildthings;
}
@ -4110,7 +4098,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
}
// set up world state
P_SpawnSpecials ();
P_SpawnSpecials();
// disable reflective planes on sloped sectors.
for (auto &sec : level.sectors)
@ -4133,8 +4121,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
P_InitHealthGroups();
times[16].Clock();
if (reloop) P_LoopSidedefs (false);
PO_Init (); // Initialize the polyobjs
if (reloop) P_LoopSidedefs(false);
PO_Init(); // Initialize the polyobjs
if (!level.IsReentering())
P_FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
times[16].Unclock();
@ -4146,12 +4134,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
// if deathmatch, randomly spawn the active players
if (deathmatch)
{
for (i=0 ; i<MAXPLAYERS ; i++)
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
players[i].mo = NULL;
G_DeathMatchSpawnPlayer (i);
G_DeathMatchSpawnPlayer(i);
}
}
}
@ -4171,7 +4159,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
// [SP] move unfriendly players around
// horribly hacky - yes, this needs rewritten.
if (level.deathmatchstarts.Size () > 0)
if (level.deathmatchstarts.Size() > 0)
{
for (i = 0; i < MAXPLAYERS; ++i)
{
@ -4180,7 +4168,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
if (!(players[i].mo->flags & MF_FRIENDLY))
{
AActor * oldSpawn = players[i].mo;
G_DeathMatchSpawnPlayer (i);
G_DeathMatchSpawnPlayer(i);
oldSpawn->Destroy();
}
}
@ -4194,11 +4182,11 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
TThinkerIterator<AActor> it;
AActor * mo;
while ((mo=it.Next()))
while ((mo = it.Next()))
{
if (mo->flags & MF_COUNTKILL)
{
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE|SECF_ENDLEVEL)) == (SECF_ENDGODMODE|SECF_ENDLEVEL))
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE | SECF_ENDLEVEL)) == (SECF_ENDGODMODE | SECF_ENDLEVEL))
{
mo->ClearCounters();
}
@ -4214,20 +4202,20 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
R_OldBlend = 0xffffffff;
// [RH] Remove all particles
P_ClearParticles ();
P_ClearParticles();
times[17].Clock();
// preload graphics and sounds
if (precache)
{
P_PrecacheLevel ();
S_PrecacheLevel ();
P_PrecacheLevel();
S_PrecacheLevel();
}
times[17].Unclock();
if (deathmatch)
{
AnnounceGameStart ();
AnnounceGameStart();
}
// This check was previously done at run time each time the heightsec was checked.
@ -4247,12 +4235,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
}
}
P_ResetSightCounters (true);
P_ResetSightCounters(true);
//Printf ("free memory: 0x%x\n", Z_FreeMemory());
if (showloadtimes)
{
Printf ("---Total load times---\n");
Printf("---Total load times---\n");
for (i = 0; i < 18; ++i)
{
static const char *timenames[] =
@ -4276,7 +4264,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
"init polys",
"precache"
};
Printf ("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
Printf("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
}
}
MapThingsConverted.Clear();
@ -4294,8 +4282,6 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0]));
}
//
// P_Init
//

View file

@ -104,6 +104,13 @@ public:
}
}
TArray<uint8_t> Read(unsigned lumpindex)
{
TArray<uint8_t> buffer(Size(lumpindex), true);
Read(lumpindex, buffer.Data(), (int)buffer.Size());
return buffer;
}
uint32_t Size(unsigned int lumpindex)
{
if (lumpindex<countof(MapLumps) && MapLumps[lumpindex].Reader.isOpen())

View file

@ -434,10 +434,13 @@ void P_RemoveThing(AActor * actor)
bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck)
{
if (!thing)
return false;
FState * RaiseState = thing->GetRaiseState();
if (RaiseState == NULL)
{
return true; // monster doesn't have a raise state
return false; // monster doesn't have a raise state
}
AActor *info = thing->GetDefault ();
@ -460,6 +463,8 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck)
return false;
}
if (!P_CanResurrect(thing, raiser))
return false;
S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);

View file

@ -1223,6 +1223,7 @@ public:
{
FName key = ParseKey();
switch(key)
{
case NAME_Offsetx:
texOfs[0] = CheckInt(key);
@ -1334,6 +1335,79 @@ public:
Flag(sd->Flags, WALLF_NOAUTODECALS, key);
continue;
case NAME_nogradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_top:
Flag(sd->textures[side_t::top].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_top:
Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_top:
sd->SetSpecialColor(side_t::top, 0, CheckInt(key));
break;
case NAME_lowercolor_top:
sd->SetSpecialColor(side_t::top, 1, CheckInt(key));
break;
case NAME_nogradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_mid:
Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_mid:
sd->SetSpecialColor(side_t::mid, 0, CheckInt(key));
break;
case NAME_lowercolor_mid:
sd->SetSpecialColor(side_t::mid, 1, CheckInt(key));
break;
case NAME_nogradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::NoGradient, key);
break;
case NAME_flipgradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::FlipGradient, key);
break;
case NAME_clampgradient_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::ClampGradient, key);
break;
case NAME_useowncolors_bottom:
Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnColors, key);
break;
case NAME_uppercolor_bottom:
sd->SetSpecialColor(side_t::bottom, 0, CheckInt(key));
break;
case NAME_lowercolor_bottom:
sd->SetSpecialColor(side_t::bottom, 1, CheckInt(key));
break;
default:
break;
@ -2045,15 +2119,11 @@ public:
void ParseTextMap(MapData *map)
{
char *buffer = new char[map->Size(ML_TEXTMAP)];
isTranslated = true;
isExtended = false;
floordrop = false;
map->Read(ML_TEXTMAP, buffer);
sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), buffer, map->Size(ML_TEXTMAP));
delete [] buffer;
sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), map->Read(ML_TEXTMAP));
sc.SetCMode(true);
if (sc.CheckString("namespace"))
{

View file

@ -473,10 +473,7 @@ class USDFParser : public UDMFParserBase
public:
bool Parse(int lumpnum, FileReader &lump, int lumplen)
{
char *buffer = new char[lumplen];
lump.Read(buffer, lumplen);
sc.OpenMem(Wads.GetLumpFullName(lumpnum), buffer, lumplen);
delete [] buffer;
sc.OpenMem(Wads.GetLumpFullName(lumpnum), lump.Read(lumplen));
sc.SetCMode(true);
// Namespace must be the first field because everything else depends on it.
if (sc.CheckString("namespace"))

View file

@ -323,15 +323,12 @@ void FParseContext::ParseLump(const char *lumpname)
}
// Read the lump into a buffer and add a 0-terminator
int lumplen = Wads.LumpLength(lumpno);
char *lumpdata = new char[lumplen+1];
Wads.ReadLump(lumpno, lumpdata);
lumpdata[lumplen] = 0;
auto lumpdata = Wads.ReadLumpIntoArray(lumpno, 1);
SourceLine = 0;
SourceFile = lumpname;
char *sourcep = lumpdata;
char *sourcep = (char*)lumpdata.Data();
while ( (tokentype = GetToken(sourcep, &token)) )
{
// It is much easier to handle include statements outside the main parser.
@ -349,7 +346,6 @@ void FParseContext::ParseLump(const char *lumpname)
Parse(pParser, tokentype, token, this);
}
}
delete [] lumpdata;
SourceLine = SavedSourceLine;
SourceFile = SavedSourceFile;
}

View file

@ -88,7 +88,6 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.Line = line->linedef;
wall.Side = line->sidedef;
wall.LineSegLine = line->linedef;
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
wall.Masked = false;
wall.SubsectorDepth = subsectorDepth;
wall.StencilValue = stencilValue;
@ -102,6 +101,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = topTexZ;
wall.BottomTexZ = bottomTexZ;
wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
wall.Polyportal = polyportal;
wall.Render(thread);
@ -140,6 +140,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = topTexZ;
wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2));
wall.Wallpart = side_t::top;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top);
wall.Render(thread);
}
@ -152,6 +153,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.UnpeggedCeil1 = topceilz1;
wall.UnpeggedCeil2 = topceilz2;
wall.Wallpart = side_t::bottom;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom);
wall.Render(thread);
}
@ -162,6 +164,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
wall.TopTexZ = MAX(middleceilz1, middleceilz2);
wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2);
wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
wall.Masked = true;
wall.Additive = !!(wall.Line->flags & ML_ADDTRANS);
@ -212,7 +215,6 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
wall.LineSegLine = line->linedef;
wall.Line = fakeFloor->master;
wall.Side = fakeFloor->master->sidedef[0];
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
wall.SectorLightLevel = frontsector->lightlevel;
wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
if (!wall.Additive && fakeFloor->alpha == 255)
@ -231,6 +233,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
wall.TopTexZ = topTexZ;
wall.BottomTexZ = bottomTexZ;
wall.Wallpart = side_t::mid;
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
if (fakeFloor->flags & FF_UPPERTEXTURE)
wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top);
else if (fakeFloor->flags & FF_LOWERTEXTURE)

View file

@ -64,6 +64,7 @@ struct WorkSection
int sectorindex;
int mapsection;
bool hasminisegs;
bool bad; // Did not produce a proper area and cannot be triangulated by tesselation.
TArray<WorkSectionLine*>segments;
TArray<side_t *> originalSides; // The segs will lose some of these while working on them.
TArray<int> subsectors;
@ -184,6 +185,33 @@ public:
{
CompileSections(pair->Value, rawsections);
}
// Make sure that all subsectors have a sector. In some degenerate cases a subsector may come up empty.
// An example is in Doom.wad E3M4 near linedef 1087. With the grouping data here this is relatively easy to fix.
sector_t *lastsector = &level.sectors[0];
for (auto &rawsection : rawsections)
{
sector_t *mysector = nullptr;
bool missing = false;
for (auto num : rawsection)
{
auto &sub = level.subsectors[num];
if (sub.sector == nullptr) missing = true;
else mysector = sub.sector;
}
// Should the worst case happen and no sector be found, use the last used one. Subsectors must not be sector-less!
if (mysector == nullptr) mysector = lastsector;
else lastsector = mysector;
for (auto num : rawsection)
{
auto &sub = level.subsectors[num];
if (sub.sector == nullptr)
{
sub.sector = mysector;
}
}
}
subsectormap.Clear();
return rawsections;
}
@ -253,8 +281,7 @@ public:
{
MakeOutline(list, lineForSeg);
}
rawsections.Clear();
rawsections.ShrinkToFit();
rawsections.Reset();
// Assign partners after everything has been collected
for (auto &section : sections)
@ -281,6 +308,7 @@ public:
TArray<seg_t *> outersegs;
TArray<seg_t *> loopedsegs;
bool hasminisegs = false;
bool bad = false;
// Collect all the segs that make up the outline of this section.
for (auto j : rawsection)
@ -371,7 +399,8 @@ public:
{
// Did not find another one but have an unclosed loop. This should never happen and would indicate broken nodes.
// Error out and let the calling code deal with it.
I_Error("Unclosed loop in sector %d at position (%d, %d)\n", loopedsegs[0]->Subsector->render_sector->Index(), (int)loopedsegs[0]->v1->fX(), (int)loopedsegs[0]->v1->fY());
DPrintf(DMSG_NOTIFY, "Unclosed loop in sector %d at position (%d, %d)\n", loopedsegs[0]->Subsector->render_sector->Index(), (int)loopedsegs[0]->v1->fX(), (int)loopedsegs[0]->v1->fY());
bad = true;
}
seg = nullptr;
loopedsegs.Push(nullptr); // A separator is not really needed but useful for debugging.
@ -402,6 +431,7 @@ public:
section.sectorindex = sector;
section.mapsection = mapsec;
section.hasminisegs = hasminisegs;
section.bad = bad;
section.originalSides = std::move(foundsides);
section.segments = std::move(sectionlines);
section.subsectors = std::move(rawsection);
@ -720,8 +750,59 @@ public:
curgroup++;
}
}
};
//=============================================================================
//
// Check if some subsectors have come up empty on sections.
// In this case assign the best fit from the containing sector.
// This is only to ensure that the section pointer is not null.
// These are always degenerate and do not produce any actual render output.
//
//=============================================================================
void FixMissingReferences()
{
for (auto &sub : level.subsectors)
{
if (sub.section == nullptr)
{
int sector = sub.sector->Index();
int mapsection = sub.mapsection;
auto sections = level.sections.SectionsForSector(sector);
FSection *bestfit = nullptr;
for (auto &section : sections)
{
if (bestfit == nullptr)
{
bestfit = &section;
}
else if (bestfit->mapsection != section.mapsection && section.mapsection == mapsection)
{
bestfit = &section;
}
else if (section.mapsection == mapsection)
{
BoundingRect rc;
for (unsigned i = 0; i < sub.numlines; i++)
{
rc.addVertex(sub.firstline[i].v1->fX(), sub.firstline[i].v1->fY());
rc.addVertex(sub.firstline[i].v2->fX(), sub.firstline[i].v2->fY());
}
// Pick the one closer to this subsector.
if (rc.distanceTo(section.bounds) < rc.distanceTo(bestfit->bounds))
{
bestfit = &section;
}
}
}
// This should really never happen, but better be safe than sorry and assign at least something.
if (bestfit == nullptr) bestfit = &level.sections.allSections[0];
sub.section = bestfit;
}
}
}
};
//=============================================================================
@ -787,6 +868,7 @@ void CreateSections(FSectionContainer &container)
creat.FindOuterLoops();
creat.GroupSections();
creat.ConstructOutput(container);
creat.FixMissingReferences();
}
CCMD(printsections)

View file

@ -325,7 +325,7 @@ public:
return !normal.XY().isZero();
}
DVector3 Normal() const
const DVector3 &Normal() const
{
return normal;
}
@ -645,8 +645,6 @@ public:
void SetColor(int r, int g, int b, int desat);
void SetFade(int r, int g, int b);
void SetFogDensity(int dens);
void SetSpecialColor(int num, int r, int g, int b);
void SetSpecialColor(int num, PalEntry rgb);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
int GetFloorLight () const;
int GetCeilingLight () const;
@ -917,6 +915,17 @@ public:
Flags &= ~SECF_SPECIALFLAGS;
}
void SetSpecialColor(int slot, int r, int g, int b)
{
SpecialColors[slot] = PalEntry(255, r, g, b);
}
void SetSpecialColor(int slot, PalEntry rgb)
{
rgb.a = 255;
SpecialColors[slot] = rgb;
}
inline bool PortalBlocksView(int plane);
inline bool PortalBlocksSight(int plane);
inline bool PortalBlocksMovement(int plane);
@ -1138,16 +1147,31 @@ struct side_t
{
top=0,
mid=1,
bottom=2
bottom=2,
none = 1, // this is just for clarification in a mapping table
};
enum EColorSlot
{
walltop = 0,
wallbottom = 1,
};
struct part
{
enum EPartFlags
{
NoGradient = 1,
FlipGradient = 2,
ClampGradient = 4,
UseOwnColors = 8,
};
double xOffset;
double yOffset;
double xScale;
double yScale;
TObjPtr<DInterpolation*> interpolation;
FTextureID texture;
int flags;
PalEntry SpecialColors[2];
void InitFrom(const part &other)
{
@ -1270,6 +1294,28 @@ struct side_t
textures[which].yScale *= delta;
}
void SetSpecialColor(int which, int slot, int r, int g, int b)
{
textures[which].SpecialColors[slot] = PalEntry(255, r, g, b);
}
void SetSpecialColor(int which, int slot, PalEntry rgb)
{
rgb.a = 255;
textures[which].SpecialColors[slot] = rgb;
}
// Note that the sector being passed in here may not be the actual sector this sidedef belongs to
// (either for polyobjects or FakeFlat'ed temporaries.)
PalEntry GetSpecialColor(int which, int slot, sector_t *frontsector) const
{
auto &part = textures[which];
if (part.flags & part::NoGradient) slot = 0;
if (part.flags & part::FlipGradient) slot ^= 1;
return (part.flags & part::UseOwnColors) ? part.SpecialColors[slot] : frontsector->SpecialColors[sector_t::walltop + slot];
}
DInterpolation *SetInterpolation(int position);
void StopInterpolation(int position);

View file

@ -230,7 +230,7 @@ bool F7ZFile::Open(bool quiet)
Archive = NULL;
if (!quiet)
{
Printf("\n" TEXTCOLOR_RED "%s: ", Filename);
Printf("\n" TEXTCOLOR_RED "%s: ", FileName.GetChars());
if (res == SZ_ERROR_UNSUPPORTED)
{
Printf("Decoder does not support this archive\n");
@ -309,7 +309,7 @@ bool F7ZFile::Open(bool quiet)
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
{
if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename);
if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", FileName.GetChars());
return false;
}
}

View file

@ -102,9 +102,9 @@ FDirectory::FDirectory(const char * directory)
#ifdef _WIN32
free((void *)directory);
#endif
dirname.ReplaceChars('\\', '/');
FixPathSeperator(dirname);
if (dirname[dirname.Len()-1] != '/') dirname += '/';
Filename = copystring(dirname);
FileName = dirname;
}
@ -195,7 +195,7 @@ int FDirectory::AddDirectory(const char *dirpath)
return 0;
}
const size_t namepos = strlen(Filename);
const size_t namepos = strlen(FileName);
FString pathfix;
while ((ent = fts_read(fts)) != NULL)
@ -248,7 +248,7 @@ int FDirectory::AddDirectory(const char *dirpath)
bool FDirectory::Open(bool quiet)
{
NumLumps = AddDirectory(Filename);
NumLumps = AddDirectory(FileName);
if (!quiet) Printf(", %d lumps\n", NumLumps);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump));
return true;
@ -268,7 +268,7 @@ void FDirectory::AddEntry(const char *fullpath, int size)
lump_p->mFullPath = fullpath;
// [mxd] Convert name to lowercase
FString name = fullpath + strlen(Filename);
FString name = fullpath + strlen(FileName);
name.ToLower();
// The lump's name is only the part relative to the main directory

View file

@ -85,7 +85,6 @@ public:
FGrpFile::FGrpFile(const char *filename, FileReader &file)
: FUncompressedFile(filename, file)
{
Lumps = NULL;
}
//==========================================================================
@ -104,7 +103,7 @@ bool FGrpFile::Open(bool quiet)
GrpLump *fileinfo = new GrpLump[NumLumps];
Reader.Read (fileinfo, NumLumps * sizeof(GrpLump));
Lumps = new FUncompressedLump[NumLumps];
Lumps.Resize(NumLumps);
int Position = sizeof(GrpInfo) + NumLumps * sizeof(GrpLump);

View file

@ -69,17 +69,17 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file)
bool FLumpFile::Open(bool quiet)
{
FString name(ExtractFileBase (Filename));
FString name(ExtractFileBase (FileName));
Lumps = new FUncompressedLump[1]; // must use array allocator
uppercopy(Lumps->Name, name);
Lumps->Name[8] = 0;
Lumps->Owner = this;
Lumps->Position = 0;
Lumps->LumpSize = (int)Reader.GetLength();
Lumps->Namespace = ns_global;
Lumps->Flags = 0;
Lumps->FullName = NULL;
Lumps.Resize(1);
uppercopy(Lumps[0].Name, name);
Lumps[0].Name[8] = 0;
Lumps[0].Owner = this;
Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength();
Lumps[0].Namespace = ns_global;
Lumps[0].Flags = 0;
Lumps[0].FullName = NULL;
NumLumps = 1;
if (!quiet)
{

View file

@ -80,7 +80,6 @@ public:
FPakFile::FPakFile(const char *filename, FileReader &file)
: FUncompressedFile(filename, file)
{
Lumps = NULL;
}
//==========================================================================
@ -101,7 +100,7 @@ bool FPakFile::Open(bool quiet)
Reader.Seek (header.dirofs, FileReader::SeekSet);
Reader.Read (fileinfo, NumLumps * sizeof(dpackfile_t));
Lumps = new FUncompressedLump[NumLumps];
Lumps.Resize(NumLumps);
if (!quiet && !batchrun) Printf(", %d lumps\n", NumLumps);

View file

@ -165,7 +165,7 @@ bool FWadFile::Open(bool quiet)
// Check again to detect broken wads
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
{
I_Error("Cannot load broken WAD file %s\n", Filename);
I_Error("Cannot load broken WAD file %s\n", FileName.GetChars());
}
}
@ -194,7 +194,7 @@ bool FWadFile::Open(bool quiet)
{
if (Lumps[i].LumpSize != 0)
{
Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", Filename, Lumps[i].Name);
Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].Name);
Lumps[i].Name[0] = 0;
}
Lumps[i].LumpSize = Lumps[i].Position = 0;
@ -439,7 +439,7 @@ void FWadFile::SkinHack ()
"The maps in %s will not be loaded because it has a skin.\n"
TEXTCOLOR_BLUE
"You should remove the skin from the wad to play these maps.\n",
Filename);
FileName.GetChars());
}
}

View file

@ -181,7 +181,7 @@ bool FZipFile::Open(bool quiet)
if (centraldir == 0)
{
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", Filename);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", FileName.GetChars());
return false;
}
@ -193,7 +193,7 @@ bool FZipFile::Open(bool quiet)
if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0)
{
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", Filename);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
return false;
}
@ -229,7 +229,7 @@ bool FZipFile::Open(bool quiet)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{
free(directory);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
return false;
}
@ -300,7 +300,7 @@ bool FZipFile::Open(bool quiet)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{
free(directory);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
return false;
}
@ -320,7 +320,7 @@ bool FZipFile::Open(bool quiet)
zip_fh->Method != METHOD_IMPLODE &&
zip_fh->Method != METHOD_SHRINK)
{
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name.GetChars(), zip_fh->Method);
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method);
skipped++;
continue;
}
@ -328,7 +328,7 @@ bool FZipFile::Open(bool quiet)
zip_fh->Flags = LittleShort(zip_fh->Flags);
if (zip_fh->Flags & ZF_ENCRYPTED)
{
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name.GetChars());
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars());
skipped++;
continue;
}

View file

@ -156,7 +156,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
return false;
}
const FString dirName = ExtractFileBase(archive->Filename);
const FString dirName = ExtractFileBase(archive->FileName);
const FString fileName = ExtractFileBase(resPath, true);
const FString filePath = dirName + '/' + fileName;
@ -323,9 +323,8 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet)
//==========================================================================
FResourceFile::FResourceFile(const char *filename)
: FileName(filename)
{
if (filename != NULL) Filename = copystring(filename);
else Filename = NULL;
}
FResourceFile::FResourceFile(const char *filename, FileReader &r)
@ -336,7 +335,6 @@ FResourceFile::FResourceFile(const char *filename, FileReader &r)
FResourceFile::~FResourceFile()
{
if (Filename != NULL) delete [] Filename;
}
int lumpcmp(const void * a, const void * b)
@ -653,12 +651,6 @@ FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r)
: FResourceFile(filename, r)
{}
FUncompressedFile::~FUncompressedFile()
{
if (Lumps != NULL) delete [] Lumps;
}
//==========================================================================
//
@ -667,9 +659,8 @@ FUncompressedFile::~FUncompressedFile()
//==========================================================================
FExternalLump::FExternalLump(const char *_filename, int filesize)
: Filename(_filename)
{
filename = _filename? copystring(_filename) : NULL;
if (filesize == -1)
{
FileReader f;
@ -690,11 +681,6 @@ FExternalLump::FExternalLump(const char *_filename, int filesize)
}
FExternalLump::~FExternalLump()
{
if (filename != NULL) delete [] filename;
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
@ -707,7 +693,7 @@ int FExternalLump::FillCache()
Cache = new char[LumpSize];
FileReader f;
if (f.OpenFile(filename))
if (f.OpenFile(Filename))
{
f.Read(Cache, LumpSize);
}
@ -722,19 +708,19 @@ int FExternalLump::FillCache()
bool FMemoryFile::Open(bool quiet)
{
FString name(ExtractFileBase(Filename));
FString fname(ExtractFileBase(Filename, true));
FString name(ExtractFileBase(FileName));
FString fname(ExtractFileBase(FileName, true));
Lumps = new FUncompressedLump[1]; // must use array allocator
uppercopy(Lumps->Name, name);
Lumps->Name[8] = 0;
Lumps->FullName = fname;
Lumps->Owner = this;
Lumps->Position = 0;
Lumps->LumpSize = (int)Reader.GetLength();
Lumps->Namespace = ns_global;
Lumps->Flags = 0;
Lumps->FullName = NULL;
Lumps.Resize(1);
uppercopy(Lumps[0].Name, name);
Lumps[0].Name[8] = 0;
Lumps[0].FullName = fname;
Lumps[0].Owner = this;
Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength();
Lumps[0].Namespace = ns_global;
Lumps[0].Flags = 0;
Lumps[0].FullName = nullptr;
NumLumps = 1;
return true;
}

View file

@ -82,7 +82,7 @@ class FResourceFile
{
public:
FileReader Reader;
const char *Filename;
FString FileName;
protected:
uint32_t NumLumps;
@ -133,21 +133,19 @@ struct FUncompressedLump : public FResourceLump
class FUncompressedFile : public FResourceFile
{
protected:
FUncompressedLump * Lumps = nullptr;
TArray<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename);
FUncompressedFile(const char *filename, FileReader &r);
virtual ~FUncompressedFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
struct FExternalLump : public FResourceLump
{
const char *filename; // the actual file name. This is not necessarily the same as the lump name!
FString Filename;
FExternalLump(const char *_filename, int filesize = -1);
~FExternalLump();
virtual int FillCache();
};

View file

@ -21,6 +21,10 @@ public:
void Open(const char *lumpname);
bool OpenFile(const char *filename);
void OpenMem(const char *name, const char *buffer, int size);
void OpenMem(const char *name, const TArray<uint8_t> &buffer)
{
OpenMem(name, (const char*)buffer.Data(), buffer.Size());
}
void OpenString(const char *name, FString buffer);
void OpenLumpNum(int lump);
void Close();

View file

@ -443,7 +443,7 @@ static void DoParse(int lumpnum)
// If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors.
if (FScriptPosition::ErrorCounter > 0)
{
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(baselump).GetChars());
}
#ifndef NDEBUG
@ -457,7 +457,7 @@ static void DoParse(int lumpnum)
if (Args->CheckParm("-dumpast"))
{
FString ast = ZCC_PrintAST(state.TopNode);
FString filename = Wads.GetLumpFullPath(lumpnum);
FString filename = Wads.GetLumpFullPath(baselump);
filename.ReplaceChars(":\\/?|", '.');
filename << ".ast";
FileWriter *ff = FileWriter::Open(filename);
@ -469,19 +469,19 @@ static void DoParse(int lumpnum)
}
PSymbolTable symtable;
auto newns = Wads.GetLumpFile(lumpnum) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(lumpnum));
ZCCCompiler cc(state, NULL, symtable, newns, lumpnum, state.ParseVersion);
auto newns = Wads.GetLumpFile(baselump) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(baselump));
ZCCCompiler cc(state, NULL, symtable, newns, baselump, state.ParseVersion);
cc.Compile();
if (FScriptPosition::ErrorCounter > 0)
{
// Abort if the compiler produced any errors. Also do not compile further lumps, because they very likely miss some stuff.
I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, Wads.GetLumpFullPath(baselump).GetChars());
}
else if (FScriptPosition::WarnCounter > 0)
{
// If we got warnings, but no errors, print the information but continue.
Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(baselump).GetChars());
}
}

View file

@ -157,14 +157,14 @@ public:
Count = 0;
Array = NULL;
}
TArray (int max, bool reserve = false)
TArray (size_t max, bool reserve = false)
{
Most = max;
Count = reserve? max : 0;
Most = (unsigned)max;
Count = (unsigned)(reserve? max : 0);
Array = (T *)M_Malloc (sizeof(T)*max);
if (reserve)
if (reserve && Count > 0)
{
for (unsigned i = 0; i < Count; i++) ::new(&Array[i]) T();
ConstructEmpty(0, Count - 1);
}
}
TArray (const TArray<T,TT> &other)
@ -362,17 +362,6 @@ public:
}
}
// Reserves a range of entries in the middle of the array, shifting elements as needed
void ReserveAt(unsigned int index, unsigned int amount)
{
Grow(amount);
memmove(&Array[index + amount], &Array[index], sizeof(T)*(Count - index - amount));
for (unsigned i = 0; i < amount; i++)
{
::new ((void *)&Array[index + i]) T();
}
}
void ShrinkToFit ()
{
if (Most > Count)
@ -411,10 +400,7 @@ public:
{
// Adding new entries
Grow (amount - Count);
for (unsigned int i = Count; i < amount; ++i)
{
::new((void *)&Array[i]) T;
}
ConstructEmpty(Count, amount - 1);
}
else if (Count != amount)
{
@ -423,6 +409,18 @@ public:
}
Count = amount;
}
// Ensures that the array has at most amount entries.
// Useful in cases where the initial allocation may be larger than the final result.
// Resize would create a lot of unneeded code in those cases.
void Clamp(unsigned int amount)
{
if (Count > amount)
{
// Deleting old entries
DoDelete(amount, Count - 1);
Count = amount;
}
}
void Alloc(unsigned int amount)
{
// first destroys all content and then rebuilds the array.
@ -433,15 +431,12 @@ public:
}
// Reserves amount entries at the end of the array, but does nothing
// with them.
unsigned int Reserve (unsigned int amount)
unsigned int Reserve (size_t amount)
{
Grow (amount);
Grow ((unsigned)amount);
unsigned int place = Count;
Count += amount;
for (unsigned int i = place; i < Count; ++i)
{
::new((void *)&Array[i]) T;
}
Count += (unsigned)amount;
if (Count > 0) ConstructEmpty(place, Count - 1);
return place;
}
unsigned int Size () const
@ -463,7 +458,12 @@ public:
void Reset()
{
Clear();
ShrinkToFit();
Most = 0;
if (Array != nullptr)
{
M_Free(Array);
Array = nullptr;
}
}
private:
T *Array;
@ -501,6 +501,15 @@ private:
Array[i].~T();
}
}
void ConstructEmpty(unsigned int first, unsigned int last)
{
assert(last != ~0u);
for (unsigned int i = first; i <= last; ++i)
{
::new(&Array[i]) T;
}
}
};
// TDeletingArray -----------------------------------------------------------

View file

@ -419,7 +419,8 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel)
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel,
uint32_t *indices, size_t indexcount)
{
// Use an equation similar to player sprites to determine shade
@ -487,9 +488,20 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
poly.mIndexIndex = mIndices.Size();
poly.mIndexCount += (npoints - 2) * 3;
for (int i = 2; i < npoints; ++i)
if (indices == nullptr || indexcount == 0)
{
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
for (int i = 2; i < npoints; ++i)
{
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
}
}
else
{
int addr = mIndices.Reserve(indexcount);
for (size_t i = 0; i < indexcount; i++)
{
mIndices[addr + i] = addr + indices[i];
}
}
AddCommand(&poly);

View file

@ -130,7 +130,7 @@ public:
void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms);
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel);
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, uint32_t *indices, size_t indexcount);
void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin);
void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style);

View file

@ -1253,9 +1253,9 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim)
void DFrameBuffer::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip, uint32_t *indices, size_t indexcount)
{
m2DDrawer.AddPoly(tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel);
m2DDrawer.AddPoly(tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel, indices, indexcount);
}
//==========================================================================

View file

@ -529,7 +529,7 @@ public:
// Fill a simple polygon with a texture
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip, uint32_t *indices, size_t indexcount);
// Set an area to a specified color
void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color);

View file

@ -1281,6 +1281,30 @@ void FWadCollection::ReadLump (int lump, void *dest)
}
}
//==========================================================================
//
// W_ReadLump
//
// Loads the lump into a TArray and returns it.
//
//==========================================================================
TArray<uint8_t> FWadCollection::ReadLumpIntoArray(int lump, int pad)
{
auto lumpr = OpenLumpReader(lump);
auto size = lumpr.GetLength();
TArray<uint8_t> data(size + pad);
auto numread = lumpr.Read(data.Data(), size);
if (numread != size)
{
I_Error("W_ReadLump: only read %ld of %ld on lump %i\n",
numread, size, lump);
}
if (pad > 0) memset(&data[size], 0, pad);
return data;
}
//==========================================================================
//
// ReadLump - variant 2
@ -1389,7 +1413,7 @@ const char *FWadCollection::GetWadName (int wadnum) const
return NULL;
}
name = Files[wadnum]->Filename;
name = Files[wadnum]->FileName;
slash = strrchr (name, '/');
return slash != NULL ? slash+1 : name;
}
@ -1452,10 +1476,10 @@ const char *FWadCollection::GetWadFullName (int wadnum) const
{
if ((unsigned int)wadnum >= Files.Size())
{
return NULL;
return nullptr;
}
return Files[wadnum]->Filename;
return Files[wadnum]->FileName;
}

View file

@ -148,6 +148,7 @@ public:
void ReadLump (int lump, void *dest);
TArray<uint8_t> ReadLumpIntoArray(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FMemLump isn't writable!)
FMemLump ReadLump (int lump);
FMemLump ReadLump (const char *name) { return ReadLump (GetNumForName (name)); }

View file

@ -1,5 +1,6 @@
in vec4 pixelpos;
in vec3 glowdist;
in vec3 gradientdist;
in vec4 vWorldNormal;
in vec4 vEyeNormal;
@ -111,7 +112,7 @@ vec4 getTexel(vec2 st)
}
if (uObjectColor2.a == 0.0) texel *= uObjectColor;
else texel *= mix(uObjectColor, uObjectColor2, glowdist.z);
else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z);
return desaturate(texel);
}

View file

@ -7,6 +7,7 @@ layout(location = 3) in vec4 aVertex2;
layout(location = 4) in vec4 aNormal;
out vec4 pixelpos;
out vec3 glowdist;
out vec3 gradientdist;
out vec4 vWorldNormal;
out vec4 vEyeNormal;
@ -37,16 +38,28 @@ void main()
pixelpos.xyz = worldcoord.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
float topatpoint = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z);
float bottomatpoint = -((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z);
glowdist.x = topatpoint - worldcoord.y;
glowdist.y = worldcoord.y - bottomatpoint;
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
if (uGlowTopColor.a > 0 || uGlowBottomColor.a > 0)
{
float topatpoint = (uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z;
float bottomatpoint = (uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z;
glowdist.x = topatpoint - worldcoord.y;
glowdist.y = worldcoord.y - bottomatpoint;
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uObjectColor2.a != 0)
{
float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z;
float bottomatpoint = (uGradientBottomPlane.w + uGradientBottomPlane.x * worldcoord.x + uGradientBottomPlane.y * worldcoord.z) * uGradientBottomPlane.z;
gradientdist.x = topatpoint - worldcoord.y;
gradientdist.y = worldcoord.y - bottomatpoint;
gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uSplitBottomPlane.z != 0.0)
{
gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
gl_ClipDistance[3] = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
gl_ClipDistance[4] = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
}
vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0);

View file

@ -445,6 +445,13 @@ class Actor : Thinker native
return true;
}
// Called by revival/resurrection to check if one can resurrect the other.
// "other" can be null when not passive.
virtual bool CanResurrect(Actor other, bool passive)
{
return true;
}
// Called when an actor is to be reflected by a disc of repulsion.
// Returns true to continue normal blast processing.
virtual bool SpecialBlastHandling (Actor source, double strength)
@ -1085,6 +1092,7 @@ class Actor : Thinker native
native void A_RaiseChildren(int flags = 0);
native void A_RaiseSiblings(int flags = 0);
native bool A_RaiseSelf(int flags = 0);
native bool RaiseActor(Actor other, int flags = 0);
native bool CanRaise();
native void Revive();
action native bool, Actor A_ThrowGrenade(class<Actor> itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true);

View file

@ -940,6 +940,7 @@ enum EDmgFlags
DMG_USEANGLE = 512,
DMG_NO_PAIN = 1024,
DMG_EXPLOSION = 2048,
DMG_NO_ENHANCE = 4096,
}
enum EReplace

View file

@ -45,6 +45,12 @@ struct Side native play
bottom=2
};
enum EColorPos
{
walltop = 0,
wallbottom = 1
}
enum EWallFlags
{
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
@ -57,6 +63,7 @@ struct Side native play
WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog.
};
native readonly Sector sector; // Sector the SideDef is facing.
//DBaseDecal* AttachedDecals; // [RH] Decals bound to the wall
native readonly Line linedef;
@ -77,6 +84,7 @@ struct Side native play
native void SetTextureYScale(int which, double scale);
native double GetTextureYScale(int which);
native void MultiplyTextureYScale(int which, double delta);
native void SetSpecialColor(int tier, int position, Color scolor);
//native DInterpolation *SetInterpolation(int position);
//native void StopInterpolation(int position);