diff --git a/source/common/audio/sound/oalsound.h b/source/common/audio/sound/oalsound.h index a333d772d..13fa3e588 100644 --- a/source/common/audio/sound/oalsound.h +++ b/source/common/audio/sound/oalsound.h @@ -48,6 +48,8 @@ #define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 #define ALC_HRTF_SPECIFIER_SOFT 0x1995 #define ALC_HRTF_ID_SOFT 0x1996 +#define ALC_OUTPUT_LIMITER_SOFT 0x199A + typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); #ifdef AL_ALEXT_PROTOTYPES @@ -181,6 +183,7 @@ private: bool EXT_disconnect; bool SOFT_HRTF; bool SOFT_pause_device; + bool SOFT_output_limiter; } ALC; struct { bool EXT_source_distance_model; diff --git a/source/common/audio/sound/s_sound.cpp b/source/common/audio/sound/s_sound.cpp index 269a49133..9c2ad6ab1 100644 --- a/source/common/audio/sound/s_sound.cpp +++ b/source/common/audio/sound/s_sound.cpp @@ -463,7 +463,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, } // If this sound doesn't like playing near itself, don't play it if that's what would happen. - if (near_limit > 0 && CheckSoundLimit(sfx, pos, near_limit, limit_range, type, source, channel)) + if (near_limit > 0 && CheckSoundLimit(sfx, pos, near_limit, limit_range, type, source, channel, attenuation)) { chanflags |= CHANF_EVICTED; } @@ -675,7 +675,7 @@ void SoundEngine::RestartChannel(FSoundChan *chan) // If this sound doesn't like playing near itself, don't play it if // that's what would happen. - if (chan->NearLimit > 0 && CheckSoundLimit(&S_sfx[chan->SoundID], pos, chan->NearLimit, chan->LimitRange, 0, NULL, 0)) + if (chan->NearLimit > 0 && CheckSoundLimit(&S_sfx[chan->SoundID], pos, chan->NearLimit, chan->LimitRange, 0, NULL, 0, chan->DistanceScale)) { return; } @@ -816,7 +816,7 @@ bool SoundEngine::CheckSingular(int sound_id) //========================================================================== bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, float limit_range, - int sourcetype, const void *actor, int channel) + int sourcetype, const void *actor, int channel, float attenuation) { FSoundChan *chan; int count; @@ -835,7 +835,9 @@ bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_ } CalcPosVel(chan, &chanorigin, NULL); - if ((chanorigin - pos).LengthSquared() <= limit_range) + // scale the limit distance with the attenuation. An attenuation of 0 means the limit distance is infinite and all sounds within the level are inside the limit. + float attn = std::min(chan->DistanceScale, attenuation); + if (attn <= 0 || (chanorigin - pos).LengthSquared() <= limit_range / attn) { count++; } diff --git a/source/common/audio/sound/s_soundinternal.h b/source/common/audio/sound/s_soundinternal.h index b3292637f..11dac776a 100644 --- a/source/common/audio/sound/s_soundinternal.h +++ b/source/common/audio/sound/s_soundinternal.h @@ -234,7 +234,7 @@ private: bool CheckSingular(int sound_id); virtual TArray ReadSound(int lumpnum) = 0; protected: - virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel); + virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel, float attenuation); virtual FSoundID ResolveSound(const void *ent, int srctype, FSoundID soundid, float &attenuation); public: diff --git a/source/common/console/c_console.cpp b/source/common/console/c_console.cpp index bcbdfdfdb..0b4a74a53 100644 --- a/source/common/console/c_console.cpp +++ b/source/common/console/c_console.cpp @@ -614,7 +614,7 @@ void C_DrawConsole () } else { - if (conflat.isValid()) + if (conflat.isValid() && gamestate != GS_FULLCONSOLE) { int conbright = 255 - APART(conshade); PalEntry pe((uint8_t(255 * con_alpha)), conbright, conbright, conbright); diff --git a/source/common/engine/startupinfo.h b/source/common/engine/startupinfo.h index 5054a4507..f47fa351f 100644 --- a/source/common/engine/startupinfo.h +++ b/source/common/engine/startupinfo.h @@ -12,6 +12,7 @@ struct FStartupInfo int Type; int LoadLights = -1; int LoadBrightmaps = -1; + int LoadWidescreen = -1; int modern = 0; enum { diff --git a/source/common/menu/menu.h b/source/common/menu/menu.h index 86db161ce..d6f200bfc 100644 --- a/source/common/menu/menu.h +++ b/source/common/menu/menu.h @@ -93,6 +93,7 @@ public: bool mAnimatedTransition; int mVirtWidth; int mVirtHeight; + bool mCustomSizeSet; void Reset(); }; diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp index ad89b6c27..f510b6d7a 100644 --- a/source/common/menu/menudef.cpp +++ b/source/common/menu/menudef.cpp @@ -267,10 +267,8 @@ static bool CheckSkipOptionBlock(FScanner &sc) // //============================================================================= -static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) +static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &sizecompatible, int insertIndex) { - bool sizeset = false; - bool sizecompatible = true; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -284,7 +282,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) if (!CheckSkipGameBlock(sc)) { // recursively parse sub-block - ParseListMenuBody(sc, desc); + DoParseListMenuBody(sc, desc, sizecompatible, insertIndex); } } else if (sc.Compare("ifnotgame")) @@ -292,7 +290,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) if (!CheckSkipGameBlock(sc, false)) { // recursively parse sub-block - ParseListMenuBody(sc, desc); + DoParseListMenuBody(sc, desc, sizecompatible, insertIndex); } } else if (sc.Compare("ifoption")) @@ -300,7 +298,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) if (!CheckSkipOptionBlock(sc)) { // recursively parse sub-block - ParseListMenuBody(sc, desc); + DoParseListMenuBody(sc, desc, sizecompatible, insertIndex); } } else if (sc.Compare("Class")) @@ -382,6 +380,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } else if (sc.Compare("size")) { + desc->mCustomSizeSet = true; if (sc.CheckNumber()) { desc->mVirtWidth = sc.Number; @@ -418,6 +417,17 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) PClass *cls = PClass::FindClass(buildname); if (cls != nullptr && cls->IsDescendantOf("ListMenuItem")) { + bool inserting = insertIndex >= 0; + bool isSelectable = cls->IsDescendantOf("ListMenuItemSelectable"); + double oldYpos = desc->mYpos; + + // [Player701] If this is a selectable item and we're inserting in the middle, + // set the Y position of the descriptor to the Y of the item we're inserting before. + if (isSelectable && inserting) + { + desc->mYpos = desc->mItems[insertIndex]->mYpos; + } + auto func = dyn_cast(cls->FindSymbol("Init", true)); if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protected init method. { @@ -528,11 +538,36 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); params[0] = item; VMCallWithDefaults(func->Variants[0].Implementation, params, nullptr, 0); - desc->mItems.Push((DMenuItemBase*)item); - if (cls->IsDescendantOf("ListMenuItemSelectable")) + if (!inserting) { - desc->mYpos += desc->mLinespacing; + desc->mItems.Push(item); + } + else + { + // [Player701] Insert item in between + desc->mItems.Insert(insertIndex, item); + insertIndex++; + } + + if (isSelectable) + { + if (inserting) + { + // [Player701] If we've inserted a selectable item, + // shift all following selectable items downwards + // NB: index has been incremented, so we're not affecting the newly inserted item here. + for (unsigned int i = insertIndex; i < desc->mItems.Size(); i++) + { + auto item = desc->mItems[i]; + if (item->GetClass()->IsDescendantOf("ListMenuItemSelectable")) + { + desc->mItems[i]->mYpos += desc->mLinespacing; + } + } + } + + desc->mYpos = oldYpos + desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1; } success = true; @@ -544,16 +579,24 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } } } - if (!sizeset && sizecompatible) // allow unclean scaling on this menu - { - desc->mVirtWidth = -2; - } for (auto &p : desc->mItems) { GC::WriteBarrier(p); } } +static void ParseListMenuBody(FScanner& sc, DListMenuDescriptor* desc, int insertIndex) +{ + bool sizecompatible = true; + DoParseListMenuBody(sc, desc, sizecompatible, insertIndex); + if (!desc->mCustomSizeSet && !sizecompatible) + { + // No custom size and incompatible items, + // so force clean scaling for this menu + desc->mVirtWidth = -1; + } +} + //============================================================================= // // @@ -700,11 +743,62 @@ static void ParseListMenu(FScanner &sc) desc->mWRight = 0; desc->mCenter = false; desc->mFromEngine = fileSystem.GetFileContainer(sc.LumpNum) == 0; // flags menu if the definition is from the IWAD. + desc->mVirtWidth = -2; + desc->mCustomSizeSet = false; - ParseListMenuBody(sc, desc); + ParseListMenuBody(sc, desc, -1); ReplaceMenu(sc, desc); } +//============================================================================= +// +// [Player701] Allow extending list menus +// +//============================================================================= + +static void ParseAddListMenu(FScanner& sc) +{ + sc.MustGetString(); + + DMenuDescriptor** pOld = MenuDescriptors.CheckKey(sc.String); + if (pOld == nullptr || *pOld == nullptr || !(*pOld)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor))) + { + sc.ScriptError("%s is not a list menu that can be extended", sc.String); + return; + } + + bool before = sc.CheckString("BEFORE"); + bool after = sc.CheckString("AFTER"); + + int insertIndex = -1; + + if (before || after) + { + // Find an existing menu item to use as insertion point + sc.MustGetString(); + + auto n = (*pOld)->mItems.Size(); + for (unsigned int i = 0; i < n; i++) + { + auto item = (*pOld)->mItems[i]; + + if (item->mAction == sc.String) + { + insertIndex = before ? i : i + 1; + break; + } + } + + // Inserting after the last item is the same as inserting at the end + if (insertIndex == n) insertIndex = -1; + + // Don't error out if we haven't found a suitable item + // to avoid backwards compatibility issues. + } + + ParseListMenuBody(sc, (DListMenuDescriptor*)(*pOld), insertIndex); +} + //============================================================================= // // @@ -1048,6 +1142,7 @@ static void ParseAddOptionMenu(FScanner &sc) if (pOld == nullptr || *pOld == nullptr || !(*pOld)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) { sc.ScriptError("%s is not an option menu that can be extended", sc.String); + return; } ParseOptionMenuBody(sc, (DOptionMenuDescriptor*)(*pOld)); } @@ -1296,12 +1391,17 @@ void M_ParseMenuDefs() } else if (sc.Compare("DEFAULTLISTMENU")) { - ParseListMenuBody(sc, DefaultListMenuSettings); + bool s = false; + DoParseListMenuBody(sc, DefaultListMenuSettings, s, -1); if (DefaultListMenuSettings->mItems.Size() > 0) { I_FatalError("You cannot add menu items to the menu default settings."); } } + else if (sc.Compare("ADDLISTMENU")) + { + ParseAddListMenu(sc); + } else if (sc.Compare("OPTIONVALUE")) { ParseOptionValue(sc); diff --git a/source/common/platform/win32/i_system.cpp b/source/common/platform/win32/i_system.cpp index 48bf64541..6a6119bf2 100644 --- a/source/common/platform/win32/i_system.cpp +++ b/source/common/platform/win32/i_system.cpp @@ -112,6 +112,7 @@ EXTERN_CVAR (Bool, queryiwad); EXTERN_CVAR (Bool, disableautoload) EXTERN_CVAR (Bool, autoloadlights) EXTERN_CVAR (Bool, autoloadbrightmaps) +EXTERN_CVAR (Bool, autoloadwidescreen) EXTERN_CVAR (Int, vid_preferbackend) extern HWND Window, ConWindow, GameTitleWindow; @@ -529,6 +530,7 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, disableautoload ? BST_CHECKED : BST_UNCHECKED, 0 ); SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, autoloadlights ? BST_CHECKED : BST_UNCHECKED, 0 ); SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, autoloadbrightmaps ? BST_CHECKED : BST_UNCHECKED, 0 ); + SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_SETCHECK, autoloadwidescreen ? BST_CHECKED : BST_UNCHECKED, 0 ); // Set up our version string. sprintf(szString, "Version %s.", GetVersionString()); @@ -583,6 +585,7 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa disableautoload = SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0 ) == BST_CHECKED; autoloadlights = SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; autoloadbrightmaps = SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; + autoloadwidescreen = SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; ctrl = GetDlgItem (hDlg, IDC_IWADLIST); EndDialog(hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0)); } diff --git a/source/common/platform/win32/resource.h b/source/common/platform/win32/resource.h index f6eff6188..f07a37083 100644 --- a/source/common/platform/win32/resource.h +++ b/source/common/platform/win32/resource.h @@ -153,6 +153,7 @@ #define IDC_WELCOME_NOAUTOLOAD 4023 #define IDC_WELCOME_LIGHTS 4024 #define IDC_WELCOME_BRIGHTMAPS 4025 +#define IDC_WELCOME_WIDESCREEN 1087 #define IDC_WELCOME_VULKAN 4026 #define IDC_WELCOME_VULKAN1 4026