From 05836916708c458d58c2ac2ce96b24a1bcd891d1 Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Sun, 19 Feb 2017 06:08:50 -0800 Subject: [PATCH 1/6] Add bash-style console shortcuts --- src/c_console.cpp | 153 +++++++++++++++++++++++++++++++++++++- src/posix/sdl/i_input.cpp | 8 +- src/zstring.cpp | 1 - 3 files changed, 157 insertions(+), 5 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 0b1e582874..17e46e182e 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -206,6 +206,9 @@ struct FCommandBuffer unsigned CursorPos; unsigned StartPos; // First character to display + FString YankBuffer; // Deleted text buffer + bool AppendToYankBuffer; // Append consecutive deletes to buffer + FCommandBuffer() { CursorPos = StartPos = 0; @@ -278,6 +281,30 @@ struct FCommandBuffer StartPos = MAX(0, n); } + unsigned WordBoundaryRight() + { + unsigned index = CursorPos; + while (index < Text.Len() && Text[index] == ' ') { + index++; + } + while (index < Text.Len() && Text[index] != ' ') { + index++; + } + return index; + } + + unsigned WordBoundaryLeft() + { + int index = CursorPos - 1; + while (index > -1 && Text[index] == ' ') { + index--; + } + while (index > -1 && Text[index] != ' ') { + index--; + } + return (unsigned)index + 1; + } + void CursorStart() { CursorPos = 0; @@ -309,6 +336,18 @@ struct FCommandBuffer } } + void CursorWordLeft() + { + CursorPos = WordBoundaryLeft(); + MakeStartPosGood(); + } + + void CursorWordRight() + { + CursorPos = WordBoundaryRight(); + MakeStartPosGood(); + } + void DeleteLeft() { if (CursorPos > 0) @@ -328,6 +367,50 @@ struct FCommandBuffer } } + void DeleteWordLeft() + { + if (CursorPos > 0) + { + unsigned index = WordBoundaryLeft(); + if (AppendToYankBuffer) { + YankBuffer = FString(&Text[index], CursorPos - index) + YankBuffer; + } else { + YankBuffer = FString(&Text[index], CursorPos - index); + } + Text.Remove(index, CursorPos - index); + CursorPos = index; + MakeStartPosGood(); + } + } + + void DeleteLineLeft() + { + if (CursorPos > 0) + { + if (AppendToYankBuffer) { + YankBuffer = FString(&Text[0], CursorPos) + YankBuffer; + } else { + YankBuffer = FString(&Text[0], CursorPos); + } + Text.Remove(0, CursorPos); + CursorStart(); + } + } + + void DeleteLineRight() + { + if (CursorPos < Text.Len()) + { + if (AppendToYankBuffer) { + YankBuffer += FString(&Text[CursorPos], Text.Len() - CursorPos); + } else { + YankBuffer = FString(&Text[CursorPos], Text.Len() - CursorPos); + } + Text.Truncate(CursorPos); + CursorEnd(); + } + } + void AddChar(int character) { ///FIXME: Not Unicode-aware @@ -1345,6 +1428,7 @@ DEFINE_ACTION_FUNCTION(_Console, Printf) static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) { int data1 = ev->data1; + bool keepappending = false; switch (ev->subtype) { @@ -1352,8 +1436,22 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) return false; case EV_GUI_Char: + if (ev->data2) + { + // Bash-style shortcuts + if (data1 == 'b') + { + buffer.CursorWordLeft(); + break; + } + else if (data1 == 'f') + { + buffer.CursorWordRight(); + break; + } + } // Add keypress to command line - buffer.AddChar(ev->data1); + buffer.AddChar(data1); HistPos = NULL; TabbedLast = false; TabbedList = false; @@ -1654,6 +1752,56 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) break; } break; + + // Bash-style shortcuts + case 'A': + if (ev->data3 & GKM_CTRL) + { + buffer.CursorStart(); + } + break; + case 'E': + if (ev->data3 & GKM_CTRL) + { + buffer.CursorEnd(); + } + break; + case 'W': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteWordLeft(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'U': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteLineLeft(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'K': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteLineRight(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'Y': + if (ev->data3 & GKM_CTRL) + { + buffer.AddString(buffer.YankBuffer); + TabbedLast = false; + TabbedList = false; + HistPos = NULL; + } + break; } break; @@ -1664,6 +1812,9 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) break; #endif } + + buffer.AppendToYankBuffer = keepappending; + // Ensure that the cursor is always visible while typing CursorTicker = C_BLINKRATE; cursoron = 1; diff --git a/src/posix/sdl/i_input.cpp b/src/posix/sdl/i_input.cpp index 759da062cd..57ea03d928 100644 --- a/src/posix/sdl/i_input.cpp +++ b/src/posix/sdl/i_input.cpp @@ -395,9 +395,10 @@ void MessagePump (const SDL_Event &sev) { event.type = EV_GUI_Event; event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp; - event.data3 = ((sev.key.keysym.mod & KMOD_SHIFT) ? GKM_SHIFT : 0) | - ((sev.key.keysym.mod & KMOD_CTRL) ? GKM_CTRL : 0) | - ((sev.key.keysym.mod & KMOD_ALT) ? GKM_ALT : 0); + SDL_Keymod kmod = SDL_GetModState(); + event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); if (event.subtype == EV_GUI_KeyDown) { @@ -458,6 +459,7 @@ void MessagePump (const SDL_Event &sev) event.type = EV_GUI_Event; event.subtype = EV_GUI_Char; event.data1 = sev.text.text[0]; + event.data2 = !!(SDL_GetModState() & KMOD_ALT); D_PostEvent (&event); } break; diff --git a/src/zstring.cpp b/src/zstring.cpp index 83a2a20d81..a74edd01b5 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -393,7 +393,6 @@ void FString::Remove(size_t index, size_t remlen) } else { - remlen = Len() - remlen < remlen ? Len() - remlen : remlen; if (Data()->RefCount == 1) { // Can do this in place memmove(Chars + index, Chars + index + remlen, Len() - index - remlen); From b5d4a5946524cb7b23893c2a2eff9bb11be3ddca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:09:50 +0100 Subject: [PATCH 2/6] - fixed: Meta properties must not be serialized. --- src/dobjtype.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index cd128b6560..c8a89e9551 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2307,7 +2307,7 @@ void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArrayFlags & VARF_Transient)) + if (!(field->Flags & (VARF_Transient|VARF_Meta))) { field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset); } @@ -2340,6 +2340,11 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n", label, TypeName.GetChars()); } + else if ((static_cast(sym)->Flags & (VARF_Transient | VARF_Meta))) + { + DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n", + label, TypeName.GetChars()); + } else { readsomething |= static_cast(sym)->Type->ReadValue(ar, nullptr, @@ -2638,7 +2643,7 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void * // Don't write this part if it has no non-transient variables for (unsigned i = 0; i < type->Fields.Size(); ++i) { - if (!(type->Fields[i]->Flags & VARF_Transient)) + if (!(type->Fields[i]->Flags & (VARF_Transient|VARF_Meta))) { // Tag this section with the class it came from in case // a more-derived class has variables that shadow a less- From 0de79042d4b388cf4e23478d661eb6f28e385719 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:20:46 +0100 Subject: [PATCH 3/6] - fixed: 'Bloodtype' cannot use the generic property definition because it needs special handling for optional arguments. This reinstates the native handler. --- src/scripting/thingdef_properties.cpp | 27 +++++++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e41523b8cf..af79e1d04c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1059,6 +1059,33 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) static_cast(info)->BloodColor = pe; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(bloodtype, Sss, Actor) +{ + PROP_STRING_PARM(str, 0) + PROP_STRING_PARM(str1, 1) + PROP_STRING_PARM(str2, 2) + + FName blood = str; + // normal blood + defaults->NameVar("BloodType") = blood; + + if (PROP_PARM_COUNT > 1) + { + blood = str1; + } + // blood splatter + defaults->NameVar("BloodType2") = blood; + + if (PROP_PARM_COUNT > 2) + { + blood = str2; + } + // axe blood + defaults->NameVar("BloodType3") = blood; +} //========================================================================== // diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 97e2bf6bb8..4c62863df4 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -224,7 +224,7 @@ class Actor : Thinker native Property DontHurtShooter: DontHurtShooter; Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; - Property BloodType: BloodType, BloodType2, BloodType3; + //Property BloodType: BloodType, BloodType2, BloodType3; Property FastSpeed: FastSpeed; Property HowlSound: HowlSound; Property GibHealth: GibHealth; From 9b2f31e69292c79c989955a70f2bcc243fd2d143 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:54:37 +0100 Subject: [PATCH 4/6] - had to add a hack because some people had to exploit implementation-dependent behavior of the PulseLight type. --- src/dobjtype.cpp | 1 - src/gl/dynlights/a_dynlight.cpp | 3 ++- src/gl/dynlights/gl_dynlight.cpp | 28 ++++++++++++++++++---------- src/gl/dynlights/gl_dynlight.h | 1 + 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c8a89e9551..a2a5a6883b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3402,7 +3402,6 @@ PClass *PClass::FindClassTentative(FName name) PClass *type = static_cast(GetClass()->CreateNew()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); - assert(MetaSize == 0); Derive(type, name); type->Size = TentativeClass; TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket); diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 1255401ae9..bd25752165 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -204,7 +204,8 @@ void ADynamicLight::Activate(AActor *activator) float pulseTime = specialf1 / TICRATE; m_lastUpdate = level.maptime; - m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime); + if (!swapped) m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime); + else m_cycler.SetParams(float(args[LIGHT_INTENSITY]), float(args[LIGHT_SECONDARY_INTENSITY]), pulseTime); m_cycler.ShouldCycle(true); m_cycler.SetCycleType(CYCLE_Sin); m_currentRadius = m_cycler.GetVal(); diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index 5ce79fd09a..4b0eac499d 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -135,6 +135,16 @@ public: void SetDontLightSelf(bool add) { m_dontlightself = add; } void SetAttenuate(bool on) { m_attenuate = on; } void SetHalo(bool halo) { m_halo = halo; } + + void OrderIntensities() + { + if (m_Args[LIGHT_INTENSITY] > m_Args[LIGHT_SECONDARY_INTENSITY]) + { + std::swap(m_Args[LIGHT_INTENSITY], m_Args[LIGHT_SECONDARY_INTENSITY]); + m_swapped = true; + } + } + protected: FName m_Name; int m_Args[5]; @@ -143,6 +153,7 @@ protected: ELightType m_type; int8_t m_attenuate; bool m_subtractive, m_additive, m_halo, m_dontlightself; + bool m_swapped = false; }; TArray LightDefaults; @@ -178,8 +189,8 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const light->SetOffset(m_Pos); light->halo = m_halo; for (int a = 0; a < 3; a++) light->args[a] = clamp((int)(m_Args[a]), 0, 255); - light->args[LIGHT_INTENSITY] = int(m_Args[LIGHT_INTENSITY]); - light->args[LIGHT_SECONDARY_INTENSITY] = int(m_Args[LIGHT_SECONDARY_INTENSITY]); + light->args[LIGHT_INTENSITY] = m_Args[LIGHT_INTENSITY]; + light->args[LIGHT_SECONDARY_INTENSITY] = m_Args[LIGHT_SECONDARY_INTENSITY]; light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF); if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE; if (m_additive) light->flags4 |= MF4_ADDITIVE; @@ -190,11 +201,13 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const float pulseTime = float(m_Param / TICRATE); light->m_lastUpdate = level.maptime; - light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight); + if (m_swapped) light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight); + else light->m_cycler.SetParams(float(light->args[LIGHT_INTENSITY]), float(light->args[LIGHT_SECONDARY_INTENSITY]), pulseTime, oldtype == PulseLight); light->m_cycler.ShouldCycle(true); light->m_cycler.SetCycleType(CYCLE_Sin); light->m_currentRadius = light->m_cycler.GetVal(); if (light->m_currentRadius <= 0) light->m_currentRadius = 1; + light->swapped = m_swapped; } switch (m_attenuate) @@ -474,13 +487,7 @@ void gl_ParsePulseLight(FScanner &sc) sc.ScriptError("Unknown tag: %s\n", sc.String); } } - if (defaults->GetArg(LIGHT_INTENSITY) > defaults->GetArg(LIGHT_SECONDARY_INTENSITY)) - { - auto i = defaults->GetArg(LIGHT_INTENSITY); - auto j = defaults->GetArg(LIGHT_SECONDARY_INTENSITY); - defaults->SetArg(LIGHT_INTENSITY, j); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, i); - } + defaults->OrderIntensities(); gl_AddLightDefaults(defaults); } @@ -564,6 +571,7 @@ void gl_ParseFlickerLight(FScanner &sc) sc.ScriptError("Unknown tag: %s\n", sc.String); } } + defaults->OrderIntensities(); gl_AddLightDefaults(defaults); } else diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index ee581e74a7..4733d853f4 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -141,6 +141,7 @@ public: bool halo; BYTE color2[3]; bool visibletoplayer; + bool swapped; int bufferindex; From 3c21ca9cb18e240b2503cb255e02f452f71774e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 22:06:39 +0100 Subject: [PATCH 5/6] - added a compatibility option to move vertices and applied it to E1M6 of Masters of Chaos. This map has a door/lift combination that could trap the player without any chance to get out because both elements are so close together that it was almost impossible to trigger the lift. Moved two vertices by one map unit to make enough room. --- src/compatibility.cpp | 25 ++++++++++++++++++++++++- wadsrc/static/compatibility.txt | 6 ++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 0b27a1efa0..37531d40fa 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -86,6 +86,7 @@ enum CP_SETTHINGZ, CP_SETTAG, CP_SETTHINGFLAGS, + CP_SETVERTEX, }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -345,7 +346,19 @@ void ParseCompatibility() sc.MustGetNumber(); CompatParams.Push(sc.Number); } - else + else if (sc.Compare("setvertex")) + { + if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); + CompatParams.Push(CP_SETVERTEX); + sc.MustGetNumber(); + CompatParams.Push(sc.Number); + sc.MustGetFloat(); + CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels + sc.MustGetFloat(); + CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels + flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES; + } + else { sc.UnGet(); break; @@ -600,6 +613,16 @@ void SetCompatibilityParams() i += 3; break; } + case CP_SETVERTEX: + { + if ((unsigned)CompatParams[i + 1] < level.vertexes.Size()) + { + level.vertexes[CompatParams[i + 1]].p.X = CompatParams[i + 2] / 256.; + level.vertexes[CompatParams[i + 1]].p.Y = CompatParams[i + 3] / 256.; + } + i += 4; + break; + } } } } diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 020d8477d6..9f7564b95f 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -497,6 +497,12 @@ ABC4EB5A1535ECCD0061AD14F3547908 // Plutonia Experiment, map26 setsectorspecial 156 0 } +B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6 +{ + setvertex 1650 -3072 2671 + setvertex 1642 -2944 2671 +} + 712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect { setsectortag 545 32000 From 384accbc860b46a5293784572421c649b067204c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Mar 2017 10:12:11 +0200 Subject: [PATCH 6/6] Fixed name and placement of 'All except doors' localized string --- wadsrc/static/language.eng | 1 - wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/language.eng b/wadsrc/static/language.eng index 66757cee70..bf0a0a91d6 100644 --- a/wadsrc/static/language.eng +++ b/wadsrc/static/language.eng @@ -106,7 +106,6 @@ CMPTMNU_RENDERINGBEHAVIOR = "Rendering Behaviour"; CMPTMNU_SOUNDBEHAVIOR = "Sound Behaviour"; CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only"; -OPTVAL_NODOORS = "All except doors"; C_GRAY = "\ccgrey"; C_DARKGRAY = "\cudark grey"; diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 64cf4034bf..55477ee2e2 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2286,6 +2286,7 @@ OPTVAL_FRONT = "Front"; OPTVAL_ANIMATED = "Animated"; OPTVAL_ROTATED = "Rotated"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only"; +OPTVAL_NODOORS = "All except doors"; OPTVAL_DOUBLE = "Double"; OPTVAL_TRIPLE = "Triple"; OPTVAL_QUADRUPLE = "Quadruple"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b66b381bad..2dd3e5e559 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1014,7 +1014,7 @@ OptionValue MapBackTypes OptionValue MapTriggers { 0, "$OPTVAL_OFF" - 1, "$OPTVAL_NO_DOORS" + 1, "$OPTVAL_NODOORS" 2, "$OPTVAL_ON" }