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 0b1e58287..17e46e182 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 759da062c..57ea03d92 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 83a2a20d8..a74edd01b 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 cd128b656..c8a89e955 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 e41523b8c..af79e1d04 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 97e2bf6bb..4c62863df 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 c8a89e955..a2a5a6883 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 1255401ae..bd2575216 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 5ce79fd09..4b0eac499 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 ee581e74a..4733d853f 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 0b27a1efa..37531d40f 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 020d8477d..9f7564b95 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 66757cee7..bf0a0a91d 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 64cf4034b..55477ee2e 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 b66b381ba..2dd3e5e55 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" }