From c1e39ca06abeca7fc622e5560baeae836f92ab6b Mon Sep 17 00:00:00 2001 From: jplebreton Date: Fri, 9 Jun 2017 18:16:01 -0700 Subject: [PATCH 01/10] fix erroneous 8th secret sector in nerve.wad aka No Rest For The Living map04 (called level04 in the wad) --- wadsrc/static/compatibility.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 8863326e1..b6e57bc1a 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -629,6 +629,11 @@ ABC4EB5A1535ECCD0061AD14F3547908 // Plutonia Experiment, map26 setsectorspecial 156 0 } +FF635FB9A2F076566299910F8C78F707 // nerve.wad, level04 +{ + setsectorspecial 868 0 +} + B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6 { setvertex 1650 -3072 2671 @@ -731,4 +736,4 @@ CA3773ED313E8899311F3DD0CA195A68 // e3m6 setsectortexture 145 floor F_CONCRP setsectorlight 138 192 setwalltexture 3431 back top BRKGRY01 -} \ No newline at end of file +} From a0cc78d6aa321f70644be709e14eebaca87db33c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 10 Jun 2017 10:16:42 +0200 Subject: [PATCH 02/10] - Fix softpoly wall clipping bug --- src/polyrenderer/scene/poly_wall.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 87ee9ec12..db95ec94a 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -117,10 +117,10 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan double topceilz1 = frontceilz1; double topceilz2 = frontceilz2; - double topfloorz1 = MIN(backceilz1, frontceilz1); - double topfloorz2 = MIN(backceilz2, frontceilz2); - double bottomceilz1 = MAX(frontfloorz1, backfloorz1); - double bottomceilz2 = MAX(frontfloorz2, backfloorz2); + double topfloorz1 = MAX(MIN(backceilz1, frontceilz1), frontfloorz1); + double topfloorz2 = MAX(MIN(backceilz2, frontceilz2), frontfloorz2); + double bottomceilz1 = MIN(MAX(frontfloorz1, backfloorz1), frontceilz1); + double bottomceilz2 = MIN(MAX(frontfloorz2, backfloorz2), frontceilz2); double bottomfloorz1 = frontfloorz1; double bottomfloorz2 = frontfloorz2; double middleceilz1 = topfloorz1; @@ -135,7 +135,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan { wall.SetCoords(line->v1->fPos(), line->v2->fPos(), topceilz1, topfloorz1, topceilz2, topfloorz2); wall.TopTexZ = topTexZ; - wall.BottomTexZ = MIN(topfloorz1, topfloorz2); + wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2)); wall.Texpart = side_t::top; wall.Render(worldToClip, clipPlane, cull); } @@ -143,7 +143,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor) { wall.SetCoords(line->v1->fPos(), line->v2->fPos(), bottomceilz1, bottomfloorz1, bottomceilz2, bottomfloorz2); - wall.TopTexZ = MAX(bottomceilz1, bottomceilz2); + wall.TopTexZ = MAX(MAX(frontfloorz1, backfloorz1), MAX(frontfloorz2, backfloorz2)); wall.BottomTexZ = bottomTexZ; wall.UnpeggedCeil1 = topceilz1; wall.UnpeggedCeil2 = topceilz2; From 3b8570003acfd01e21bfc944d553f5752835b0c5 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 10 Jun 2017 11:16:58 +0200 Subject: [PATCH 03/10] - Improved softpoly sprite clipping --- src/polyrenderer/scene/poly_plane.cpp | 10 ++--- src/polyrenderer/scene/poly_plane.h | 2 +- src/polyrenderer/scene/poly_scene.cpp | 54 +++++++++++++++++++++------ src/polyrenderer/scene/poly_scene.h | 2 +- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 88ae14e10..ad471b4f0 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -33,7 +33,7 @@ EXTERN_CVAR(Int, r_3dfloors) -void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) +void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t ceilingSubsectorDepth, uint32_t floorSubsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals) { RenderPolyPlane plane; @@ -61,7 +61,7 @@ void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipP double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot); if (fakeHeight < viewpoint.Pos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot)) { - plane.Render3DFloor(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, false, fakeFloor); + plane.Render3DFloor(worldToClip, clipPlane, sub, floorSubsectorDepth, stencilValue, false, fakeFloor); } } @@ -82,13 +82,13 @@ void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipP double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot); if (fakeHeight > viewpoint.Pos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot)) { - plane.Render3DFloor(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, true, fakeFloor); + plane.Render3DFloor(worldToClip, clipPlane, sub, ceilingSubsectorDepth, stencilValue, true, fakeFloor); } } } - plane.Render(worldToClip, clipPlane, cull, sub, subsectorDepth, stencilValue, true, skyCeilingHeight, sectorPortals); - plane.Render(worldToClip, clipPlane, cull, sub, subsectorDepth, stencilValue, false, skyFloorHeight, sectorPortals); + plane.Render(worldToClip, clipPlane, cull, sub, ceilingSubsectorDepth, stencilValue, true, skyCeilingHeight, sectorPortals); + plane.Render(worldToClip, clipPlane, cull, sub, floorSubsectorDepth, stencilValue, false, skyFloorHeight, sectorPortals); } void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, F3DFloor *fakeFloor) diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index ce2192594..bb022aea9 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -30,7 +30,7 @@ class PolyCull; class RenderPolyPlane { public: - static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); + static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t ceilingSubsectorDepth, uint32_t floorSubsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals); private: struct UVTransform diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index ad0d88d34..2e5b04840 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -30,7 +30,6 @@ #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" -CVAR(Bool, r_debug_cull, 0, 0) EXTERN_CVAR(Int, r_portal_recursions) ///////////////////////////////////////////////////////////////////////////// @@ -92,19 +91,52 @@ void RenderPolyScene::ClearBuffers() void RenderPolyScene::RenderSectors() { - if (r_debug_cull) + int count = (int)Cull.PvsSectors.size(); + auto subsectors = Cull.PvsSectors.data(); + + int nextCeilingZChange = 0; + int nextFloorZChange = 0; + uint32_t ceilingSubsectorDepth = 0; + uint32_t floorSubsectorDepth = 0; + + for (int i = 0; i < count; i++) { - for (auto it = Cull.PvsSectors.rbegin(); it != Cull.PvsSectors.rend(); ++it) - RenderSubsector(*it); - } - else - { - for (auto it = Cull.PvsSectors.begin(); it != Cull.PvsSectors.end(); ++it) - RenderSubsector(*it); + // The software renderer only updates the clipping if the sector height changes. + // Find the subsector depths for when that happens. + if (i == nextCeilingZChange) + { + double z = subsectors[i]->sector->ceilingplane.Zat0(); + nextCeilingZChange++; + while (nextCeilingZChange < count) + { + double nextZ = subsectors[nextCeilingZChange]->sector->ceilingplane.Zat0(); + if (nextZ > z) + break; + z = nextZ; + nextCeilingZChange++; + } + ceilingSubsectorDepth = NextSubsectorDepth + nextCeilingZChange - i - 1; + } + if (i == nextFloorZChange) + { + double z = subsectors[i]->sector->floorplane.Zat0(); + nextFloorZChange++; + while (nextFloorZChange < count) + { + double nextZ = subsectors[nextFloorZChange]->sector->floorplane.Zat0(); + if (nextZ < z) + break; + z = nextZ; + nextFloorZChange++; + } + floorSubsectorDepth = NextSubsectorDepth + nextFloorZChange - i - 1; + } + + RenderSubsector(subsectors[i], ceilingSubsectorDepth, floorSubsectorDepth); } } -void RenderPolyScene::RenderSubsector(subsector_t *sub) +void RenderPolyScene::RenderSubsector(subsector_t *sub, uint32_t ceilingSubsectorDepth, uint32_t floorSubsectorDepth) { sector_t *frontsector = sub->sector; frontsector->MoreFlags |= SECF_DRAWN; @@ -147,7 +179,7 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub) if (sub->sector->CenterFloor() != sub->sector->CenterCeiling()) { - RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, Cull, sub, subsectorDepth, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); + RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, Cull, sub, ceilingSubsectorDepth, floorSubsectorDepth, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals); } if (mainBSP) diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index 8dafc949b..e4a1dff4f 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -86,7 +86,7 @@ private: void ClearBuffers(); void RenderPortals(int portalDepth); void RenderSectors(); - void RenderSubsector(subsector_t *sub); + void RenderSubsector(subsector_t *sub, uint32_t ceilingSubsectorDepth, uint32_t floorSubsectorDepth); void RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); void RenderSprite(AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); void RenderSprite(AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); From 8a300b99e9fec79a02831fcf387715330ac67f9b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 10 Jun 2017 15:50:44 +0300 Subject: [PATCH 04/10] Fixed interpolation points chaining Ambush flag cannot be used for marking visited points because HandleSpawnFlags() is no longer virtual See E1M4 from Rise Of The Wool Ball v1.1 as example of broken chain --- wadsrc/static/zscript/shared/movingcamera.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/shared/movingcamera.txt b/wadsrc/static/zscript/shared/movingcamera.txt index c6af13b42..6ed206d4b 100644 --- a/wadsrc/static/zscript/shared/movingcamera.txt +++ b/wadsrc/static/zscript/shared/movingcamera.txt @@ -45,6 +45,8 @@ class InterpolationPoint : Actor { InterpolationPoint Next; + + bool bVisited; default { @@ -66,9 +68,9 @@ class InterpolationPoint : Actor while (me != null) { - if (me.bAmbush) return; + if (me.bVisited) return; - me.bAmbush = true; + me.bVisited = true; let iterator = ActorIterator.Create(me.args[3] + 256 * me.args[4], "InterpolationPoint"); me.Next = InterpolationPoint(iterator.Next ()); From e0ece283aa9cb22e75c50adedaebb3bc4e147ff7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 10 Jun 2017 16:05:57 +0300 Subject: [PATCH 05/10] Added support for Rise Of The Wool Ball as IWAD --- wadsrc/static/iwadinfo.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index 6dc584a58..1c01f9f38 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -1,5 +1,16 @@ // Must be sorted in identification order (easiest to recognize first!) +IWad +{ + Name = "Rise Of The Wool Ball" + Autoname = "woolball.rotwb" + Game = "Doom" + Config = "WoolBall" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "E3M6", "B3DED", "WORLDMAP", "NUCLSKYM", "PLANETLE", "MEOWZEKI", "ZEKIINTR", "NOWAYBAC" + BannerColors = "32 54 43", "c6 dc d1" +} + IWad { Name = "Delaweare" @@ -432,4 +443,5 @@ Names "hacx2.wad" "square1.pk3" "delaweare.wad" + "rotwb.wad" } From c6b68df51d2812a104785fed656f2a5992c80b3f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 10 Jun 2017 10:35:48 -0400 Subject: [PATCH 06/10] - moved Rise of the Wall ball down in the detection list as far as it would safely go - since that was a directive when WadSmoosh was added. --- wadsrc/static/iwadinfo.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index 1c01f9f38..bd244253d 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -1,16 +1,5 @@ // Must be sorted in identification order (easiest to recognize first!) -IWad -{ - Name = "Rise Of The Wool Ball" - Autoname = "woolball.rotwb" - Game = "Doom" - Config = "WoolBall" - Mapinfo = "mapinfo/doom2.txt" - MustContain = "E3M6", "B3DED", "WORLDMAP", "NUCLSKYM", "PLANETLE", "MEOWZEKI", "ZEKIINTR", "NOWAYBAC" - BannerColors = "32 54 43", "c6 dc d1" -} - IWad { Name = "Delaweare" @@ -340,6 +329,17 @@ IWad BannerColors = "54 54 54", "a8 a8 a8" } +IWad +{ + Name = "Rise Of The Wool Ball" + Autoname = "woolball.rotwb" + Game = "Doom" + Config = "WoolBall" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "E3M6", "B3DED", "WORLDMAP", "NUCLSKYM", "PLANETLE", "MEOWZEKI", "ZEKIINTR", "NOWAYBAC" + BannerColors = "32 54 43", "c6 dc d1" +} + IWad { Name = "DOOM Shareware" From 54056252193ea0c9af3047666cff8532dd70f2d5 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 10 Jun 2017 10:57:45 -0400 Subject: [PATCH 07/10] - added Blade of Agony (Chapter 2) as an IWAD --- wadsrc/static/iwadinfo.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index bd244253d..37f947317 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -388,6 +388,16 @@ IWad Load = "nerve.wad" } +IWad +{ + Name = "WolfenDoom: Blade of Agony" + Game = "Doom" + BannerColors = "E30000", "E3E3E3" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "BOALIB", "C1M1", "Episode3", "MSPUB0" + Config = "BoA" +} + // Doom 2 must be last to be checked becaude MAP01 is its only requirement IWad { @@ -444,4 +454,5 @@ Names "square1.pk3" "delaweare.wad" "rotwb.wad" + "boa_c2.pk3" } From 8482653bbc800f4271b8c791a69bbd9c7243f19b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Jun 2017 08:52:04 +0200 Subject: [PATCH 08/10] Menu protection features - added a '-nocustommenu' command line options. This is for disabling user menus that intentionally or accidentally disable crucial menu features. - do not allow replacement of the main options menu. This menu contains engine-critical settings and may change at any time when new features get added. For now it will be the only one that gets protected but this may soon be extended to some of its submenus as well. --- src/menu/menudef.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 37ca2fc0a..33645dd66 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -54,6 +54,7 @@ #include "vm.h" #include "types.h" #include "gameconfigfile.h" +#include "m_argv.h" @@ -520,6 +521,12 @@ static bool ReplaceMenu(FScanner &sc, DMenuDescriptor *desc) DMenuDescriptor **pOld = MenuDescriptors.CheckKey(desc->mMenuName); if (pOld != nullptr && *pOld != nullptr) { + if (desc->mMenuName == NAME_Optionsmenu) + { + sc.ScriptMessage("Cannot replace the main options menu!"); + return true; + } + if (!CheckCompatible(desc, *pOld)) { sc.ScriptMessage("Tried to replace menu '%s' with a menu of different type", desc->mMenuName.GetChars()); @@ -980,6 +987,7 @@ void M_ParseMenuDefs() sc.ScriptError("Unknown keyword '%s'", sc.String); } } + if (Args->CheckParm("-nocustommenu")) break; } DefaultListMenuClass = DefaultListMenuSettings->mClass; DefaultListMenuSettings = nullptr; From ee3d73478a44e95a9ce335087368a11a40cb84ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Jun 2017 09:57:10 +0200 Subject: [PATCH 09/10] - added blanket protection to all submenus of OptionsMenu, except the player menu. Sadly, some mods are truly careless enough to modify the engine internal menus to add their own things, which should have no business whatsoever in there. As an example, in a D4D version released in May, the Display Options menu is showing quite a bit of outdated content and missing important settings. --- src/menu/menu.h | 1 + src/menu/menudef.cpp | 5 +-- wadsrc/static/menudef.txt | 70 +++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/menu/menu.h b/src/menu/menu.h index 7e985df6d..d5dd0d5c4 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -124,6 +124,7 @@ public: FName mMenuName; FString mNetgameMessage; PClass *mClass = nullptr; + bool mProtected = false; virtual size_t PropagateMark() { return 0; } }; diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 33645dd66..504fd9785 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -521,9 +521,9 @@ static bool ReplaceMenu(FScanner &sc, DMenuDescriptor *desc) DMenuDescriptor **pOld = MenuDescriptors.CheckKey(desc->mMenuName); if (pOld != nullptr && *pOld != nullptr) { - if (desc->mMenuName == NAME_Optionsmenu) + if ((*pOld)->mProtected) { - sc.ScriptMessage("Cannot replace the main options menu!"); + sc.ScriptMessage("Cannot replace protected menu %s!", desc->mMenuName.GetChars()); return true; } @@ -881,6 +881,7 @@ static void ParseOptionMenu(FScanner &sc) desc->mScrollTop = DefaultOptionMenuSettings->mScrollTop; desc->mIndent = DefaultOptionMenuSettings->mIndent; desc->mDontDim = DefaultOptionMenuSettings->mDontDim; + desc->mProtected = sc.CheckString("protected"); ParseOptionMenuBody(sc, desc); ReplaceMenu(sc, desc); diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 287430e5f..aec8a3925 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -335,7 +335,7 @@ DefaultOptionMenu } } -OptionMenu "OptionsMenu" +OptionMenu "OptionsMenu" protected { Title "$OPTMNU_TITLE" Submenu "$OPTMNU_CONTROLS", "CustomizeControls" @@ -422,7 +422,7 @@ ListMenu "PlayerMenu" // //------------------------------------------------------------------------------------------- -OptionMenu "CustomizeControls" +OptionMenu "CustomizeControls" protected { Title "$CNTRLMNU_TITLE" ScrollTop 2 @@ -536,7 +536,7 @@ OptionString "Cursors" "-", "$OPTSTR_SYSTEMCURSOR" } -OptionMenu "MouseOptions" +OptionMenu "MouseOptions" protected { Title "$MOUSEMNU_TITLE" Option "$MOUSEMNU_ENABLEMOUSE", "use_mouse", "YesNo" @@ -566,7 +566,7 @@ OptionMenu "MouseOptions" // //------------------------------------------------------------------------------------------- -OptionMenu "JoystickOptionsDefaults" +OptionMenu "JoystickOptionsDefaults" protected { Title "$JOYMNU_OPTIONS" Option "$JOYMNU_ENABLE", "use_joystick", "YesNo" @@ -585,7 +585,7 @@ OptionMenu "JoystickOptionsDefaults" // The rest will be filled in by joystick code if devices get connected or disconnected } -OptionMenu "JoystickOptions" +OptionMenu "JoystickOptions" protected { Title "$JOYMNU_OPTIONS" } @@ -606,7 +606,7 @@ OptionValue "Inversion" 1, "$OPTVAL_INVERTED" } -OptionMenu "JoystickConfigMenu" +OptionMenu "JoystickConfigMenu" protected { Title "$JOY_CONFIG" Class "JoystickConfigMenu" @@ -706,7 +706,7 @@ OptionValue GPUSwitch } -OptionMenu "TrueColorOptions" +OptionMenu "TrueColorOptions" protected { Title "$TCMNU_TITLE" StaticText " " @@ -716,7 +716,7 @@ OptionMenu "TrueColorOptions" Option "$TCMNU_MIPMAP", "r_mipmap", "OnOff" } -OptionMenu "SWROptions" +OptionMenu "SWROptions" protected { Title "$DSPLYMNU_SWOPT" Submenu "$DSPLYMNU_TCOPT", "TrueColorOptions" @@ -727,7 +727,7 @@ OptionMenu "SWROptions" Option "$DSPLYMNU_GZDFULLBRIGHT", "r_fullbrightignoresectorcolor", "OnOff" } -OptionMenu "VideoOptions" +OptionMenu "VideoOptions" protected { Title "$DSPLYMNU_TITLE" @@ -840,7 +840,7 @@ OptionValue ZDoomStrife 1.0, "$OPTVAL_STRIFE" } -OptionMenu "HUDOptions" +OptionMenu "HUDOptions" protected { Title "$HUDMNU_TITLE" Submenu "$HUDMNU_SCALEOPT", "ScalingOptions" @@ -864,7 +864,7 @@ OptionMenu "HUDOptions" Option "$HUDMNU_HAZARDFLASHES", "pf_hazard", "ZDoomStrife" } -OptionMenu "ScalingOptions" +OptionMenu "ScalingOptions" protected { Title "$SCALEMNU_TITLE" ScaleSlider "$HUDMNU_UISCALE", "uiscale", 0.0, 8.0, 1.0, "$SCALEMNU_ADAPT" @@ -925,7 +925,7 @@ OptionValue "AltHUDAmmoOrder" 1, "$OPTVAL_AMMOTEXTIMAGE" } -OptionMenu "AltHUDOptions" +OptionMenu "AltHUDOptions" protected { Title "$ALTHUDMNU_TITLE" //Indent 220 @@ -981,7 +981,7 @@ OptionValue dehopt 2, "$OPTVAL_ONLYLASTONE" } -OptionMenu "MiscOptions" +OptionMenu "MiscOptions" protected { Title "$MISCMNU_TITLE" //Indent 220 @@ -1072,7 +1072,7 @@ OptionValue MapTriggers 2, "$OPTVAL_ON" } -OptionMenu AutomapOptions +OptionMenu AutomapOptions protected { Title "$AUTOMAPMNU_TITLE" Option "$AUTOMAPMNU_COLORSET", "am_colorset", "MapColorTypes" @@ -1105,7 +1105,7 @@ OptionMenu AutomapOptions // //------------------------------------------------------------------------------------------- -OptionMenu MapControlsMenu +OptionMenu MapControlsMenu protected { Title "$MAPCNTRLMNU_TITLE" ScrollTop 2 @@ -1132,7 +1132,7 @@ OptionMenu MapControlsMenu // //------------------------------------------------------------------------------------------- -OptionMenu MapColorMenu +OptionMenu MapColorMenu protected { Title "$MAPCOLORMNU_TITLE" SafeCommand "$MAPCOLORMNU_DEFAULTMAPCOLORS", "am_restorecolors" @@ -1194,7 +1194,7 @@ OptionMenu MapColorMenu // //------------------------------------------------------------------------------------------- -OptionMenu ColorPickerMenu +OptionMenu ColorPickerMenu protected { Title "$MNU_COLORPICKER" // This menu will be created by the calling code @@ -1223,7 +1223,7 @@ OptionValue DevMessageLevels 4, "$OPTVAL_EVERYTHING" } -OptionMenu MessageOptions +OptionMenu MessageOptions protected { Title "$MSGMNU_TITLE" Option "$MSGMNU_SHOWMESSAGES", "show_messages", "OnOff" @@ -1252,7 +1252,7 @@ OptionMenu MessageOptions // //------------------------------------------------------------------------------------------- -OptionMenu ScoreboardOptions +OptionMenu ScoreboardOptions protected { Title "$SCRBRDMNU_TITLE" StaticText "$SCRBRDMNU_COOPERATIVE", 1 @@ -1307,7 +1307,7 @@ OptionValue JumpCrouchFreeLook } -OptionMenu GameplayOptions +OptionMenu GameplayOptions protected { Title "$GMPLYMNU_TITLE" //Indent 222 @@ -1392,7 +1392,7 @@ OptionValue CompatModes 4, "$OPTVAL_ZDOOM2063" } -OptionMenu "CompatibilityOptions" +OptionMenu "CompatibilityOptions" protected { Title "$CMPTMNU_TITLE" Option "$CMPTMNU_MODE", "compatmode", "CompatModes", "", 1 @@ -1583,7 +1583,7 @@ OptionString SoundBackendsOpenALOnly "null", "$OPTSTR_NOSOUND" } -OptionMenu OpenALSoundItems +OptionMenu OpenALSoundItems protected { Title "$OPENALMNU_TITLE" Option "$OPENALMNU_PLAYBACKDEVICE", "snd_aldevice", "ALDevices" @@ -1597,7 +1597,7 @@ OptionValue MidiDevices // filled in by the sound code } -OptionMenu SoundOptions +OptionMenu SoundOptions protected { Title "$SNDMNU_TITLE" Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 @@ -1646,7 +1646,7 @@ OptionValue OplCores 3, "$OPTVAL_NUKEDOPL3" } -OptionMenu AdvSoundOptions +OptionMenu AdvSoundOptions protected { Title "$ADVSNDMNU_TITLE" Option "$ADVSNDMNU_SAMPLERATE", "snd_samplerate", "SampleRates" @@ -1688,22 +1688,22 @@ OptionMenu AdvSoundOptions Option "$ADVSNDMNU_REVERB", "wildmidi_reverb", "OnOff" } -OptionMenu GusConfigMenu +OptionMenu GusConfigMenu protected { Title "$ADVSNDMNU_SELCONFIG" } -OptionMenu WildMidiConfigMenu +OptionMenu WildMidiConfigMenu protected { Title "$ADVSNDMNU_SELCONFIG" } -OptionMenu TimidityExeMenu +OptionMenu TimidityExeMenu protected { Title "$ADVSNDMNU_SELCONFIG" } -OptionMenu FluidPatchsetMenu +OptionMenu FluidPatchsetMenu protected { Title "$ADVSNDMNU_SELCONFIG" } @@ -1742,7 +1742,7 @@ OptionValue ModVolumeRamps } -OptionMenu ModReplayerOptions +OptionMenu ModReplayerOptions protected { Title "$MODMNU_TITLE" Slider "$MODMNU_MASTERVOLUME", "mod_dumb_mastervolume", 1, 16, 0.5, 1 @@ -1792,7 +1792,7 @@ OptionValue "GLCOCOA" 1, "$OPTVAL_GL" } -OptionMenu RendererMenu +OptionMenu RendererMenu protected { Title "$RNDMNU_TITLE" Option "$RNDMNU_RENDERER", "vid_renderer", "PolyDoom" @@ -1848,7 +1848,7 @@ OptionValue RatiosTFT -1, "$OPTVAL_ALL" } -OptionMenu VideoModeMenu +OptionMenu VideoModeMenu protected { Title "$VIDMNU_TITLE" @@ -1883,7 +1883,7 @@ OptionMenu VideoModeMenu * *=======================================*/ -OptionMenu NetworkOptions +OptionMenu NetworkOptions protected { Title "$NETMNU_TITLE" StaticText "$NETMNU_LOCALOPTIONS", 1 @@ -2108,7 +2108,7 @@ OptionValue VRMode 7, "$OPTVAL_QUADBUFFERED" } -OptionMenu "GLTextureGLOptions" +OptionMenu "GLTextureGLOptions" protected { Title "$GLTEXMNU_TITLE" Option "$GLTEXMNU_TEXENABLED", gl_texture, "YesNo" @@ -2125,7 +2125,7 @@ OptionMenu "GLTextureGLOptions" Option "$GLTEXMNU_SORTDRAWLIST", gl_sort_textures, "YesNo" } -OptionMenu "GLLightOptions" +OptionMenu "GLLightOptions" protected { Title "$GLLIGHTMNU_TITLE" Option "$TCMNU_DYNLIGHTS", "r_dynlights", "OnOff" @@ -2137,7 +2137,7 @@ OptionMenu "GLLightOptions" Option "$GLLIGHTMNU_LIGHTSHADOWMAP", gl_light_shadowmap, "YesNo" } -OptionMenu "OpenGLOptions" +OptionMenu "OpenGLOptions" protected { Title "$GLMNU_TITLE" Submenu "$GLMNU_TEXOPT", "GLTextureGLOptions" From f1ad42c4e5685136e44b6ab7478c1923997b05da Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Jun 2017 22:30:40 +0200 Subject: [PATCH 10/10] - instead of discarding protected menu replacements, try to merge them with the original version. Testing with Adventures of Square this mostly works, but it is clear that a list of old and deleted CVARs still needs to be added so that any items referring to those can be eliminated as well. Some stuff is still slipping through that refers to features which no longer exist. --- src/menu/menu.cpp | 2 +- src/menu/menu.h | 7 ++-- src/menu/menudef.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++-- src/namedef.h | 11 +++++++ 4 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 4ea76fe65..8893b5769 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -1121,7 +1121,7 @@ DEFINE_FIELD(FOptionMenuSettings, mLinespacing) struct IJoystickConfig; // These functions are used by dynamic menu creation. -DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v) +DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, int v) { auto c = PClass::FindClass("OptionMenuItemStaticText"); auto p = c->CreateNew(); diff --git a/src/menu/menu.h b/src/menu/menu.h index d5dd0d5c4..d5211421f 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -109,6 +109,7 @@ extern FSavegameManager savegameManager; class DMenu; extern DMenu *CurrentMenu; extern int MenuTime; +class DMenuItemBase; //============================================================================= // @@ -125,18 +126,17 @@ public: FString mNetgameMessage; PClass *mClass = nullptr; bool mProtected = false; + TArray mItems; virtual size_t PropagateMark() { return 0; } }; -class DMenuItemBase; class DListMenuDescriptor : public DMenuDescriptor { DECLARE_CLASS(DListMenuDescriptor, DMenuDescriptor) public: - TArray mItems; int mSelectedItem; double mSelectOfsX; double mSelectOfsY; @@ -187,7 +187,6 @@ class DOptionMenuDescriptor : public DMenuDescriptor DECLARE_CLASS(DOptionMenuDescriptor, DMenuDescriptor) public: - TArray mItems; FString mTitle; int mSelectedItem; int mDrawTop; @@ -350,7 +349,7 @@ void M_MarkMenus(); struct IJoystickConfig; -DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v); +DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, int v = -1); DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center); DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings); DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 504fd9785..e3184d316 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -516,6 +516,52 @@ static bool CheckCompatible(DMenuDescriptor *newd, DMenuDescriptor *oldd) return newd->mClass->IsDescendantOf(oldd->mClass); } +static int GetGroup(DMenuItemBase *desc) +{ + if (desc->IsKindOf(NAME_OptionMenuItemCommand)) return 2; + if (desc->IsKindOf(NAME_OptionMenuItemSubmenu)) return 1; + if (desc->IsKindOf(NAME_OptionMenuItemControlBase)) return 3; + if (desc->IsKindOf(NAME_OptionMenuItemOptionBase)) return 4; + if (desc->IsKindOf(NAME_OptionMenuSliderBase)) return 4; + if (desc->IsKindOf(NAME_OptionMenuFieldBase)) return 4; + if (desc->IsKindOf(NAME_OptionMenuItemColorPicker)) return 4; + if (desc->IsKindOf(NAME_OptionMenuItemStaticText)) return 5; + if (desc->IsKindOf(NAME_OptionMenuItemStaticTextSwitchable)) return 5; + return 0; +} + +static bool FindMatchingItem(DMenuItemBase *desc) +{ + int grp = GetGroup(desc); + if (grp == 0) return false; // no idea what this is. + if (grp == 5) return true; // static texts always match + + FName name = desc->mAction; + if (grp == 1) + { + // Check for presence of menu + auto menu = MenuDescriptors.CheckKey(name); + if (menu == nullptr) return true; + } + else if (grp == 4) + { + // Check for presence of CVAR and blacklist + auto cv = GetCVar(nullptr, name.GetChars()); + if (cv == nullptr) return true; + } + + MenuDescriptorList::Iterator it(MenuDescriptors); + MenuDescriptorList::Pair *pair; + while (it.NextPair(pair)) + { + for (auto it : pair->Value->mItems) + { + if (it->mAction == name && GetGroup(it) == grp) return true; + } + } + return false; +} + static bool ReplaceMenu(FScanner &sc, DMenuDescriptor *desc) { DMenuDescriptor **pOld = MenuDescriptors.CheckKey(desc->mMenuName); @@ -523,7 +569,32 @@ static bool ReplaceMenu(FScanner &sc, DMenuDescriptor *desc) { if ((*pOld)->mProtected) { - sc.ScriptMessage("Cannot replace protected menu %s!", desc->mMenuName.GetChars()); + // If this tries to replace an option menu with an option menu, let's append all new entries to the old menu. + // Otherwise bail out because for list menus it's not that simple. + if (desc->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)) || (*pOld)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor))) + { + sc.ScriptMessage("Cannot replace protected menu %s.", desc->mMenuName.GetChars()); + return true; + } + for (int i = desc->mItems.Size()-1; i >= 0; i--) + { + if (FindMatchingItem(desc->mItems[i])) + { + desc->mItems.Delete(i); + } + } + if (desc->mItems.Size() > 0) + { + auto sep = CreateOptionMenuItemStaticText("---------------", CR_YELLOW); + (*pOld)->mItems.Push(sep); + for (auto it : desc->mItems) + { + (*pOld)->mItems.Push(it); + } + desc->mItems.Clear(); + + sc.ScriptMessage("Merged %d items into %s", desc->mItems.Size(), desc->mMenuName.GetChars()); + } return true; } @@ -1400,9 +1471,9 @@ static void InitKeySections() for (unsigned i = 0; i < KeySections.Size(); i++) { FKeySection *sect = &KeySections[i]; - DMenuItemBase *item = CreateOptionMenuItemStaticText(" ", false); + DMenuItemBase *item = CreateOptionMenuItemStaticText(" "); menu->mItems.Push(item); - item = CreateOptionMenuItemStaticText(sect->mTitle, true); + item = CreateOptionMenuItemStaticText(sect->mTitle, 1); menu->mItems.Push(item); for (unsigned j = 0; j < sect->mActions.Size(); j++) { diff --git a/src/namedef.h b/src/namedef.h index cc3e65088..3d8fd684f 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -927,3 +927,14 @@ xx(MessageBoxMenu) xx(Both) xx(Physical) xx(Visual) + +xx(OptionMenuItemSubmenu) +xx(OptionMenuItemCommand) +xx(OptionMenuItemControlBase) +xx(OptionMenuItemOptionBase) +xx(OptionMenuSliderBase) +xx(OptionMenuFieldBase) +xx(OptionMenuItemColorPicker) +xx(OptionMenuItemStaticText) +xx(OptionMenuItemStaticTextSwitchable) +xx(mAction)