From 910e4dbcf02edc566cd2776d389c4b2294bf0594 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sun, 19 Jan 2025 17:19:54 -0700 Subject: [PATCH 01/57] Better flat visibility checks for Ortho projection. --- src/rendering/hwrenderer/scene/hw_flats.cpp | 12 ++++++------ src/rendering/r_utility.cpp | 3 +++ src/rendering/r_utility.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index f423c73fc..f14757ade 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -518,7 +518,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) // // // - if (((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))&& !(vp.IsOrtho() && (vp.PitchSin < 0.0))) + if ((which & SSRF_RENDERFLOOR) && (vp.IsOrtho() ? vp.ViewVector3D.dot(frontsector->floorplane.Normal()) < 0.0 : frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERFLOOR))) { // process the original floor first. @@ -576,7 +576,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) // // // - if (((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING))) && !(vp.IsOrtho() && (vp.PitchSin > 0.0))) + if ((which & SSRF_RENDERCEILING) && (vp.IsOrtho() ? vp.ViewVector3D.dot(frontsector->ceilingplane.Normal()) < 0.0 : frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING))) { // process the original ceiling first. @@ -661,7 +661,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top < lastceilingheight) { - if (vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos)) + if ((vp.IsOrtho() ? vp.ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -675,7 +675,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom < lastceilingheight) { - if (vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos)) + if ((vp.IsOrtho() ? vp.ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -701,7 +701,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot); if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX)) { - if (vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos)) + if ((vp.IsOrtho() ? vp.ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos))) { SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; @@ -722,7 +722,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) double ff_top = rover->top.plane->ZatPoint(sector->centerspot); if (ff_top > lastfloorheight) { - if (vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos)) + if ((vp.IsOrtho() ? vp.ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos))) { SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG)); Colormap.FadeColor = frontsector->Colormap.FadeColor; diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 3a3fdd70e..cd0c3d0c2 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -704,6 +704,9 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) ViewVector.X = v.X; ViewVector.Y = v.Y; HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees()); + ViewVector3D.X = v.X * PitchCos; + ViewVector3D.Y = v.Y * PitchCos; + ViewVector3D.Z = -PitchSin; if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) { diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index f7e4a1e1d..d82b03e68 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -25,6 +25,7 @@ struct FRenderViewpoint DRotator Angles; // Camera angles FRotator HWAngles; // Actual rotation angles for the hardware renderer DVector2 ViewVector; // HWR only: direction the camera is facing. + DVector3 ViewVector3D; // 3D direction the camera is facing. AActor *ViewActor; // either the same as camera or nullptr FLevelLocals *ViewLevel; // The level this viewpoint is on. From 527a09c66b6d76731b616ab1a631d6b714bb50ab Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Thu, 30 Jan 2025 22:10:45 -0700 Subject: [PATCH 02/57] 3D floor flats now respect r_dithertransparency flag (how did this make it into vkdoom but not gzdoom?) --- .../hwrenderer/scene/hw_drawinfo.cpp | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 3453b6e50..4068fbbb8 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -698,10 +698,50 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* } break; case TRACE_HitFloor: - res.Sector->floorplane.dithertransflag = true; + if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) + { + res.Sector->floorplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + { + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + { + if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos)) + { + rover->top.plane->dithertransflag = true; + break; // Out of for loop + } + } + } + } break; case TRACE_HitCeiling: - res.Sector->ceilingplane.dithertransflag = true; + if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) + { + res.Sector->ceilingplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + { + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + { + if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos)) + { + rover->bottom.plane->dithertransflag = true; + break; // Out of for loop + } + } + } + } break; case TRACE_HitActor: default: From 8a66eff437836ab87fc3a93630bfce48310c2e11 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Tue, 11 Feb 2025 19:51:21 -0700 Subject: [PATCH 03/57] Added visual rendering for LinePortals and SkyPortals for OoB viewpoints. SkyPortals will be stenciled, and will always use perspective projection. Disabled interpolation when portalgroup changes (portal transition occurs) if viewpoint is OoB (was necessary for fog of war when r_radarclipper is set to true). Tightened up radar clipper by making it more aggressive. Voided walls wont' get filled in by a floor or ceiling sky (because of the stencil). Ceiling sky will be half-infinitely tall upwards, and floor sky will be half-infinitely tall downwards. Use only floor skies and a good GLSKYBOX for top-down/isometric cameras. Level.ReplaceTextures("F_SKY1", "SKY1", TexMan.NOT_FLOOR); (zscript) is a nice trick for WorldLoaded(). --- src/rendering/hwrenderer/hw_entrypoint.cpp | 1 + src/rendering/hwrenderer/scene/hw_bsp.cpp | 75 ++++++----------- src/rendering/hwrenderer/scene/hw_clipper.cpp | 18 ++--- .../hwrenderer/scene/hw_drawinfo.cpp | 81 ++++++++++--------- src/rendering/hwrenderer/scene/hw_drawinfo.h | 1 + src/rendering/hwrenderer/scene/hw_portal.cpp | 24 ++++-- src/rendering/hwrenderer/scene/hw_portal.h | 4 +- src/rendering/hwrenderer/scene/hw_sky.cpp | 2 +- src/rendering/hwrenderer/scene/hw_walls.cpp | 2 - src/rendering/r_utility.cpp | 20 ++++- src/rendering/r_utility.h | 1 + 11 files changed, 118 insertions(+), 111 deletions(-) diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index e55c041a6..0252fbc40 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -167,6 +167,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou bool iso_ortho = (camera->ViewPos != NULL) && (camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC); if (iso_ortho && (camera->ViewPos->Offset.Length() > 0)) inv_iso_dist = 1.0/camera->ViewPos->Offset.Length(); di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio * inv_iso_dist, iso_ortho); + di->ProjectionMatrix2 = eye.GetProjection(fov, ratio, fovratio, false); // Regular ol' perspective projection matrix // Stereo mode specific viewpoint adjustment vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees()); diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 2c1abdf7c..ced71a6fa 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -287,15 +287,16 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) auto &clipperr = *rClipper; angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less) if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180)) { - if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR, endAngleR); + if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) { if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); backsector = hw_FakeFlat(seg->backsector, in_area, true); - if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR, endAngleR); + if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); } } @@ -313,7 +314,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) { currentsubsector->flags |= SSECMF_DRAWN; } - if ((r_radarclipper || !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR)) + if (Viewpoint.IsAllowedOoB() && (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR)) { currentsubsector->flags |= SSECMF_DRAWN; } @@ -326,31 +327,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) return; } - if (Viewpoint.IsAllowedOoB()) // No need for vertical clipping if viewpoint not allowed out of bounds - { - auto &clipperv = *vClipper; - angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1)); - angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1)); - angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2)); - angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2)); - angle_t temp; - // Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top) - if(int(startPitch) > int(startPitch2)) // Handle zero crossing - { - temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange - } - if(int(endPitch) > int(endPitch2)) // Handle zero crossing - { - temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange - } - - if (!clipperv.SafeCheckRange(startPitch, endPitch2)) - { - return; - } - } - - if (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)) + if (Viewpoint.IsAllowedOoB() && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))) currentsubsector->flags |= SSECMF_DRAWN; uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ); @@ -729,8 +706,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return; - // cull everything if subsector outside vertical clipper - if ((sub->polys == nullptr) && (!Viewpoint.IsOrtho() || !((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper))) + // cull everything if subsector outside all relevant clippers + if ((sub->polys == nullptr)) { auto &clipper = *mClipper; auto &clipperv = *vClipper; @@ -739,7 +716,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) seg_t * seg = sub->firstline; bool anglevisible = false; bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds - bool radarvisible = false; + bool radarvisible = !(Viewpoint.IsAllowedOoB()) || !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch); angle_t pitchtemp; angle_t pitchmin = ANGLE_90; angle_t pitchmax = 0; @@ -748,13 +725,19 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) { if((seg->v1 != nullptr) && (seg->v2 != nullptr)) { - angle_t startAngle = clipper.GetClipAngle(seg->v2); - angle_t endAngle = clipper.GetClipAngle(seg->v1); - if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle); - angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); - angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); - if (startAngleR-endAngleR >= ANGLE_180) - radarvisible |= (clipperr.SafeCheckRange(startAngleR, endAngleR) || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch)); + if (!anglevisible) + { + angle_t startAngle = clipper.GetClipAngle(seg->v2); + angle_t endAngle = clipper.GetClipAngle(seg->v1); + if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle); + } + if (!radarvisible) + { + angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); + angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + if (startAngleR-endAngleR >= ANGLE_180) radarvisible |= clipperr.SafeCheckRange(startAngleR, endAngleR); + } + if (!pitchvisible) { pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1)); @@ -988,8 +971,8 @@ void HWDrawInfo::RenderOrthoNoFog() { if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)) { - double vxdbl = Viewpoint.camera->X(); - double vydbl = Viewpoint.camera->Y(); + double vxdbl = Viewpoint.OffPos.X; + double vydbl = Viewpoint.OffPos.Y; double ext = Viewpoint.camera->ViewPos->Offset.Length() ? 3.0 * Viewpoint.camera->ViewPos->Offset.Length() * tan (Viewpoint.FieldOfView.Radians()*0.5) : 100.0; FBoundingBox viewbox(vxdbl, vydbl, ext); @@ -1014,16 +997,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites) viewy = FLOAT2FIXED(Viewpoint.Pos.Y); if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB()) { - if (Viewpoint.camera->tracer != NULL) - { - viewx = FLOAT2FIXED(Viewpoint.camera->tracer->X()); - viewy = FLOAT2FIXED(Viewpoint.camera->tracer->Y()); - } - else - { - viewx = FLOAT2FIXED(Viewpoint.camera->X()); - viewy = FLOAT2FIXED(Viewpoint.camera->Y()); - } + viewx = FLOAT2FIXED(Viewpoint.OffPos.X); + viewy = FLOAT2FIXED(Viewpoint.OffPos.Y); } validcount++; // used for processing sidedefs only once by the renderer. diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index 059a39981..7444af309 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -394,18 +394,10 @@ angle_t Clipper::PointToPseudoAngle(double x, double y) { double vecx = x - viewpoint->Pos.X; double vecy = y - viewpoint->Pos.Y; - if ((viewpoint->camera != NULL) && amRadar) + if (amRadar) { - if (viewpoint->camera->tracer != NULL) - { - vecx = x - viewpoint->camera->tracer->X(); - vecy = y - viewpoint->camera->tracer->Y(); - } - else - { - vecx = x - viewpoint->camera->X(); - vecy = y - viewpoint->camera->Y(); - } + vecx = x - viewpoint->OffPos.X; + vecy = y - viewpoint->OffPos.Y; } if (vecx == 0 && vecy == 0) @@ -467,7 +459,7 @@ angle_t Clipper::PointToPseudoPitch(double x, double y, double z) angle_t Clipper::PointToPseudoOrthoAngle(double x, double y) { - DVector3 disp = DVector3( x, y, 0 ) - viewpoint->camera->Pos(); + DVector3 disp = DVector3(x, y, 0) - viewpoint->OffPos; if (viewpoint->camera->ViewPos->Offset.XY().Length() == 0) { return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() ); @@ -491,7 +483,7 @@ angle_t Clipper::PointToPseudoOrthoAngle(double x, double y) angle_t Clipper::PointToPseudoOrthoPitch(double x, double y, double z) { - DVector3 disp = DVector3( x, y, z ) - viewpoint->camera->Pos(); + DVector3 disp = DVector3(x, y, z) - viewpoint->OffPos; if (viewpoint->camera->ViewPos->Offset.XY().Length() > 0) { double yproj = viewpoint->PitchSin * disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Cos(); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 4068fbbb8..10ee57b88 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -160,6 +160,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni VPUniforms.mProjectionMatrix.loadIdentity(); VPUniforms.mViewMatrix.loadIdentity(); VPUniforms.mNormalViewMatrix.loadIdentity(); + ProjectionMatrix2.loadIdentity(); VPUniforms.mViewHeight = viewheight; if (lightmode == ELightMode::Build) { @@ -684,60 +685,70 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* userdata) { - int* count = (int*)userdata; + BitArray* CurMapSections = (BitArray*)userdata; double bf, bc; - (*count)++; + switch(res.HitType) { case TRACE_HitWall: if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS)) { - bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY()); - bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY()); - if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS; + sector_t* linesec = res.Line->sidedef[res.Side]->sector; + if (linesec->subsectorcount > 0 && (*CurMapSections)[linesec->subsectors[0]->mapsection]) + { + bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY()); + bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY()); + if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS; + } } break; case TRACE_HitFloor: - if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) { - res.Sector->floorplane.dithertransflag = true; - } - else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors - { - F3DFloor *rover; - int kk; - for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) { - rover = res.Sector->e->XFloor.ffloors[kk]; - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + res.Sector->floorplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) { - if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos)) + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) { - rover->top.plane->dithertransflag = true; - break; // Out of for loop + if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos)) + { + rover->top.plane->dithertransflag = true; + break; // Out of for loop + } } } } } break; case TRACE_HitCeiling: - if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) { - res.Sector->ceilingplane.dithertransflag = true; - } - else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors - { - F3DFloor *rover; - int kk; - for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) { - rover = res.Sector->e->XFloor.ffloors[kk]; - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + res.Sector->ceilingplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) { - if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos)) + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) { - rover->bottom.plane->dithertransflag = true; - break; // Out of for loop + if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos)) + { + rover->bottom.plane->dithertransflag = true; + break; // Out of for loop + } } } } @@ -763,13 +774,11 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) DVector3 vvec = actorpos - Viewpoint.Pos; if (Viewpoint.IsOrtho()) { - vvec += Viewpoint.camera->Pos() - actorpos; - vvec *= 5.0; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection()) + vvec = 5.0 * Viewpoint.camera->ViewPos->Offset.Length() * Viewpoint.ViewVector3D; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection()) } double distance = vvec.Length() - actor->radius; DVector3 campos = actorpos - vvec; sector_t* startsec; - int count = 0; vvec = vvec.Unit(); campos.X -= horix; campos.Y += horiy; campos.Z += actor->Height * 0.25; @@ -777,10 +786,10 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) { startsec = Level->PointInRenderSubsector(campos)->sector; Trace(campos, startsec, vvec, distance, - 0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count); + 0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections); campos.Z += actor->Height * 0.5; Trace(campos, startsec, vvec, distance, - 0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count); + 0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections); campos.Z -= actor->Height * 0.5; campos.X += horix; campos.Y -= horiy; } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index ce848e297..e4cbeb98e 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -150,6 +150,7 @@ struct HWDrawInfo Clipper *rClipper; // Radar clipper FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state + VSMatrix ProjectionMatrix2; TArray Portals; TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray hudsprites; // These may just be stored by value. diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index b0ea3a8c9..b103f0f81 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -125,6 +125,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di { HWPortal * best = nullptr; unsigned bestindex = 0; + bool usestencil = outer_di->Viewpoint.IsAllowedOoB(); // Find the one with the highest amount of lines. // Normally this is also the one that saves the largest amount @@ -145,7 +146,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di } // If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area. - if (p->boundingBox.contains(outer_di->Viewpoint.Pos)) + if (p->boundingBox.contains(usestencil ? outer_di->Viewpoint.OffPos : outer_di->Viewpoint.Pos)) { best = p; bestindex = i; @@ -157,7 +158,13 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di if (best) { portals.Delete(bestindex); - RenderPortal(best, state, false, outer_di); + if (usestencil) + { + tempmatrix = outer_di->VPUniforms.mProjectionMatrix; // ensure perspective projection matrix for skies + outer_di->VPUniforms.mProjectionMatrix = outer_di->ProjectionMatrix2; + } + RenderPortal(best, state, usestencil, outer_di); + if (usestencil) outer_di->VPUniforms.mProjectionMatrix = tempmatrix; delete best; return true; } @@ -410,20 +417,23 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) // Set the clipper to the minimal visible area clipper->SafeAddClipRange(0, 0xffffffff); + auto outvp = outer_di->Viewpoint; + DVector3 outPos = clipper->amRadar ? outvp.OffPos : outvp.Pos; + angle_t padding = clipper->amRadar ? 0x00200000 : 0x00000000; // Make radar clipping more aggressive (reveal less) for (unsigned int i = 0; i < lines.Size(); i++) { - DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset; - DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset; + DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outPos).Angle() + angleOffset; + DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outPos).Angle() + angleOffset; if (deltaangle(endAngle, startAngle) < nullAngle) { - clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); + clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs() + padding, endAngle.BAMs() - padding); } } // and finally clip it to the visible area angle_t a1 = di->FrustumAngle(); - if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); + if (!clipper->amRadar && a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); // lock the parts that have just been clipped out. clipper->SetSilhouette(); @@ -608,6 +618,8 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl P_TranslatePortalZ(origin, vp.Pos.Z); P_TranslatePortalXY(origin, vp.Path[0].X, vp.Path[0].Y); P_TranslatePortalXY(origin, vp.Path[1].X, vp.Path[1].Y); + P_TranslatePortalXY(origin, vp.OffPos.X, vp.OffPos.Y); + P_TranslatePortalZ(origin, vp.OffPos.Z); if (!vp.showviewer && vp.camera != nullptr && P_PointOnLineSidePrecise(vp.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(vp.Path[1], glport->lines[0]->mDestination)) { double distp = (vp.Path[0] - vp.Path[1]).Length(); diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 29481f9e3..760b8c435 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -112,6 +112,8 @@ struct FPortalSceneState int skyboxrecursion = 0; + VSMatrix tempmatrix; + void BeginScene() { UniqueSkies.Clear(); @@ -145,7 +147,7 @@ public: virtual bool NeedDepthBuffer() { return true; } virtual void DrawContents(HWDrawInfo *di, FRenderState &state) { - if (Setup(di, state, di->mClipper)) + if (Setup(di, state, (di->Viewpoint.IsAllowedOoB() ? di->rClipper : di->mClipper))) { di->DrawScene(DM_PORTAL); Shutdown(di, state); diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 6d77a275d..93fc827cc 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -130,7 +130,6 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect) { int ptype = -1; - if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Couldn't prevent sky portal occlusion. Skybox is bad in ortho too. FSectorPortal *sportal = sector->ValidatePortal(plane); if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code @@ -155,6 +154,7 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { + if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; auto glport = sector->GetPortalGroup(plane); if (glport != NULL) { diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 5c5e357d5..97b0c91a6 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -2181,8 +2181,6 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s } bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]; - // Don't render portal insides if in orthographic mode - if (di->di) isportal &= !(di->di->Viewpoint.IsOrtho()); //return; // [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index cd0c3d0c2..035ac6de7 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -550,8 +550,12 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player const int prevPortalGroup = viewLvl->PointInRenderSubsector(iView->Old.Pos)->sector->PortalGroup; const int curPortalGroup = viewLvl->PointInRenderSubsector(iView->New.Pos)->sector->PortalGroup; - const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); - viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac; + if (viewPoint.IsAllowedOoB() && prevPortalGroup != curPortalGroup) viewPoint.Pos = iView->New.Pos; + else + { + const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); + viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac; + } viewPoint.Path[0] = viewPoint.Path[1] = iView->New.Pos; } } @@ -708,6 +712,18 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) ViewVector3D.Y = v.Y * PitchCos; ViewVector3D.Z = -PitchSin; + if (IsOrtho() || IsAllowedOoB()) // These auto-ensure that camera and camera->ViewPos exist + { + if (camera->tracer != NULL) + { + OffPos = camera->tracer->Pos(); + } + else + { + OffPos = Pos + ViewVector3D * camera->ViewPos->Offset.Length(); + } + } + if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) { ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen. diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index d82b03e68..0c2f47833 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -26,6 +26,7 @@ struct FRenderViewpoint FRotator HWAngles; // Actual rotation angles for the hardware renderer DVector2 ViewVector; // HWR only: direction the camera is facing. DVector3 ViewVector3D; // 3D direction the camera is facing. + DVector3 OffPos; // Viewpoint position to use for Ortho and OoB calculations AActor *ViewActor; // either the same as camera or nullptr FLevelLocals *ViewLevel; // The level this viewpoint is on. From e73c283a97f3dce3544148f05e4f9e675098e7e7 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Thu, 13 Feb 2025 21:54:36 -0700 Subject: [PATCH 04/57] Making 3D-floors respond to r_dithertransparency properly. --- src/gamedata/r_defs.h | 5 ++++ src/rendering/hwrenderer/scene/hw_bsp.cpp | 5 ++-- .../hwrenderer/scene/hw_drawinfo.cpp | 30 +++++++++++++++++-- src/rendering/hwrenderer/scene/hw_walls.cpp | 22 ++++++++++++-- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index a6f4c2c4f..663f3aa38 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -1196,6 +1196,9 @@ enum WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative WALLF_DITHERTRANS = 8192, // Render with dithering transparency shader (gets reset every frame) + WALLF_DITHERTRANS_TOP = WALLF_DITHERTRANS << 0, // Top tier (gets reset every frame) + WALLF_DITHERTRANS_MID = WALLF_DITHERTRANS << 1, // Mid tier (gets reset every frame) + WALLF_DITHERTRANS_BOTTOM = WALLF_DITHERTRANS << 2, // Bottom tier (gets reset every frame) }; struct side_t @@ -1271,6 +1274,8 @@ struct side_t int numsegs; int sidenum; + int dithertranscount; + int GetLightLevel (bool foggy, int baselight, int which, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const; void SetLight(int16_t l) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index ced71a6fa..5e64c8fdd 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -297,6 +297,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); backsector = hw_FakeFlat(seg->backsector, in_area, true); if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); + backsector = nullptr; } } @@ -335,7 +336,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) if (!seg->backsector) { if(!Viewpoint.IsAllowedOoB()) - if (!(seg->sidedef->Flags & WALLF_DITHERTRANS)) clipper.SafeAddClipRange(startAngle, endAngle); + if (!(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle); } else if (!ispoly) // Two-sided polyobjects never obstruct the view { @@ -362,7 +363,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) if (hw_CheckClip(seg->sidedef, currentsector, backsector)) { - if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS)) + if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle); } } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 10ee57b88..0fc7bc896 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -691,14 +691,28 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* switch(res.HitType) { case TRACE_HitWall: - if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS)) { sector_t* linesec = res.Line->sidedef[res.Side]->sector; if (linesec->subsectorcount > 0 && (*CurMapSections)[linesec->subsectors[0]->mapsection]) { bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY()); bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY()); - if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS; + if (res.Line->sidedef[!res.Side]) + { + // Two sided line! So let's find out if mid, top, or bottom texture needs dithered transparency + bf = max(bf, res.Line->sidedef[!res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY())); + bc = min(bc, res.Line->sidedef[!res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY())); + if (res.HitPos.Z <= bf) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_BOTTOM; + else if (res.HitPos.Z < bc) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID; + else res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_TOP; + + res.Line->sidedef[res.Side]->dithertranscount = max(1, res.Line->sidedef[!res.Side]->sector->e->XFloor.ffloors.Size()); + } + else if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) + { + res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID; + res.Line->sidedef[res.Side]->dithertranscount = 1; + } } } break; @@ -793,6 +807,18 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) campos.Z -= actor->Height * 0.5; campos.X += horix; campos.Y -= horiy; } + + // Tracers don't work on 3D floors when you are starting in the same sector (standing under them, for example) + if (actor->Sector->e->XFloor.ffloors.Size()) // 3D floor + { + F3DFloor *rover; + for (int kk = 0; kk < (int)actor->Sector->e->XFloor.ffloors.Size(); kk++) + { + rover = actor->Sector->e->XFloor.ffloors[kk]; + rover->top.plane->dithertransflag = true; + rover->bottom.plane->dithertransflag = true; + } + } } } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 97b0c91a6..47e651bd4 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -83,15 +83,31 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t void HWWall::RenderWall(FRenderState &state, int textured) { - if (seg->sidedef->Flags & WALLF_DITHERTRANS) state.SetEffect(EFF_DITHERTRANS); + bool ditherT = (type == RENDERWALL_BOTTOM) && (seg->sidedef->Flags & WALLF_DITHERTRANS_BOTTOM); + ditherT |= (type == RENDERWALL_TOP) && (seg->sidedef->Flags & WALLF_DITHERTRANS_TOP); + ditherT |= seg->sidedef->Flags & WALLF_DITHERTRANS_MID; + if (ditherT) + { + state.SetEffect(EFF_DITHERTRANS); + } assert(vertcount > 0); state.SetLightIndex(dynlightindex); state.Draw(DT_TriangleFan, vertindex, vertcount); vertexcount += vertcount; - if (seg->sidedef->Flags & WALLF_DITHERTRANS) + if (ditherT) { state.SetEffect(EFF_NONE); - seg->sidedef->Flags &= ~WALLF_DITHERTRANS; // reset this every frame + switch(type) // reset this every frame + { + case RENDERWALL_TOP: + seg->sidedef->Flags &= ~WALLF_DITHERTRANS_TOP; + break; + case RENDERWALL_BOTTOM: + seg->sidedef->Flags &= ~WALLF_DITHERTRANS_BOTTOM; + break; + default: + if (seg->sidedef->dithertranscount-- <= 0) seg->sidedef->Flags &= ~WALLF_DITHERTRANS_MID; + } } } From a0f3ed11cdcb017f704ba822a26a4a7e1c999c9d Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sat, 15 Feb 2025 21:44:15 -0700 Subject: [PATCH 05/57] Reflective flats now work with OoB viewpoints, including ortho. Had to create a new type of portal stencil for the HWPlaneMirrorPortal. Stacked sector portals could be made to work the same way, but there are clipper issues, revealing out-of-view sections of the map on the other side. Hence sector portal rendering is still disabled in OoB viewpoints. --- src/rendering/hwrenderer/scene/hw_bsp.cpp | 25 +++++++++++++++---- .../hwrenderer/scene/hw_drawinfo.cpp | 5 ++-- src/rendering/hwrenderer/scene/hw_flats.cpp | 6 +++++ src/rendering/hwrenderer/scene/hw_portal.cpp | 25 +++++++++++++++++-- src/rendering/hwrenderer/scene/hw_portal.h | 4 ++- src/rendering/hwrenderer/scene/hw_sky.cpp | 2 +- src/rendering/hwrenderer/scene/hw_walls.cpp | 3 ++- 7 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 5e64c8fdd..3f834fcf6 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -718,6 +718,9 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) bool anglevisible = false; bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds bool radarvisible = !(Viewpoint.IsAllowedOoB()) || !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch); + bool ceilreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror ceiling")); + bool floorreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror floor")); + double planez = (ceilreflect ? sector->ceilingplane.ZatPoint(Viewpoint.Pos) : sector->floorplane.ZatPoint(Viewpoint.Pos)); angle_t pitchtemp; angle_t pitchmin = ANGLE_90; angle_t pitchmax = 0; @@ -741,16 +744,28 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) if (!pitchvisible) { - pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1)); - pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1)); + pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), + (ceilreflect || floorreflect) ? + 2 * planez - sector->floorplane.ZatPoint(seg->v1) : + sector->floorplane.ZatPoint(seg->v1)); + pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), + (ceilreflect || floorreflect) ? + 2 * planez - sector->ceilingplane.ZatPoint(seg->v1) : + sector->ceilingplane.ZatPoint(seg->v1)); pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); } if (pitchvisible && anglevisible && radarvisible) break; if (!pitchvisible) { - pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2)); + pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), + (ceilreflect || floorreflect) ? + 2 * planez - sector->floorplane.ZatPoint(seg->v2) : + sector->floorplane.ZatPoint(seg->v2)); if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp; - pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2)); + pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), + (ceilreflect || floorreflect) ? + 2 * planez - sector->ceilingplane.ZatPoint(seg->v2) : + sector->ceilingplane.ZatPoint(seg->v2)); if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp; pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); } @@ -819,7 +834,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) SetupSprite.Unclock(); } } - if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS)) + if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS) && mCurrentPortal == nullptr) { // [DVR] Not parallelizable due to variables RTnum and RenderedTargets[] for (auto p = sector->touching_renderthings; p != nullptr; p = p->m_snext) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 0fc7bc896..404203933 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -717,7 +717,7 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* } break; case TRACE_HitFloor: - if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection] && res.HitVector.dot(res.Sector->floorplane.Normal()) < 0.0) { if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) { @@ -743,7 +743,7 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* } break; case TRACE_HitCeiling: - if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection] && res.HitVector.dot(res.Sector->ceilingplane.Normal()) < 0.0) { if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) { @@ -779,6 +779,7 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* void HWDrawInfo::SetDitherTransFlags(AActor* actor) { + // This should really be moved to a shader and have the GPU do some shape-tracing. if (actor && actor->Sector) { FTraceResults results; diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index f14757ade..317ba9399 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -47,6 +47,7 @@ #include "hw_drawstructs.h" #include "hw_renderstate.h" #include "texturemanager.h" +#include "hw_viewpointbuffer.h" #ifdef _DEBUG CVAR(Int, gl_breaksec, -1, 0) @@ -314,6 +315,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) int rel = getExtraLight(); state.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y); + double zshift = (plane.plane.Normal().Z > 0.0 ? 0.01f : -0.01f); // The HWPlaneMirrorPortal::DrawPortalStencil() z-fights with flats SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, alpha); SetFog(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), &Colormap, false); @@ -364,7 +366,11 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) else state.AlphaFunc(Alpha_GEqual, 0.f); state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1); SetPlaneTextureRotation(state, &plane, texture); + di->VPUniforms.mViewMatrix.translate(0.0, zshift, 0.0); + screen->mViewpoints->SetViewpoint(state, &di->VPUniforms); DrawSubsectors(di, state); + di->VPUniforms.mViewMatrix.translate(0.0, -zshift, 0.0); + screen->mViewpoints->SetViewpoint(state, &di->VPUniforms); state.EnableTextureMatrix(false); } state.SetRenderStyle(DefaultRenderStyle()); diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index b103f0f81..01ab23b8a 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -158,13 +158,14 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di if (best) { portals.Delete(bestindex); - if (usestencil) + if (usestencil && ((strcmp(best->GetName(), "Sky") == 0) || (strcmp(best->GetName(), "Skybox") == 0))) { tempmatrix = outer_di->VPUniforms.mProjectionMatrix; // ensure perspective projection matrix for skies outer_di->VPUniforms.mProjectionMatrix = outer_di->ProjectionMatrix2; } RenderPortal(best, state, usestencil, outer_di); - if (usestencil) outer_di->VPUniforms.mProjectionMatrix = tempmatrix; + if (usestencil && ((strcmp(best->GetName(), "Sky") == 0) || (strcmp(best->GetName(), "Skybox") == 0))) + outer_di->VPUniforms.mProjectionMatrix = tempmatrix; delete best; return true; } @@ -332,6 +333,7 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci bool needdepth = NeedDepthBuffer(); // Restore the old view + auto &vp = di->Viewpoint; if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; @@ -870,12 +872,31 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c state->PlaneMirrorFlag++; di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + vp.ViewVector3D.Z = - vp.ViewVector3D.Z; + vp.OffPos.Z = 2 * planez - vp.OffPos.Z; ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; } + +void HWPlaneMirrorPortal::DrawPortalStencil(FRenderState &state, int pass) +{ + bool isceiling = planesused & (1 << sector_t::ceiling); + for (unsigned int i = 0; i < lines.Size(); i++) + { + flat.section = lines[i].sub->section; + flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection + + state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); + state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + } +} + + void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { auto state = mState; diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 760b8c435..ab9fec945 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -59,13 +59,14 @@ class HWPortal TArray mPrimIndices; unsigned int mTopCap = ~0u, mBottomCap = ~0u; - void DrawPortalStencil(FRenderState &state, int pass); + virtual void DrawPortalStencil(FRenderState &state, int pass); public: FPortalSceneState * mState; TArray lines; BoundingRect boundingBox; int planesused = 0; + HWFlat flat; HWPortal(FPortalSceneState *s, bool local = false) : mState(s), boundingBox(false) { @@ -295,6 +296,7 @@ struct HWPlaneMirrorPortal : public HWScenePortalBase protected: bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; + void DrawPortalStencil(FRenderState &state, int pass) override; virtual void * GetSource() const { return origin; } virtual const char *GetName(); secplane_t * origin; diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 93fc827cc..4610f00da 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -154,7 +154,7 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { - if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; + if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Almost works (with planemirrorportal stencil), but no quite auto glport = sector->GetPortalGroup(plane); if (glport != NULL) { diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 47e651bd4..d5271d05f 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -644,7 +644,8 @@ void HWWall::PutPortal(HWWallDispatcher *di, int ptype, int plane) break; case PORTALTYPE_PLANEMIRROR: - if (portalState.PlaneMirrorMode * planemirror->fC() <= 0) + if (ddi->Viewpoint.IsOrtho() ? (ddi->Viewpoint.ViewVector3D.dot(planemirror->Normal()) < 0) + : (portalState.PlaneMirrorMode * planemirror->fC() <= 0)) { planemirror = portalState.UniquePlaneMirrors.Get(planemirror); portal = ddi->FindPortal(planemirror); From 60157796c04a92a61b87d031cf7b4797ba61d82b Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Mon, 17 Feb 2025 19:23:26 -0700 Subject: [PATCH 06/57] Stacked sector portals now render for OoB viewpoints. --- src/rendering/hwrenderer/scene/hw_portal.cpp | 27 +++++++++++++++++++- src/rendering/hwrenderer/scene/hw_portal.h | 1 + src/rendering/hwrenderer/scene/hw_sky.cpp | 7 +++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 01ab23b8a..7746aa338 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -805,10 +805,18 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c vp.Pos += origin->mDisplacement; vp.ActorPos += origin->mDisplacement; vp.ViewActor = nullptr; + vp.OffPos += origin->mDisplacement; // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - + if (lines.Size() > 0) + { + flat.plane.GetFromSector(lines[0].sub->sector, + lines[0].sub->sector->GetPortal(sector_t::ceiling)->mType & (PORTS_STACKEDSECTORTHING | PORTS_PORTAL | PORTS_LINKEDPORTAL) ? + sector_t::ceiling : sector_t::floor); + di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos), + flat.plane.plane.Normal().Z > 0 ? -1.f : 1.f); + } di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); SetupCoverage(di); ClearClipper(di, clipper); @@ -816,6 +824,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. subsector_t *sub = di->Level->PointInRenderSubsector(vp.Pos); + if (vp.IsAllowedOoB()) sub = di->Level->PointInRenderSubsector(vp.OffPos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { clipper->SafeAddClipRange(0, ANGLE_MAX); @@ -825,6 +834,22 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c } +void HWSectorStackPortal::DrawPortalStencil(FRenderState &state, int pass) +{ + bool isceiling = planesused & (1 << sector_t::ceiling); + for (unsigned int i = 0; i < lines.Size(); i++) + { + flat.section = lines[i].sub->section; + flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection + + state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); + state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + } +} + + void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { if (origin->plane != -1) screen->instack[origin->plane]--; diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index ab9fec945..50034df6a 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -270,6 +270,7 @@ struct HWSectorStackPortal : public HWScenePortalBase TArray subsectors; protected: bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void DrawPortalStencil(FRenderState &state, int pass) override; void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return origin; } virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one. diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 4610f00da..b39df6695 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -154,12 +154,15 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { - if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Almost works (with planemirrorportal stencil), but no quite + if (di->di && di->di->Viewpoint.IsAllowedOoB()) + { + secplane_t myplane = plane ? sector->ceilingplane : sector->floorplane; + if (di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; + } auto glport = sector->GetPortalGroup(plane); if (glport != NULL) { if (sector->PortalBlocksView(plane)) return; - if (di->di && screen->instack[1 - plane]) return; ptype = PORTALTYPE_SECTORSTACK; portal = glport; From 5ba6bd204f3db80b35dd344905874a8fd84504b2 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Mon, 17 Feb 2025 20:18:33 -0700 Subject: [PATCH 07/57] Small correction to OoB viewpoint stacked-sector portal visibility. OoB is not the same as Ortho. --- src/rendering/hwrenderer/scene/hw_sky.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index b39df6695..2aef16c8f 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -157,7 +157,9 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al if (di->di && di->di->Viewpoint.IsAllowedOoB()) { secplane_t myplane = plane ? sector->ceilingplane : sector->floorplane; - if (di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; + if (di->di->Viewpoint.IsOrtho() && di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return; + else if (plane==1 && di->di->Viewpoint.Pos.Z >= myplane.ZatPoint(di->di->Viewpoint.Pos)) return; + else if (plane==0 && di->di->Viewpoint.Pos.Z <= myplane.ZatPoint(di->di->Viewpoint.Pos)) return; } auto glport = sector->GetPortalGroup(plane); if (glport != NULL) From c7d25f14523646fd58a265edbd46efaf32ca5d59 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sat, 29 Mar 2025 09:36:36 -0600 Subject: [PATCH 08/57] Addressing some small regression by conditioning a few calculations on OoB viewpoints. Branching Frustum calculation to old method. --- src/rendering/hwrenderer/scene/hw_bsp.cpp | 26 ++++++++----- .../hwrenderer/scene/hw_drawinfo.cpp | 39 ++++++++++++++----- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 3f834fcf6..a927872f6 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -285,19 +285,25 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) angle_t startAngle = clipper.GetClipAngle(seg->v2); angle_t endAngle = clipper.GetClipAngle(seg->v1); auto &clipperr = *rClipper; - angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); - angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + angle_t startAngleR = 0; + angle_t endAngleR = 0; angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less) - if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180)) + if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) { - if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); - else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) + startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); + endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); + + if (startAngleR - endAngleR >= ANGLE_180) { - if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); - backsector = hw_FakeFlat(seg->backsector, in_area, true); - if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); - backsector = nullptr; + if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); + else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) + { + if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); + backsector = hw_FakeFlat(seg->backsector, in_area, true); + if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR); + backsector = nullptr; + } } } @@ -708,7 +714,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return; // cull everything if subsector outside all relevant clippers - if ((sub->polys == nullptr)) + if (Viewpoint.IsAllowedOoB() && (sub->polys == nullptr)) { auto &clipper = *mClipper; auto &clipperv = *vClipper; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 404203933..0e647e307 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -268,8 +268,8 @@ void HWDrawInfo::ClearBuffers() void HWDrawInfo::UpdateCurrentMapSection() { int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB()) - mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection; + if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); } @@ -363,20 +363,19 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player) // //----------------------------------------------------------------------------- -angle_t HWDrawInfo::FrustumAngle() +angle_t OoBFrustumAngle(FRenderViewpoint* Viewpoint) { // If pitch is larger than this you can look all around at an FOV of 90 degrees - if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff; - else if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 46.0 && !Viewpoint.IsAllowedOoB()) return 0xffffffff; // Just like 4.12.2 and older did + if (fabs(Viewpoint->HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff; int aspMult = AspectMultiplier(r_viewwindow.WidescreenRatio); // 48 == square window - double absPitch = fabs(Viewpoint.HWAngles.Pitch.Degrees()); + double absPitch = fabs(Viewpoint->HWAngles.Pitch.Degrees()); // Smaller aspect ratios still clip too much. Need a better solution if (aspMult > 36 && absPitch > 30.0) return 0xffffffff; else if (aspMult > 40 && absPitch > 25.0) return 0xffffffff; else if (aspMult > 45 && absPitch > 20.0) return 0xffffffff; else if (aspMult > 47 && absPitch > 10.0) return 0xffffffff; - double xratio = r_viewwindow.FocalTangent / Viewpoint.PitchCos; + double xratio = r_viewwindow.FocalTangent / Viewpoint->PitchCos; double floatangle = 0.05 + atan ( xratio ) * 48.0 / aspMult; // this is radians angle_t a1 = DAngle::fromRad(floatangle).BAMs(); @@ -384,6 +383,28 @@ angle_t HWDrawInfo::FrustumAngle() return a1; } +angle_t HWDrawInfo::FrustumAngle() +{ + if (Viewpoint.IsAllowedOoB()) + { + return OoBFrustumAngle(&Viewpoint); + } + else + { + float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees()); + + // If the pitch is larger than this you can look all around at a FOV of 90° + if (tilt > 46.0f) return 0xffffffff; + + // ok, this is a gross hack that barely works... + // but at least it doesn't overestimate too much... + double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees() * 48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; + angle_t a1 = DAngle::fromDeg(floatangle).BAMs(); + if (a1 >= ANGLE_180) return 0xffffffff; + return a1; + } +} + //----------------------------------------------------------------------------- // // Setup the modelview matrix @@ -1043,8 +1064,8 @@ void HWDrawInfo::ProcessScene(bool toscreen) portalState.BeginScene(); int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection; - if (Viewpoint.IsAllowedOoB()) - mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection; + if (Viewpoint.IsAllowedOoB() || Viewpoint.IsOrtho()) + mapsection = Level->PointInRenderSubsector(Viewpoint.OffPos)->mapsection; CurrentMapSections.Set(mapsection); DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN); From 96a3e8d4054240b4cd3c34aeacd3028cb6ed6dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 2 Mar 2025 14:45:00 -0300 Subject: [PATCH 09/57] rework how vector local type restrictions are managed --- src/common/scripting/backend/codegen.cpp | 13 ++++++------- src/common/scripting/core/types.cpp | 4 ++++ src/common/scripting/core/types.h | 5 +++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 1fcaeae2c..d06841c83 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -12748,16 +12748,15 @@ ExpEmit FxFunctionPtrCast::Emit(VMFunctionBuilder *build) FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) :FxExpression(EFX_LocalVariableDeclaration, p) { - // Local FVector isn't different from Vector - if (type == TypeFVector2) type = TypeVector2; - else if (type == TypeFVector3) type = TypeVector3; - else if (type == TypeFVector4) type = TypeVector4; - else if (type == TypeFQuaternion) type = TypeQuaternion; + if(type != type->GetLocalType()) + { + ScriptPosition.Message(MSG_WARNING, "Type '%s' not allowed in local variables, changing to '%s'", type->DescriptiveName(), type->GetLocalType()->DescriptiveName()); + } - ValueType = type; + ValueType = type->GetLocalType(); VarFlags = varflags; Name = name; - RegCount = type->RegCount; + RegCount = ValueType->RegCount; Init = initval; clearExpr = nullptr; } diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index d99f7eb13..6b15cb735 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -401,6 +401,7 @@ void PType::StaticInit() TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegCount = 2; TypeFVector2->isOrdered = true; + TypeFVector2->SetLocalType(TypeVector2); TypeFVector3 = new PStruct(NAME_FVector3, nullptr); TypeFVector3->AddField(NAME_X, TypeFloat32); @@ -415,6 +416,7 @@ void PType::StaticInit() TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegCount = 3; TypeFVector3->isOrdered = true; + TypeFVector3->SetLocalType(TypeVector3); TypeFVector4 = new PStruct(NAME_FVector4, nullptr); TypeFVector4->AddField(NAME_X, TypeFloat32); @@ -431,6 +433,7 @@ void PType::StaticInit() TypeFVector4->RegType = REGT_FLOAT; TypeFVector4->RegCount = 4; TypeFVector4->isOrdered = true; + TypeFVector4->SetLocalType(TypeVector4); TypeQuaternion = new PStruct(NAME_Quat, nullptr); @@ -464,6 +467,7 @@ void PType::StaticInit() TypeFQuaternion->RegType = REGT_FLOAT; TypeFQuaternion->RegCount = 4; TypeFQuaternion->isOrdered = true; + TypeFQuaternion->SetLocalType(TypeQuaternion); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index f09ddb32b..164d41767 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -109,6 +109,11 @@ public: EScopeFlags ScopeFlags = (EScopeFlags)0; bool SizeKnown = true; + PType * LocalType = nullptr; + + PType * SetLocalType(PType * LocalType) { this->LocalType = LocalType; return this; } + PType * GetLocalType() { return LocalType ? LocalType : this; } + PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); virtual bool isNumeric() { return false; } From 3a24dfcd2e71b720e52e3a56d31b4d90b0b46e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 2 Mar 2025 15:18:43 -0300 Subject: [PATCH 10/57] add better descriptive name for vectors/quats --- src/common/scripting/core/types.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 6b15cb735..20ce7e05d 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -359,6 +359,7 @@ void PType::StaticInit() TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegCount = 2; TypeVector2->isOrdered = true; + TypeVector2->mDescriptiveName = "Vector2"; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -373,6 +374,7 @@ void PType::StaticInit() TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegCount = 3; TypeVector3->isOrdered = true; + TypeVector3->mDescriptiveName = "Vector3"; TypeVector4 = new PStruct(NAME_Vector4, nullptr); TypeVector4->AddField(NAME_X, TypeFloat64); @@ -389,6 +391,7 @@ void PType::StaticInit() TypeVector4->RegType = REGT_FLOAT; TypeVector4->RegCount = 4; TypeVector4->isOrdered = true; + TypeVector4->mDescriptiveName = "Vector4"; TypeFVector2 = new PStruct(NAME_FVector2, nullptr); @@ -401,6 +404,7 @@ void PType::StaticInit() TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegCount = 2; TypeFVector2->isOrdered = true; + TypeFVector2->mDescriptiveName = "FVector2"; TypeFVector2->SetLocalType(TypeVector2); TypeFVector3 = new PStruct(NAME_FVector3, nullptr); @@ -416,6 +420,7 @@ void PType::StaticInit() TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegCount = 3; TypeFVector3->isOrdered = true; + TypeFVector3->mDescriptiveName = "FVector3"; TypeFVector3->SetLocalType(TypeVector3); TypeFVector4 = new PStruct(NAME_FVector4, nullptr); @@ -433,6 +438,7 @@ void PType::StaticInit() TypeFVector4->RegType = REGT_FLOAT; TypeFVector4->RegCount = 4; TypeFVector4->isOrdered = true; + TypeFVector4->mDescriptiveName = "FVector4"; TypeFVector4->SetLocalType(TypeVector4); @@ -450,6 +456,7 @@ void PType::StaticInit() TypeQuaternion->moveOp = OP_MOVEV4; TypeQuaternion->RegType = REGT_FLOAT; TypeQuaternion->RegCount = 4; + TypeQuaternion->mDescriptiveName = "Quat"; TypeQuaternion->isOrdered = true; TypeFQuaternion = new PStruct(NAME_FQuat, nullptr); @@ -467,6 +474,7 @@ void PType::StaticInit() TypeFQuaternion->RegType = REGT_FLOAT; TypeFQuaternion->RegCount = 4; TypeFQuaternion->isOrdered = true; + TypeFQuaternion->mDescriptiveName = "FQuat"; TypeFQuaternion->SetLocalType(TypeQuaternion); From a0592816cd3fc97ef7eb87e82bec1e63a5a7ccec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 2 Mar 2025 15:19:43 -0300 Subject: [PATCH 11/57] don't allow backing types of string/array/map/etc to be referenced as actual types --- src/common/scripting/core/types.h | 2 + src/common/scripting/frontend/zcc-parse.lemon | 1 + src/common/scripting/frontend/zcc_compile.cpp | 29 +++++++-- src/common/scripting/frontend/zcc_compile.h | 2 +- wadsrc/static/zscript/engine/base.zs | 6 +- wadsrc/static/zscript/engine/dynarrays.zs | 16 ++--- wadsrc/static/zscript/engine/maps.zs | 64 +++++++++---------- 7 files changed, 72 insertions(+), 48 deletions(-) diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index 164d41767..9b840c1f6 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -109,6 +109,8 @@ public: EScopeFlags ScopeFlags = (EScopeFlags)0; bool SizeKnown = true; + bool TypeInternal = false; + PType * LocalType = nullptr; PType * SetLocalType(PType * LocalType) { this->LocalType = LocalType; return this; } diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 199771949..1df141c33 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -432,6 +432,7 @@ struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; } struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; } struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; } struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; } +struct_flags(X) ::= struct_flags(A) INTERNAL. { X.Flags = A.Flags | ZCC_Internal; } struct_flags(X) ::= struct_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Version = C.String->GetChars(); } opt_struct_body(X) ::= . { X = NULL; } diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index faef50959..4603e8a1b 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -729,6 +729,8 @@ void ZCCCompiler::CreateStructTypes() syms = &OutNamespace->Symbols; } + + if (s->NodeName() == NAME__ && fileSystem.GetFileContainer(Lump) == 0) { // This is just a container for syntactic purposes. @@ -743,11 +745,17 @@ void ZCCCompiler::CreateStructTypes() { s->strct->Type = NewStruct(s->NodeName(), outer, false, AST.FileNo); } + if (s->strct->Flags & ZCC_Version) { s->strct->Type->mVersion = s->strct->Version; } + if (s->strct->Flags & ZCC_Internal) + { + s->strct->Type->TypeInternal = true; + } + auto &sf = s->Type()->ScopeFlags; if (mVersion >= MakeVersion(2, 4, 0)) { @@ -809,6 +817,12 @@ void ZCCCompiler::CreateClassTypes() PClass *parent; auto ParentName = c->cls->ParentName; + if (c->cls->Flags & ZCC_Internal) + { + Error(c->cls, "'Internal' not allowed for classes"); + } + + // The parent exists, we may create a type for this class if (ParentName != nullptr && ParentName->SiblingNext == ParentName) { parent = PClass::FindClass(ParentName->Id); @@ -845,7 +859,6 @@ void ZCCCompiler::CreateClassTypes() Error(c->cls, "Class '%s' cannot extend sealed class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars()); } - // The parent exists, we may create a type for this class if (c->cls->Flags & ZCC_Native) { // If this is a native class, its own type must also already exist and not be a runtime class. @@ -1868,7 +1881,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n { Error(field, "%s: @ not allowed for user scripts", name.GetChars()); } - retval = ResolveUserType(btype, btype->UserType, outertype? &outertype->Symbols : nullptr, true); + retval = ResolveUserType(outertype, btype, btype->UserType, outertype? &outertype->Symbols : nullptr, true); break; case ZCC_UserType: @@ -1898,7 +1911,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n default: - retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); + retval = ResolveUserType(outertype, btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); break; } break; @@ -2153,7 +2166,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n * @param nativetype Distinguishes between searching for a native type or a user type. * @returns the PType found for this user type */ -PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *symt, bool nativetype) +PType *ZCCCompiler::ResolveUserType(PType *outertype, ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *symt, bool nativetype) { // Check the symbol table for the identifier. PSymbol *sym = nullptr; @@ -2170,10 +2183,18 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSy return TypeError; } + //only allow references to internal types inside internal types + if (ptype->TypeInternal && !outertype->TypeInternal) + { + Error(type, "Type %s not accessible", FName(type->UserType->Id).GetChars()); + return TypeError; + } + if (id->SiblingNext != type->UserType) { assert(id->SiblingNext->NodeType == AST_Identifier); ptype = ResolveUserType( + outertype, type, static_cast(id->SiblingNext), &ptype->Symbols, diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index 19e9f8ff0..bf1407189 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -134,7 +134,7 @@ protected: FString FlagsToString(uint32_t flags); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize); - PType *ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *sym, bool nativetype); + PType *ResolveUserType(PType *outertype, ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *sym, bool nativetype); static FString UserTypeName(ZCC_BasicType *type); TArray OrderStructs(); void AddStruct(TArray &new_order, ZCC_StructWork *struct_def); diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index fa212ba38..14cedaed4 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -189,7 +189,7 @@ struct Vector3 } */ -struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this. +struct _ native internal // These are the global variables, the struct is only here to avoid extending the parser for this. { native readonly Array AllClasses; native internal readonly Map AllServices; @@ -903,7 +903,7 @@ enum EmptyTokenType // Although String is a builtin type, this is a convenient way to attach methods to it. // All of these methods are available on strings -struct StringStruct native +struct StringStruct native internal { native static vararg String Format(String fmt, ...); native vararg void AppendFormat(String fmt, ...); @@ -952,7 +952,7 @@ struct Translation version("2.4") } // Convenient way to attach functions to Quat -struct QuatStruct native +struct QuatStruct native internal { native static Quat SLerp(Quat from, Quat to, double t); native static Quat NLerp(Quat from, Quat to, double t); diff --git a/wadsrc/static/zscript/engine/dynarrays.zs b/wadsrc/static/zscript/engine/dynarrays.zs index f9e6a680d..28f36b313 100644 --- a/wadsrc/static/zscript/engine/dynarrays.zs +++ b/wadsrc/static/zscript/engine/dynarrays.zs @@ -1,7 +1,7 @@ // The VM uses 7 integral data types, so for dynamic array support we need one specific set of functions for each of these types. // Do not use these structs directly, they are incomplete and only needed to create prototypes for the needed functions. -struct DynArray_I8 native +struct DynArray_I8 native internal { native readonly int Size; @@ -21,7 +21,7 @@ struct DynArray_I8 native native void Clear (); } -struct DynArray_I16 native +struct DynArray_I16 native internal { native readonly int Size; @@ -41,7 +41,7 @@ struct DynArray_I16 native native void Clear (); } -struct DynArray_I32 native +struct DynArray_I32 native internal { native readonly int Size; @@ -62,7 +62,7 @@ struct DynArray_I32 native native void Clear (); } -struct DynArray_F32 native +struct DynArray_F32 native internal { native readonly int Size; @@ -82,7 +82,7 @@ struct DynArray_F32 native native void Clear (); } -struct DynArray_F64 native +struct DynArray_F64 native internal { native readonly int Size; @@ -102,7 +102,7 @@ struct DynArray_F64 native native void Clear (); } -struct DynArray_Ptr native +struct DynArray_Ptr native internal { native readonly int Size; @@ -122,7 +122,7 @@ struct DynArray_Ptr native native void Clear (); } -struct DynArray_Obj native +struct DynArray_Obj native internal { native readonly int Size; @@ -142,7 +142,7 @@ struct DynArray_Obj native native void Clear (); } -struct DynArray_String native +struct DynArray_String native internal { native readonly int Size; diff --git a/wadsrc/static/zscript/engine/maps.zs b/wadsrc/static/zscript/engine/maps.zs index b871edf05..0e71c3b05 100644 --- a/wadsrc/static/zscript/engine/maps.zs +++ b/wadsrc/static/zscript/engine/maps.zs @@ -1,5 +1,5 @@ -struct Map_I32_I8 native +struct Map_I32_I8 native internal { native void Copy(Map_I32_I8 other); native void Move(Map_I32_I8 other); @@ -18,7 +18,7 @@ struct Map_I32_I8 native native void Remove(int key); } -struct MapIterator_I32_I8 native +struct MapIterator_I32_I8 native internal { native bool Init(Map_I32_I8 other); native bool ReInit(); @@ -31,7 +31,7 @@ struct MapIterator_I32_I8 native native void SetValue(int value); } -struct Map_I32_I16 native +struct Map_I32_I16 native internal { native void Copy(Map_I32_I16 other); native void Move(Map_I32_I16 other); @@ -50,7 +50,7 @@ struct Map_I32_I16 native native void Remove(int key); } -struct MapIterator_I32_I16 native +struct MapIterator_I32_I16 native internal { native bool Init(Map_I32_I16 other); native bool ReInit(); @@ -63,7 +63,7 @@ struct MapIterator_I32_I16 native native void SetValue(int value); } -struct Map_I32_I32 native +struct Map_I32_I32 native internal { native void Copy(Map_I32_I32 other); native void Move(Map_I32_I32 other); @@ -82,7 +82,7 @@ struct Map_I32_I32 native native void Remove(int key); } -struct MapIterator_I32_I32 native +struct MapIterator_I32_I32 native internal { native bool Init(Map_I32_I32 other); native bool ReInit(); @@ -95,7 +95,7 @@ struct MapIterator_I32_I32 native native void SetValue(int value); } -struct Map_I32_F32 native +struct Map_I32_F32 native internal { native void Copy(Map_I32_F32 other); native void Move(Map_I32_F32 other); @@ -114,7 +114,7 @@ struct Map_I32_F32 native native void Remove(int key); } -struct MapIterator_I32_F32 native +struct MapIterator_I32_F32 native internal { native bool Init(Map_I32_F32 other); native bool ReInit(); @@ -127,7 +127,7 @@ struct MapIterator_I32_F32 native native void SetValue(double value); } -struct Map_I32_F64 native +struct Map_I32_F64 native internal { native void Copy(Map_I32_F64 other); native void Move(Map_I32_F64 other); @@ -146,7 +146,7 @@ struct Map_I32_F64 native native void Remove(int key); } -struct MapIterator_I32_F64 native +struct MapIterator_I32_F64 native internal { native bool Init(Map_I32_F64 other); native bool ReInit(); @@ -159,7 +159,7 @@ struct MapIterator_I32_F64 native native void SetValue(double value); } -struct Map_I32_Obj native +struct Map_I32_Obj native internal { native void Copy(Map_I32_Obj other); native void Move(Map_I32_Obj other); @@ -178,7 +178,7 @@ struct Map_I32_Obj native native void Remove(int key); } -struct MapIterator_I32_Obj native +struct MapIterator_I32_Obj native internal { native bool Init(Map_I32_Obj other); native bool ReInit(); @@ -191,7 +191,7 @@ struct MapIterator_I32_Obj native native void SetValue(Object value); } -struct Map_I32_Ptr native +struct Map_I32_Ptr native internal { native void Copy(Map_I32_Ptr other); native void Move(Map_I32_Ptr other); @@ -210,7 +210,7 @@ struct Map_I32_Ptr native native void Remove(int key); } -struct MapIterator_I32_Ptr native +struct MapIterator_I32_Ptr native internal { native bool Init(Map_I32_Ptr other); native bool Next(); @@ -220,7 +220,7 @@ struct MapIterator_I32_Ptr native native void SetValue(voidptr value); } -struct Map_I32_Str native +struct Map_I32_Str native internal { native void Copy(Map_I32_Str other); native void Move(Map_I32_Str other); @@ -239,7 +239,7 @@ struct Map_I32_Str native native void Remove(int key); } -struct MapIterator_I32_Str native +struct MapIterator_I32_Str native internal { native bool Init(Map_I32_Str other); native bool ReInit(); @@ -254,7 +254,7 @@ struct MapIterator_I32_Str native // --------------- -struct Map_Str_I8 native +struct Map_Str_I8 native internal { native void Copy(Map_Str_I8 other); native void Move(Map_Str_I8 other); @@ -273,7 +273,7 @@ struct Map_Str_I8 native native void Remove(String key); } -struct MapIterator_Str_I8 native +struct MapIterator_Str_I8 native internal { native bool Init(Map_Str_I8 other); native bool ReInit(); @@ -286,7 +286,7 @@ struct MapIterator_Str_I8 native native void SetValue(int value); } -struct Map_Str_I16 native +struct Map_Str_I16 native internal { native void Copy(Map_Str_I16 other); native void Move(Map_Str_I16 other); @@ -305,7 +305,7 @@ struct Map_Str_I16 native native void Remove(String key); } -struct MapIterator_Str_I16 native +struct MapIterator_Str_I16 native internal { native bool Init(Map_Str_I16 other); native bool ReInit(); @@ -318,7 +318,7 @@ struct MapIterator_Str_I16 native native void SetValue(int value); } -struct Map_Str_I32 native +struct Map_Str_I32 native internal { native void Copy(Map_Str_I32 other); native void Move(Map_Str_I32 other); @@ -337,7 +337,7 @@ struct Map_Str_I32 native native void Remove(String key); } -struct MapIterator_Str_I32 native +struct MapIterator_Str_I32 native internal { native bool Init(Map_Str_I32 other); native bool ReInit(); @@ -350,7 +350,7 @@ struct MapIterator_Str_I32 native native void SetValue(int value); } -struct Map_Str_F32 native +struct Map_Str_F32 native internal { native void Copy(Map_Str_F32 other); native void Move(Map_Str_F32 other); @@ -369,7 +369,7 @@ struct Map_Str_F32 native native void Remove(String key); } -struct MapIterator_Str_F32 native +struct MapIterator_Str_F32 native internal { native bool Init(Map_Str_F32 other); native bool ReInit(); @@ -382,7 +382,7 @@ struct MapIterator_Str_F32 native native void SetValue(double value); } -struct Map_Str_F64 native +struct Map_Str_F64 native internal { native void Copy(Map_Str_F64 other); native void Move(Map_Str_F64 other); @@ -401,7 +401,7 @@ struct Map_Str_F64 native native void Remove(String key); } -struct MapIterator_Str_F64 native +struct MapIterator_Str_F64 native internal { native bool Init(Map_Str_F64 other); native bool ReInit(); @@ -414,7 +414,7 @@ struct MapIterator_Str_F64 native native void SetValue(double value); } -struct Map_Str_Obj native +struct Map_Str_Obj native internal { native void Copy(Map_Str_Obj other); native void Move(Map_Str_Obj other); @@ -433,7 +433,7 @@ struct Map_Str_Obj native native void Remove(String key); } -struct MapIterator_Str_Obj native +struct MapIterator_Str_Obj native internal { native bool Init(Map_Str_Obj other); native bool ReInit(); @@ -446,7 +446,7 @@ struct MapIterator_Str_Obj native native void SetValue(Object value); } -struct Map_Str_Ptr native +struct Map_Str_Ptr native internal { native void Copy(Map_Str_Ptr other); native void Move(Map_Str_Ptr other); @@ -465,7 +465,7 @@ struct Map_Str_Ptr native native void Remove(String key); } -struct MapIterator_Str_Ptr native +struct MapIterator_Str_Ptr native internal { native bool Init(Map_Str_Ptr other); native bool ReInit(); @@ -478,7 +478,7 @@ struct MapIterator_Str_Ptr native native void SetValue(voidptr value); } -struct Map_Str_Str native +struct Map_Str_Str native internal { native void Copy(Map_Str_Str other); native void Move(Map_Str_Str other); @@ -497,7 +497,7 @@ struct Map_Str_Str native native void Remove(String key); } -struct MapIterator_Str_Str native +struct MapIterator_Str_Str native internal { native bool Init(Map_Str_Str other); native bool ReInit(); From cb1edbde013060fedf81a2e5b1d8898c7817b279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 2 Mar 2025 16:58:37 -0300 Subject: [PATCH 12/57] restrict internal structs to gzdoom.pk3 --- src/common/scripting/frontend/zcc_compile.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 4603e8a1b..e097c8f50 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -753,7 +753,14 @@ void ZCCCompiler::CreateStructTypes() if (s->strct->Flags & ZCC_Internal) { - s->strct->Type->TypeInternal = true; + if(fileSystem.GetFileContainer(Lump) == 0) + { + s->strct->Type->TypeInternal = true; + } + else + { + Error(s->strct, "Internal structs are only allowed in the root pk3"); + } } auto &sf = s->Type()->ScopeFlags; From b3333e0a517d1b3a6347f51f49bf5427b0bdc12c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 4 Mar 2025 08:36:13 -0300 Subject: [PATCH 13/57] Allow `>>` in parser for aggregate types makes stuff like Array> parse properly (bit hacky but can't do much better without restructuring the scanner/lexer) --- src/common/engine/sc_man.h | 5 ++ src/common/scripting/frontend/zcc-parse.lemon | 84 +++++++++++++++---- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/common/engine/sc_man.h b/src/common/engine/sc_man.h index 5873523a1..d90da6474 100644 --- a/src/common/engine/sc_man.h +++ b/src/common/engine/sc_man.h @@ -85,6 +85,11 @@ public: ParseVersion = ver; } + bool CheckParseVersion(VersionInfo ver) + { + return ParseVersion >= ver; + } + void SetCMode(bool cmode); void SetNoOctals(bool cmode) { NoOctals = cmode; } void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; } diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 1df141c33..10db694b9 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -958,6 +958,7 @@ type_name(X) ::= DOT dottable_id(A). /* Aggregate types */ %type aggregate_type {ZCC_Type *} +%type aggregate_type_pre {ZCC_Type *} %type type {ZCC_Type *} %type type_list {ZCC_Type *} %type type_list_or_void {ZCC_Type *} @@ -966,30 +967,92 @@ type_name(X) ::= DOT dottable_id(A). %type array_size{ZCC_Expression *} %type array_size_expr{ZCC_Expression *} -aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMap */ +aggregate_type_pre(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B). /* ZSMap */ { NEW_AST_NODE(MapType,map,T); map->KeyType = A; map->ValueType = B; X = map; + X->ArraySize = NULL; } -aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMapIterator */ +aggregate_type_pre(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B). /* ZSMapIterator */ { NEW_AST_NODE(MapIteratorType,map_it,T); map_it->KeyType = A; map_it->ValueType = B; X = map_it; + X->ArraySize = NULL; } -aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray */ +aggregate_type_pre(X) ::= ARRAY(T) LT type_or_array(A). /* TArray */ { NEW_AST_NODE(DynArrayType,arr,T); arr->ElementType = A; X = arr; + X->ArraySize = NULL; } -aggregate_type(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ } +aggregate_type_pre(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } + +aggregate_type_pre(X) ::= CLASS(T) LT dottable_id(A). /* class */ +{ + NEW_AST_NODE(ClassType,cls,T); + cls->Restriction = A; + X = cls; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= aggregate_type_pre(A) GT. { X = A; X->ArraySize = NULL; } + +aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA aggregate_type_pre(B) RSH. /* ZSMap> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(MapType,map,T); + map->KeyType = A; + map->ValueType = B; + X = map; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA aggregate_type_pre(B) RSH. /* ZSMapIterator> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(MapIteratorType,map_it,T); + map_it->KeyType = A; + map_it->ValueType = B; + X = map_it; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= ARRAY(T) LT aggregate_type_pre(A) RSH. /* TArray> */ +{ + if(!stat->sc->CheckParseVersion(MakeVersion(4, 15, 1))) + { + stat->sc->ScriptMessage(">> without space in parametrized types only supported for zscript >= 4.15.1"); + FScriptPosition::ErrorCounter++; + } + NEW_AST_NODE(DynArrayType,arr,T); + arr->ElementType = A; + X = arr; + X->ArraySize = NULL; +} + +aggregate_type(X) ::= CLASS(T). /* class */ +{ + NEW_AST_NODE(ClassType,cls,T); + cls->Restriction = NULL; + X = cls; + X->ArraySize = NULL; +} %type func_ptr_type {ZCC_FuncPtrType *} %type func_ptr_params {ZCC_FuncPtrParamDecl *} @@ -1003,7 +1066,7 @@ fn_ptr_flag(X) ::= CLEARSCOPE. { X.Int = ZCC_ClearScope; } //fn_ptr_flag(X) ::= VIRTUALSCOPE. { X.Int = ZCC_VirtualScope; } //virtual scope not allowed -func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN GT. /* Function<...(...)> */ +func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN. /* Function<...(...)> */ { NEW_AST_NODE(FuncPtrType,fn_ptr,T); fn_ptr->RetType = A; @@ -1012,7 +1075,7 @@ func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN fun X = fn_ptr; } -func_ptr_type(X) ::= FNTYPE(T) LT VOID GT. /* Function */ +func_ptr_type(X) ::= FNTYPE(T) LT VOID. /* Function */ { NEW_AST_NODE(FuncPtrType,fn_ptr,T); fn_ptr->RetType = nullptr; @@ -1054,15 +1117,6 @@ func_ptr_param(X) ::= func_param_flags(A) type(B) AND. X = parm; } -aggregate_type(X) ::= CLASS(T) class_restrictor(A). /* class */ -{ - NEW_AST_NODE(ClassType,cls,T); - cls->Restriction = A; - X = cls; -} -class_restrictor(X) ::= . { X = NULL; } -class_restrictor(X) ::= LT dottable_id(A) GT. { X = A; /*X-overwrites-A*/ } - type(X) ::= type_name(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } type(X) ::= aggregate_type(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; } From dd92a972f5d007cf02033015ccb6ac196cdd9820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 4 Mar 2025 08:59:03 -0300 Subject: [PATCH 14/57] rename vm internal structs to make room for compilation-unit-internal structs/classes --- src/common/scripting/core/types.h | 2 +- src/common/scripting/frontend/zcc-parse.lemon | 12 ++-- src/common/scripting/frontend/zcc_compile.cpp | 6 +- src/common/scripting/frontend/zcc_parser.h | 49 +++++++------- wadsrc/static/zscript/engine/base.zs | 6 +- wadsrc/static/zscript/engine/dynarrays.zs | 16 ++--- wadsrc/static/zscript/engine/maps.zs | 64 +++++++++---------- 7 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index 9b840c1f6..8ae8b92ea 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -109,7 +109,7 @@ public: EScopeFlags ScopeFlags = (EScopeFlags)0; bool SizeKnown = true; - bool TypeInternal = false; + bool VMInternalStruct = false; PType * LocalType = nullptr; diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 10db694b9..eb136bde5 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -427,12 +427,12 @@ struct_def(X) ::= EXTEND STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRAC } %type struct_flags{ClassFlagsBlock} -struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; } -struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; } -struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; } -struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; } -struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; } -struct_flags(X) ::= struct_flags(A) INTERNAL. { X.Flags = A.Flags | ZCC_Internal; } +struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; } +struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Version = A.Version; } +struct_flags(X) ::= struct_flags(A) UNSAFE LPAREN INTERNAL RPAREN. { X.Flags = A.Flags | ZCC_VMInternalStruct; X.Version = A.Version; } struct_flags(X) ::= struct_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Version = C.String->GetChars(); } opt_struct_body(X) ::= . { X = NULL; } diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index e097c8f50..52163d772 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -751,11 +751,11 @@ void ZCCCompiler::CreateStructTypes() s->strct->Type->mVersion = s->strct->Version; } - if (s->strct->Flags & ZCC_Internal) + if (s->strct->Flags & ZCC_VMInternalStruct) { if(fileSystem.GetFileContainer(Lump) == 0) { - s->strct->Type->TypeInternal = true; + s->strct->Type->VMInternalStruct = true; } else { @@ -2191,7 +2191,7 @@ PType *ZCCCompiler::ResolveUserType(PType *outertype, ZCC_BasicType *type, ZCC_I } //only allow references to internal types inside internal types - if (ptype->TypeInternal && !outertype->TypeInternal) + if (ptype->VMInternalStruct && !outertype->VMInternalStruct) { Error(type, "Type %s not accessible", FName(type->UserType->Id).GetChars()); return TypeError; diff --git a/src/common/scripting/frontend/zcc_parser.h b/src/common/scripting/frontend/zcc_parser.h index d0b6264da..bf20f5cac 100644 --- a/src/common/scripting/frontend/zcc_parser.h +++ b/src/common/scripting/frontend/zcc_parser.h @@ -41,30 +41,31 @@ struct ZCCToken // Variable / Function / Class modifiers enum { - ZCC_Native = 1 << 0, - ZCC_Static = 1 << 1, - ZCC_Private = 1 << 2, - ZCC_Protected = 1 << 3, - ZCC_Latent = 1 << 4, - ZCC_Final = 1 << 5, - ZCC_Meta = 1 << 6, - ZCC_Action = 1 << 7, - ZCC_Deprecated = 1 << 8, - ZCC_ReadOnly = 1 << 9, - ZCC_FuncConst = 1 << 10, - ZCC_Abstract = 1 << 11, - ZCC_Extension = 1 << 12, - ZCC_Virtual = 1 << 13, - ZCC_Override = 1 << 14, - ZCC_Transient = 1 << 15, - ZCC_VarArg = 1 << 16, - ZCC_UIFlag = 1 << 17, // there's also token called ZCC_UI - ZCC_Play = 1 << 18, - ZCC_ClearScope = 1 << 19, - ZCC_VirtualScope = 1 << 20, - ZCC_Version = 1 << 21, - ZCC_Internal = 1 << 22, - ZCC_Sealed = 1 << 23, + ZCC_Native = 1 << 0, + ZCC_Static = 1 << 1, + ZCC_Private = 1 << 2, + ZCC_Protected = 1 << 3, + ZCC_Latent = 1 << 4, + ZCC_Final = 1 << 5, + ZCC_Meta = 1 << 6, + ZCC_Action = 1 << 7, + ZCC_Deprecated = 1 << 8, + ZCC_ReadOnly = 1 << 9, + ZCC_FuncConst = 1 << 10, + ZCC_Abstract = 1 << 11, + ZCC_Extension = 1 << 12, + ZCC_Virtual = 1 << 13, + ZCC_Override = 1 << 14, + ZCC_Transient = 1 << 15, + ZCC_VarArg = 1 << 16, + ZCC_UIFlag = 1 << 17, // there's also token called ZCC_UI + ZCC_Play = 1 << 18, + ZCC_ClearScope = 1 << 19, + ZCC_VirtualScope = 1 << 20, + ZCC_Version = 1 << 21, + ZCC_Internal = 1 << 22, + ZCC_Sealed = 1 << 23, + ZCC_VMInternalStruct = 1 << 24, }; // Function parameter modifiers diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 14cedaed4..33c14eef6 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -189,7 +189,7 @@ struct Vector3 } */ -struct _ native internal // These are the global variables, the struct is only here to avoid extending the parser for this. +struct _ native unsafe(internal) // These are the global variables, the struct is only here to avoid extending the parser for this. { native readonly Array AllClasses; native internal readonly Map AllServices; @@ -903,7 +903,7 @@ enum EmptyTokenType // Although String is a builtin type, this is a convenient way to attach methods to it. // All of these methods are available on strings -struct StringStruct native internal +struct StringStruct native unsafe(internal) { native static vararg String Format(String fmt, ...); native vararg void AppendFormat(String fmt, ...); @@ -952,7 +952,7 @@ struct Translation version("2.4") } // Convenient way to attach functions to Quat -struct QuatStruct native internal +struct QuatStruct native unsafe(internal) { native static Quat SLerp(Quat from, Quat to, double t); native static Quat NLerp(Quat from, Quat to, double t); diff --git a/wadsrc/static/zscript/engine/dynarrays.zs b/wadsrc/static/zscript/engine/dynarrays.zs index 28f36b313..d21c70e1a 100644 --- a/wadsrc/static/zscript/engine/dynarrays.zs +++ b/wadsrc/static/zscript/engine/dynarrays.zs @@ -1,7 +1,7 @@ // The VM uses 7 integral data types, so for dynamic array support we need one specific set of functions for each of these types. // Do not use these structs directly, they are incomplete and only needed to create prototypes for the needed functions. -struct DynArray_I8 native internal +struct DynArray_I8 native unsafe(internal) { native readonly int Size; @@ -21,7 +21,7 @@ struct DynArray_I8 native internal native void Clear (); } -struct DynArray_I16 native internal +struct DynArray_I16 native unsafe(internal) { native readonly int Size; @@ -41,7 +41,7 @@ struct DynArray_I16 native internal native void Clear (); } -struct DynArray_I32 native internal +struct DynArray_I32 native unsafe(internal) { native readonly int Size; @@ -62,7 +62,7 @@ struct DynArray_I32 native internal native void Clear (); } -struct DynArray_F32 native internal +struct DynArray_F32 native unsafe(internal) { native readonly int Size; @@ -82,7 +82,7 @@ struct DynArray_F32 native internal native void Clear (); } -struct DynArray_F64 native internal +struct DynArray_F64 native unsafe(internal) { native readonly int Size; @@ -102,7 +102,7 @@ struct DynArray_F64 native internal native void Clear (); } -struct DynArray_Ptr native internal +struct DynArray_Ptr native unsafe(internal) { native readonly int Size; @@ -122,7 +122,7 @@ struct DynArray_Ptr native internal native void Clear (); } -struct DynArray_Obj native internal +struct DynArray_Obj native unsafe(internal) { native readonly int Size; @@ -142,7 +142,7 @@ struct DynArray_Obj native internal native void Clear (); } -struct DynArray_String native internal +struct DynArray_String native unsafe(internal) { native readonly int Size; diff --git a/wadsrc/static/zscript/engine/maps.zs b/wadsrc/static/zscript/engine/maps.zs index 0e71c3b05..dbc2f4dad 100644 --- a/wadsrc/static/zscript/engine/maps.zs +++ b/wadsrc/static/zscript/engine/maps.zs @@ -1,5 +1,5 @@ -struct Map_I32_I8 native internal +struct Map_I32_I8 native unsafe(internal) { native void Copy(Map_I32_I8 other); native void Move(Map_I32_I8 other); @@ -18,7 +18,7 @@ struct Map_I32_I8 native internal native void Remove(int key); } -struct MapIterator_I32_I8 native internal +struct MapIterator_I32_I8 native unsafe(internal) { native bool Init(Map_I32_I8 other); native bool ReInit(); @@ -31,7 +31,7 @@ struct MapIterator_I32_I8 native internal native void SetValue(int value); } -struct Map_I32_I16 native internal +struct Map_I32_I16 native unsafe(internal) { native void Copy(Map_I32_I16 other); native void Move(Map_I32_I16 other); @@ -50,7 +50,7 @@ struct Map_I32_I16 native internal native void Remove(int key); } -struct MapIterator_I32_I16 native internal +struct MapIterator_I32_I16 native unsafe(internal) { native bool Init(Map_I32_I16 other); native bool ReInit(); @@ -63,7 +63,7 @@ struct MapIterator_I32_I16 native internal native void SetValue(int value); } -struct Map_I32_I32 native internal +struct Map_I32_I32 native unsafe(internal) { native void Copy(Map_I32_I32 other); native void Move(Map_I32_I32 other); @@ -82,7 +82,7 @@ struct Map_I32_I32 native internal native void Remove(int key); } -struct MapIterator_I32_I32 native internal +struct MapIterator_I32_I32 native unsafe(internal) { native bool Init(Map_I32_I32 other); native bool ReInit(); @@ -95,7 +95,7 @@ struct MapIterator_I32_I32 native internal native void SetValue(int value); } -struct Map_I32_F32 native internal +struct Map_I32_F32 native unsafe(internal) { native void Copy(Map_I32_F32 other); native void Move(Map_I32_F32 other); @@ -114,7 +114,7 @@ struct Map_I32_F32 native internal native void Remove(int key); } -struct MapIterator_I32_F32 native internal +struct MapIterator_I32_F32 native unsafe(internal) { native bool Init(Map_I32_F32 other); native bool ReInit(); @@ -127,7 +127,7 @@ struct MapIterator_I32_F32 native internal native void SetValue(double value); } -struct Map_I32_F64 native internal +struct Map_I32_F64 native unsafe(internal) { native void Copy(Map_I32_F64 other); native void Move(Map_I32_F64 other); @@ -146,7 +146,7 @@ struct Map_I32_F64 native internal native void Remove(int key); } -struct MapIterator_I32_F64 native internal +struct MapIterator_I32_F64 native unsafe(internal) { native bool Init(Map_I32_F64 other); native bool ReInit(); @@ -159,7 +159,7 @@ struct MapIterator_I32_F64 native internal native void SetValue(double value); } -struct Map_I32_Obj native internal +struct Map_I32_Obj native unsafe(internal) { native void Copy(Map_I32_Obj other); native void Move(Map_I32_Obj other); @@ -178,7 +178,7 @@ struct Map_I32_Obj native internal native void Remove(int key); } -struct MapIterator_I32_Obj native internal +struct MapIterator_I32_Obj native unsafe(internal) { native bool Init(Map_I32_Obj other); native bool ReInit(); @@ -191,7 +191,7 @@ struct MapIterator_I32_Obj native internal native void SetValue(Object value); } -struct Map_I32_Ptr native internal +struct Map_I32_Ptr native unsafe(internal) { native void Copy(Map_I32_Ptr other); native void Move(Map_I32_Ptr other); @@ -210,7 +210,7 @@ struct Map_I32_Ptr native internal native void Remove(int key); } -struct MapIterator_I32_Ptr native internal +struct MapIterator_I32_Ptr native unsafe(internal) { native bool Init(Map_I32_Ptr other); native bool Next(); @@ -220,7 +220,7 @@ struct MapIterator_I32_Ptr native internal native void SetValue(voidptr value); } -struct Map_I32_Str native internal +struct Map_I32_Str native unsafe(internal) { native void Copy(Map_I32_Str other); native void Move(Map_I32_Str other); @@ -239,7 +239,7 @@ struct Map_I32_Str native internal native void Remove(int key); } -struct MapIterator_I32_Str native internal +struct MapIterator_I32_Str native unsafe(internal) { native bool Init(Map_I32_Str other); native bool ReInit(); @@ -254,7 +254,7 @@ struct MapIterator_I32_Str native internal // --------------- -struct Map_Str_I8 native internal +struct Map_Str_I8 native unsafe(internal) { native void Copy(Map_Str_I8 other); native void Move(Map_Str_I8 other); @@ -273,7 +273,7 @@ struct Map_Str_I8 native internal native void Remove(String key); } -struct MapIterator_Str_I8 native internal +struct MapIterator_Str_I8 native unsafe(internal) { native bool Init(Map_Str_I8 other); native bool ReInit(); @@ -286,7 +286,7 @@ struct MapIterator_Str_I8 native internal native void SetValue(int value); } -struct Map_Str_I16 native internal +struct Map_Str_I16 native unsafe(internal) { native void Copy(Map_Str_I16 other); native void Move(Map_Str_I16 other); @@ -305,7 +305,7 @@ struct Map_Str_I16 native internal native void Remove(String key); } -struct MapIterator_Str_I16 native internal +struct MapIterator_Str_I16 native unsafe(internal) { native bool Init(Map_Str_I16 other); native bool ReInit(); @@ -318,7 +318,7 @@ struct MapIterator_Str_I16 native internal native void SetValue(int value); } -struct Map_Str_I32 native internal +struct Map_Str_I32 native unsafe(internal) { native void Copy(Map_Str_I32 other); native void Move(Map_Str_I32 other); @@ -337,7 +337,7 @@ struct Map_Str_I32 native internal native void Remove(String key); } -struct MapIterator_Str_I32 native internal +struct MapIterator_Str_I32 native unsafe(internal) { native bool Init(Map_Str_I32 other); native bool ReInit(); @@ -350,7 +350,7 @@ struct MapIterator_Str_I32 native internal native void SetValue(int value); } -struct Map_Str_F32 native internal +struct Map_Str_F32 native unsafe(internal) { native void Copy(Map_Str_F32 other); native void Move(Map_Str_F32 other); @@ -369,7 +369,7 @@ struct Map_Str_F32 native internal native void Remove(String key); } -struct MapIterator_Str_F32 native internal +struct MapIterator_Str_F32 native unsafe(internal) { native bool Init(Map_Str_F32 other); native bool ReInit(); @@ -382,7 +382,7 @@ struct MapIterator_Str_F32 native internal native void SetValue(double value); } -struct Map_Str_F64 native internal +struct Map_Str_F64 native unsafe(internal) { native void Copy(Map_Str_F64 other); native void Move(Map_Str_F64 other); @@ -401,7 +401,7 @@ struct Map_Str_F64 native internal native void Remove(String key); } -struct MapIterator_Str_F64 native internal +struct MapIterator_Str_F64 native unsafe(internal) { native bool Init(Map_Str_F64 other); native bool ReInit(); @@ -414,7 +414,7 @@ struct MapIterator_Str_F64 native internal native void SetValue(double value); } -struct Map_Str_Obj native internal +struct Map_Str_Obj native unsafe(internal) { native void Copy(Map_Str_Obj other); native void Move(Map_Str_Obj other); @@ -433,7 +433,7 @@ struct Map_Str_Obj native internal native void Remove(String key); } -struct MapIterator_Str_Obj native internal +struct MapIterator_Str_Obj native unsafe(internal) { native bool Init(Map_Str_Obj other); native bool ReInit(); @@ -446,7 +446,7 @@ struct MapIterator_Str_Obj native internal native void SetValue(Object value); } -struct Map_Str_Ptr native internal +struct Map_Str_Ptr native unsafe(internal) { native void Copy(Map_Str_Ptr other); native void Move(Map_Str_Ptr other); @@ -465,7 +465,7 @@ struct Map_Str_Ptr native internal native void Remove(String key); } -struct MapIterator_Str_Ptr native internal +struct MapIterator_Str_Ptr native unsafe(internal) { native bool Init(Map_Str_Ptr other); native bool ReInit(); @@ -478,7 +478,7 @@ struct MapIterator_Str_Ptr native internal native void SetValue(voidptr value); } -struct Map_Str_Str native internal +struct Map_Str_Str native unsafe(internal) { native void Copy(Map_Str_Str other); native void Move(Map_Str_Str other); @@ -497,7 +497,7 @@ struct Map_Str_Str native internal native void Remove(String key); } -struct MapIterator_Str_Str native internal +struct MapIterator_Str_Str native unsafe(internal) { native bool Init(Map_Str_Str other); native bool ReInit(); From 974aacfb7b62df176d1758ed7baeb8ab34c601ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 4 Mar 2025 10:25:02 -0300 Subject: [PATCH 15/57] fix crash if chat key is pressed during the loading screen --- src/ct_chat.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index a12bb9f20..b6d96aa4e 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -251,14 +251,18 @@ void CT_Drawer (void) { // [MK] allow the status bar to take over chat prompt drawing bool skip = false; - IFVIRTUALPTR(StatusBar, DBaseStatusBar, DrawChat) + + if(StatusBar) { - FString txt = ChatQueue; - VMValue params[] = { (DObject*)StatusBar, &txt }; - int rv; - VMReturn ret(&rv); - VMCall(func, params, countof(params), &ret, 1); - if (!!rv) return; + IFVIRTUALPTR(StatusBar, DBaseStatusBar, DrawChat) + { + FString txt = ChatQueue; + VMValue params[] = { (DObject*)StatusBar, &txt }; + int rv; + VMReturn ret(&rv); + VMCall(func, params, countof(params), &ret, 1); + if (!!rv) return; + } } FStringf prompt("%s ", GStrings.GetString("TXT_SAY")); @@ -269,8 +273,8 @@ void CT_Drawer (void) scalex = 1; int scale = active_con_scale(drawer); int screen_width = twod->GetWidth() / scale; - int screen_height= twod->GetHeight() / scale; - int st_y = StatusBar->GetTopOfStatusbar() / scale; + int screen_height = twod->GetHeight() / scale; + int st_y = StatusBar ? (StatusBar->GetTopOfStatusbar() / scale) : screen_height; y += ((twod->GetHeight() == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y; From c3f95426ba551d4f4a4ab35b0ed3f7063037483b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 4 Mar 2025 10:37:33 -0300 Subject: [PATCH 16/57] stop game from getting stuck in chat mode if the main menu is open --- src/g_game.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/g_game.cpp b/src/g_game.cpp index 84a410fe2..786bf0629 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1000,6 +1000,8 @@ bool G_Responder (event_t *ev) if (gameaction == ga_nothing && (demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL)) { + if (chatmodeon) chatmodeon = 0; + const char *cmd = Bindings.GetBind (ev->data1); if (ev->type == EV_KeyDown) From 8326d21cd09219e1e883c5c7dc54b853a998c402 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Thu, 6 Mar 2025 10:55:11 -0700 Subject: [PATCH 17/57] Revert using older stencil method for stacked sectors (and reflective flats) if viewpoint is not allowed OoB. There was some bug with nearby skyplanes otherwise. --- src/rendering/hwrenderer/scene/hw_portal.cpp | 51 ++++++++++++++------ src/rendering/hwrenderer/scene/hw_portal.h | 4 +- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 7746aa338..6877f7982 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -507,6 +507,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe } auto &vp = di->Viewpoint; + state->vpIsAllowedOoB = vp.IsAllowedOoB(); di->UpdateCurrentMapSection(); di->mClipPortal = this; @@ -611,6 +612,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl return false; } auto &vp = di->Viewpoint; + state->vpIsAllowedOoB = vp.IsAllowedOoB(); di->mClipPortal = this; line_t *origin = glport->lines[0]->mOrigin; @@ -690,6 +692,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe return false; } auto &vp = di->Viewpoint; + state->vpIsAllowedOoB = vp.IsAllowedOoB(); state->skyboxrecursion++; state->PlaneMirrorMode = 0; @@ -801,6 +804,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c FSectorPortalGroup *portal = origin; auto &vp = di->Viewpoint; + state->vpIsAllowedOoB = vp.IsAllowedOoB(); vp.Pos += origin->mDisplacement; vp.ActorPos += origin->mDisplacement; @@ -836,16 +840,23 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c void HWSectorStackPortal::DrawPortalStencil(FRenderState &state, int pass) { - bool isceiling = planesused & (1 << sector_t::ceiling); - for (unsigned int i = 0; i < lines.Size(); i++) + if (mState->vpIsAllowedOoB) { - flat.section = lines[i].sub->section; - flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; - flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); - // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection + bool isceiling = planesused & (1 << sector_t::ceiling); + for (unsigned int i = 0; i < lines.Size(); i++) + { + flat.section = lines[i].sub->section; + flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection - state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); - state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); + state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + } + } + else + { + HWPortal::DrawPortalStencil(state, pass); } } @@ -884,6 +895,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); auto &vp = di->Viewpoint; + state->vpIsAllowedOoB = vp.IsAllowedOoB(); old_pm = state->PlaneMirrorMode; // the player is always visible in a mirror. @@ -908,16 +920,23 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c void HWPlaneMirrorPortal::DrawPortalStencil(FRenderState &state, int pass) { - bool isceiling = planesused & (1 << sector_t::ceiling); - for (unsigned int i = 0; i < lines.Size(); i++) + if (mState->vpIsAllowedOoB) { - flat.section = lines[i].sub->section; - flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; - flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); - // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection + bool isceiling = planesused & (1 << sector_t::ceiling); + for (unsigned int i = 0; i < lines.Size(); i++) + { + flat.section = lines[i].sub->section; + flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection - state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); - state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); + state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0); + } + } + else + { + HWPortal::DrawPortalStencil(state, pass); } } diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 50034df6a..207cefc2f 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -59,8 +59,6 @@ class HWPortal TArray mPrimIndices; unsigned int mTopCap = ~0u, mBottomCap = ~0u; - virtual void DrawPortalStencil(FRenderState &state, int pass); - public: FPortalSceneState * mState; TArray lines; @@ -84,6 +82,7 @@ public: virtual bool NeedDepthBuffer() { return true; } virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0; virtual void RenderAttached(HWDrawInfo *di) {} + virtual void DrawPortalStencil(FRenderState &state, int pass); void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); @@ -106,6 +105,7 @@ struct FPortalSceneState int PlaneMirrorMode = 0; bool inskybox = 0; + bool vpIsAllowedOoB = 0; UniqueList UniqueSkies; UniqueList UniqueHorizons; From 190896ae1c00815d1cbcb8de42a95aa67829ca0c Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Fri, 7 Mar 2025 21:57:10 -0700 Subject: [PATCH 18/57] Forgot to account for when both floor and ceiling of a sector are portals. --- src/rendering/hwrenderer/scene/hw_portal.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 6877f7982..965582a2e 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -815,9 +815,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c if (origin->plane != -1) screen->instack[origin->plane]++; if (lines.Size() > 0) { - flat.plane.GetFromSector(lines[0].sub->sector, - lines[0].sub->sector->GetPortal(sector_t::ceiling)->mType & (PORTS_STACKEDSECTORTHING | PORTS_PORTAL | PORTS_LINKEDPORTAL) ? - sector_t::ceiling : sector_t::floor); + flat.plane.GetFromSector(lines[0].sub->sector, origin->plane); di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos), flat.plane.plane.Normal().Z > 0 ? -1.f : 1.f); } From bda5b7048d4470ab11d828d043edd83d0e22f259 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Fri, 7 Mar 2025 23:47:12 -0700 Subject: [PATCH 19/57] Handle sectors within sectors for stacked portals and plane mirrors (affects OoB only). --- src/rendering/hwrenderer/scene/hw_portal.cpp | 10 ++++++---- src/rendering/hwrenderer/scene/hw_sky.cpp | 10 ++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index 965582a2e..cc7289480 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -815,6 +815,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c if (origin->plane != -1) screen->instack[origin->plane]++; if (lines.Size() > 0) { + flat.plane.GetFromSector(lines[0].sub->sector, origin->plane); di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos), flat.plane.plane.Normal().Z > 0 ? -1.f : 1.f); @@ -841,11 +842,12 @@ void HWSectorStackPortal::DrawPortalStencil(FRenderState &state, int pass) if (mState->vpIsAllowedOoB) { bool isceiling = planesused & (1 << sector_t::ceiling); - for (unsigned int i = 0; i < lines.Size(); i++) + for (unsigned i = 0; isection; - flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; - flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); + subsector_t *sub = subsectors[i]; + flat.section = sub->section; + flat.iboindex = sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor]; + flat.plane.GetFromSector(sub->sector, isceiling ? sector_t::ceiling : sector_t::floor); // if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y); diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 2aef16c8f..ce89b545a 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -319,7 +319,10 @@ void HWWall::SkyTop(HWWallDispatcher *di, seg_t * seg,sector_t * fs,sector_t * b if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. - return; + if (!(di->di && di->di->Viewpoint.IsAllowedOoB())) + { + return; + } } } else @@ -398,7 +401,10 @@ void HWWall::SkyBottom(HWWallDispatcher *di, seg_t * seg,sector_t * fs,sector_t if (backreflect > 0 && bs->floorplane.fD() == fs->floorplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. - return; + if (!(di->di && di->di->Viewpoint.IsAllowedOoB())) + { + return; + } } } else From df724a8f0834f2293c535390d68ca98ac53f6077 Mon Sep 17 00:00:00 2001 From: dileepvr Date: Sat, 8 Mar 2025 07:10:59 -0700 Subject: [PATCH 20/57] Update hw_portal OoB height clip Hopefully the last bug squash. --- src/rendering/hwrenderer/scene/hw_portal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index cc7289480..4d1ce3f8b 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -813,7 +813,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - if (lines.Size() > 0) + if (vp.IsAllowedOoB() && lines.Size() > 0) { flat.plane.GetFromSector(lines[0].sub->sector, origin->plane); From 40aef53e266fb90655a9daf95f33cb98f6bded64 Mon Sep 17 00:00:00 2001 From: dileepvr Date: Sat, 8 Mar 2025 07:33:58 -0700 Subject: [PATCH 21/57] Remove bitwise opeartion on bool Visual Studio compiler was giving the warning: `warning C4805: '|=': unsafe mix of type 'bool' and type 'int' in operation` --- src/rendering/hwrenderer/scene/hw_walls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index d5271d05f..527c02c0d 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -85,7 +85,7 @@ void HWWall::RenderWall(FRenderState &state, int textured) { bool ditherT = (type == RENDERWALL_BOTTOM) && (seg->sidedef->Flags & WALLF_DITHERTRANS_BOTTOM); ditherT |= (type == RENDERWALL_TOP) && (seg->sidedef->Flags & WALLF_DITHERTRANS_TOP); - ditherT |= seg->sidedef->Flags & WALLF_DITHERTRANS_MID; + ditherT = ditherT || (seg->sidedef->Flags & WALLF_DITHERTRANS_MID); if (ditherT) { state.SetEffect(EFF_DITHERTRANS); From d924573d8a6f1eac10cf96b1bc522b3ab4bb7785 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sat, 22 Feb 2025 14:32:19 +0200 Subject: [PATCH 22/57] Exposed DDoor to ZScript. Also added a ZScript-only enum for the movement direction.. --- src/playsim/mapthinkers/a_doors.cpp | 12 ++++++++++ src/playsim/mapthinkers/a_doors.h | 14 +++++------ wadsrc/static/zscript/doombase.zs | 36 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/playsim/mapthinkers/a_doors.cpp b/src/playsim/mapthinkers/a_doors.cpp index 2d8d2c70c..e32068565 100644 --- a/src/playsim/mapthinkers/a_doors.cpp +++ b/src/playsim/mapthinkers/a_doors.cpp @@ -40,6 +40,7 @@ #include "g_levellocals.h" #include "animations.h" #include "texturemanager.h" +#include "vm.h" //============================================================================ // @@ -64,6 +65,17 @@ void DDoor::Serialize(FSerializer &arc) ("lighttag", m_LightTag); } +DEFINE_FIELD(DDoor, m_Type) +DEFINE_FIELD(DDoor, m_TopDist) +DEFINE_FIELD(DDoor, m_BotSpot) +DEFINE_FIELD(DDoor, m_BotDist) +DEFINE_FIELD(DDoor, m_OldFloorDist) +DEFINE_FIELD(DDoor, m_Speed) +DEFINE_FIELD(DDoor, m_Direction) +DEFINE_FIELD(DDoor, m_TopWait) +DEFINE_FIELD(DDoor, m_TopCountdown) +DEFINE_FIELD(DDoor, m_LightTag) + //============================================================================ // // T_VerticalDoor diff --git a/src/playsim/mapthinkers/a_doors.h b/src/playsim/mapthinkers/a_doors.h index 88c0c5667..e815b55ae 100644 --- a/src/playsim/mapthinkers/a_doors.h +++ b/src/playsim/mapthinkers/a_doors.h @@ -17,16 +17,10 @@ public: doorWaitClose, }; - void Construct(sector_t *sector); - void Construct(sector_t *sec, EVlDoor type, double speed, int delay, int lightTag, int topcountdown); - - void Serialize(FSerializer &arc); - void Tick (); -protected: EVlDoor m_Type; double m_TopDist; double m_BotDist, m_OldFloorDist; - vertex_t *m_BotSpot; + vertex_t* m_BotSpot; double m_Speed; // 1 = up, 0 = waiting at top, -1 = down @@ -40,6 +34,12 @@ protected: int m_LightTag; + void Construct(sector_t *sector); + void Construct(sector_t *sec, EVlDoor type, double speed, int delay, int lightTag, int topcountdown); + + void Serialize(FSerializer &arc); + void Tick (); +protected: void DoorSound (bool raise, class DSeqNode *curseq=NULL) const; private: diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index bb76cfb65..181bdae04 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -649,6 +649,42 @@ class MovingFloor : Mover native class MovingCeiling : Mover native {} +class Door : MovingCeiling native +{ + enum EVlDoor + { + doorClose, + doorOpen, + doorRaise, + doorWaitRaise, + doorCloseWaitOpen, + doorWaitClose, + }; + + native readonly EVlDoor m_Type; + native readonly double m_TopDist; + native readonly double m_BotDist, m_OldFloorDist; + native readonly Vertex m_BotSpot; + native readonly double m_Speed; + + // 1 = up, 0 = waiting at top, -1 = down + enum EDirection + { + dirUp, + dirWait, + dirDown + } + native readonly int m_Direction; + + // tics to wait at the top + native readonly int m_TopWait; + // (keep in case a door going down is reset) + // when it reaches 0, start going down + native readonly int m_TopCountdown; + + native readonly int m_LightTag; +} + class Floor : MovingFloor native { // only here so that some constants and functions can be added. Not directly usable yet. From 0dc4c7db90ed130bf78bf95c9e27b80b4c805e4f Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sat, 22 Feb 2025 14:41:27 +0200 Subject: [PATCH 23/57] Exposed DPlat to ZScript. --- src/playsim/mapthinkers/a_plats.cpp | 12 +++++++++ src/playsim/mapthinkers/a_plats.h | 3 +-- wadsrc/static/zscript/doombase.zs | 41 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/playsim/mapthinkers/a_plats.cpp b/src/playsim/mapthinkers/a_plats.cpp index c688295e4..fb41a6559 100644 --- a/src/playsim/mapthinkers/a_plats.cpp +++ b/src/playsim/mapthinkers/a_plats.cpp @@ -36,6 +36,7 @@ #include "serializer.h" #include "p_spec.h" #include "g_levellocals.h" +#include "vm.h" static FRandom pr_doplat ("DoPlat"); @@ -62,6 +63,17 @@ void DPlat::Serialize(FSerializer &arc) ("tag", m_Tag); } +DEFINE_FIELD(DPlat, m_Type) +DEFINE_FIELD(DPlat, m_Speed) +DEFINE_FIELD(DPlat, m_Low) +DEFINE_FIELD(DPlat, m_High) +DEFINE_FIELD(DPlat, m_Wait) +DEFINE_FIELD(DPlat, m_Count) +DEFINE_FIELD(DPlat, m_Status) +DEFINE_FIELD(DPlat, m_OldStatus) +DEFINE_FIELD(DPlat, m_Crush) +DEFINE_FIELD(DPlat, m_Tag) + //----------------------------------------------------------------------------- // // diff --git a/src/playsim/mapthinkers/a_plats.h b/src/playsim/mapthinkers/a_plats.h index fd8d4e975..2427021ef 100644 --- a/src/playsim/mapthinkers/a_plats.h +++ b/src/playsim/mapthinkers/a_plats.h @@ -38,8 +38,6 @@ public: bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } void Construct(sector_t *sector); -protected: - double m_Speed; double m_Low; double m_High; @@ -50,6 +48,7 @@ protected: int m_Crush; int m_Tag; EPlatType m_Type; +protected: void PlayPlatSound (const char *sound); const char *GetSoundByType () const; diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 181bdae04..c1de2203b 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -646,6 +646,47 @@ class Mover : SectorEffect native class MovingFloor : Mover native {} +class Plat : MovingFloor native +{ + enum EPlatState + { + up, + down, + waiting, + in_stasis + }; + + enum EPlatType + { + platPerpetualRaise, + platDownWaitUpStay, + platDownWaitUpStayStone, + platUpWaitDownStay, + platUpNearestWaitDownStay, + platDownByValue, + platUpByValue, + platUpByValueStay, + platRaiseAndStay, + platToggle, + platDownToNearestFloor, + platDownToLowestCeiling, + platRaiseAndStayLockout, + }; + + bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } + + native double m_Speed; + native double m_Low; + native double m_High; + native int m_Wait; + native int m_Count; + native EPlatState m_Status; + native readonly EPlatState m_OldStatus; + native int m_Crush; + native int m_Tag; + native EPlatType m_Type; +} + class MovingCeiling : Mover native {} From 5503ec052d8095ee75263d6204cb3ce416673c2c Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sat, 22 Feb 2025 15:07:45 +0200 Subject: [PATCH 24/57] Exposed more of the Ceiling thinker. - Exposed the rest of the ceiling member fields and getters. - Added an IsCrusher() method. - Added getOldDirection() getter. - Fixed Door direction enum. - Forgot to make Plat readonly on previous commit. --- src/playsim/mapthinkers/a_ceiling.cpp | 25 +++++++++++++++ src/playsim/mapthinkers/a_ceiling.h | 17 +++++----- wadsrc/static/zscript/doombase.zs | 46 ++++++++++++++++++++------- 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/playsim/mapthinkers/a_ceiling.cpp b/src/playsim/mapthinkers/a_ceiling.cpp index 1afdf4509..c2205fca9 100644 --- a/src/playsim/mapthinkers/a_ceiling.cpp +++ b/src/playsim/mapthinkers/a_ceiling.cpp @@ -72,6 +72,31 @@ void DCeiling::Serialize(FSerializer &arc) .Enum("crushmode", m_CrushMode); } +DEFINE_FIELD(DCeiling, m_Type) +DEFINE_FIELD(DCeiling, m_BottomHeight) +DEFINE_FIELD(DCeiling, m_TopHeight) +DEFINE_FIELD(DCeiling, m_Speed) +DEFINE_FIELD(DCeiling, m_Speed1) +DEFINE_FIELD(DCeiling, m_Speed2) +DEFINE_FIELD(DCeiling, m_Silent) +DEFINE_FIELD(DCeiling, m_CrushMode) + +DEFINE_ACTION_FUNCTION(DCeiling, getCrush) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getCrush()); +} +DEFINE_ACTION_FUNCTION(DCeiling, getDirection) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getDirection()); +} +DEFINE_ACTION_FUNCTION(DCeiling, getOldDirection) +{ + PARAM_SELF_PROLOGUE(DCeiling); + ACTION_RETURN_INT(self->getOldDirection()); +} + //============================================================================ // // diff --git a/src/playsim/mapthinkers/a_ceiling.h b/src/playsim/mapthinkers/a_ceiling.h index 2954fb118..92b0c22bb 100644 --- a/src/playsim/mapthinkers/a_ceiling.h +++ b/src/playsim/mapthinkers/a_ceiling.h @@ -47,6 +47,14 @@ public: crushSlowdown = 2 }; + ECeiling m_Type; + double m_BottomHeight; + double m_TopHeight; + double m_Speed; + double m_Speed1; // [RH] dnspeed of crushers + double m_Speed2; // [RH] upspeed of crushers + ECrushMode m_CrushMode; + int m_Silent; void Construct(sector_t *sec); void Construct(sector_t *sec, double speed1, double speed2, int silent); @@ -56,17 +64,10 @@ public: int getCrush() const { return m_Crush; } int getDirection() const { return m_Direction; } + int getOldDirection() const { return m_OldDirection; } protected: - ECeiling m_Type; - double m_BottomHeight; - double m_TopHeight; - double m_Speed; - double m_Speed1; // [RH] dnspeed of crushers - double m_Speed2; // [RH] upspeed of crushers int m_Crush; - ECrushMode m_CrushMode; - int m_Silent; int m_Direction; // 1 = up, 0 = waiting, -1 = down // [RH] Need these for BOOM-ish transferring ceilings diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index c1de2203b..0f153628a 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -675,16 +675,16 @@ class Plat : MovingFloor native bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } - native double m_Speed; - native double m_Low; - native double m_High; - native int m_Wait; - native int m_Count; - native EPlatState m_Status; + native readonly double m_Speed; + native readonly double m_Low; + native readonly double m_High; + native readonly int m_Wait; + native readonly int m_Count; + native readonly EPlatState m_Status; native readonly EPlatState m_OldStatus; - native int m_Crush; - native int m_Tag; - native EPlatType m_Type; + native readonly int m_Crush; + native readonly int m_Tag; + native readonly EPlatType m_Type; } class MovingCeiling : Mover native @@ -711,9 +711,9 @@ class Door : MovingCeiling native // 1 = up, 0 = waiting at top, -1 = down enum EDirection { - dirUp, + dirDown = -1, dirWait, - dirDown + dirUp, } native readonly int m_Direction; @@ -813,7 +813,29 @@ class Ceiling : MovingCeiling native crushHexen = 1, crushSlowdown = 2 } - + + // 1 = up, 0 = waiting, -1 = down + enum EDirection + { + dirDown = -1, + dirWait, + dirUp, + } + + native readonly ECeiling m_Type; + native readonly double m_BottomHeight; + native readonly double m_TopHeight; + native readonly double m_Speed; + native readonly double m_Speed1; // [RH] dnspeed of crushers + native readonly double m_Speed2; // [RH] upspeed of crushers + native readonly ECrushMode m_CrushMode; + native readonly int m_Silent; + + bool IsCrusher() const { return m_Type == ceilCrushAndRaise || m_Type == ceilLowerAndCrush || m_Type == ceilCrushRaiseAndStay; } + native int getCrush() const; + native int getDirection() const; + native int getOldDirection() const; + deprecated("3.8", "Use Level.CreateCeiling() instead") static bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom) { return level.CreateCeiling(sec, type, ln, speed, speed2, height, crush, silent, change, crushmode); From a655f65b9b904f6b4ad404b20754f86eaa27d38d Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sun, 23 Feb 2025 05:02:10 +0200 Subject: [PATCH 25/57] Exposed more of the Floor thinker. --- src/playsim/mapthinkers/a_floor.cpp | 16 +++++++++++++++ wadsrc/static/zscript/doombase.zs | 31 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 0d330e4e9..e81c10713 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -96,6 +96,22 @@ void DFloor::Serialize(FSerializer &arc) ("instant", m_Instant); } +DEFINE_FIELD(DFloor, m_Type) +DEFINE_FIELD(DFloor, m_Crush) +DEFINE_FIELD(DFloor, m_Direction) +DEFINE_FIELD(DFloor, m_NewSpecial) +DEFINE_FIELD(DFloor, m_Texture) +DEFINE_FIELD(DFloor, m_FloorDestDist) +DEFINE_FIELD(DFloor, m_Speed) +DEFINE_FIELD(DFloor, m_ResetCount) +DEFINE_FIELD(DFloor, m_OrgDist) +DEFINE_FIELD(DFloor, m_Delay) +DEFINE_FIELD(DFloor, m_PauseTime) +DEFINE_FIELD(DFloor, m_StepTime) +DEFINE_FIELD(DFloor, m_PerStepTime) +DEFINE_FIELD(DFloor, m_Hexencrush) +DEFINE_FIELD(DFloor, m_Instant) + //========================================================================== // // MOVE A FLOOR TO ITS DESTINATION (UP OR DOWN) diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 0f153628a..46fdc4239 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -768,6 +768,37 @@ class Floor : MovingFloor native genFloorChg }; + enum EStair + { + buildUp, + buildDown + }; + + enum EStairType + { + stairUseSpecials = 1, + stairSync = 2, + stairCrush = 4, + }; + + native readonly EFloor m_Type; + native readonly int m_Crush; + native readonly bool m_Hexencrush; + native readonly bool m_Instant; + native readonly int m_Direction; + native readonly SecSpecial m_NewSpecial; + native readonly TextureID m_Texture; + native readonly double m_FloorDestDist; + native readonly double m_Speed; + + // [RH] New parameters used to reset and delay stairs + native readonly double m_OrgDist; + native readonly int m_ResetCount; + native readonly int m_Delay; + native readonly int m_PauseTime; + native readonly int m_StepTime; + native readonly int m_PerStepTime; + deprecated("3.8", "Use Level.CreateFloor() instead") static bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false) { return level.CreateFloor(sec, floortype, ln, speed, height, crush, change, crushmode, hereticlower); From 89235ea15df618427d95debdfe2ab4e461970634 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sun, 23 Feb 2025 05:19:16 +0200 Subject: [PATCH 26/57] Exposed DElevator to ZScript. --- src/playsim/mapthinkers/a_floor.cpp | 8 +++++++- src/playsim/mapthinkers/a_floor.h | 12 +++++++----- wadsrc/static/zscript/doombase.zs | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index e81c10713..d4492d9e0 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -903,6 +903,12 @@ void DElevator::Serialize(FSerializer &arc) ("interp_ceiling", m_Interp_Ceiling); } +DEFINE_FIELD(DElevator, m_Type) +DEFINE_FIELD(DElevator, m_Direction) +DEFINE_FIELD(DElevator, m_FloorDestDist) +DEFINE_FIELD(DElevator, m_CeilingDestDist) +DEFINE_FIELD(DElevator, m_Speed) + //========================================================================== // // @@ -973,7 +979,7 @@ void DElevator::Tick () } } - if (res == EMoveResult::pastdest) // if destination height acheived + if (res == EMoveResult::pastdest) // if destination height achieved { // make floor stop sound SN_StopSequence (m_Sector, CHAN_FLOOR); diff --git a/src/playsim/mapthinkers/a_floor.h b/src/playsim/mapthinkers/a_floor.h index e0331bca6..891ce948e 100644 --- a/src/playsim/mapthinkers/a_floor.h +++ b/src/playsim/mapthinkers/a_floor.h @@ -105,6 +105,13 @@ public: elevateLower }; + EElevator m_Type; + int m_Direction; + double m_FloorDestDist; + double m_CeilingDestDist; + double m_Speed; + + void Construct(sector_t *sec); void OnDestroy() override; @@ -112,11 +119,6 @@ public: void Tick (); protected: - EElevator m_Type; - int m_Direction; - double m_FloorDestDist; - double m_CeilingDestDist; - double m_Speed; TObjPtr m_Interp_Ceiling; TObjPtr m_Interp_Floor; diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 46fdc4239..c4582c15e 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -643,6 +643,25 @@ class SectorEffect : Thinker native class Mover : SectorEffect native {} +class Elevator : Mover native +{ + enum EElevator + { + elevateUp, + elevateDown, + elevateCurrent, + // [RH] For FloorAndCeiling_Raise/Lower + elevateRaise, + elevateLower + }; + + native readonly EElevator m_Type; + native readonly int m_Direction; + native readonly double m_FloorDestDist; + native readonly double m_CeilingDestDist; + native readonly double m_Speed; +} + class MovingFloor : Mover native {} From 9d45ee15b7554dfe136a89b39e174381549f6e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 7 Mar 2025 17:22:24 -0300 Subject: [PATCH 27/57] fix function-pointer cast parsing --- src/common/scripting/frontend/zcc-parse.lemon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index eb136bde5..95e99cfa3 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -1529,7 +1529,7 @@ primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B) X = expr; } -primary(X) ::= LPAREN func_ptr_type(A) RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast +primary(X) ::= LPAREN func_ptr_type(A) GT RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast { NEW_AST_NODE(FunctionPtrCast, expr, A); expr->Operation = PEX_FunctionPtrCast; From e1e93b1b46e802ecceb36d4dea5f5ce4bf593998 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Fri, 7 Mar 2025 13:47:56 +0800 Subject: [PATCH 28/57] Interpolate turning 180 degrees --- wadsrc/static/zscript/actors/player/player.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 6bfb58344..1af41c1c0 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1289,7 +1289,7 @@ class PlayerPawn : Actor if (player.turnticks) { player.turnticks--; - Angle += (180. / TURN180_TICKS); + A_SetAngle(Angle + (180. / TURN180_TICKS), SPF_INTERPOLATE); } else { From 9c1d45dd6861d1f46722d48689003e043c5d0a98 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 8 Mar 2025 14:14:53 -0600 Subject: [PATCH 29/57] Added particle rendering to VisualThinkers. To activate, use `SetParticleType(int type)`. To deactivate, use `DisableParticle()`. Types are: - PT_DEFAULT (default value; uses `gl_particles_style`) - PT_SQUARE - PT_ROUND - PT_SMOOTH While in this mode: - `Texture` & `Translation` are ignored - `Scale.X` sets the size - `SColor` sets the color Misc changes: - Removed warning on textureless destruction --- src/playsim/p_effect.cpp | 40 ++++++++++++++++--- src/playsim/p_effect.h | 8 ++++ src/playsim/p_visualthinker.h | 8 ++++ src/rendering/hwrenderer/scene/hw_sprites.cpp | 28 +++++++++---- wadsrc/static/zscript/constants.zs | 14 +++++++ wadsrc/static/zscript/visualthinker.zs | 26 ++++++++++++ 6 files changed, 110 insertions(+), 14 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index c16d4a982..dabf0ed16 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1108,7 +1108,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnVisualThinker, SpawnVisualThink void DVisualThinker::UpdateSpriteInfo() { PT.style = ERenderStyle(GetRenderStyle()); - if((PT.flags & SPF_LOCAL_ANIM) && PT.texture != AnimatedTexture) + + if ((PT.flags & SPF_LOCAL_ANIM) && PT.texture != AnimatedTexture) { AnimatedTexture = PT.texture; TexAnim.InitStandaloneAnimation(PT.animData, PT.texture, Level->maptime); @@ -1127,6 +1128,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, UpdateSpriteInfo, UpdateSpriteInfo return 0; } +bool DVisualThinker::ValidTexture() +{ + return ((flags & VTF_IsParticle) || PT.texture.isValid()); +} // This runs just like Actor's, make sure to call Super.Tick() in ZScript. void DVisualThinker::Tick() @@ -1134,10 +1139,8 @@ void DVisualThinker::Tick() if (ObjectFlags & OF_EuthanizeMe) return; - // There won't be a standard particle for this, it's only for graphics. - if (!PT.texture.isValid()) + if (!ValidTexture()) { - Printf("No valid texture, destroyed"); Destroy(); return; } @@ -1156,7 +1159,6 @@ void DVisualThinker::Tick() PT.Pos.X = newxy.X; PT.Pos.Y = newxy.Y; PT.Pos.Z += PT.Vel.Z; - subsector_t * ss = Level->PointInRenderSubsector(PT.Pos); // Handle crossing a sector portal. @@ -1246,7 +1248,33 @@ DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, SetTranslation, SetTranslation) return 0; } -static int IsFrozen(DVisualThinker * self) +int DVisualThinker::GetParticleType() const +{ + int flag = (flags & VTF_IsParticle); + switch (flag) + { + case VTF_ParticleSquare: + return PT_SQUARE; + case VTF_ParticleRound: + return PT_ROUND; + case VTF_ParticleSmooth: + return PT_SMOOTH; + } + return PT_DEFAULT; +} + +static int GetParticleType(DVisualThinker* self) +{ + return self->GetParticleType(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, GetParticleType, GetParticleType) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + ACTION_RETURN_INT(self->GetParticleType()); +} + +static int IsFrozen(DVisualThinker* self) { return !!(self->Level->isFrozen() && !(self->PT.flags & SPF_NOTIMEFREEZE)); } diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 29042b293..b23efb01b 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -53,6 +53,14 @@ struct FLevelLocals; // [RH] Particle details +enum EParticleStyle +{ + PT_DEFAULT = -1, // Use gl_particles_style + PT_SQUARE = 0, + PT_ROUND = 1, + PT_SMOOTH = 2, +}; + enum EParticleFlags { SPF_FULLBRIGHT = 1 << 0, diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index 16043effd..69faada9f 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -20,6 +20,12 @@ enum EVisualThinkerFlags VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. VTF_DontInterpolate = 1 << 4, // disable all interpolation VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' + + VTF_ParticleDefault = 0x40, + VTF_ParticleSquare = 0x80, + VTF_ParticleRound = 0xC0, + VTF_ParticleSmooth = 0x100, + VTF_IsParticle = 0x1C0, // Renders as a particle instead }; class DVisualThinker : public DThinker @@ -53,6 +59,8 @@ public: void SetTranslation(FName trname); int GetRenderStyle() const; bool isFrozen(); + bool ValidTexture(); + int GetParticleType() const; int GetLightLevel(sector_t *rendersector) const; FVector3 InterpolatedPosition(double ticFrac) const; float InterpolatedRoll(double ticFrac) const; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index f3ab6d4c3..26643e745 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1409,7 +1409,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (!particle || particle->alpha <= 0) return; - if (spr && spr->PT.texture.isNull()) + if (spr && !spr->ValidTexture()) return; lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); @@ -1477,17 +1477,29 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (paused || (di->Level->isFrozen() && !(particle->flags & SPF_NOTIMEFREEZE))) timefrac = 0.; - if (spr) + + if (spr && !(spr->flags & VTF_IsParticle)) { AdjustVisualThinker(di, spr, sector); } else { - bool has_texture = particle->texture.isValid(); - bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; - - int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles - + bool has_texture = false; + bool custom_animated_texture = false; + int particle_style = 0; + float size = particle->size; + if (!spr) + { + has_texture = particle->texture.isValid(); + custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; + particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles + } + else + { + size = float(spr->Scale.X); + const int ptype = spr->GetParticleType(); + particle_style = (ptype != PT_DEFAULT) ? ptype : gl_particles_style; + } // [BB] Load the texture for round or smooth particles if (particle_style) { @@ -1549,7 +1561,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (particle_style == 1) factor = 1.3f / 7.f; else if (particle_style == 2) factor = 2.5f / 7.f; else factor = 1 / 7.f; - float scalefac=particle->size * factor; + float scalefac= size * factor; float ps = di->Level->pixelstretch; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 9b0a0f709..6ffb36b71 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1527,4 +1527,18 @@ enum EVisualThinkerFlags VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. VTF_DontInterpolate = 1 << 4, // disable all interpolation VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' + + VTF_ParticleDefault = 0x40, + VTF_ParticleSquare = 0x80, + VTF_ParticleRound = 0xC0, + VTF_ParticleSmooth = 0x100, + VTF_IsParticle = 0x1C0 +}; + +enum EParticleStyle +{ + PT_DEFAULT = -1, // Use gl_particles_style + PT_SQUARE = 0, + PT_ROUND = 1, + PT_SMOOTH = 2, }; diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index d5dc2253a..34c4643f5 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -60,4 +60,30 @@ Class VisualThinker : Thinker native } return p; } + + native int GetParticleType() const; + + void SetParticleType(EParticleStyle type = PT_DEFAULT) + { + switch(type) + { + Default: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleDefault; + break; + case PT_SQUARE: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleSquare; + break; + case PT_ROUND: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleRound; + break; + case PT_SMOOTH: + VisualThinkerFlags = (VisualThinkerFlags & ~VTF_IsParticle) | VTF_ParticleSmooth; + break; + } + } + + void DisableParticle() + { + VisualThinkerFlags &= ~VTF_IsParticle; + } } From 911951d967df3e0f231525705d5ec1061d1b4459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 9 Mar 2025 16:54:41 -0300 Subject: [PATCH 30/57] remove K&R C function declaration bullshit from lemon.c should be enough to fix GCC15 compilation without fucking up size_t/etc --- tools/lemon/lemon.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index bdc004a17..e5fd16905 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -53,7 +53,7 @@ extern int access(char *path, int mode); #endif static int showPrecedenceConflict = 0; -static void *msort(void *list, void *next, int (*cmp)()); +static void *msort(void *list, void *next, int (*cmp)(void*, void*)); /* ** Compilers are getting increasingly pedantic about type conversions @@ -359,7 +359,7 @@ struct symbol **Symbol_arrayof(void); /* Routines to manage the state table */ -int Configcmp(const char *, const char *); +int Configcmp(void *, void *); struct state *State_new(void); void State_init(void); int State_insert(struct state *, struct config *); @@ -403,10 +403,10 @@ static struct action *Action_new(void){ ** positive if the first action is less than, equal to, or greater than ** the first */ -static int actioncmp(ap1,ap2) -struct action *ap1; -struct action *ap2; +static int actioncmp(void *_ap1,void *_ap2) { + struct action * ap1 = (struct action *)_ap1; + struct action * ap2 = (struct action *)_ap2; int rc; rc = ap1->sp->index - ap2->sp->index; if( rc==0 ){ @@ -1757,9 +1757,9 @@ int main(int argc, char **argv) ** The "next" pointers for elements in the lists a and b are ** changed. */ -static void *merge(void *a,void *b,int (*cmp)(),size_t offset) +static void *merge(void *a,void *b,int (*cmp)(void *a, void *b),size_t offset) { - char *ptr, *head; + void *ptr, *head; if( a==0 ){ head = b; @@ -1805,11 +1805,11 @@ static void *merge(void *a,void *b,int (*cmp)(),size_t offset) ** The "next" pointers for elements in list are changed. */ #define LISTSIZE 30 -static void *msort(void *list,void *next,int (*cmp)()) +static void *msort(void *list,void *next,int (*cmp)(void*, void*)) { size_t offset; - char *ep; - char *set[LISTSIZE]; + void *ep; + void *set[LISTSIZE]; int i; offset = (size_t)next - (size_t)list; for(i=0; irp->index - b->rp->index; if( x==0 ) x = a->dot - b->dot; @@ -5147,8 +5145,10 @@ int Configcmp(const char *_a,const char *_b) } /* Compare two states */ -PRIVATE int statecmp(struct config *a, struct config *b) +PRIVATE int statecmp(void *_a, void *_b) { + const struct config *a = (const struct config *) _a; + const struct config *b = (const struct config *) _b; int rc; for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){ rc = a->rp->index - b->rp->index; @@ -5377,7 +5377,7 @@ int Configtable_insert(struct config *data) h = ph & (x4a->size-1); np = x4a->ht[h]; while( np ){ - if( Configcmp((const char *) np->data,(const char *) data)==0 ){ + if( Configcmp(np->data, data)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; @@ -5430,7 +5430,7 @@ struct config *Configtable_find(struct config *key) h = confighash(key) & (x4a->size-1); np = x4a->ht[h]; while( np ){ - if( Configcmp((const char *) np->data,(const char *) key)==0 ) break; + if( Configcmp(np->data,key)==0 ) break; np = np->next; } return np ? np->data : 0; From dbd9978cf87fb6d93924b8e75e85068f2b965148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 9 Mar 2025 16:57:28 -0300 Subject: [PATCH 31/57] fix non-void forward declarations as well --- tools/lemon/lemon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index e5fd16905..45f458d72 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -72,12 +72,12 @@ static struct action *Action_new(void); static struct action *Action_sort(struct action *); /********** From the file "build.h" ************************************/ -void FindRulePrecedences(); -void FindFirstSets(); -void FindStates(); -void FindLinks(); -void FindFollowSets(); -void FindActions(); +void FindRulePrecedences(struct lemon *xp); +void FindFirstSets(struct lemon *lemp); +void FindStates(struct lemon *lemp); +void FindLinks(struct lemon *lemp); +void FindFollowSets(struct lemon *lemp); +void FindActions(struct lemon *lemp); /********* From the file "configlist.h" *********************************/ void Configlist_init(void); From 786b9806f6d154c82c8762bb3b945e4fe4715b4d Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Sun, 9 Mar 2025 12:34:44 +0000 Subject: [PATCH 32/57] Fix building with GCC 15 --- libraries/ZWidget/include/zwidget/window/window.h | 1 + src/common/utility/r_memory.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/ZWidget/include/zwidget/window/window.h b/libraries/ZWidget/include/zwidget/window/window.h index 0539f773f..4cdb748d8 100644 --- a/libraries/ZWidget/include/zwidget/window/window.h +++ b/libraries/ZWidget/include/zwidget/window/window.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/src/common/utility/r_memory.h b/src/common/utility/r_memory.h index d9db538ca..41abe0be5 100644 --- a/src/common/utility/r_memory.h +++ b/src/common/utility/r_memory.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include From 34cbe3d8a0ea4534bf6405a16db799de135eb8d0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 16 Mar 2025 18:54:35 +0100 Subject: [PATCH 33/57] Fix memory leak in mixins --- src/common/scripting/frontend/zcc_compile.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 52163d772..fdc34b117 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -597,8 +597,13 @@ ZCCCompiler::~ZCCCompiler() { delete c; } + for (auto m : Mixins) + { + delete m; + } Structs.Clear(); Classes.Clear(); + Mixins.Clear(); } //========================================================================== From cfe275f81ccb10c210a137ec45565b837c63f513 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Fri, 14 Mar 2025 00:26:28 +0800 Subject: [PATCH 34/57] Properly assign tags to various Raven game items --- wadsrc/static/language.def | 21 +++++++++++++++++++ .../zscript/actors/heretic/hereticammo.zs | 1 + .../zscript/actors/heretic/hereticarmor.zs | 2 ++ .../actors/heretic/hereticartifacts.zs | 1 + .../zscript/actors/heretic/heretickeys.zs | 3 +++ .../static/zscript/actors/hexen/hexenkeys.zs | 11 ++++++++++ .../zscript/actors/raven/ravenhealth.zs | 1 + 7 files changed, 40 insertions(+) diff --git a/wadsrc/static/language.def b/wadsrc/static/language.def index 103d4d3a9..2700fbb20 100644 --- a/wadsrc/static/language.def +++ b/wadsrc/static/language.def @@ -391,5 +391,26 @@ TAG_ARTIINVULNERABILITY = "$$TXT_ARTIINVULNERABILITY"; TAG_ARTITELEPORT = "$$TXT_ARTITELEPORT"; TAG_ARTITOMEOFPOWER = "$$TXT_ARTITOMEOFPOWER"; TAG_ARTITORCH = "$$TXT_ARTITORCH"; +TAG_ITEMBAGOFHOLDING = "$$TXT_ITEMBAGOFHOLDING"; +TAG_ITEMSHIELD1 = "$$TXT_ITEMSHIELD2"; +TAG_ITEMSHIELD2 = "$$TXT_ITEMSHIELD2"; +TAG_GOTGREENKEY = "$$TXT_GOTGREENKEY"; +TAG_GOTBLUEKEY = "$$TXT_GOTBLUEKEY"; +TAG_GOTYELLOWKEY = "$$TXT_GOTYELLOWKEY"; +TAG_ITEMSUPERMAP = "$$TXT_ITEMSUPERMAP"; + +TAG_KEY_STEEL = "$$TXT_KEY_STEEL"; +TAG_KEY_CAVE = "$$TXT_KEY_CAVE"; +TAG_KEY_AXE = "$$TXT_KEY_AXE"; +TAG_KEY_FIRE = "$$TXT_KEY_FIRE"; +TAG_KEY_EMERALD = "$$TXT_KEY_EMERALD"; +TAG_KEY_DUNGEON = "$$TXT_KEY_DUNGEON"; +TAG_KEY_SILVER = "$$TXT_KEY_SILVER"; +TAG_KEY_RUSTED = "$$TXT_KEY_RUSTED"; +TAG_KEY_HORN = "$$TXT_KEY_HORN"; +TAG_KEY_SWAMP = "$$TXT_KEY_SWAMP"; +TAG_KEY_CASTLE = "$$TXT_KEY_CASTLE"; + +TAG_ITEMHEALTH = "$$TXT_ITEMHEALTH"; OPTMNU_SWRENDERER = "$$DSPLYMNU_SWOPT"; diff --git a/wadsrc/static/zscript/actors/heretic/hereticammo.zs b/wadsrc/static/zscript/actors/heretic/hereticammo.zs index 6464cf9dc..daf6d3ea7 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticammo.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticammo.zs @@ -237,6 +237,7 @@ Class BagOfHolding : BackpackItem Default { Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING"; + Tag "$TAG_ITEMBAGOFHOLDING"; +COUNTITEM +FLOATBOB } diff --git a/wadsrc/static/zscript/actors/heretic/hereticarmor.zs b/wadsrc/static/zscript/actors/heretic/hereticarmor.zs index 8cbcb9fbc..b95a71ad9 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticarmor.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticarmor.zs @@ -7,6 +7,7 @@ Class SilverShield : BasicArmorPickup { +FLOATBOB Inventory.Pickupmessage "$TXT_ITEMSHIELD1"; + Tag "$TAG_ITEMSHIELD1"; Inventory.Icon "SHLDA0"; Armor.Savepercent 50; Armor.Saveamount 100; @@ -27,6 +28,7 @@ Class EnchantedShield : BasicArmorPickup { +FLOATBOB Inventory.Pickupmessage "$TXT_ITEMSHIELD2"; + Tag "$TAG_ITEMSHIELD2"; Inventory.Icon "SHD2A0"; Armor.Savepercent 75; Armor.Saveamount 200; diff --git a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs index b620b04b4..117d37586 100644 --- a/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs +++ b/wadsrc/static/zscript/actors/heretic/hereticartifacts.zs @@ -9,6 +9,7 @@ Class SuperMap : MapRevealer +FLOATBOB Inventory.MaxAmount 0; Inventory.PickupMessage "$TXT_ITEMSUPERMAP"; + Tag "$TAG_ITEMSUPERMAP"; } States { diff --git a/wadsrc/static/zscript/actors/heretic/heretickeys.zs b/wadsrc/static/zscript/actors/heretic/heretickeys.zs index d5532ce01..b2bf3f363 100644 --- a/wadsrc/static/zscript/actors/heretic/heretickeys.zs +++ b/wadsrc/static/zscript/actors/heretic/heretickeys.zs @@ -16,6 +16,7 @@ Class KeyGreen : HereticKey Default { Inventory.PickupMessage "$TXT_GOTGREENKEY"; + Tag "$TAG_GOTGREENKEY"; Inventory.Icon "GKEYICON"; } States @@ -33,6 +34,7 @@ Class KeyBlue : HereticKey Default { Inventory.PickupMessage "$TXT_GOTBLUEKEY"; + Tag "$TAG_GOTBLUEKEY"; Inventory.Icon "BKEYICON"; } States @@ -50,6 +52,7 @@ Class KeyYellow : HereticKey Default { Inventory.PickupMessage "$TXT_GOTYELLOWKEY"; + Tag "$TAG_GOTYELLOWKEY"; Inventory.Icon "YKEYICON"; } States diff --git a/wadsrc/static/zscript/actors/hexen/hexenkeys.zs b/wadsrc/static/zscript/actors/hexen/hexenkeys.zs index 9bf9f426c..c0ec85ce7 100644 --- a/wadsrc/static/zscript/actors/hexen/hexenkeys.zs +++ b/wadsrc/static/zscript/actors/hexen/hexenkeys.zs @@ -14,6 +14,7 @@ class KeySteel : HexenKey { Inventory.Icon "KEYSLOT1"; Inventory.PickupMessage "$TXT_KEY_STEEL"; + Tag "$TAG_KEY_STEEL"; } States { @@ -29,6 +30,7 @@ class KeyCave : HexenKey { Inventory.Icon "KEYSLOT2"; Inventory.PickupMessage "$TXT_KEY_CAVE"; + Tag "$TAG_KEY_CAVE"; } States { @@ -44,6 +46,7 @@ class KeyAxe : HexenKey { Inventory.Icon "KEYSLOT3"; Inventory.PickupMessage "$TXT_KEY_AXE"; + Tag "$TAG_KEY_AXE"; } States { @@ -59,6 +62,7 @@ class KeyFire : HexenKey { Inventory.Icon "KEYSLOT4"; Inventory.PickupMessage "$TXT_KEY_FIRE"; + Tag "$TAG_KEY_FIRE"; } States { @@ -74,6 +78,7 @@ class KeyEmerald : HexenKey { Inventory.Icon "KEYSLOT5"; Inventory.PickupMessage "$TXT_KEY_EMERALD"; + Tag "$TAG_KEY_EMERALD"; } States { @@ -89,6 +94,7 @@ class KeyDungeon : HexenKey { Inventory.Icon "KEYSLOT6"; Inventory.PickupMessage "$TXT_KEY_DUNGEON"; + Tag "$TAG_KEY_DUNGEON"; } States { @@ -104,6 +110,7 @@ class KeySilver : HexenKey { Inventory.Icon "KEYSLOT7"; Inventory.PickupMessage "$TXT_KEY_SILVER"; + Tag "$TAG_KEY_SILVER"; } States { @@ -119,6 +126,7 @@ class KeyRusted : HexenKey { Inventory.Icon "KEYSLOT8"; Inventory.PickupMessage "$TXT_KEY_RUSTED"; + Tag "$TAG_KEY_RUSTED"; } States { @@ -134,6 +142,7 @@ class KeyHorn : HexenKey { Inventory.Icon "KEYSLOT9"; Inventory.PickupMessage "$TXT_KEY_HORN"; + Tag "$TAG_KEY_HORN"; } States { @@ -149,6 +158,7 @@ class KeySwamp : HexenKey { Inventory.Icon "KEYSLOTA"; Inventory.PickupMessage "$TXT_KEY_SWAMP"; + Tag "$TAG_KEY_SWAMP"; } States { @@ -164,6 +174,7 @@ class KeyCastle : HexenKey { Inventory.Icon "KEYSLOTB"; Inventory.PickupMessage "$TXT_KEY_CASTLE"; + Tag "$TAG_KEY_CASTLE"; } States { diff --git a/wadsrc/static/zscript/actors/raven/ravenhealth.zs b/wadsrc/static/zscript/actors/raven/ravenhealth.zs index cf7c79d0a..7bf14ae15 100644 --- a/wadsrc/static/zscript/actors/raven/ravenhealth.zs +++ b/wadsrc/static/zscript/actors/raven/ravenhealth.zs @@ -5,6 +5,7 @@ class CrystalVial : Health +FLOATBOB Inventory.Amount 10; Inventory.PickupMessage "$TXT_ITEMHEALTH"; + Tag "$TAG_ITEMHEALTH"; } States { From ae80d096648a061406ade04bb079e859d66a1226 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Mar 2025 09:38:51 +0100 Subject: [PATCH 35/57] disable Build light mode due to being broken. --- src/g_level.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index a1759cdce..f4d105125 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -150,7 +150,7 @@ CUSTOM_CVAR(Bool, gl_notexturefill, false, CVAR_NOINITCALL) CUSTOM_CVAR(Int, gl_maplightmode, -1, CVAR_NOINITCALL | CVAR_CHEAT) // this is just for testing. -1 means 'inactive' { - if (self > 5 || self < -1) self = -1; + if (self > 4 || self < -1) self = -1; } CUSTOM_CVARD(Int, gl_lightmode, 1, CVAR_ARCHIVE, "Select lighting mode. 2 is vanilla accurate, 1 is accurate to the ZDoom software renderer and 0 is a less demanding non-shader implementation") From 453722c7f1478fc1ecd8392b586bfb4840efb66e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Mar 2025 09:44:14 +0100 Subject: [PATCH 36/57] forgot to save the MAPINFO part. --- src/gamedata/g_mapinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index ea6192080..39d21e597 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -1580,7 +1580,7 @@ DEFINE_MAP_OPTION(lightmode, false) parse.sc.MustGetNumber(); if (parse.sc.Number == 8 || parse.sc.Number == 16) info->lightmode = ELightMode::NotSet; - else if (parse.sc.Number >= 0 && parse.sc.Number <= 5) + else if (parse.sc.Number >= 0 && parse.sc.Number < 5) { info->lightmode = ELightMode(parse.sc.Number); } From 72f9c0f9b70f55d7f0345575a857dd822a0295cf Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sun, 30 Mar 2025 18:15:53 -0500 Subject: [PATCH 37/57] Exported: * GetLumpContainer * GetContainerName * GetLumpFullPath for WADS struct, useful for debugging custom-made parsers and identifying where problems may arise. All credit goes to Jay for the code. --- src/common/scripting/interface/vmnatives.cpp | 21 ++++++++++++++++++++ wadsrc/static/zscript/engine/base.zs | 3 +++ 2 files changed, 24 insertions(+) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index c1bb2a2b5..1b4cdb746 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -853,6 +853,27 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) ACTION_RETURN_STRING(fileSystem.GetFileFullName(lump)); } +DEFINE_ACTION_FUNCTION(_Wads, GetLumpContainer) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_INT(fileSystem.GetFileContainer(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetContainerName) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_STRING(fileSystem.GetResourceFileName(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullPath) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_STRING(fileSystem.GetFileFullPath(lump)); +} + DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) { PARAM_PROLOGUE; diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 33c14eef6..48eb46343 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -893,6 +893,9 @@ struct Wads // todo: make FileSystem an alias to 'Wads' native static string GetLumpName(int lump); native static string GetLumpFullName(int lump); native static int GetLumpNamespace(int lump); + native static int GetLumpContainer(int lump); + native static string GetContainerName(int lump); + native static string GetLumpFullPath(int lump); } enum EmptyTokenType From 7ad2111bed465f85d884b95b633d416ed981e04b Mon Sep 17 00:00:00 2001 From: DyNaM1Kk <42520902+DyNaM1Kk@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:01:20 +0400 Subject: [PATCH 38/57] Added autoSwitch parameter to A_ReFire --- wadsrc/static/zscript/actors/inventory/stateprovider.zs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/actors/inventory/stateprovider.zs b/wadsrc/static/zscript/actors/inventory/stateprovider.zs index e02287258..bba4adb3b 100644 --- a/wadsrc/static/zscript/actors/inventory/stateprovider.zs +++ b/wadsrc/static/zscript/actors/inventory/stateprovider.zs @@ -413,7 +413,7 @@ class StateProvider : Inventory // //--------------------------------------------------------------------------- - action void A_ReFire(statelabel flash = null) + action void A_ReFire(statelabel flash = null, bool autoSwitch = true) { let player = player; bool pending; @@ -438,7 +438,7 @@ class StateProvider : Inventory else { player.refire = 0; - player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, true); + player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, autoSwitch); } } From ff442b866bb0e81abf22873551b4fd0ed14b524e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Apr 2025 07:51:03 +0200 Subject: [PATCH 39/57] rewrote XY and XYZ accessors for vectors to be read-only and not use type punning. --- src/common/utility/vectors.h | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index 47eb59793..299a08985 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -539,15 +539,9 @@ struct TVector3 return *this; } - // returns the XY fields as a 2D-vector. - constexpr const Vector2& XY() const + constexpr Vector2 XY() const { - return *reinterpret_cast(this); - } - - constexpr Vector2& XY() - { - return *reinterpret_cast(this); + return Vector2(X, Y); } // Add a 3D vector and a 2D vector. @@ -785,28 +779,16 @@ struct TVector4 } // returns the XY fields as a 2D-vector. - constexpr const Vector2& XY() const + constexpr Vector2 XY() const { - return *reinterpret_cast(this); + return Vector2(X, Y); } - constexpr Vector2& XY() + constexpr Vector3 XYZ() const { - return *reinterpret_cast(this); + return Vector3(X, Y, Z); } - // returns the XY fields as a 2D-vector. - constexpr const Vector3& XYZ() const - { - return *reinterpret_cast(this); - } - - constexpr Vector3& XYZ() - { - return *reinterpret_cast(this); - } - - // Test for approximate equality bool ApproximatelyEquals(const TVector4 &other) const { @@ -1789,7 +1771,9 @@ struct TRotator template inline TVector3::TVector3 (const TRotator &rot) { - XY() = rot.Pitch.Cos() * rot.Yaw.ToVector(); + auto XY = rot.Pitch.Cos() * rot.Yaw.ToVector(); + X = XY.X; + Y = XY.Y; Z = rot.Pitch.Sin(); } From 49cca9e8fe3d630b04c9f4749a9abeab6f84de82 Mon Sep 17 00:00:00 2001 From: Peppersawce <157759066+Peppersawce@users.noreply.github.com> Date: Sat, 5 Apr 2025 14:18:33 +0200 Subject: [PATCH 40/57] Haiku support patch --- CMakeLists.txt | 2 +- libraries/ZVulkan/CMakeLists.txt | 6 +++++- libraries/ZWidget/CMakeLists.txt | 6 +++++- src/common/engine/i_specialpaths.h | 2 +- src/common/rendering/gl_load/gl_load.c | 2 +- src/version.h | 2 ++ 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac374e55..92e7d6702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,7 +309,7 @@ else() # If we're compiling with a custom GCC on the Mac (which we know since g++-4.2 doesn't support C++11) statically link libgcc. set( ALL_C_FLAGS "-static-libgcc" ) endif() - elseif( NOT MINGW ) + elseif( NOT MINGW AND NOT HAIKU ) # Generic GCC/Clang requires position independent executable to be enabled explicitly set( ALL_C_FLAGS "${ALL_C_FLAGS} -fPIE" ) set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie" ) diff --git a/libraries/ZVulkan/CMakeLists.txt b/libraries/ZVulkan/CMakeLists.txt index 3b47b7b68..4cd713323 100644 --- a/libraries/ZVulkan/CMakeLists.txt +++ b/libraries/ZVulkan/CMakeLists.txt @@ -188,7 +188,11 @@ if(WIN32) add_definitions(-DUNICODE -D_UNICODE) else() set(ZVULKAN_SOURCES ${ZVULKAN_SOURCES} ${ZVULKAN_UNIX_SOURCES}) - set(ZVULKAN_LIBS ${CMAKE_DL_LIBS} -ldl) + if(NOT HAIKU) + set(ZVULKAN_LIBS ${CMAKE_DL_LIBS} -ldl) + else() + set(ZVULKAN_LIBS ${CMAKE_DL_LIBS}) + endif() add_definitions(-DUNIX -D_UNIX) add_link_options(-pthread) endif() diff --git a/libraries/ZWidget/CMakeLists.txt b/libraries/ZWidget/CMakeLists.txt index 68c048e22..329caf96e 100644 --- a/libraries/ZWidget/CMakeLists.txt +++ b/libraries/ZWidget/CMakeLists.txt @@ -130,7 +130,11 @@ elseif(APPLE) add_link_options(-pthread) else() set(ZWIDGET_SOURCES ${ZWIDGET_SOURCES} ${ZWIDGET_SDL2_SOURCES}) - set(ZWIDGET_LIBS ${CMAKE_DL_LIBS} -ldl) + if(NOT HAIKU) + set(ZWIDGET_LIBS ${CMAKE_DL_LIBS} -ldl) + else() + set(ZWIDGET_LIBS ${CMAKE_DL_LIBS}) + endif() add_definitions(-DUNIX -D_UNIX) add_link_options(-pthread) endif() diff --git a/src/common/engine/i_specialpaths.h b/src/common/engine/i_specialpaths.h index 01710b672..fb75230f5 100644 --- a/src/common/engine/i_specialpaths.h +++ b/src/common/engine/i_specialpaths.h @@ -2,7 +2,7 @@ #include "zstring.h" -#ifdef __unix__ +#if defined(__unix__) || defined(__HAIKU__) FString GetUserFile (const char *path); #endif FString M_GetAppDataPath(bool create); diff --git a/src/common/rendering/gl_load/gl_load.c b/src/common/rendering/gl_load/gl_load.c index d5ba4e49f..bb2141e7c 100644 --- a/src/common/rendering/gl_load/gl_load.c +++ b/src/common/rendering/gl_load/gl_load.c @@ -134,7 +134,7 @@ static PROC WinGetProcAddress(const char *name) #if defined(__APPLE__) #define IntGetProcAddress(name) AppleGLGetProcAddress(name) #else - #if defined(__sgi) || defined(__sun) || defined(__unix__) + #if defined(__sgi) || defined(__sun) || defined(__unix__) || defined(__HAIKU__) void* SDL_GL_GetProcAddress(const char* proc); #define IntGetProcAddress(name) SDL_GL_GetProcAddress((const char*)name) //#define IntGetProcAddress(name) PosixGetProcAddress((const GLubyte*)name) diff --git a/src/version.h b/src/version.h index 58e7927a1..b77d6d0fd 100644 --- a/src/version.h +++ b/src/version.h @@ -110,6 +110,8 @@ const char *GetVersionString(); #if defined(__APPLE__) || defined(_WIN32) #define GAME_DIR GAMENAME +#elif defined(__HAIKU__) +#define GAME_DIR "config/settings/" GAMENAME #else #define GAME_DIR ".config/" GAMENAMELOWERCASE #endif From 0e77b01fc462930443572779b142988a1c5d11ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Thu, 20 Feb 2025 05:21:45 -0300 Subject: [PATCH 41/57] fix OptionMenuItemCommand::DoCommand for new 4.15 keyword --- wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs index 9fc0d66ff..39430278a 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs @@ -184,7 +184,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu return self; } - private native static void DoCommand(String cmd, bool unsafe); // This is very intentionally limited to this menu item to prevent abuse. + private native static void DoCommand(String cmd, bool is_unsafe); // This is very intentionally limited to this menu item to prevent abuse. override bool Activate() { From c72888dcf8e0fce7089f1e1aa32b8e6b940df679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 9 Apr 2025 14:47:17 -0300 Subject: [PATCH 42/57] fix bad cherry pick --- src/common/engine/sc_man_scanner.re | 1 + src/common/engine/sc_man_tokens.h | 1 + src/common/scripting/frontend/zcc_parser.cpp | 1 + wadsrc/static/zscript.txt | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index 5af7e62f9..83158632b 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -177,6 +177,7 @@ std2: /* Other keywords from UnrealScript */ 'abstract' { RET(TK_Abstract); } 'foreach' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_ForEach : TK_Identifier); } + 'unsafe' { RET(ParseVersion >= MakeVersion(4, 14, 2)? TK_Unsafe : TK_Identifier); } 'true' { RET(TK_True); } 'false' { RET(TK_False); } 'none' { RET(TK_None); } diff --git a/src/common/engine/sc_man_tokens.h b/src/common/engine/sc_man_tokens.h index 487003125..85bb55d42 100644 --- a/src/common/engine/sc_man_tokens.h +++ b/src/common/engine/sc_man_tokens.h @@ -80,6 +80,7 @@ xx(TK_Color, "'color'") xx(TK_Goto, "'goto'") xx(TK_Abstract, "'abstract'") xx(TK_ForEach, "'foreach'") +xx(TK_Unsafe, "'unsafe'") xx(TK_True, "'true'") xx(TK_False, "'false'") xx(TK_None, "'none'") diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index 6ea3c316e..35c6cc74e 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -251,6 +251,7 @@ static void InitTokenMap() TOKENDEF (TK_Do, ZCC_DO); TOKENDEF (TK_For, ZCC_FOR); TOKENDEF (TK_ForEach, ZCC_FOREACH); + TOKENDEF (TK_Unsafe, ZCC_UNSAFE); TOKENDEF (TK_While, ZCC_WHILE); TOKENDEF (TK_Until, ZCC_UNTIL); TOKENDEF (TK_If, ZCC_IF); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 11a0e8c5c..46e9879da 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "4.12" +version "4.14.2" // Generic engine code #include "zscript/engine/base.zs" From 5730719182924c13a9bc28b86b07ff889b9a048f Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 19 Mar 2025 10:24:21 -0400 Subject: [PATCH 43/57] Fixed player respawning Pass appropriate information to the VM --- src/playsim/p_mobj.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 970011850..4149c8da2 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5726,8 +5726,10 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag IFVIRTUALPTRNAME(p->mo, NAME_PlayerPawn, ResetAirSupply) { + int drowning = 0; VMValue params[] = { p->mo, false }; - VMCall(func, params, 2, nullptr, 0); + VMReturn rets[] = { &drowning }; + VMCall(func, params, 2, rets, 1); } for (int ii = 0; ii < MAXPLAYERS; ++ii) @@ -5762,7 +5764,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag IFVM(PlayerPawn, FilterCoopRespawnInventory) { VMValue params[] = { p->mo, oldactor, ((heldWeap == nullptr || (heldWeap->ObjectFlags & OF_EuthanizeMe)) ? nullptr : heldWeap) }; - VMCall(func, params, 2, nullptr, 0); + VMCall(func, params, 3, nullptr, 0); } } if (oldactor != NULL) From f5032b149b3a1df108140619b81b1272c5b3341c Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 19 Mar 2025 13:57:26 -0400 Subject: [PATCH 44/57] Added missing return values in VM calls These are not supported by the JIT and must always be passed. --- src/common/cutscenes/screenjob.cpp | 4 +++- src/g_statusbar/sbarinfo_commands.cpp | 8 ++++---- src/intermission/intermission.cpp | 4 +++- src/p_conversation.cpp | 4 +++- src/playsim/fragglescript/t_func.cpp | 4 +++- src/playsim/p_interaction.cpp | 5 ++++- src/playsim/p_map.cpp | 2 +- src/playsim/p_teleport.cpp | 2 +- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/common/cutscenes/screenjob.cpp b/src/common/cutscenes/screenjob.cpp index fa3752ba7..6220291ea 100644 --- a/src/common/cutscenes/screenjob.cpp +++ b/src/common/cutscenes/screenjob.cpp @@ -270,8 +270,10 @@ void ScreenJobDraw() ScaleOverrider ovr(twod); IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, RunFrame) { + int ret = 0; VMValue parm[] = { cutscene.runner, smoothratio }; - VMCall(func, parm, 2, nullptr, 0); + VMReturn rets[] = { &ret }; + VMCall(func, parm, 2, rets, 1); } } } diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index a28d43e19..e927b1616 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -1441,10 +1441,10 @@ class CommandDrawNumber : public CommandDrawString static VMFunction *func = nullptr; if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, inventoryItem }; - int retv; - VMReturn ret(&retv); - VMCall(func, params, 2, &ret, 1); - num = retv < 0? 0 : retv / TICRATE + 1; + int ret1 = 0, ret2 = 0; + VMReturn rets[] = { &ret1, &ret2 }; + VMCall(func, params, 2, rets, 2); + num = ret1 < 0? 0 : ret1 / TICRATE + 1; break; } case INVENTORY: diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 24915f9f7..0ae8e41da 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -325,8 +325,10 @@ void DIntermissionScreenCutscene::Drawer () ScaleOverrider ovr(twod); IFVIRTUALPTRNAME(mScreenJobRunner, NAME_ScreenJobRunner, RunFrame) { + int res = 0; VMValue parm[] = { mScreenJobRunner, I_GetTimeFrac() }; - VMCall(func, parm, 2, nullptr, 0); + VMReturn ret[] = { &res }; + VMCall(func, parm, 2, ret, 1); } } diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index f51d498f2..417b0e49f 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -218,8 +218,10 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount) IFVM(Actor, TakeInventory) { + int taken = false; VMValue params[] = { player->mo, itemtype, amount, false, false }; - VMCall(func, params, 5, nullptr, 0); + VMReturn rets[] = { &taken }; + VMCall(func, params, 5, rets, 1); } } diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index f9fff1b9e..fe7699c35 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -2532,8 +2532,10 @@ void FParser::SF_PlayerWeapon() IFVM(PlayerPawn, PickNewWeapon) { + AActor* weap = nullptr; VMValue param[] = { Level->Players[playernum]->mo, (void*)nullptr }; - VMCall(func, param, 2, nullptr, 0); + VMReturn rets[] = { (void**)&weap }; + VMCall(func, param, 2, rets, 1); } } } diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index 60b6f3059..2d1f7d7d4 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -336,7 +336,10 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf } } - VMCall(func, params, 1, nullptr, 0); + AActor* unused = nullptr; + int unused2 = 0, unused3 = 0; + VMReturn ret[] = { (void**)&unused, &unused2, &unused3 }; + VMCall(func, params, 1, ret, 3); // Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need // to stay, otherwise they won't respawn correctly. diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 949514f2a..5b427e0f7 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -215,7 +215,7 @@ bool P_CanCrossLine(AActor *mo, line_t *line, DVector3 next) assert(VIndex != ~0u); } - VMValue params[] = { mo, line, next.X, next.Y, next.Z, false }; + VMValue params[] = { mo, line, next.X, next.Y, next.Z }; VMReturn ret; int retval; ret.IntAt(&retval); diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index a198f2b27..f26bb6fcb 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -249,7 +249,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) IFVIRTUALPTR(thing, AActor, PostTeleport) { VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees(), flags }; - VMCall(func, params, countof(params), nullptr, 1); + VMCall(func, params, countof(params), nullptr, 0); } } return true; From 56999fecd242faa75a1f64c4e7015fa6eefbfe31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Thu, 17 Apr 2025 18:35:43 -0300 Subject: [PATCH 45/57] fix bug with direct cvar assignment being mistakenly allowed --- src/common/console/c_cvars.h | 18 ++++++++++++++++++ src/g_game.cpp | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index ccc3cfa6a..27cf8aa38 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -589,6 +589,8 @@ class FBoolCVarRef { FBoolCVar* ref; public: + int operator= (const FBoolCVarRef&) = delete; + int operator= (FBoolCVarRef&&) = delete; inline bool operator= (bool val) { *ref = val; return val; } inline operator bool () const { return **ref; } @@ -602,7 +604,11 @@ class FIntCVarRef FIntCVar* ref; public: + int operator= (const FIntCVarRef&) = delete; + int operator= (FIntCVarRef&&) = delete; + int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } inline int operator *() const { return **ref; } inline FIntCVar* operator->() { return ref; } @@ -613,6 +619,8 @@ class FFloatCVarRef { FFloatCVar* ref; public: + int operator= (const FFloatCVarRef&) = delete; + int operator= (FFloatCVarRef&&) = delete; float operator= (float val) { *ref = val; return val; } inline operator float () const { return **ref; } @@ -625,6 +633,8 @@ class FStringCVarRef { FStringCVar* ref; public: + int operator= (const FStringCVarRef&) = delete; + int operator= (FStringCVarRef&&) = delete; const char* operator= (const char* val) { *ref = val; return val; } inline operator const char* () const { return **ref; } @@ -637,6 +647,8 @@ class FColorCVarRef { FColorCVar* ref; public: + int operator= (const FColorCVarRef&) = delete; + int operator= (FColorCVarRef&&) = delete; //uint32_t operator= (uint32_t val) { *ref = val; return val; } inline operator uint32_t () const { return **ref; } @@ -649,6 +661,9 @@ class FFlagCVarRef { FFlagCVar* ref; public: + int operator= (const FFlagCVarRef&) = delete; + int operator= (FFlagCVarRef&&) = delete; + inline bool operator= (bool val) { *ref = val; return val; } inline bool operator= (const FFlagCVar& val) { *ref = val; return val; } inline operator int () const { return **ref; } @@ -660,6 +675,9 @@ class FMaskCVarRef { FMaskCVar* ref; public: + int operator= (const FMaskCVarRef&) = delete; + int operator= (FMaskCVarRef&&) = delete; + //int operator= (int val) { *ref = val; return val; } inline operator int () const { return **ref; } inline int operator *() const { return **ref; } diff --git a/src/g_game.cpp b/src/g_game.cpp index 786bf0629..35f2672db 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -300,7 +300,7 @@ CCMD (turnspeeds) } if (i <= 4) { - *angleturn[3] = *angleturn[2]; + *angleturn[3] = **angleturn[2]; } } } From e406770efac49dcea7dccfb43daf7e7b972a53b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Thu, 17 Apr 2025 18:38:15 -0300 Subject: [PATCH 46/57] save togglehud to ini so that it can be properly restored on crash/exit --- src/d_main.cpp | 22 +++++++++++----------- src/d_main.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 875f892bf..343c9c36a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -310,8 +310,6 @@ CUSTOM_CVAR(Int, I_FriendlyWindowTitle, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_N } CVAR(Bool, cl_nointros, false, CVAR_ARCHIVE) - -bool hud_toggled = false; bool wantToRestart; bool DrawFSHUD; // [RH] Draw fullscreen HUD? bool devparm; // started game with -devparm @@ -356,16 +354,18 @@ static int pagetic; // //========================================================================== +CVAR(Int, saved_screenblocks, 10, CVAR_ARCHIVE) +CVAR(Bool, saved_drawplayersprite, true, CVAR_ARCHIVE) +CVAR(Bool, saved_showmessages, true, CVAR_ARCHIVE) +CVAR(Bool, hud_toggled, false, CVAR_ARCHIVE) + void D_ToggleHud() { - static int saved_screenblocks; - static bool saved_drawplayersprite, saved_showmessages; - if ((hud_toggled = !hud_toggled)) { - saved_screenblocks = screenblocks; - saved_drawplayersprite = r_drawplayersprites; - saved_showmessages = show_messages; + saved_screenblocks = *screenblocks; + saved_drawplayersprite = *r_drawplayersprites; + saved_showmessages = *show_messages; screenblocks = 12; r_drawplayersprites = false; show_messages = false; @@ -374,9 +374,9 @@ void D_ToggleHud() } else { - screenblocks = saved_screenblocks; - r_drawplayersprites = saved_drawplayersprite; - show_messages = saved_showmessages; + screenblocks =*saved_screenblocks; + r_drawplayersprites = *saved_drawplayersprite; + show_messages = *saved_showmessages; } } CCMD(togglehud) diff --git a/src/d_main.h b/src/d_main.h index 0d4a33079..b5a08750c 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -34,7 +34,7 @@ #include "c_cvars.h" extern bool advancedemo; -extern bool hud_toggled; +EXTERN_CVAR(Bool, hud_toggled); void D_ToggleHud(); struct event_t; From ce922225e7835dc3bd581ef3ec496e9f868b7020 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 1 Apr 2025 15:20:00 -0400 Subject: [PATCH 47/57] Added OnLoad virtual Allows for things to be reinitialized where needed for Thinkers. Moved hidden state of items over to OnLoad. --- src/playsim/dthinker.cpp | 14 ++++++++++++-- src/playsim/dthinker.h | 1 + src/playsim/p_mobj.cpp | 1 - .../static/zscript/actors/inventory/inventory.zs | 10 ++++++++++ wadsrc/static/zscript/doombase.zs | 1 + 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 51cf3a670..47efc9c0d 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -355,12 +355,12 @@ void FThinkerCollection::SerializeThinkers(FSerializer &arc, bool hubLoad) else if (thinker->ObjectFlags & OF_JustSpawned) { FreshThinkers[i].AddTail(thinker); - thinker->PostSerialize(); + thinker->CallPostSerialize(); } else { Thinkers[i].AddTail(thinker); - thinker->PostSerialize(); + thinker->CallPostSerialize(); } } } @@ -773,6 +773,16 @@ void DThinker::PostSerialize() { } +void DThinker::CallPostSerialize() +{ + PostSerialize(); + IFOVERRIDENVIRTUALPTRNAME(this, NAME_Thinker, OnLoad) + { + VMValue params[] = { this }; + VMCall(func, params, 1, nullptr, 0); + } +} + //========================================================================== // // diff --git a/src/playsim/dthinker.h b/src/playsim/dthinker.h index 78dcd1520..03e9ecc91 100644 --- a/src/playsim/dthinker.h +++ b/src/playsim/dthinker.h @@ -104,6 +104,7 @@ public: virtual void PostBeginPlay (); // Called just before the first tick virtual void CallPostBeginPlay(); // different in actor. virtual void PostSerialize(); + void CallPostSerialize(); void Serialize(FSerializer &arc) override; size_t PropagateMark(); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 4149c8da2..3db0e3506 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -217,7 +217,6 @@ void AActor::Serialize(FSerializer &arc) A("angles", Angles) A("frame", frame) A("scale", Scale) - A("nolocalrender", NoLocalRender) // Note: This will probably be removed later since a better solution is needed A("renderstyle", RenderStyle) A("renderflags", renderflags) A("renderflags2", renderflags2) diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 607c4f7c4..40a89cb08 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -85,6 +85,11 @@ class Inventory : Actor Inventory.PickupSound "misc/i_pkup"; Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } + + override void OnLoad() + { + UpdateLocalPickupStatus(); + } //native override void Tick(); @@ -1113,6 +1118,11 @@ class Inventory : Actor return pickedUp[client.PlayerNumber()]; } + void UpdateLocalPickupStatus() + { + DisableLocalRendering(consoleplayer, pickedUp[consoleplayer]); + } + // When items are dropped, clear their local pick ups. void ClearLocalPickUps() { diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index c4582c15e..4c8295cec 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -187,6 +187,7 @@ class Thinker : Object native play virtual native void Tick(); virtual native void PostBeginPlay(); + virtual void OnLoad() {} native void ChangeStatNum(int stat); static clearscope int Tics2Seconds(int tics) From 4162c4b19eb820970f6816b71c7f560422d003aa Mon Sep 17 00:00:00 2001 From: dileepvr Date: Sun, 20 Apr 2025 09:46:39 -0600 Subject: [PATCH 48/57] Fixed pitch culling in reflective flats for OoB Viewpoints The vertical clipper needed viewpoint pitch sign to be flipped to work correctly. Only relevant for OoB viewpoints. --- src/rendering/hwrenderer/scene/hw_drawinfo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 0e647e307..10fce9648 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -486,7 +486,9 @@ void HWDrawInfo::CreateScene(bool drawpsprites) { double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping if (a2 > 179.0) a2 = 179.0; - vClipper->SafeAddClipRangeDegPitches(vp.HWAngles.Pitch.Degrees() - a2, vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range + double pitchmult = (portalState.PlaneMirrorFlag % 2 != 0) ? -1.0 : 1.0; + vClipper->SafeAddClipRangeDegPitches(pitchmult * vp.HWAngles.Pitch.Degrees() - a2, pitchmult * vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range + Viewpoint.PitchSin *= pitchmult; } // reset the portal manager From 451b5cb5d9b9b228be96802d5f40a398daa35edd Mon Sep 17 00:00:00 2001 From: dileepvr Date: Sun, 20 Apr 2025 11:27:05 -0600 Subject: [PATCH 49/57] Boolean op instead of mod with 2 `( ... & 1)` is simpler than `(... % 2 != 0)`. --- src/rendering/hwrenderer/scene/hw_drawinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 10fce9648..e8f578dfe 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -486,7 +486,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites) { double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping if (a2 > 179.0) a2 = 179.0; - double pitchmult = (portalState.PlaneMirrorFlag % 2 != 0) ? -1.0 : 1.0; + double pitchmult = (portalState.PlaneMirrorFlag & 1) ? -1.0 : 1.0; vClipper->SafeAddClipRangeDegPitches(pitchmult * vp.HWAngles.Pitch.Degrees() - a2, pitchmult * vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range Viewpoint.PitchSin *= pitchmult; } From a2236c144e5b5e37f5cde0c2d5df9e32972af9d3 Mon Sep 17 00:00:00 2001 From: dileepvr Date: Sun, 20 Apr 2025 13:27:48 -0600 Subject: [PATCH 50/57] Ensure boolean to suppress compiler warning Finally used `!!(...)` somewhere. --- src/rendering/hwrenderer/scene/hw_drawinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index e8f578dfe..e16a549d9 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -486,7 +486,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites) { double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping if (a2 > 179.0) a2 = 179.0; - double pitchmult = (portalState.PlaneMirrorFlag & 1) ? -1.0 : 1.0; + double pitchmult = !!(portalState.PlaneMirrorFlag & 1) ? -1.0 : 1.0; vClipper->SafeAddClipRangeDegPitches(pitchmult * vp.HWAngles.Pitch.Degrees() - a2, pitchmult * vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range Viewpoint.PitchSin *= pitchmult; } From bf6f1753052d68c0fd9fbf3b2810342cd6a8b4c2 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 23 Apr 2025 12:12:06 -0500 Subject: [PATCH 51/57] SpawnBlood now returns an actor spawned by the function. --- src/playsim/p_local.h | 2 +- src/playsim/p_mobj.cpp | 9 +++++---- wadsrc/static/zscript/actors/actor.zs | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 584cfc43f..6575ad3e5 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -106,7 +106,7 @@ enum EPuffFlags }; AActor *P_SpawnPuff(AActor *source, PClassActor *pufftype, const DVector3 &pos, DAngle hitdir, DAngle particledir, int updown, int flags = 0, AActor *vict = NULL); -void P_SpawnBlood (const DVector3 &pos, DAngle angle, int damage, AActor *originator); +AActor *P_SpawnBlood (const DVector3 &pos, DAngle angle, int damage, AActor *originator); void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_RipperBlood (AActor *mo, AActor *bleeder); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 3db0e3506..46728cea0 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -6382,9 +6382,9 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPuff) // //--------------------------------------------------------------------------- -void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) +AActor *P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) { - AActor *th; + AActor *th = nullptr; PClassActor *bloodcls = originator->GetBloodType(); DVector3 pos = pos1; pos.Z += pr_spawnblood.Random2() / 64.; @@ -6469,6 +6469,8 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina if (bloodtype >= 1) P_DrawSplash2 (originator->Level, 40, pos, dir, 2, originator->BloodColor); + + return th; } DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) @@ -6479,8 +6481,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) PARAM_FLOAT(z); PARAM_ANGLE(dir); PARAM_INT(damage); - P_SpawnBlood(DVector3(x, y, z), dir, damage, self); - return 0; + ACTION_RETURN_OBJECT(P_SpawnBlood(DVector3(x, y, z), dir, damage, self)); } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index a809e674d..a34319524 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -775,7 +775,7 @@ class Actor : Thinker native native Actor OldSpawnMissile(Actor dest, class type, Actor owner = null); native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor victim = null); - native void SpawnBlood (Vector3 pos1, double dir, int damage); + native Actor SpawnBlood (Vector3 pos1, double dir, int damage); native void BloodSplatter (Vector3 pos, double hitangle, bool axe = false); native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false, int flags = 0); native void PlaySpawnSound(Actor missile); From 2d030d5313bdba7f6840c5490b1307b01c67a9e5 Mon Sep 17 00:00:00 2001 From: DyNaM1Kk Date: Sat, 26 Apr 2025 23:46:38 +0400 Subject: [PATCH 52/57] Added am_showlevelname CVar Allows controlling the visibility of the level name on the automap. --- src/am_map.cpp | 1 + src/g_statusbar/shared_sbar.cpp | 3 +++ src/scripting/vmthunks.cpp | 13 ++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index ec6381754..5a7ca9e6a 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -170,6 +170,7 @@ CVAR(Bool, am_showmonsters, true, CVAR_ARCHIVE); CVAR(Bool, am_showitems, false, CVAR_ARCHIVE); CVAR(Bool, am_showtime, true, CVAR_ARCHIVE); CVAR(Bool, am_showtotaltime, false, CVAR_ARCHIVE); +CVAR(Bool, am_showlevelname, true, CVAR_ARCHIVE); CVAR(Int, am_colorset, 0, CVAR_ARCHIVE); CVAR(Bool, am_customcolors, true, CVAR_ARCHIVE); CVAR(Int, am_map_secrets, 1, CVAR_ARCHIVE); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 5890fd58f..faacecc18 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -85,6 +85,7 @@ EXTERN_CVAR (Bool, am_showsecrets) EXTERN_CVAR (Bool, am_showitems) EXTERN_CVAR (Bool, am_showtime) EXTERN_CVAR (Bool, am_showtotaltime) +EXTERN_CVAR (Bool, am_showlevelname) EXTERN_CVAR(Bool, inter_subtitles) EXTERN_CVAR(Bool, ui_screenborder_classic_scaling) @@ -598,6 +599,8 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) } FormatMapName(primaryLevel, crdefault, &textbuffer); + if (textbuffer.IsEmpty()) + return; if (!generic_ui) { diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index a43c2f468..68560a69e 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2282,6 +2282,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetSpotState, GetSpotState) //--------------------------------------------------------------------------- EXTERN_CVAR(Int, am_showmaplabel) +EXTERN_CVAR(Bool, am_showlevelname) void FormatMapName(FLevelLocals *self, int cr, FString *result) { @@ -2295,13 +2296,19 @@ void FormatMapName(FLevelLocals *self, int cr, FString *result) if (self->info->MapLabel.IsNotEmpty()) { if (self->info->MapLabel.Compare("*")) - *result << self->info->MapLabel << ": "; + *result << self->info->MapLabel; } else if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub)) { - *result << self->MapName << ": "; + *result << self->MapName; + } + + if (am_showlevelname) + { + if (!result->IsEmpty()) + *result << ": "; + *result << mapnamecolor << self->LevelName; } - *result << mapnamecolor << self->LevelName; } DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, FormatMapName, FormatMapName) From fc470b4f7c3336d6e6601dc57e9b9c56f5c9f04f Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Mon, 28 Apr 2025 20:24:42 -0500 Subject: [PATCH 53/57] fix dsdhacked actors not spawning when placed in a map --- src/gamedata/d_dehacked.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 8ddcc7935..040735874 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -139,6 +139,7 @@ static PClassActor* FindInfoName(int index, bool mustexist = false) cls = static_cast(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor))); NewClassType(cls, -1); // This needs a VM type to work as intended. cls->InitializeDefaults(); + PClassActor::AllActorClasses.Push(cls); } if (cls) { @@ -3714,7 +3715,11 @@ void FinishDehPatch () mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++); bool newlycreated; subclass = static_cast(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated, 0)); - if (newlycreated) subclass->InitializeDefaults(); + if (newlycreated) + { + subclass->InitializeDefaults(); + PClassActor::AllActorClasses.Push(subclass); + } } while (subclass == nullptr); NewClassType(subclass, 0); // This needs a VM type to work as intended. From 16dffcbbf0823eaffed8212d1b4bc8c6e007035f Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Tue, 29 Apr 2025 01:21:53 -0500 Subject: [PATCH 54/57] add a few commonly-used gzdoom-specific properties to the dehacked parser --- src/gamedata/d_dehacked.cpp | 69 +++++++++++++++++++++++++++++++++++-- src/namedef_custom.h | 3 ++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 040735874..1f6fc92c2 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -1204,6 +1204,8 @@ static int PatchThing (int thingy, int flags) AActor *info; uint8_t dummy[sizeof(AActor)]; bool hadHeight = false; + bool hadProjHeight = false; + bool hadPhysHeight = false; bool hadTranslucency = false; bool hadStyle = false; FStateDefinitions statedef; @@ -1263,8 +1265,17 @@ static int PatchThing (int thingy, int flags) } else if (linelen == 6 && stricmp (Line1, "Height") == 0) { - info->Height = DEHToDouble(val); - info->projectilepassheight = 0; // needs to be disabled + // [XA] This is a bit more complex now, since projectilepassheight + // and "physical height" now both exist. if either of these are + // defined, then override the Height field accordingly. + if(!hadPhysHeight) + { + info->Height = DEHToDouble(val); + } + if(!hadProjHeight) + { + info->projectilepassheight = 0; // needs to be disabled + } hadHeight = true; } else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) @@ -1460,6 +1471,47 @@ static int PatchThing (int thingy, int flags) info->missilechancemult = DEHToDouble(val); } + // [XA] Fields for common GZDoom-specific values that + // are desirable to set in a cross-port DEHACKED mod. + // adding these prevents users from having to reimplement + // actors in zscript just to define these few fields. + else if (!stricmp(Line1, "Projectile pass height")) + { + info->projectilepassheight = DEHToDouble(val); + hadProjHeight = true; + } + else if (!stricmp(Line1, "Physical height")) + { + // [XA] This is a synonym for Height that is intended + // to be ignored in any ports that don't support + // projectilepassheight -- this is needed because + // other ports' "Height x" is actually equivalent + // to Zdoom's "ProjectilePassHeight x; Height y", + // i.e. the definition of the Height var is different. + info->Height = DEHToDouble(val); + hadPhysHeight = true; + } + else if (!stricmp(Line1, "Tag")) + { + stripwhite(Line2); + info->SetTag(Line2); + } + else if (!stricmp(Line1, "Obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_Obituary) = Line2; + } + else if (!stricmp(Line1, "Melee obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_HitObituary) = Line2; + } + else if (!stricmp(Line1, "Self obituary")) + { + stripwhite(Line2); + info->StringVar(NAME_SelfObituary) = Line2; + } + else if (linelen > 6) { if (stricmp (Line1 + linelen - 6, " frame") == 0) @@ -1728,12 +1780,23 @@ static int PatchThing (int thingy, int flags) else Printf (unknown_str, Line1, "Thing", thingy); } + // [XA] sanity check: to avoid ambiguity, an actor that defines + // ProjectilePassHeight must also define PhysicalHeight, and vice-versa. + if(hadPhysHeight && !hadProjHeight) + { + I_Error("Thing %d: DEHACKED actors that set 'Physical height' must also set 'Projectile pass height'\n", thingy); + } + else if(!hadPhysHeight && hadProjHeight) + { + I_Error("Thing %d: DEHACKED actors that set 'Projectile pass height' must also set 'Physical height'\n", thingy); + } + if (info != (AActor *)&dummy) { // Reset heights for things hanging from the ceiling that // don't specify a new height. if (info->flags & MF_SPAWNCEILING && - !hadHeight && + !hadHeight && !hadPhysHeight && thingy <= (int)OrgHeights.Size() && thingy > 0) { info->Height = OrgHeights[thingy - 1]; diff --git a/src/namedef_custom.h b/src/namedef_custom.h index dbf94dbaf..15b9d48d9 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -480,6 +480,9 @@ xx(PowerupType) xx(PlayerPawn) xx(RipSound) xx(Archvile) +xx(Obituary) +xx(HitObituary) +xx(SelfObituary) xx(ResolveState) From eee9382d88f171236fb435b7d910fedb69add286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 29 Apr 2025 08:14:34 -0300 Subject: [PATCH 55/57] 4.14.2 --- src/version.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/version.h b/src/version.h index b77d6d0fd..79a236c6a 100644 --- a/src/version.h +++ b/src/version.h @@ -41,21 +41,21 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.15pre" +#define VERSIONSTR "4.14.2" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,14,9999,0 -#define RC_PRODUCTVERSION 4,14,9999,0 +#define RC_FILEVERSION 4,14,2,0 +#define RC_PRODUCTVERSION 4,14,2,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 15 -#define VER_REVISION 0 +#define VER_MINOR 14 +#define VER_REVISION 2 // This should always refer to the GZDoom version a derived port is based on and not reflect the derived port's version number! #define ENG_MAJOR 4 -#define ENG_MINOR 15 -#define ENG_REVISION 0 +#define ENG_MINOR 14 +#define ENG_REVISION 2 // Version identifier for network games. // Bump it every time you do a release unless you're certain you From 3befb3f5e7a0f67209bb6922cca8170d71fa95a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 29 Apr 2025 15:37:28 -0300 Subject: [PATCH 56/57] limit light alpha mult to renderflag --- src/playsim/actor.h | 1 + src/rendering/hwrenderer/hw_dynlightdata.cpp | 2 +- src/rendering/hwrenderer/scene/hw_spritelight.cpp | 2 +- src/scripting/thingdef_data.cpp | 1 + wadsrc/static/zscript/actors/shared/dynlights.zs | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 2f461e108..7e132fa73 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -508,6 +508,7 @@ enum ActorRenderFlag2 RF2_ISOMETRICSPRITES = 0x0080, RF2_SQUAREPIXELS = 0x0100, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling RF2_STRETCHPIXELS = 0x0200, // don't apply SQUAREPIXELS for ROLLSPRITES + RF2_LIGHTMULTALPHA = 0x0400, // attached lights use alpha as intensity multiplier }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/rendering/hwrenderer/hw_dynlightdata.cpp b/src/rendering/hwrenderer/hw_dynlightdata.cpp index 0c264a1f7..bf516e637 100644 --- a/src/rendering/hwrenderer/hw_dynlightdata.cpp +++ b/src/rendering/hwrenderer/hw_dynlightdata.cpp @@ -92,7 +92,7 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f cs = 1.0f; } - if (light->target) + if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA)) cs *= (float)light->target->Alpha; float r = light->GetRed() / 255.0f * cs; diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index ca67296d7..eec49dd93 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -177,7 +177,7 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig lg = light->GetGreen() / 255.0f; lb = light->GetBlue() / 255.0f; - if (light->target) + if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA)) { float alpha = (float)light->target->Alpha; lr *= alpha; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index e17e28c35..73d579e31 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -389,6 +389,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2), DEFINE_FLAG(RF2, SQUAREPIXELS, AActor, renderflags2), DEFINE_FLAG(RF2, STRETCHPIXELS, AActor, renderflags2), + DEFINE_FLAG(RF2, LIGHTMULTALPHA, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index 8c5d0850d..5e4670c99 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -73,6 +73,7 @@ class DynamicLight : Actor +FIXMAPTHINGPOS +INVISIBLE +NOTONAUTOMAP + +LIGHTMULTALPHA } //========================================================================== From 99aa489d09015a95bb78df2b30ede29f328cc874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 29 Jan 2025 01:31:37 -0300 Subject: [PATCH 57/57] 4.14.2 model refactor cherry pick * split frame info calculation from RenderFrameModels * clean up FindModelFrame * refactor model overrides into its own function * refactor frame rendering into RenderModelFrame * split frame processing into ProcessModelFrame --- src/common/models/model.cpp | 2 +- src/common/models/model.h | 4 +- src/r_data/models.cpp | 462 +++++++++++++---------- src/r_data/models.h | 37 +- src/rendering/hwrenderer/hw_precache.cpp | 2 +- 5 files changed, 302 insertions(+), 205 deletions(-) diff --git a/src/common/models/model.cpp b/src/common/models/model.cpp index 0f1603415..bc1a02efd 100644 --- a/src/common/models/model.cpp +++ b/src/common/models/model.cpp @@ -45,7 +45,7 @@ TDeletingArray Models; TArray SpriteModelFrames; -TMap BaseSpriteModelFrames; +TMap BaseSpriteModelFrames; ///////////////////////////////////////////////////////////////////////////// diff --git a/src/common/models/model.h b/src/common/models/model.h index b6d3f4803..60341fac5 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -16,14 +16,16 @@ class FModelRenderer; class FGameTexture; class IModelVertexBuffer; class FModel; +class PClass; struct FSpriteModelFrame; FTextureID LoadSkin(const char* path, const char* fn); void FlushModels(); + extern TDeletingArray Models; extern TArray SpriteModelFrames; -extern TMap BaseSpriteModelFrames; +extern TMap BaseSpriteModelFrames; #define MD3_MAX_SURFACES 32 #define MIN_MODELS 4 diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index bc9473b07..53f4cfacf 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -313,19 +313,18 @@ void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to, } } -void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor) +CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* data, AActor* actor, bool is_decoupled, double tic) { // [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation // and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame. - int smf_flags = smf->getFlags(actor->modelData); + int smf_flags = smf->getFlags(data); const FSpriteModelFrame * smfNext = nullptr; float inter = 0.; - bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS); - ModelAnimFrameInterp decoupled_frame; + ModelAnimFrame * decoupled_frame_prev = nullptr; // if prev_frame == -1: interpolate(main_frame, next_frame, inter), else: interpolate(interpolate(main_prev_frame, main_frame, inter_main), interpolate(next_prev_frame, next_frame, inter_next), inter) // 4-way interpolation is needed to interpolate animation switches between animations that aren't 35hz @@ -333,15 +332,10 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr if(is_decoupled) { smfNext = smf = &BaseSpriteModelFrames[actor->GetClass()]; - if(actor->modelData && !(actor->modelData->curAnim.flags & MODELANIM_NONE)) + if(data && !(data->curAnim.flags & MODELANIM_NONE)) { - double tic = actor->Level->totaltime; - if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen()) - { - tic += I_GetTimeFrac(); - } - - calcFrames(actor->modelData->curAnim, tic, decoupled_frame, inter); + calcFrames(data->curAnim, tic, decoupled_frame, inter); + decoupled_frame_prev = &data->prevAnim; } } else if (gl_interpolate_model_frames && !(smf_flags & MDL_NOINTERPOLATION)) @@ -388,173 +382,226 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr unsigned modelsamount = smf->modelsAmount; //[SM] - if we added any models for the frame to also render, then we also need to update modelsAmount for this smf - if (actor->modelData != nullptr) + if (data != nullptr) { - if (actor->modelData->models.Size() > modelsamount) - modelsamount = actor->modelData->models.Size(); + if (data->models.Size() > modelsamount) + modelsamount = data->models.Size(); } - TArray surfaceskinids; + return + { + smf_flags, + smfNext, + inter, + is_decoupled, + decoupled_frame, + decoupled_frame_prev, + modelsamount + }; +} + +bool CalcModelOverrides(int i, const FSpriteModelFrame *smf, DActorModelData* data, const CalcModelFrameInfo &info, ModelDrawInfo &out, bool is_decoupled) +{ + //reset drawinfo + out.modelid = -1; + out.animationid = -1; + out.modelframe = -1; + out.modelframenext = -1; + out.skinid.SetNull(); + out.surfaceskinids.Clear(); + + if (data) + { + //modelID + if (data->models.Size() > i && data->models[i].modelID >= 0) + { + out.modelid = data->models[i].modelID; + } + else if(data->models.Size() > i && data->models[i].modelID == -2) + { + return false; + } + else if(smf->modelsAmount > i) + { + out.modelid = smf->modelIDs[i]; + } + + //animationID + if (data->animationIDs.Size() > i && data->animationIDs[i] >= 0) + { + out.animationid = data->animationIDs[i]; + } + else if(smf->modelsAmount > i) + { + out.animationid = smf->animationIDs[i]; + } + if(!is_decoupled) + { + //modelFrame + if (data->modelFrameGenerators.Size() > i + && (unsigned)data->modelFrameGenerators[i] < info.modelsamount + && smf->modelframes[data->modelFrameGenerators[i]] >= 0 + ) { + out.modelframe = smf->modelframes[data->modelFrameGenerators[i]]; + + if (info.smfNext) + { + if(info.smfNext->modelframes[data->modelFrameGenerators[i]] >= 0) + { + out.modelframenext = info.smfNext->modelframes[data->modelFrameGenerators[i]]; + } + else + { + out.modelframenext = info.smfNext->modelframes[i]; + } + } + } + else if(smf->modelsAmount > i) + { + out.modelframe = smf->modelframes[i]; + if (info.smfNext) out.modelframenext = info.smfNext->modelframes[i]; + } + } + + //skinID + if (data->skinIDs.Size() > i && data->skinIDs[i].isValid()) + { + out.skinid = data->skinIDs[i]; + } + else if(smf->modelsAmount > i) + { + out.skinid = smf->skinIDs[i]; + } + + //surfaceSkinIDs + if(data->models.Size() > i && data->models[i].surfaceSkinIDs.Size() > 0) + { + unsigned sz1 = smf->surfaceskinIDs.Size(); + unsigned sz2 = data->models[i].surfaceSkinIDs.Size(); + unsigned start = i * MD3_MAX_SURFACES; + + out.surfaceskinids = data->models[i].surfaceSkinIDs; + out.surfaceskinids.Resize(MD3_MAX_SURFACES); + + for (unsigned surface = 0; surface < MD3_MAX_SURFACES; surface++) + { + if (sz2 > surface && (data->models[i].surfaceSkinIDs[surface].isValid())) + { + continue; + } + if((surface + start) < sz1) + { + out.surfaceskinids[surface] = smf->surfaceskinIDs[surface + start]; + } + else + { + out.surfaceskinids[surface].SetNull(); + } + } + } + } + else + { + out.modelid = smf->modelIDs[i]; + out.animationid = smf->animationIDs[i]; + out.modelframe = smf->modelframes[i]; + if (info.smfNext) out.modelframenext = info.smfNext->modelframes[i]; + out.skinid = smf->skinIDs[i]; + } + + return (out.modelid >= 0 && out.modelid < Models.size()); +} + + +const TArray * ProcessModelFrame(FModel * animation, bool nextFrame, int i, const FSpriteModelFrame *smf, DActorModelData* modelData, const CalcModelFrameInfo &frameinfo, ModelDrawInfo &drawinfo, bool is_decoupled, double tic) +{ + const TArray* animationData = nullptr; + + if (drawinfo.animationid >= 0) + { + animation = Models[drawinfo.animationid]; + animationData = animation->AttachAnimationData(); + } + + const TArray *boneData = nullptr; + + if(is_decoupled) + { + if(frameinfo.decoupled_frame.frame1 >= 0) + { + boneData = animation->CalculateBones( + frameinfo.decoupled_frame_prev ? *frameinfo.decoupled_frame_prev : nullptr, + frameinfo.decoupled_frame, + frameinfo.inter, + animationData); + } + } + else + { + boneData = animation->CalculateBones( + nullptr, + { + nextFrame ? frameinfo.inter : -1.0f, + drawinfo.modelframe, + drawinfo.modelframenext + }, + -1.0f, + animationData); + } + + return boneData; +} + +static inline void RenderModelFrame(FModelRenderer *renderer, int i, const FSpriteModelFrame *smf, DActorModelData* modelData, const CalcModelFrameInfo &frameinfo, ModelDrawInfo &drawinfo, bool is_decoupled, double tic, FTranslationID translation, int &boneStartingPosition, bool &evaluatedSingle) +{ + FModel * mdl = Models[drawinfo.modelid]; + auto tex = drawinfo.skinid.isValid() ? TexMan.GetGameTexture(drawinfo.skinid, true) : nullptr; + mdl->BuildVertexBuffer(renderer); + + auto ssidp = drawinfo.surfaceskinids.Size() > 0 + ? drawinfo.surfaceskinids.Data() + : (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr); + + bool nextFrame = frameinfo.smfNext && drawinfo.modelframe != drawinfo.modelframenext; + + // [Jay] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS + if(!evaluatedSingle) + { // [Jay] TODO per-model decoupled animations + const TArray *boneData = ProcessModelFrame(mdl, nextFrame, i, smf, modelData, frameinfo, drawinfo, is_decoupled, tic); + + if(frameinfo.smf_flags & MDL_MODELSAREATTACHMENTS || is_decoupled) + { + boneStartingPosition = boneData ? screen->mBones->UploadBones(*boneData) : -1; + evaluatedSingle = true; + } + } + + mdl->RenderFrame(renderer, tex, drawinfo.modelframe, nextFrame ? drawinfo.modelframenext : drawinfo.modelframe, nextFrame ? frameinfo.inter : -1.f, translation, ssidp, boneStartingPosition); +} + +void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor) +{ + double tic = actor->Level->totaltime; + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen()) + { + tic += I_GetTimeFrac(); + } + + bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS); + + DActorModelData* modelData = actor ? actor->modelData.ForceGet() : nullptr; + + CalcModelFrameInfo frameinfo = CalcModelFrame(Level, smf, curState, curTics, modelData, actor, is_decoupled, tic); + ModelDrawInfo drawinfo; int boneStartingPosition = -1; bool evaluatedSingle = false; - for (unsigned i = 0; i < modelsamount; i++) + for (unsigned i = 0; i < frameinfo.modelsamount; i++) { - int modelid = -1; - int animationid = -1; - int modelframe = -1; - int modelframenext = -1; - FTextureID skinid(nullptr); - - surfaceskinids.Clear(); - - if (actor->modelData != nullptr) + if (CalcModelOverrides(i, smf, modelData, frameinfo, drawinfo, is_decoupled)) { - //modelID - if (actor->modelData->models.Size() > i && actor->modelData->models[i].modelID >= 0) - { - modelid = actor->modelData->models[i].modelID; - } - else if(actor->modelData->models.Size() > i && actor->modelData->models[i].modelID == -2) - { - continue; - } - else if(smf->modelsAmount > i) - { - modelid = smf->modelIDs[i]; - } - - //animationID - if (actor->modelData->animationIDs.Size() > i && actor->modelData->animationIDs[i] >= 0) - { - animationid = actor->modelData->animationIDs[i]; - } - else if(smf->modelsAmount > i) - { - animationid = smf->animationIDs[i]; - } - if(!is_decoupled) - { - //modelFrame - if (actor->modelData->modelFrameGenerators.Size() > i - && (unsigned)actor->modelData->modelFrameGenerators[i] < modelsamount - && smf->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0 - ) { - modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]]; - - if (smfNext) - { - if(smfNext->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0) - { - modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]]; - } - else - { - modelframenext = smfNext->modelframes[i]; - } - } - } - else if(smf->modelsAmount > i) - { - modelframe = smf->modelframes[i]; - if (smfNext) modelframenext = smfNext->modelframes[i]; - } - } - - //skinID - if (actor->modelData->skinIDs.Size() > i && actor->modelData->skinIDs[i].isValid()) - { - skinid = actor->modelData->skinIDs[i]; - } - else if(smf->modelsAmount > i) - { - skinid = smf->skinIDs[i]; - } - - //surfaceSkinIDs - if(actor->modelData->models.Size() > i && actor->modelData->models[i].surfaceSkinIDs.Size() > 0) - { - unsigned sz1 = smf->surfaceskinIDs.Size(); - unsigned sz2 = actor->modelData->models[i].surfaceSkinIDs.Size(); - unsigned start = i * MD3_MAX_SURFACES; - - surfaceskinids = actor->modelData->models[i].surfaceSkinIDs; - surfaceskinids.Resize(MD3_MAX_SURFACES); - - for (unsigned surface = 0; surface < MD3_MAX_SURFACES; surface++) - { - if (sz2 > surface && (actor->modelData->models[i].surfaceSkinIDs[surface].isValid())) - { - continue; - } - if((surface + start) < sz1) - { - surfaceskinids[surface] = smf->surfaceskinIDs[surface + start]; - } - else - { - surfaceskinids[surface].SetNull(); - } - } - } - } - else - { - modelid = smf->modelIDs[i]; - animationid = smf->animationIDs[i]; - modelframe = smf->modelframes[i]; - if (smfNext) modelframenext = smfNext->modelframes[i]; - skinid = smf->skinIDs[i]; - } - - if (modelid >= 0 && modelid < Models.size()) - { - FModel * mdl = Models[modelid]; - auto tex = skinid.isValid() ? TexMan.GetGameTexture(skinid, true) : nullptr; - mdl->BuildVertexBuffer(renderer); - - auto ssidp = surfaceskinids.Size() > 0 - ? surfaceskinids.Data() - : (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr); - - - bool nextFrame = smfNext && modelframe != modelframenext; - - - // [RL0] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS - if(!evaluatedSingle) - { - const TArray *boneData = nullptr; - FModel* animation = mdl; - const TArray* animationData = nullptr; - - if (animationid >= 0) - { - animation = Models[animationid]; - animationData = animation->AttachAnimationData(); - } - - if(is_decoupled) - { - if(decoupled_frame.frame1 >= 0) - { - boneData = animation->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, animationData); - } - } - else - { - boneData = animation->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, animationData); - } - - if(smf_flags & MDL_MODELSAREATTACHMENTS || is_decoupled) - { - boneStartingPosition = boneData ? screen->mBones->UploadBones(*boneData) : -1; - evaluatedSingle = true; - } - } - - mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : -1.f, translation, ssidp, boneStartingPosition); + RenderModelFrame(renderer, i, smf, modelData, frameinfo, drawinfo, is_decoupled, tic, translation, boneStartingPosition, evaluatedSingle); } } } @@ -1068,33 +1115,24 @@ void ParseModelDefLump(int Lump) // //=========================================================================== -FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped) +FSpriteModelFrame * FindModelFrameRaw(const AActor * actorDefaults, const PClass * ti, int sprite, int frame, bool dropped) { - auto def = GetDefaultByType(ti); - if (def->hasmodel) + if(actorDefaults->hasmodel) { - if(def->flags9 & MF9_DECOUPLEDANIMATIONS) + FSpriteModelFrame smf; + + memset(&smf, 0, sizeof(smf)); + smf.type = ti; + smf.sprite = sprite; + smf.frame = frame; + + int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; + + while (hash>=0) { - FSpriteModelFrame * smf = BaseSpriteModelFrames.CheckKey((void*)ti); - if(smf) return smf; - } - else - { - FSpriteModelFrame smf; - - memset(&smf, 0, sizeof(smf)); - smf.type=ti; - smf.sprite=sprite; - smf.frame=frame; - - int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; - - while (hash>=0) - { - FSpriteModelFrame * smff = &SpriteModelFrames[hash]; - if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; - hash=smff->hashnext; - } + FSpriteModelFrame * smff = &SpriteModelFrames[hash]; + if (smff->type == ti && smff->sprite == sprite && smff->frame == frame) return smff; + hash = smff->hashnext; } } @@ -1108,28 +1146,52 @@ FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, if (sprframe->Voxel != nullptr) { int index = sprframe->Voxel->VoxeldefIndex; - if (dropped && sprframe->Voxel->DroppedSpin !=sprframe->Voxel->PlacedSpin) index++; + if (dropped && sprframe->Voxel->DroppedSpin != sprframe->Voxel->PlacedSpin) index++; return &SpriteModelFrames[index]; } } } + return nullptr; } -FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped) +FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped) { - if(!thing) return nullptr; + auto def = GetDefaultByType(ti); - if(thing->flags9 & MF9_DECOUPLEDANIMATIONS) + if (def->hasmodel) { - return BaseSpriteModelFrames.CheckKey((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass()); + if(def->flags9 & MF9_DECOUPLEDANIMATIONS) + { + FSpriteModelFrame * smf = BaseSpriteModelFrames.CheckKey(ti); + if(smf) return smf; + } + } + + return FindModelFrameRaw(def, ti, sprite, frame, dropped); +} + +FSpriteModelFrame * FindModelFrame(const PClass * ti, bool is_decoupled, int sprite, int frame, bool dropped) +{ + if(!ti) return nullptr; + + if(is_decoupled) + { + return BaseSpriteModelFrames.CheckKey(ti); } else { - return FindModelFrameRaw((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass(), sprite, frame, dropped); + return FindModelFrameRaw(GetDefaultByType(ti), ti, sprite, frame, dropped); } } +FSpriteModelFrame * FindModelFrame(AActor * thing, int sprite, int frame, bool dropped) +{ + if(!thing) return nullptr; + + return FindModelFrame((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass(), (thing->flags9 & MF9_DECOUPLEDANIMATIONS), sprite, frame, dropped); +} + //=========================================================================== // // IsHUDModelForPlayerAvailable diff --git a/src/r_data/models.h b/src/r_data/models.h index 4a7154446..7d9d7acd4 100644 --- a/src/r_data/models.h +++ b/src/r_data/models.h @@ -62,8 +62,11 @@ enum MDL_FORCECULLBACKFACES = 1<<14, }; -FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped); -FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped); +FSpriteModelFrame * FindModelFrame(AActor * thing, int sprite, int frame, bool dropped); +FSpriteModelFrame * FindModelFrame(const PClass * ti, bool is_decoupled, int sprite, int frame, bool dropped); +FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped); +//FSpriteModelFrame * FindModelFrameRaw(const AActor * actorDefaults, const PClass * ti, int sprite, int frame, bool dropped); + bool IsHUDModelForPlayerAvailable(player_t * player); // Check if circle potentially intersects with node AABB @@ -114,6 +117,36 @@ void BSPWalkCircle(FLevelLocals *Level, float x, float y, float radiusSquared, c void RenderModel(FModelRenderer* renderer, float x, float y, float z, FSpriteModelFrame* smf, AActor* actor, double ticFrac); void RenderHUDModel(FModelRenderer* renderer, DPSprite* psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf); +struct CalcModelFrameInfo +{ + int smf_flags; + const FSpriteModelFrame * smfNext; + float inter; + bool is_decoupled; + ModelAnimFrameInterp decoupled_frame; + ModelAnimFrame * decoupled_frame_prev; + unsigned modelsamount; +}; + +struct ModelDrawInfo +{ + TArray surfaceskinids; + int modelid; + int animationid; + int modelframe; + int modelframenext; + FTextureID skinid; +}; + +class DActorModelData; + +CalcModelFrameInfo CalcModelFrame(FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, DActorModelData* modelData, AActor* actor, bool is_decoupled, double tic); + +// returns true if the model isn't removed +bool CalcModelOverrides(int modelindex, const FSpriteModelFrame *smf, DActorModelData* modelData, const CalcModelFrameInfo &frameinfo, ModelDrawInfo &drawinfo, bool is_decoupled); + +const TArray * ProcessModelFrame(FModel * animation, bool nextFrame, int i, const FSpriteModelFrame *smf, DActorModelData* modelData, const CalcModelFrameInfo &frameinfo, ModelDrawInfo &drawinfo, bool is_decoupled, double tic); + EXTERN_CVAR(Float, cl_scaleweaponfov) #endif diff --git a/src/rendering/hwrenderer/hw_precache.cpp b/src/rendering/hwrenderer/hw_precache.cpp index d6837252d..699faf706 100644 --- a/src/rendering/hwrenderer/hw_precache.cpp +++ b/src/rendering/hwrenderer/hw_precache.cpp @@ -159,7 +159,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl { auto &state = cls->GetStates()[i]; spritelist[state.sprite].Insert(gltrans, true); - FSpriteModelFrame * smf = FindModelFrameRaw(cls, state.sprite, state.Frame, false); + FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false); if (smf != NULL) { for (int i = 0; i < smf->modelsAmount; i++)