From d6346fb0c6987a5bad559fee5b4a61b5270070dd Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 3 Oct 2016 21:44:00 +0300 Subject: [PATCH 01/28] Fixed compilation with GCC or Clang --- src/g_shared/sbarinfo_commands.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 13c98d833..d105ab818 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1187,12 +1187,12 @@ class CommandDrawNumber : public CommandDrawString if (!(cvartype == CVAR_Bool || cvartype == CVAR_Int)) { - sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName); + sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName.GetChars()); } } else { - sc.ScriptMessage("CVar '%s' does not exist", cvarName); + sc.ScriptMessage("CVar '%s' does not exist", cvarName.GetChars()); } if (parenthesized) sc.MustGetToken(')'); From 5d99e7dafe28fbc92978c5b30ebcfed8013a4ff6 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 3 Oct 2016 22:13:33 +0300 Subject: [PATCH 02/28] Fixed compilation on platforms other than Windows --- src/g_shared/sbarinfo_commands.cpp | 4 ++-- src/gl/stereo3d/gl_interleaved3d.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 13c98d833..d105ab818 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1187,12 +1187,12 @@ class CommandDrawNumber : public CommandDrawString if (!(cvartype == CVAR_Bool || cvartype == CVAR_Int)) { - sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName); + sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName.GetChars()); } } else { - sc.ScriptMessage("CVar '%s' does not exist", cvarName); + sc.ScriptMessage("CVar '%s' does not exist", cvarName.GetChars()); } if (parenthesized) sc.MustGetToken(')'); diff --git a/src/gl/stereo3d/gl_interleaved3d.cpp b/src/gl/stereo3d/gl_interleaved3d.cpp index 329dec953..036a84b0b 100644 --- a/src/gl/stereo3d/gl_interleaved3d.cpp +++ b/src/gl/stereo3d/gl_interleaved3d.cpp @@ -104,10 +104,13 @@ void RowInterleaved3D::Present() const // Compute absolute offset from top of screen to top of current display window // because we need screen-relative, not window-relative, scan line parity int windowVOffset = 0; + +#ifdef _WIN32 if (! fullscreen) { I_SaveWindowedPos(); // update win_y CVAR windowVOffset = win_y; } +#endif // _WIN32 GLRenderer->mPresent3dRowShader->VerticalPixelOffset.Set( windowVOffset // fixme: vary with window location From 594b344be9a91bcd1da6bebb8b3047069554b8de Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Mon, 3 Oct 2016 22:00:49 -0500 Subject: [PATCH 03/28] Don't use MIN when clamping topclip. - This was fine with fixed point numbers, since they could never be outside of short range when converted to regular ints. With floating point numbers now, that condition no longer holds. --- src/r_things.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index a45a6826a..179ffec97 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2097,7 +2097,7 @@ void R_DrawSprite (vissprite_t *spr) { // seen below floor: clip top if (!spr->bIsVoxel && h > topclip) { - topclip = MIN (h, viewheight); + topclip = short(MIN(h, viewheight)); } hzt = MIN(hzt, hz); } @@ -2127,7 +2127,7 @@ void R_DrawSprite (vissprite_t *spr) { // seen in the middle: clip top if (!spr->bIsVoxel && h > topclip) { - topclip = MIN (h, viewheight); + topclip = MIN(h, viewheight); } hzt = MIN(hzt, hz); } @@ -2181,7 +2181,7 @@ void R_DrawSprite (vissprite_t *spr) int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); if (h > topclip) { - topclip = MIN(h, viewheight); + topclip = short(MIN(h, viewheight)); } } hzt = MIN(hzt, sclipTop); @@ -2204,7 +2204,7 @@ void R_DrawSprite (vissprite_t *spr) h = (centeryfrac - FixedMul (h-viewz, scale)) >> FRACBITS; if (h > topclip) { - topclip = MIN (h, viewheight); + topclip = short(MIN(h, viewheight)); } } #endif From 15cbf4bae66359a3ffe9eb2b20b30ca31df39768 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 4 Oct 2016 09:28:19 +0200 Subject: [PATCH 04/28] - fixed: DecoHandleRuntimeState must check all parent classes when trying to determine if the target is a valid state. It should also ensure that both the calling and target state belong to the same actor. Although unlikely it cannot be entirely ruled out that a bogus index randomly points to a seemingly valid state elsewhere. --- src/thingdef/thingdef_expression.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 700ac94bb..c2b2d25e6 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4956,6 +4956,25 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) return this; } +static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int index) +{ + PClassActor *cls = stateowner->GetClass(); + + while (cls != RUNTIME_CLASS(AActor)) + { + // both calling and target state need to belong to the same class. + if (cls->OwnsState(stateinfo->mCallingState)) + { + return cls->OwnsState(stateinfo->mCallingState + index); + } + + // We can safely assume the ParentClass is of type PClassActor + // since we stop when we see the Actor base class. + cls = static_cast(cls->ParentClass); + } + return false; +} + static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) { PARAM_PROLOGUE; @@ -4963,7 +4982,7 @@ static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numpa PARAM_POINTER(stateinfo, FStateParamInfo); PARAM_INT(index); - if (index == 0 || !stateowner->GetClass()->OwnsState(stateinfo->mCallingState + index)) + if (index == 0 || !VerifyJumpTarget(stateowner, stateinfo, index)) { // Null is returned if the location was invalid which means that no jump will be performed // if used as return value From 0e9f808c8a3000b376aa607a987a8d96a969a45f Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 4 Oct 2016 10:04:33 -0500 Subject: [PATCH 05/28] Fixed: FLATSPRITES were drawn backwards. --- src/gl/scene/gl_sprite.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index ab88f2f9c..e9748fba6 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -138,10 +138,10 @@ void GLSprite::CalculateVertices(FVector3 *v) mat.Rotate(0, 1, 0, - actor->Angles.Roll.Degrees); mat.Translate(-x, -z, -y); } - v[0] = mat * FVector3(x1, z, y2); - v[1] = mat * FVector3(x2, z, y2); - v[2] = mat * FVector3(x1, z, y1); - v[3] = mat * FVector3(x2, z, y1); + v[0] = mat * FVector3(x2, z, y2); + v[1] = mat * FVector3(x1, z, y2); + v[2] = mat * FVector3(x2, z, y1); + v[3] = mat * FVector3(x1, z, y1); return; } From 2d320a2e86ba63b438c6423bc80035415e22f26a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 09:59:19 +0200 Subject: [PATCH 06/28] - added an option to disable the pickup screen flash. --- src/g_shared/a_pickups.cpp | 4 +++- wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e80e54818..d24f114bd 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -23,6 +23,8 @@ #include "serializer.h" static FRandom pr_restore ("RestorePos"); +CVAR(Bool, r_pickupflash, true, CVAR_ARCHIVE); + IMPLEMENT_CLASS(PClassInventory) @@ -1089,7 +1091,7 @@ void AInventory::Touch (AActor *toucher) if (player != NULL) { PlayPickupSound (player->mo); - if (!(ItemFlags & IF_NOSCREENFLASH)) + if (!(ItemFlags & IF_NOSCREENFLASH) && r_pickupflash) { player->bonuscount = BONUSADD; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 4839e1146..87ecb865b 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1803,6 +1803,7 @@ DSPLYMNU_DIMCOLOR = "Dim color"; DSPLYMNU_MOVEBOB = "View bob amount while moving"; DSPLYMNU_STILLBOB = "View bob amount while not moving"; DSPLYMNU_BOBSPEED = "Weapon bob speed"; +DSPLYMNU_PIFLASH = "Show pickup screen flash"; // HUD Options HUDMNU_TITLE = "HUD Options"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 0bcbd3af7..17eb80666 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -675,6 +675,7 @@ OptionMenu "VideoOptions" Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 + Option "$DSPLYMNU_PIFLASH", "r_pickupflash", "OnOff" Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes" From 5b350dcdd502b5c744ec67ebde7e7d2279033e86 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 16:27:12 +0200 Subject: [PATCH 07/28] - gave Boom's point pusher and puller things the NOCLIP flag so that they won't get moved around by scrollers. --- wadsrc/static/actors/shared/sharedmisc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/actors/shared/sharedmisc.txt b/wadsrc/static/actors/shared/sharedmisc.txt index bfe7d5519..fe5ac72d8 100644 --- a/wadsrc/static/actors/shared/sharedmisc.txt +++ b/wadsrc/static/actors/shared/sharedmisc.txt @@ -75,12 +75,14 @@ ACTOR PointPusher { +NOBLOCKMAP +INVISIBLE + +NOCLIP } ACTOR PointPuller { +NOBLOCKMAP +INVISIBLE + +NOCLIP } // Bloody gibs ------------------------------------------------------------- From aeb5377821df5914d2d279c43dedf57190f4e6bb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 16:45:12 +0200 Subject: [PATCH 08/28] - do not generate SYSEX events when playing MIDIs through FMod, because there has been a report that it doesn't work correctly. --- src/sound/music_hmi_midiout.cpp | 2 +- src/sound/music_smf_midiout.cpp | 2 +- src/sound/music_xmi_midiout.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/music_hmi_midiout.cpp b/src/sound/music_hmi_midiout.cpp index 21790784c..7d9d36926 100644 --- a/src/sound/music_hmi_midiout.cpp +++ b/src/sound/music_hmi_midiout.cpp @@ -657,7 +657,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdi if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = ReadVarLen(track); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/music_smf_midiout.cpp b/src/sound/music_smf_midiout.cpp index ffcbc9f62..a045998a8 100644 --- a/src/sound/music_smf_midiout.cpp +++ b/src/sound/music_smf_midiout.cpp @@ -598,7 +598,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->TrackP += len; } diff --git a/src/sound/music_xmi_midiout.cpp b/src/sound/music_xmi_midiout.cpp index a9cbcd2c6..b56e8f6f8 100644 --- a/src/sound/music_xmi_midiout.cpp +++ b/src/sound/music_xmi_midiout.cpp @@ -528,7 +528,7 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay, ptrdif if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) { len = track->ReadVarLen(); - if (len >= (MAX_EVENTS-1)*3*4) + if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS) { // This message will never fit. Throw it away. track->EventP += len; } From 59d5b42abf1e716027c0fdf10d076912e0ce1454 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 5 Oct 2016 19:02:53 +0200 Subject: [PATCH 09/28] - fixed: G_UnsnapshotLevel should abort with an error if it cannot read the savegame. - fixed: The exception handler in G_DoLoadGame needs to rethrow the exception it receives. --- src/g_game.cpp | 2 +- src/g_level.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 629202ea5..48bda24f5 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1999,7 +1999,7 @@ void G_DoLoadGame () { // delete the resource file if anything goes wrong in here. if (resfile != nullptr) delete resfile; - return; + throw; } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 90b31138d..119cde378 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1512,7 +1512,11 @@ void G_UnSnapshotLevel (bool hubLoad) if (level.info->isValid()) { FSerializer arc; - if (!arc.OpenReader(&level.info->Snapshot)) return; + if (!arc.OpenReader(&level.info->Snapshot)) + { + I_Error("Failed to load savegame"); + return; + } G_SerializeLevel (arc, hubLoad); level.FromSnapshot = true; From c56d2eecb005c6bbb8000c70cedc6f537123ba57 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 08:50:46 +0200 Subject: [PATCH 10/28] - rewrote AActor::DestroyAllInventory so that it clears the item's link to its owner and the owner's inventory list before destroying them. There have been reports about crashes in here with Linux that point to some of the code that gets called here doing unwanted things on the owner, so with these links cleared that should no longer be possible. --- src/p_mobj.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 496f52e86..022504919 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -685,11 +685,30 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate void AActor::DestroyAllInventory () { - while (Inventory != NULL) + AInventory *inv = Inventory; + if (inv != nullptr) { - AInventory *item = Inventory; - item->Destroy (); - assert (item != Inventory); + TArray toDelete; + + // Delete the list in a two stage approach. + // This is necessary because an item may destroy another item (e.g. sister weapons) + // which would break the list and leave parts of it undestroyed, maybe doing bad things later. + while (inv != nullptr) + { + toDelete.Push(inv); + AInventory *item = inv->Inventory; + inv->Inventory = nullptr; + inv->Owner = nullptr; + inv = item; + } + for (auto p : toDelete) + { + // the item may already have been deleted by another one, so check this here to avoid problems. + if (!(p->ObjectFlags & OF_EuthanizeMe)) + { + p->Destroy(); + } + } } } From d7bb5bb41ed8e853095d5207b74a2079589c716e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 12:08:38 +0200 Subject: [PATCH 11/28] - fixed: ZCC_OpInfoType::FindBestProto was missing checks for exact match of the required conversion before testing if it is a F32->F64 conversion. Of course, since 0 means that there is no conversion it also means that there is no data that could be checked. --- src/zscript/zcc_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index 0cd399d64..e1a091b18 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/zscript/zcc_expr.cpp @@ -162,11 +162,11 @@ ZCC_OpProto *ZCC_OpInfoType::FindBestProto( // [[float32 (op) int]] will choose the integer version instead of the floating point // version, which we do not want. int test_dist1 = dist1, test_dist2 = dist2; - if (routes[0][cur_route1][0]->ConvertConstant == FtoD) + if (test_dist1 > 0 && routes[0][cur_route1][0]->ConvertConstant == FtoD) { test_dist1--; } - if (routes[1][cur_route2][0]->ConvertConstant == FtoD) + if (test_dist2 > 0 && routes[1][cur_route2][0]->ConvertConstant == FtoD) { test_dist2--; } From 99c4d03ad4b3151375edb8b015bd25021c2e3193 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 6 Oct 2016 21:20:49 +0200 Subject: [PATCH 12/28] - fixed: DCeiling's main constructor could leave some fields uninitialized. --- src/p_ceiling.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 32e5d62be..e90dd2096 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -214,6 +214,12 @@ DCeiling::DCeiling (sector_t *sec, double speed1, double speed2, int silent) m_Speed = m_Speed1 = speed1; m_Speed2 = speed2; m_Silent = silent; + m_BottomHeight = 0; + m_TopHeight = 0; + m_Direction = 0; + m_Texture = FNullTextureID(); + m_Tag = 0; + m_OldDirection = 0; } //============================================================================ From 02f66fa34e2bdb63ca1ba740c5b35b7388550120 Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Thu, 6 Oct 2016 20:01:20 -0400 Subject: [PATCH 13/28] - Backported blood_fade_scalar from Skulltag - Added new pickup_fade_scalar which works the same way for pickups - Default for blood_fade_scalar is 1.0 instead of 0.5 from Skulltag. --- src/v_blend.cpp | 11 +++++++++-- wadsrc/static/menudef.txt | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/v_blend.cpp b/src/v_blend.cpp index e1552105f..c13ed547c 100644 --- a/src/v_blend.cpp +++ b/src/v_blend.cpp @@ -52,7 +52,8 @@ #include "v_palette.h" #include "d_player.h" - +CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0 +CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups // [RH] Amount of red flash for up to 114 damage points. Calculated by hand // using a logarithmic scale and my trusty HP48G. @@ -113,6 +114,9 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (CPlayer->bonuscount) { cnt = CPlayer->bonuscount << 3; + + // [SP] Allow player to tone down intensity of pickup flash. + cnt = (int)( cnt * pickup_fade_scalar ); V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f, BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend); @@ -124,7 +128,10 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (painFlash.a != 0) { cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)]; - + + // [BC] Allow users to tone down the intensity of the blood on the screen. + cnt = (int)( cnt * blood_fade_scalar ); + if (cnt) { if (cnt > maxpainblend) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 17eb80666..95eedaf25 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -660,6 +660,8 @@ OptionMenu "VideoOptions" Slider "$DSPLYMNU_BRIGHTNESS", "Gamma", 0.75, 3.0, 0.05, 2 Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" + Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 1 + Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 1 Option "$DSPLYMNU_COLUMNMETHOD", "r_columnmethod", "ColumnMethods" StaticText " " @@ -692,6 +694,7 @@ OptionMenu "VideoOptions" Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2 + } //------------------------------------------------------------------------------------------- From 3ccc85876c342a565fe74cd711ff592f5a4bea0c Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Thu, 6 Oct 2016 20:05:30 -0400 Subject: [PATCH 14/28] - Forgot to add language entries. --- wadsrc/static/language.enu | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 87ecb865b..dafd80617 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1782,6 +1782,8 @@ DSPLYMNU_CAPFPS = "Rendering Interpolation"; DSPLYMNU_COLUMNMETHOD = "Column render mode"; DSPLYMNU_WIPETYPE = "Screen wipe style"; DSPLYMNU_SHOWENDOOM = "Show ENDOOM screen"; +DSPLYMNU_BLOODFADE = "Blood Flash Intensity"; +DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity"; DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used DSPLYMNU_STRETCHSKY = "Stretch short skies"; From ee66d220348f32d8c1baa2db753c2690f51017ef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 08:46:06 +0200 Subject: [PATCH 15/28] Revert "- added an option to disable the pickup screen flash." This reverts commit 2d320a2e86ba63b438c6423bc80035415e22f26a. The feature has been superseded by pickup_fade_scalar and is no longer needed. --- src/g_shared/a_pickups.cpp | 4 +--- wadsrc/static/language.enu | 1 - wadsrc/static/menudef.txt | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index d24f114bd..e80e54818 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -23,8 +23,6 @@ #include "serializer.h" static FRandom pr_restore ("RestorePos"); -CVAR(Bool, r_pickupflash, true, CVAR_ARCHIVE); - IMPLEMENT_CLASS(PClassInventory) @@ -1091,7 +1089,7 @@ void AInventory::Touch (AActor *toucher) if (player != NULL) { PlayPickupSound (player->mo); - if (!(ItemFlags & IF_NOSCREENFLASH) && r_pickupflash) + if (!(ItemFlags & IF_NOSCREENFLASH)) { player->bonuscount = BONUSADD; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index dafd80617..50d14ab75 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1805,7 +1805,6 @@ DSPLYMNU_DIMCOLOR = "Dim color"; DSPLYMNU_MOVEBOB = "View bob amount while moving"; DSPLYMNU_STILLBOB = "View bob amount while not moving"; DSPLYMNU_BOBSPEED = "Weapon bob speed"; -DSPLYMNU_PIFLASH = "Show pickup screen flash"; // HUD Options HUDMNU_TITLE = "HUD Options"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 95eedaf25..cd004bb0d 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -677,7 +677,6 @@ OptionMenu "VideoOptions" Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 - Option "$DSPLYMNU_PIFLASH", "r_pickupflash", "OnOff" Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes" From 06ca41f8b51572717fd7b78a907bb8b9390b0b35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 13:59:29 +0200 Subject: [PATCH 16/28] - do not declare PNamedType::Outer as DObject. Ultimately we may have to get a fully qualified name out of this, so Outer should be a type that can handle this feature. The new class for this is currently used as base for PType and PSymbol so that PNamedType inherits from it and maybe later a namespace symbol can, too. --- src/dobjtype.cpp | 23 +++++++++++++++++++---- src/dobjtype.h | 37 +++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 9693da137..c3d0702f3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -670,6 +670,20 @@ void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = TypeName; } +//========================================================================== +// +// PNamedType :: QualifiedName +// +//========================================================================== + +FString PNamedType::QualifiedName() const +{ + FString out; + if (Outer != nullptr) out = Outer->QualifiedName(); + out << "::" << TypeName; + return out; +} + /* PInt *******************************************************************/ IMPLEMENT_CLASS(PInt) @@ -1752,7 +1766,7 @@ PEnum::PEnum() // //========================================================================== -PEnum::PEnum(FName name, DObject *outer) +PEnum::PEnum(FName name, PTypeBase *outer) : PNamedType(name, outer), ValueType(NULL) { } @@ -1766,7 +1780,7 @@ PEnum::PEnum(FName name, DObject *outer) // //========================================================================== -PEnum *NewEnum(FName name, DObject *outer) +PEnum *NewEnum(FName name, PTypeBase *outer) { size_t bucket; PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket); @@ -2149,7 +2163,7 @@ PStruct::PStruct() // //========================================================================== -PStruct::PStruct(FName name, DObject *outer) +PStruct::PStruct(FName name, PTypeBase *outer) : PNamedType(name, outer) { } @@ -2310,7 +2324,7 @@ size_t PStruct::PropagateMark() // //========================================================================== -PStruct *NewStruct(FName name, DObject *outer) +PStruct *NewStruct(FName name, PTypeBase *outer) { size_t bucket; PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket); @@ -3360,6 +3374,7 @@ CCMD(typetable) // Symbol tables ------------------------------------------------------------ +IMPLEMENT_ABSTRACT_CLASS(PTypeBase); IMPLEMENT_ABSTRACT_CLASS(PSymbol); IMPLEMENT_CLASS(PSymbolConst); IMPLEMENT_CLASS(PSymbolConstNumeric); diff --git a/src/dobjtype.h b/src/dobjtype.h index 62cfa6753..338c51f98 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -22,12 +22,28 @@ typedef std::pair FTypeAndOffset; // Symbol information ------------------------------------------------------- -class PSymbol : public DObject +class PTypeBase : public DObject { - DECLARE_ABSTRACT_CLASS(PSymbol, DObject); + DECLARE_ABSTRACT_CLASS(PTypeBase, DObject) + +public: + virtual FString QualifiedName() const + { + return ""; + } +}; + +class PSymbol : public PTypeBase +{ + DECLARE_ABSTRACT_CLASS(PSymbol, PTypeBase); public: virtual ~PSymbol(); + virtual FString QualifiedName() const + { + return SymbolName.GetChars(); + } + FName SymbolName; protected: @@ -153,13 +169,13 @@ extern PSymbolTable GlobalSymbols; struct ZCC_ExprConstant; class PClassType; -class PType : public DObject +class PType : public PTypeBase { //DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType); // We need to unravel the _WITH_META macro, since PClassType isn't defined yet, // and we can't define it until we've defined PClass. But we can't define that // without defining PType. - DECLARE_ABSTRACT_CLASS(PType, DObject) + DECLARE_ABSTRACT_CLASS(PType, PTypeBase) HAS_OBJECT_POINTERS; protected: enum { MetaClassNum = CLASSREG_PClassType }; @@ -332,14 +348,15 @@ class PNamedType : public PCompoundType DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType); HAS_OBJECT_POINTERS; public: - DObject *Outer; // object this type is contained within + PTypeBase *Outer; // object this type is contained within FName TypeName; // this type's name PNamedType() : Outer(NULL) {} - PNamedType(FName name, DObject *outer) : Outer(outer), TypeName(name) {} + PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {} virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + virtual FString QualifiedName() const; }; // Basic types -------------------------------------------------------------- @@ -533,7 +550,7 @@ class PEnum : public PNamedType DECLARE_CLASS(PEnum, PNamedType); HAS_OBJECT_POINTERS; public: - PEnum(FName name, DObject *outer); + PEnum(FName name, PTypeBase *outer); PType *ValueType; TMap Values; @@ -610,7 +627,7 @@ class PStruct : public PNamedType { DECLARE_CLASS(PStruct, PNamedType); public: - PStruct(FName name, DObject *outer); + PStruct(FName name, PTypeBase *outer); TArray Fields; @@ -822,8 +839,8 @@ PDynArray *NewDynArray(PType *type); PPointer *NewPointer(PType *type); PClassPointer *NewClassPointer(PClass *restrict); PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname); -PEnum *NewEnum(FName name, DObject *outer); -PStruct *NewStruct(FName name, DObject *outer); +PEnum *NewEnum(FName name, PTypeBase *outer); +PStruct *NewStruct(FName name, PTypeBase *outer); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); // Built-in types ----------------------------------------------------------- From d819aafcf309dcce2caff2215a7c8b108f9abc27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 7 Oct 2016 15:28:25 +0200 Subject: [PATCH 17/28] - changed handling of duplicate classes in DECORATE. Instead of replacing the original, the second class will get renamed now, using the originating file as an identifier. In the vast majority of cases this should do exactly what is needed: Create an unconflicting second class that can coexist with the original. Unless the class is used by name this should eliminate all problems with this, but so far I haven't seen anything that used them by name. This is choosing the lesser of two evils. While some mod out there may get broken, the old setup meant that the first class of a given name could not be written out to a savegame because it was not retrievable when loading it back. --- src/d_dehacked.cpp | 15 ++++++++--- src/dobjtype.cpp | 25 ++++++++++-------- src/thingdef/olddecorations.cpp | 3 ++- src/thingdef/thingdef.cpp | 45 +++++++++++++++++++++++++++++++-- 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 9e068b596..dd71fdf75 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2985,9 +2985,11 @@ static bool LoadDehSupp () void FinishDehPatch () { unsigned int touchedIndex; + unsigned int nameindex = 0; for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex) { + PClassActor *subclass; PClassActor *type = TouchedActors[touchedIndex]; AActor *defaults1 = GetDefaultByType (type); if (!(defaults1->flags & MF_SPECIAL)) @@ -2997,9 +2999,16 @@ void FinishDehPatch () // Create a new class that will serve as the actual pickup char typeNameBuilder[32]; - mysnprintf (typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", touchedIndex); - PClassActor *subclass = static_cast(RUNTIME_CLASS(ADehackedPickup)-> - CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup))); + // + do + { + // Retry until we find a free name. This is unlikely to happen but not impossible. + mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++); + subclass = static_cast(RUNTIME_CLASS(ADehackedPickup)-> + CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup))); + } + while (subclass == nullptr); + AActor *defaults2 = GetDefaultByType (subclass); memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c3d0702f3..37ff26fe3 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2861,10 +2861,7 @@ void PClass::InsertIntoHash () found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket); if (found != NULL) { // This type has already been inserted - // ... but there is no need whatsoever to make it a fatal error! - if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); - else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); - TypeTable.ReplaceType(this, found, bucket); + I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); } else { @@ -3029,15 +3026,23 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) PClass *existclass = static_cast(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket)); // This is a placeholder so fill it in - if (existclass != NULL && (existclass->Size == TentativeClass)) + if (existclass != nullptr) { - type = const_cast(existclass); - if (!IsDescendantOf(type->ParentClass)) + if (existclass->Size == TentativeClass) { - I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + type = const_cast(existclass); + if (!IsDescendantOf(type->ParentClass)) + { + I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + } + DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars()); + notnew = true; + } + else + { + // a different class with the same name already exists. Let the calling code deal with this. + return nullptr; } - DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars()); - notnew = true; } else { diff --git a/src/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp index 3ea0c4788..9afbfc965 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/thingdef/olddecorations.cpp @@ -140,6 +140,7 @@ DEFINE_CLASS_PROPERTY(respawns, 0, FakeInventory) // Reads an old style decoration object // //========================================================================== +PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName); void ParseOldDecoration(FScanner &sc, EDefinitionType def) { @@ -154,7 +155,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) sc.MustGetString(); typeName = FName(sc.String); - type = static_cast(parent->CreateDerivedClass (typeName, parent->Size)); + type = DecoDerivedClass(FScriptPosition(sc), parent, typeName); ResetBaggage(&bag, parent); bag.Info = type; #ifdef _DEBUG diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 32d4f1ce0..41e1e9542 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -68,13 +68,44 @@ TDeletingArray ActorDamageFuncs; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); -void ParseDecorate (FScanner &sc); +void ParseDecorate(FScanner &ctx); // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; +EXTERN_CVAR(Bool, strictdecorate); + +PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName) +{ + PClassActor *type = static_cast(parent->CreateDerivedClass(typeName, parent->Size)); + if (type == nullptr) + { + FString newname = typeName.GetChars(); + FString sourcefile = sc.FileName; + + sourcefile.Substitute(":", "@"); + newname << '@' << sourcefile; + if (strictdecorate) + { + sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars()); + } + else + { + // Due to backwards compatibility issues this cannot be an unconditional error. + sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars()); + } + type = static_cast(parent->CreateDerivedClass(newname, parent->Size)); + if (type == nullptr) + { + // This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless. + sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars()); + } + } + return type; +} //========================================================================== // // Starts a new actor definition @@ -141,7 +172,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par else { create: - ti = static_cast(parent->CreateDerivedClass (typeName, parent->Size)); + ti = DecoDerivedClass(sc, parent, typeName); } ti->Replacee = ti->Replacement = NULL; @@ -428,6 +459,16 @@ void LoadActors () while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) { FScanner sc(lump); + + if (Wads.GetLumpFile(lump) == 0) + { + // define namespace 'zdoom' + } + else + { + // use namespace 'zdoom' + } + ParseDecorate (sc); } FinishThingdef(); From 9a72ef1bf1c985e34f21c3fe5817b37e82b0b65c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 8 Oct 2016 15:47:16 +0300 Subject: [PATCH 18/28] Added detection of current macOS version --- src/posix/cocoa/i_main.mm | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index bbe344809..d8f0e74cf 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -130,6 +130,53 @@ void Mac_I_FatalError(const char* const message) } +static void I_DetectOS() +{ + SInt32 majorVersion = 0; + Gestalt(gestaltSystemVersionMajor, &majorVersion); + + SInt32 minorVersion = 0; + Gestalt(gestaltSystemVersionMinor, &minorVersion); + + SInt32 bugFixVersion = 0; + Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); + + const char* name = "Unknown version"; + + if (10 == majorVersion) switch (minorVersion) + { + case 4: name = "Mac OS X Tiger"; break; + case 5: name = "Mac OS X Leopard"; break; + case 6: name = "Mac OS X Snow Leopard"; break; + case 7: name = "Mac OS X Lion"; break; + case 8: name = "OS X Mountain Lion"; break; + case 9: name = "OS X Mavericks"; break; + case 10: name = "OS X Yosemite"; break; + case 11: name = "OS X El Capitan"; break; + case 12: name = "macOS Sierra"; break; + } + + char release[16] = {}; + size_t size = sizeof release - 1; + sysctlbyname("kern.osversion", release, &size, nullptr, 0); + + const char* const architecture = +#ifdef __i386__ + "32-bit Intel"; +#elif defined __x86_64__ + "64-bit Intel"; +#elif defined __ppc__ + "32-bit PowerPC"; +#elif defined __ppc64__ + "64-bit PowerPC"; +#else + "Unknown"; +#endif + + Printf("OS: %s %d.%d.%d (%s) %s\n", name, majorVersion, minorVersion, bugFixVersion, release, architecture); +} + + DArgs* Args; // command line arguments @@ -165,6 +212,8 @@ void OriginalMainTry(int argc, char** argv) progdir += "/"; C_InitConsole(80 * 8, 25 * 8, false); + + I_DetectOS(); D_DoomMain(); } From 779e6acb7bed8b0fa265c85fc63e28d039808512 Mon Sep 17 00:00:00 2001 From: Christopher Bruns Date: Sun, 9 Oct 2016 13:05:50 -0400 Subject: [PATCH 19/28] Create "final" two non-VR 3D modes: Column-interleaved and checkerboard. --- src/gl/renderer/gl_renderbuffers.h | 1 - src/gl/renderer/gl_renderer.cpp | 6 + src/gl/renderer/gl_renderer.h | 4 + src/gl/shaders/gl_present3dRowshader.cpp | 40 ++++-- src/gl/shaders/gl_present3dRowshader.h | 33 +++-- src/gl/shaders/gl_presentshader.cpp | 25 ++-- src/gl/shaders/gl_presentshader.h | 16 ++- src/gl/stereo3d/gl_interleaved3d.cpp | 133 +++++++++++++++--- src/gl/stereo3d/gl_interleaved3d.h | 21 ++- src/gl/stereo3d/gl_stereo_cvars.cpp | 6 + wadsrc/static/language.enu | 2 + wadsrc/static/menudef.zz | 2 + .../static/shaders/glsl/present_checker3d.fp | 37 +++++ .../static/shaders/glsl/present_column3d.fp | 35 +++++ wadsrc/static/shaders/glsl/present_row3d.fp | 6 +- 15 files changed, 300 insertions(+), 67 deletions(-) create mode 100644 wadsrc/static/shaders/glsl/present_checker3d.fp create mode 100644 wadsrc/static/shaders/glsl/present_column3d.fp diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 5fe05f5ac..4477718f4 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -2,7 +2,6 @@ #define __GL_RENDERBUFFERS_H #include "gl/shaders/gl_shader.h" -#include "gl/renderer/gl_renderer.h" class FGLBloomTextureLevel { diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index be1b96f15..0ffafef49 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -105,6 +105,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mTonemapPalette = nullptr; mBuffers = nullptr; mPresentShader = nullptr; + mPresent3dCheckerShader = nullptr; + mPresent3dColumnShader = nullptr; mPresent3dRowShader = nullptr; mBloomExtractShader = nullptr; mBloomCombineShader = nullptr; @@ -139,6 +141,8 @@ void FGLRenderer::Initialize(int width, int height) mFXAAShader = new FFXAAShader; mFXAALumaShader = new FFXAALumaShader; mPresentShader = new FPresentShader(); + mPresent3dCheckerShader = new FPresent3DCheckerShader(); + mPresent3dColumnShader = new FPresent3DColumnShader(); mPresent3dRowShader = new FPresent3DRowShader(); m2DDrawer = new F2DDrawer; @@ -192,6 +196,8 @@ FGLRenderer::~FGLRenderer() } if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; + if (mPresent3dCheckerShader) delete mPresent3dCheckerShader; + if (mPresent3dColumnShader) delete mPresent3dColumnShader; if (mPresent3dRowShader) delete mPresent3dRowShader; if (mBloomExtractShader) delete mBloomExtractShader; if (mBloomCombineShader) delete mBloomCombineShader; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 65e31c52f..19bc93af0 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -31,6 +31,8 @@ class FLensShader; class FFXAALumaShader; class FFXAAShader; class FPresentShader; +class FPresent3DCheckerShader; +class FPresent3DColumnShader; class FPresent3DRowShader; class F2DDrawer; class FHardwareTexture; @@ -109,6 +111,8 @@ public: FFXAALumaShader *mFXAALumaShader; FFXAAShader *mFXAAShader; FPresentShader *mPresentShader; + FPresent3DCheckerShader *mPresent3dCheckerShader; + FPresent3DColumnShader *mPresent3dColumnShader; FPresent3DRowShader *mPresent3dRowShader; FTexture *gllight; diff --git a/src/gl/shaders/gl_present3dRowshader.cpp b/src/gl/shaders/gl_present3dRowshader.cpp index 607e4ede6..d8369a3b6 100644 --- a/src/gl/shaders/gl_present3dRowshader.cpp +++ b/src/gl/shaders/gl_present3dRowshader.cpp @@ -38,23 +38,37 @@ #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_present3dRowshader.h" +void FPresentStereoShaderBase::Init(const char * vtx_shader_name, const char * program_name) +{ + FPresentShaderBase::Init(vtx_shader_name, program_name); + LeftEyeTexture.Init(mShader, "LeftEyeTexture"); + RightEyeTexture.Init(mShader, "RightEyeTexture"); + WindowPositionParity.Init(mShader, "WindowPositionParity"); +} + +void FPresent3DCheckerShader::Bind() +{ + if (!mShader) + { + Init("shaders/glsl/present_checker3d.fp", "shaders/glsl/presentChecker3d"); + } + mShader.Bind(); +} + +void FPresent3DColumnShader::Bind() +{ + if (!mShader) + { + Init("shaders/glsl/present_column3d.fp", "shaders/glsl/presentColumn3d"); + } + mShader.Bind(); +} + void FPresent3DRowShader::Bind() { if (!mShader) { - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present_row3d.fp", "", 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/presentRow3d"); - mShader.SetAttribLocation(0, "PositionInProjection"); - mShader.SetAttribLocation(1, "UV"); - LeftEyeTexture.Init(mShader, "LeftEyeTexture"); - RightEyeTexture.Init(mShader, "RightEyeTexture"); - InvGamma.Init(mShader, "InvGamma"); - Contrast.Init(mShader, "Contrast"); - Brightness.Init(mShader, "Brightness"); - Scale.Init(mShader, "UVScale"); - VerticalPixelOffset.Init(mShader, "VerticalPixelOffset"); + Init("shaders/glsl/present_row3d.fp", "shaders/glsl/presentRow3d"); } mShader.Bind(); } diff --git a/src/gl/shaders/gl_present3dRowshader.h b/src/gl/shaders/gl_present3dRowshader.h index 8e3bd772d..10419d7f5 100644 --- a/src/gl/shaders/gl_present3dRowshader.h +++ b/src/gl/shaders/gl_present3dRowshader.h @@ -29,22 +29,35 @@ #define GL_PRESENT3DROWSHADER_H_ #include "gl_shaderprogram.h" +#include "gl_presentshader.h" -class FPresent3DRowShader +class FPresentStereoShaderBase : public FPresentShaderBase { public: - void Bind(); - FBufferedUniformSampler LeftEyeTexture; FBufferedUniformSampler RightEyeTexture; - FBufferedUniform1f InvGamma; - FBufferedUniform1f Contrast; - FBufferedUniform1f Brightness; - FBufferedUniform2f Scale; - FBufferedUniform1i VerticalPixelOffset; + FBufferedUniform1i WindowPositionParity; -private: - FShaderProgram mShader; +protected: + void Init(const char * vtx_shader_name, const char * program_name) override; +}; + +class FPresent3DCheckerShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; +}; + +class FPresent3DColumnShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; +}; + +class FPresent3DRowShader : public FPresentStereoShaderBase +{ +public: + void Bind() override; }; // GL_PRESENT3DROWSHADER_H_ diff --git a/src/gl/shaders/gl_presentshader.cpp b/src/gl/shaders/gl_presentshader.cpp index 39d20d0fc..15acc74fb 100644 --- a/src/gl/shaders/gl_presentshader.cpp +++ b/src/gl/shaders/gl_presentshader.cpp @@ -36,21 +36,26 @@ #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_presentshader.h" +void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program_name) +{ + mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); + mShader.Compile(FShaderProgram::Fragment, vtx_shader_name, "", 330); + mShader.SetFragDataLocation(0, "FragColor"); + mShader.Link(program_name); + mShader.SetAttribLocation(0, "PositionInProjection"); + mShader.SetAttribLocation(1, "UV"); + InvGamma.Init(mShader, "InvGamma"); + Contrast.Init(mShader, "Contrast"); + Brightness.Init(mShader, "Brightness"); + Scale.Init(mShader, "UVScale"); +} + void FPresentShader::Bind() { if (!mShader) { - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present.fp", "", 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/present"); - mShader.SetAttribLocation(0, "PositionInProjection"); - mShader.SetAttribLocation(1, "UV"); + Init("shaders/glsl/present.fp", "shaders/glsl/present"); InputTexture.Init(mShader, "InputTexture"); - InvGamma.Init(mShader, "InvGamma"); - Contrast.Init(mShader, "Contrast"); - Brightness.Init(mShader, "Brightness"); - Scale.Init(mShader, "UVScale"); } mShader.Bind(); } diff --git a/src/gl/shaders/gl_presentshader.h b/src/gl/shaders/gl_presentshader.h index 6f4e899bb..6f9e1bfd7 100644 --- a/src/gl/shaders/gl_presentshader.h +++ b/src/gl/shaders/gl_presentshader.h @@ -3,19 +3,27 @@ #include "gl_shaderprogram.h" -class FPresentShader +class FPresentShaderBase { public: - void Bind(); + virtual void Bind() = 0; - FBufferedUniformSampler InputTexture; FBufferedUniform1f InvGamma; FBufferedUniform1f Contrast; FBufferedUniform1f Brightness; FBufferedUniform2f Scale; -private: +protected: + virtual void Init(const char * vtx_shader_name, const char * program_name); FShaderProgram mShader; }; +class FPresentShader : public FPresentShaderBase +{ +public: + void Bind() override; + + FBufferedUniformSampler InputTexture; +}; + #endif \ No newline at end of file diff --git a/src/gl/stereo3d/gl_interleaved3d.cpp b/src/gl/stereo3d/gl_interleaved3d.cpp index 036a84b0b..029d233e4 100644 --- a/src/gl/stereo3d/gl_interleaved3d.cpp +++ b/src/gl/stereo3d/gl_interleaved3d.cpp @@ -43,10 +43,25 @@ EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Bool, fullscreen) -EXTERN_CVAR(Int, win_y) // pixel position of top of display window +EXTERN_CVAR(Int, win_x) // screen pixel position of left of display window +EXTERN_CVAR(Int, win_y) // screen pixel position of top of display window namespace s3d { +/* static */ +const CheckerInterleaved3D& CheckerInterleaved3D::getInstance(float ipd) +{ + static CheckerInterleaved3D instance(ipd); + return instance; +} + +/* static */ +const ColumnInterleaved3D& ColumnInterleaved3D::getInstance(float ipd) +{ + static ColumnInterleaved3D instance(ipd); + return instance; +} + /* static */ const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd) { @@ -54,11 +69,7 @@ const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd) return instance; } -RowInterleaved3D::RowInterleaved3D(double ipdMeters) - : TopBottom3D(ipdMeters) -{} - -void RowInterleaved3D::Present() const +static void prepareInterleavedPresent(FPresentStereoShaderBase& shader) { GLRenderer->mBuffers->BindOutputFB(); GLRenderer->ClearBorders(); @@ -79,27 +90,102 @@ void RowInterleaved3D::Present() const const GL_IRECT& box = GLRenderer->mOutputLetterbox; glViewport(box.left, box.top, box.width, box.height); - bool applyGamma = true; + shader.Bind(); + shader.LeftEyeTexture.Set(0); + shader.RightEyeTexture.Set(1); - GLRenderer->mPresent3dRowShader->Bind(); - GLRenderer->mPresent3dRowShader->LeftEyeTexture.Set(0); - GLRenderer->mPresent3dRowShader->RightEyeTexture.Set(1); - - if (!applyGamma || GLRenderer->framebuffer->IsHWGammaActive()) + if ( GLRenderer->framebuffer->IsHWGammaActive() ) { - GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f); - GLRenderer->mPresent3dRowShader->Contrast.Set(1.0f); - GLRenderer->mPresent3dRowShader->Brightness.Set(0.0f); + shader.InvGamma.Set(1.0f); + shader.Contrast.Set(1.0f); + shader.Brightness.Set(0.0f); } else { - GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); - GLRenderer->mPresent3dRowShader->Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); - GLRenderer->mPresent3dRowShader->Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); + shader.InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); + shader.Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); + shader.Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); } - GLRenderer->mPresent3dRowShader->Scale.Set( + shader.Scale.Set( GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(), GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()); +} + +// fixme: I don't know how to get absolute window position on Mac and Linux +// fixme: I don't know how to get window border decoration size anywhere +// So for now I'll hard code the border effect on my test machine. +// Workaround for others is to fuss with vr_swap_eyes CVAR until it looks right. +// Presumably the top/left window border on my test machine has an odd number of pixels +// in the horizontal direction, and an even number in the vertical direction. +#define WINDOW_BORDER_HORIZONTAL_PARITY 1 +#define WINDOW_BORDER_VERTICAL_PARITY 0 + +void CheckerInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dCheckerShader); + + // Compute absolute offset from top of screen to top of current display window + // because we need screen-relative, not window-relative, scan line parity + int windowVOffset = 0; + int windowHOffset = 0; + +#ifdef _WIN32 + if (!fullscreen) { + I_SaveWindowedPos(); // update win_y CVAR + windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2; + windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2; + } +#endif // _WIN32 + + GLRenderer->mPresent3dCheckerShader->WindowPositionParity.Set( + (windowVOffset + + windowHOffset + + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + ) % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset + ); + + GLRenderer->RenderScreenQuad(); +} + +void s3d::CheckerInterleaved3D::AdjustViewports() const +{ + // decrease the total pixel count by 2, but keep the same aspect ratio + const float sqrt2 = 1.41421356237f; + // Change size of renderbuffer, and align to screen + GLRenderer->mSceneViewport.height /= sqrt2; + GLRenderer->mSceneViewport.top /= sqrt2; + GLRenderer->mSceneViewport.width /= sqrt2; + GLRenderer->mSceneViewport.left /= sqrt2; + + GLRenderer->mScreenViewport.height /= sqrt2; + GLRenderer->mScreenViewport.top /= sqrt2; + GLRenderer->mScreenViewport.width /= sqrt2; + GLRenderer->mScreenViewport.left /= sqrt2; +} + +void ColumnInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dColumnShader); + + // Compute absolute offset from top of screen to top of current display window + // because we need screen-relative, not window-relative, scan line parity + int windowHOffset = 0; + +#ifdef _WIN32 + if (!fullscreen) { + I_SaveWindowedPos(); // update win_y CVAR + windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2; + } +#endif // _WIN32 + + GLRenderer->mPresent3dColumnShader->WindowPositionParity.Set(windowHOffset); + + GLRenderer->RenderScreenQuad(); +} + +void RowInterleaved3D::Present() const +{ + prepareInterleavedPresent(*GLRenderer->mPresent3dRowShader); // Compute absolute offset from top of screen to top of current display window // because we need screen-relative, not window-relative, scan line parity @@ -108,13 +194,14 @@ void RowInterleaved3D::Present() const #ifdef _WIN32 if (! fullscreen) { I_SaveWindowedPos(); // update win_y CVAR - windowVOffset = win_y; + windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2; } #endif // _WIN32 - GLRenderer->mPresent3dRowShader->VerticalPixelOffset.Set( - windowVOffset // fixme: vary with window location - + box.height % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset + GLRenderer->mPresent3dRowShader->WindowPositionParity.Set( + (windowVOffset + + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + ) % 2 ); GLRenderer->RenderScreenQuad(); diff --git a/src/gl/stereo3d/gl_interleaved3d.h b/src/gl/stereo3d/gl_interleaved3d.h index 30aef7d5a..78bd19483 100644 --- a/src/gl/stereo3d/gl_interleaved3d.h +++ b/src/gl/stereo3d/gl_interleaved3d.h @@ -42,15 +42,30 @@ #include "gl/system/gl_system.h" #include "gl/renderer/gl_renderstate.h" -class FPresent3DRowShader; - namespace s3d { +class CheckerInterleaved3D : public SideBySideSquished +{ +public: + static const CheckerInterleaved3D& getInstance(float ipd); + CheckerInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {} + void Present() const override; + void AdjustViewports() const override; +}; + +class ColumnInterleaved3D : public SideBySideSquished +{ +public: + static const ColumnInterleaved3D& getInstance(float ipd); + ColumnInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {} + void Present() const override; +}; + class RowInterleaved3D : public TopBottom3D { public: static const RowInterleaved3D& getInstance(float ipd); - RowInterleaved3D(double ipdMeters); + RowInterleaved3D(double ipdMeters) : TopBottom3D(ipdMeters) {} void Present() const override; }; diff --git a/src/gl/stereo3d/gl_stereo_cvars.cpp b/src/gl/stereo3d/gl_stereo_cvars.cpp index 16296393d..fe5ae3261 100644 --- a/src/gl/stereo3d/gl_stereo_cvars.cpp +++ b/src/gl/stereo3d/gl_stereo_cvars.cpp @@ -107,6 +107,12 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode() case 12: setCurrentMode(RowInterleaved3D::getInstance(vr_ipd)); break; + case 13: + setCurrentMode(ColumnInterleaved3D::getInstance(vr_ipd)); + break; + case 14: + setCurrentMode(CheckerInterleaved3D::getInstance(vr_ipd)); + break; case 0: default: setCurrentMode(MonoView::getInstance()); diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 83cddb8c5..a5ffb4a2c 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2707,6 +2707,8 @@ OPTVAL_SBSFULL = "Side-by-side Full"; OPTVAL_SBSNARROW = "Side-by-side Narrow"; OPTVAL_TOPBOTTOM = "Top/Bottom"; OPTVAL_ROWINTERLEAVED = "Row Interleaved"; +OPTVAL_COLUMNINTERLEAVED = "Column Interleaved"; +OPTVAL_CHECKERBOARD = "Checkerboard"; OPTVAL_QUADBUFFERED = "Quad-buffered"; OPTVAL_UNCHARTED2 = "Uncharted 2"; OPTVAL_HEJLDAWSON = "Hejl Dawson"; diff --git a/wadsrc/static/menudef.zz b/wadsrc/static/menudef.zz index 7e798a039..253f984eb 100644 --- a/wadsrc/static/menudef.zz +++ b/wadsrc/static/menudef.zz @@ -180,6 +180,8 @@ OptionValue VRMode 4, "$OPTVAL_SBSNARROW" 11, "$OPTVAL_TOPBOTTOM" 12, "$OPTVAL_ROWINTERLEAVED" + 13, "$OPTVAL_COLUMNINTERLEAVED" + 14, "$OPTVAL_CHECKERBOARD" 5, "$OPTVAL_LEFTEYE" 6, "$OPTVAL_RIGHTEYE" 7, "$OPTVAL_QUADBUFFERED" diff --git a/wadsrc/static/shaders/glsl/present_checker3d.fp b/wadsrc/static/shaders/glsl/present_checker3d.fp new file mode 100644 index 000000000..5247261e0 --- /dev/null +++ b/wadsrc/static/shaders/glsl/present_checker3d.fp @@ -0,0 +1,37 @@ + +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D LeftEyeTexture; +uniform sampler2D RightEyeTexture; +uniform float InvGamma; +uniform float Contrast; +uniform float Brightness; +uniform int WindowPositionParity; // top-of-window might not be top-of-screen + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even + int thisHorizontalPixel = int(gl_FragCoord.x); // column + bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row + + thisHorizontalPixel // and each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, TexCoord); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, TexCoord); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders/glsl/present_column3d.fp b/wadsrc/static/shaders/glsl/present_column3d.fp new file mode 100644 index 000000000..b46246cf0 --- /dev/null +++ b/wadsrc/static/shaders/glsl/present_column3d.fp @@ -0,0 +1,35 @@ + +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D LeftEyeTexture; +uniform sampler2D RightEyeTexture; +uniform float InvGamma; +uniform float Contrast; +uniform float Brightness; +uniform int WindowPositionParity; // top-of-window might not be top-of-screen + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisHorizontalPixel = int(gl_FragCoord.x); // zero-based column index from left + bool isLeftEye = (thisHorizontalPixel // because we want to alternate eye view on each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, TexCoord); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, TexCoord); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders/glsl/present_row3d.fp b/wadsrc/static/shaders/glsl/present_row3d.fp index 8ae72d1e0..50b27ac26 100644 --- a/wadsrc/static/shaders/glsl/present_row3d.fp +++ b/wadsrc/static/shaders/glsl/present_row3d.fp @@ -7,7 +7,7 @@ uniform sampler2D RightEyeTexture; uniform float InvGamma; uniform float Contrast; uniform float Brightness; -uniform int VerticalPixelOffset; // top-of-window might not be top-of-screen +uniform int WindowPositionParity; // top-of-window might not be top-of-screen vec4 ApplyGamma(vec4 c) { @@ -19,9 +19,9 @@ vec4 ApplyGamma(vec4 c) void main() { - int thisVerticalPixel = int(gl_FragCoord.y + 1.0); // Bottom row is typically the right eye, when WindowHeight is even + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row - + VerticalPixelOffset // because the window might not be aligned to the screen + + WindowPositionParity // because the window might not be aligned to the screen ) % 2 == 0; vec4 inputColor; if (isLeftEye) { From a771a3edd4b9794a1afea4317250ad0b2c95642a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 8 Oct 2016 18:36:34 +0300 Subject: [PATCH 20/28] Fixed potential crash caused by A_Warp() ACSF_Warp case was refactored to express its intention clearly http://forum.zdoom.org/viewtopic.php?f=2&t=53734 --- src/p_acs.cpp | 79 +++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 0a2ccddac..71ef65f22 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5821,43 +5821,54 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) // [ZK] A_Warp in ACS case ACSF_Warp: { - int tid_dest = args[0]; - int xofs = args[1]; - int yofs = args[2]; - int zofs = args[3]; - int angle = args[4]; - int flags = args[5]; - const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : ""; - bool exact = argCount > 7 ? !!args[7] : false; - int heightoffset = argCount > 8 ? args[8] : 0; - int radiusoffset = argCount > 9 ? args[9] : 0; - int pitch = argCount > 10 ? args[10] : 0; - - FState *state = argCount > 6 ? activator->GetClass()->FindStateByString(statename, exact) : 0; - - AActor *reference; - if((flags & WARPF_USEPTR) && tid_dest != AAPTR_DEFAULT) + if (nullptr == activator) { - reference = COPY_AAPTR(activator, tid_dest); - } - else - { - reference = SingleActorFromTID(tid_dest, activator); - } - - // If there is no activator or actor to warp to, fail. - if (activator == NULL || !reference) return false; - - if (P_Thing_Warp(activator, reference, ACSToDouble(xofs), ACSToDouble(yofs), ACSToDouble(zofs), ACSToAngle(angle), flags, ACSToDouble(heightoffset), ACSToDouble(radiusoffset), ACSToAngle(pitch))) - { - if (state && argCount > 6) - { - activator->SetState(state); - } - return true; } - return false; + + const int dest = args[0]; + const int flags = args[5]; + + AActor* const reference = ((flags & WARPF_USEPTR) && (AAPTR_DEFAULT != dest)) + ? COPY_AAPTR(activator, dest) + : SingleActorFromTID(dest, activator); + + if (nullptr == reference) + { + // there is no actor to warp to + return false; + } + + const double xofs = ACSToDouble(args[1]); + const double yofs = ACSToDouble(args[2]); + const double zofs = ACSToDouble(args[3]); + const DAngle angle = ACSToAngle(args[4]); + const double heightoffset = argCount > 8 ? ACSToDouble(args[8]) : 0.0; + const double radiusoffset = argCount > 9 ? ACSToDouble(args[9]) : 0.0; + const DAngle pitch = ACSToAngle(argCount > 10 ? args[10] : 0); + + if (!P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch)) + { + return false; + } + + if (argCount > 6) + { + const char* const statename = FBehavior::StaticLookupString(args[6]); + + if (nullptr != statename) + { + const bool exact = argCount > 7 && !!args[7]; + FState* const state = activator->GetClass()->FindStateByString(statename, exact); + + if (nullptr != state) + { + activator->SetState(state); + } + } + } + + return true; } case ACSF_GetMaxInventory: actor = SingleActorFromTID(args[0], activator); From 31ca5a1900062e5e5bee074d8b2c4919361cf55b Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sat, 8 Oct 2016 11:04:12 -0500 Subject: [PATCH 21/28] Added OverlayX/Y(int layer) - Retrieves the X/Y positions of an overlay. - A_OverlayFlags and A_OverlayOffset now interpret a layer of 0 to mean 'use this calling layer'. --- src/p_pspr.cpp | 52 ++++++++++++++++++++++++++++++++-- wadsrc/static/actors/actor.txt | 2 ++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index fab7e38d8..e5b076acd 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1006,7 +1006,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset) PARAM_FLOAT_OPT(wx) { wx = 0.; } PARAM_FLOAT_OPT(wy) { wy = 32.; } PARAM_INT_OPT(flags) { flags = 0; } - A_OverlayOffset(self, layer, wx, wy, flags); + A_OverlayOffset(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), wx, wy, flags); return 0; } @@ -1033,10 +1033,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) PARAM_INT(flags); PARAM_BOOL(set); - if (self->player == nullptr) + if (!ACTION_CALL_FROM_PSPRITE()) return 0; - DPSprite *pspr = self->player->FindPSprite(layer); + DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex)); if (pspr == nullptr) return 0; @@ -1049,6 +1049,52 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) return 0; } +//--------------------------------------------------------------------------- +// +// PROC OverlayX/Y +// Action function to return the X/Y of an overlay. +//--------------------------------------------------------------------------- + +static double GetOverlayPosition(AActor *self, int layer, bool gety) +{ + if (layer) + { + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr != nullptr) + { + return gety ? (pspr->y) : (pspr->x); + } + } + return 0.; +} + +DEFINE_ACTION_FUNCTION(AActor, OverlayX) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT_OPT(layer) { layer = 0; } + + if (ACTION_CALL_FROM_PSPRITE()) + { + double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), false); + ACTION_RETURN_FLOAT(res); + } + ACTION_RETURN_FLOAT(0.); +} + +DEFINE_ACTION_FUNCTION(AActor, OverlayY) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT_OPT(layer) { layer = 0; } + + if (ACTION_CALL_FROM_PSPRITE()) + { + double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), true); + ACTION_RETURN_FLOAT(res); + } + ACTION_RETURN_FLOAT(0.); +} + //--------------------------------------------------------------------------- // // PROC OverlayID diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 44b801f51..fb6b4c832 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -58,6 +58,8 @@ ACTOR Actor native //: Thinker native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); action native int OverlayID(); + action native float OverlayX(int layer = 0); + action native float OverlayY(int layer = 0); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. From 084bf8c57691c40e22c188a8aab37a914197d3bb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 00:23:50 +0200 Subject: [PATCH 22/28] - fixed: VisibleAngle and VisiblePitch actor properties require both parameters to be present, but the second one was set to optional. --- src/thingdef/thingdef_properties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d60cda823..80ee6c22f 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1435,7 +1435,7 @@ DEFINE_PROPERTY(spriterotation, F, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(visibleangles, Ff, Actor) +DEFINE_PROPERTY(visibleangles, FF, Actor) { PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visend, 1); @@ -1446,7 +1446,7 @@ DEFINE_PROPERTY(visibleangles, Ff, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(visiblepitch, Ff, Actor) +DEFINE_PROPERTY(visiblepitch, FF, Actor) { PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visend, 1); From dde25820e24e6e243eae96d53a9a19e437bc1c6c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 09:08:31 +0200 Subject: [PATCH 23/28] - fixed winding of voxel polygons. --- src/gl/models/gl_voxels.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gl/models/gl_voxels.cpp b/src/gl/models/gl_voxels.cpp index 288b1a9db..6e84bd7ab 100644 --- a/src/gl/models/gl_voxels.cpp +++ b/src/gl/models/gl_voxels.cpp @@ -314,12 +314,12 @@ void FVoxelModel::MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &chec } if (cull & 4) { - AddFace(x, y, z, x+1, y, z, x, y, z+c, x+1, y, z+c, *col, check); + AddFace(x+1, y, z, x, y, z, x+1, y, z+c, x, y, z+c, *col, check); } if (cull & 8) { - AddFace(x+1, y+1, z, x, y+1, z, x+1, y+1, z+c, x, y+1, z+c, *col, check); - } + AddFace(x, y+1, z, x+1, y+1, z, x, y+1, z+c, x+1, y+1, z+c, *col, check); + } z+=c; col+=c; } From 7510ad1635f3c4f26b905d6d10bb95bb7a2c0e88 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 11 Oct 2016 14:52:47 +0300 Subject: [PATCH 24/28] Fixed missing fake floors in deferred buffer mode wow.wad is now genuine and authentic... --- src/gl/scene/gl_flats.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 394ca1626..c41e7664f 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -187,21 +187,18 @@ void GLFlat::DrawSubsector(subsector_t * sub) unsigned int vi[4]; vi[0] = 0; - for (unsigned int i = 1; i < sub->numlines-1; i += 2) + for (unsigned int i = 0; i < sub->numlines - 2; i += 2) { - if (i < sub->numlines - 3) + for (unsigned int j = 1; j < 4; j++) { - for (unsigned int j = 1; j < 4; j++) - { - vi[j] = MIN(i + j, sub->numlines - 1); - } - for (unsigned int x = 0; x < 4; x++) - { - vertex_t *vt = sub->firstline[vi[x]].v1; - qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f); - } - qd.Render(GL_TRIANGLE_FAN); + vi[j] = MIN(i + j, sub->numlines - 1); } + for (unsigned int x = 0; x < 4; x++) + { + vertex_t *vt = sub->firstline[vi[x]].v1; + qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f); + } + qd.Render(GL_TRIANGLE_FAN); } } From bdbc7c3fb75e4b2b0b682f135e0802b711342190 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Oct 2016 14:43:17 +0200 Subject: [PATCH 25/28] - removed CreateDamageFunction, because it's no longer needed for defining a 'damage' constant. --- src/thingdef/thingdef.cpp | 29 ----------------------------- src/thingdef/thingdef.h | 8 -------- 2 files changed, 37 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 41e1e9542..9af031b04 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -480,32 +480,3 @@ void LoadActors () if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms } - - -//========================================================================== -// -// CreateDamageFunction -// -// Creates a damage function suitable for a constant, non-expressioned -// value. -// -//========================================================================== - -VMScriptFunction *CreateDamageFunction(int dmg) -{ - if (dmg == 0) - { - // For zero damage, do not create a function so that the special collision detection case still works as before. - return NULL; - } - else - { - VMFunctionBuilder build; - build.Registers[REGT_POINTER].Get(1); // The self pointer - build.EmitRetInt(0, false, dmg); - build.EmitRetInt(1, true, 0); - VMScriptFunction *sfunc = build.MakeFunction(); - sfunc->NumArgs = 1; - return sfunc; - } -} diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 3a419b112..565da573a 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -164,14 +164,6 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) bag->statedef.MakeStateDefines(stateclass); } -//========================================================================== -// -// Damage function creation -// -//========================================================================== - -VMScriptFunction *CreateDamageFunction(int dmg); - //========================================================================== // // Action function lookup From 5dc94a10c352ae05c49b00436f5b36f55059181a Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 14:44:31 -0500 Subject: [PATCH 26/28] Added A_SetInventory. - Sets the absolute amount of an inventory actor. - Limits itself to the range [0, MaxAmount]. Setting beyondMax to true disregards the MaxAmount. Default is false. --- src/p_mobj.cpp | 2 + src/thingdef/thingdef_codeptr.cpp | 86 +++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 3 files changed, 89 insertions(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 022504919..1ebec242e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -634,6 +634,7 @@ void AActor::RemoveInventory(AInventory *item) bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite) { + amount = abs(amount); AInventory *item = FindInventory(itemclass); if (item == NULL) @@ -666,6 +667,7 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate item->IsKindOf(RUNTIME_CLASS(AAmmo))) { // Nothing to do here, except maybe res = false;? Would it make sense? + result = false; } else if (!amount || amount>=item->Amount) { diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 3b4e6203e..c6bc8215b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2622,6 +2622,92 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) ACTION_RETURN_INT(count); } +//=========================================================================== +// +// A_SetInventory +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory) +{ + PARAM_ACTION_PROLOGUE; + PARAM_CLASS(itemtype, AInventory); + PARAM_INT(amount); + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + PARAM_BOOL_OPT(beyondMax) { beyondMax = false; } + + bool res = false; + + if (itemtype == nullptr) + { + ACTION_RETURN_BOOL(false); + } + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (mobj == nullptr) + { + ACTION_RETURN_BOOL(false); + } + + AInventory *item = mobj->FindInventory(itemtype); + + if (item != nullptr) + { + // A_SetInventory sets the absolute amount. + // Subtract or set the appropriate amount as necessary. + + if (amount == item->Amount) + { + // Nothing was changed. + ACTION_RETURN_BOOL(false); + } + else if (amount <= 0) + { + //Remove it all. + res = (mobj->TakeInventory(itemtype, item->Amount, true, false)); + ACTION_RETURN_BOOL(res); + } + else if (amount < item->Amount) + { + int amt = abs(item->Amount - amount); + res = (mobj->TakeInventory(itemtype, amt, true, false)); + ACTION_RETURN_BOOL(res); + } + else + { + item->Amount = (beyondMax ? amount : clamp(amount, 0, item->MaxAmount)); + ACTION_RETURN_BOOL(true); + } + } + else + { + if (amount <= 0) + { + ACTION_RETURN_BOOL(false); + } + item = static_cast(Spawn(itemtype)); + if (item == nullptr) + { + ACTION_RETURN_BOOL(false); + } + else + { + item->Amount = amount; + item->flags |= MF_DROPPED; + item->ItemFlags |= IF_IGNORESKILL; + item->ClearCounters(); + if (!item->CallTryPickup(mobj)) + { + item->Destroy(); + ACTION_RETURN_BOOL(false); + } + ACTION_RETURN_BOOL(true); + } + } + ACTION_RETURN_BOOL(false); +} + //=========================================================================== // // A_TakeInventory diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index fb6b4c832..eecc843d3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -211,6 +211,7 @@ ACTOR Actor native //: Thinker native state A_JumpIfTargetInsideMeleeRange(state label); native state A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); native state A_JumpIfArmorType(name Type, state label, int amount = 1); + action native bool A_SetInventory(class itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false); native bool A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); native bool A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); action native bool A_SpawnItem(class itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); From 3de83b8943e1ed13aaad9da723f0671b8c3dad40 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 17:20:58 -0500 Subject: [PATCH 27/28] Added PSPF_FLIP. Flips the overlay on the X axis. --- src/p_pspr.h | 1 + src/r_things.cpp | 2 +- wadsrc/static/actors/constants.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_pspr.h b/src/p_pspr.h index 7e5109657..ea03e109f 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -57,6 +57,7 @@ enum PSPFlags PSPF_ADDBOB = 1 << 1, PSPF_POWDOUBLE = 1 << 2, PSPF_CVARFAST = 1 << 3, + PSPF_FLIP = 1 << 6, }; class DPSprite : public DObject diff --git a/src/r_things.cpp b/src/r_things.cpp index 179ffec97..ab75c15b0 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1404,7 +1404,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double vis->pic = tex; vis->ColormapNum = 0; - if (flip) + if (!(flip) != !(pspr->Flags & PSPF_FLIP)) { vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X); vis->startfrac = (tex->GetWidth() << FRACBITS) - 1; diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index dce2488c2..df3bb860b 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -598,6 +598,7 @@ enum PSPF_ADDBOB = 1 << 1, PSPF_POWDOUBLE = 1 << 2, PSPF_CVARFAST = 1 << 3, + PSPF_FLIP = 1 << 6, }; // Default psprite layers From 41bf9def805cc832fed9d7efa02b6d1a71b9f170 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 11 Oct 2016 20:15:46 -0500 Subject: [PATCH 28/28] GZDoom compatibility for PSPF_FLIP. --- src/gl/scene/gl_weapon.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index cfa5c05d7..a2a12f947 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -129,19 +129,20 @@ void FGLRenderer::DrawPSprite (player_t * player,DPSprite *psp, float sx, float y1 = viewwindowy + vh / 2 - (ftexturemid * scale); y2 = y1 + (r.height * scale) + 1; - if (!mirror) + if (!(mirror) != !(psp->Flags & PSPF_FLIP)) { - fU1=tex->GetSpriteUL(); - fV1=tex->GetSpriteVT(); - fU2=tex->GetSpriteUR(); - fV2=tex->GetSpriteVB(); + fU2 = tex->GetSpriteUL(); + fV1 = tex->GetSpriteVT(); + fU1 = tex->GetSpriteUR(); + fV2 = tex->GetSpriteVB(); } else { - fU2=tex->GetSpriteUL(); - fV1=tex->GetSpriteVT(); - fU1=tex->GetSpriteUR(); - fV2=tex->GetSpriteVB(); + fU1 = tex->GetSpriteUL(); + fV1 = tex->GetSpriteVT(); + fU2 = tex->GetSpriteUR(); + fV2 = tex->GetSpriteVB(); + } if (tex->GetTransparent() || OverrideShader != -1)