diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 60d9067669..8610691abc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -474,7 +474,6 @@ endif() # Start defining source files for ZDoom set( PLAT_WIN32_SOURCES sound/mididevices/music_win_mididevice.cpp - win32/eaxedit.cpp win32/critsec.cpp win32/fb_d3d9.cpp win32/fb_d3d9_wipe.cpp diff --git a/src/s_environment.cpp b/src/s_environment.cpp index 0e3bd12e81..4d83dd2d44 100644 --- a/src/s_environment.cpp +++ b/src/s_environment.cpp @@ -3,7 +3,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 2005-2016 Randy Heit -** Copyright 2005-2016 Christoph Oelckers +** Copyright 2005-2017 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -40,6 +40,27 @@ #include "templates.h" #include "w_wad.h" #include "i_system.h" +#include "m_misc.h" + +#include "c_cvars.h" +#include "c_dispatch.h" +#include "files.h" +#include "vm.h" +#include "dobject.h" +#include "menu/menu.h" + + + +void InitReverbMenu(); +REVERB_PROPERTIES SavedProperties; +ReverbContainer *CurrentEnv; +extern ReverbContainer *ForcedEnvironment; + +// These are for internal use only and not supposed to be user-settable +CVAR(String, reverbedit_name, "", CVAR_NOSET); +CVAR(Int, reverbedit_id1, 0, CVAR_NOSET); +CVAR(Int, reverbedit_id2, 0, CVAR_NOSET); +CVAR(String, reverbsavename, "", 0); struct FReverbField { @@ -49,6 +70,7 @@ struct FReverbField unsigned int Flag; }; + static const FReverbField ReverbFields[] = { { 0, 25, 0, &REVERB_PROPERTIES::Environment, 0 }, @@ -629,6 +651,7 @@ void S_ParseReverbDef () { ReadReverbDef (lump); } + InitReverbMenu(); } void S_UnloadReverbDef () @@ -653,3 +676,477 @@ void S_UnloadReverbDef () } Environments = &Off; } + +CUSTOM_CVAR(Bool, eaxedit_test, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + if (self) + { + ForcedEnvironment = CurrentEnv; + } + else + { + ForcedEnvironment = nullptr; + } +} + +struct EnvFlag +{ + const char *Name; + int CheckboxControl; + unsigned int Flag; +}; + +inline int HIBYTE(int i) +{ + return (i >> 8) & 255; +} + +inline int LOBYTE(int i) +{ + return i & 255; +} + +uint16_t FirstFreeID(uint16_t base, bool builtin) +{ + int tryCount = 0; + int priID = HIBYTE(base); + + // If the original sound is built-in, start searching for a new + // primary ID at 30. + if (builtin) + { + for (priID = 30; priID < 256; ++priID) + { + if (S_FindEnvironment(priID << 8) == nullptr) + { + break; + } + } + if (priID == 256) + { // Oh well. + priID = 30; + } + } + + for (;;) + { + uint16_t lastID = Environments->ID; + const ReverbContainer *env = Environments->Next; + + // Find the lowest-numbered free ID with the same primary ID as base + // If none are available, add 100 to base's primary ID and try again. + // If that fails, then the primary ID gets incremented + // by 1 until a match is found. If all the IDs searchable by this + // algorithm are in use, then you're in trouble. + + while (env != nullptr) + { + if (HIBYTE(env->ID) > priID) + { + break; + } + if (HIBYTE(env->ID) == priID) + { + if (HIBYTE(lastID) == priID) + { + if (LOBYTE(env->ID) - LOBYTE(lastID) > 1) + { + return lastID + 1; + } + } + lastID = env->ID; + } + env = env->Next; + } + if (LOBYTE(lastID) == 255) + { + if (tryCount == 0) + { + base += 100 * 256; + tryCount = 1; + } + else + { + base += 256; + } + } + else if (builtin && lastID == 0) + { + return priID << 8; + } + else + { + return lastID + 1; + } + } +} + +FString SuggestNewName(const ReverbContainer *env) +{ + const ReverbContainer *probe = nullptr; + char text[32]; + size_t len; + int number, numdigits; + + strncpy(text, env->Name, 31); + text[31] = 0; + + len = strlen(text); + while (text[len - 1] >= '0' && text[len - 1] <= '9') + { + len--; + } + number = atoi(text + len); + if (number < 1) + { + number = 1; + } + + if (text[len - 1] != ' ' && len < 31) + { + text[len++] = ' '; + } + + for (; number < 100000; ++number) + { + if (number < 10) numdigits = 1; + else if (number < 100) numdigits = 2; + else if (number < 1000) numdigits = 3; + else if (number < 10000)numdigits = 4; + else numdigits = 5; + if (len + numdigits > 31) + { + len = 31 - numdigits; + } + mysnprintf(text + len, countof(text) - len, "%d", number); + + probe = Environments; + while (probe != nullptr) + { + if (stricmp(probe->Name, text) == 0) + break; + probe = probe->Next; + } + if (probe == nullptr) + { + break; + } + } + return text; +} + +void ExportEnvironments(const char *filename, uint32_t count, const ReverbContainer **envs) +{ + FString dest = M_GetDocumentsPath() + filename; + + FileWriter *f = FileWriter::Open(dest); + + if (f != nullptr) + { + for (uint32_t i = 0; i < count; ++i) + { + const ReverbContainer *env = envs[i]; + const ReverbContainer *base; + size_t j; + + if ((unsigned int)env->Properties.Environment < 26) + { + base = DefaultEnvironments[env->Properties.Environment]; + } + else + { + base = nullptr; + } + f->Printf("\"%s\" %u %u\n{\n", env->Name, HIBYTE(env->ID), LOBYTE(env->ID)); + for (j = 0; j < countof(ReverbFields); ++j) + { + const FReverbField *ctl = &ReverbFields[j]; + const char *ctlName = ReverbFieldNames[j]; + if (ctlName) + { + if (j == 0 || + (ctl->Float && base->Properties.*ctl->Float != env->Properties.*ctl->Float) || + (ctl->Int && base->Properties.*ctl->Int != env->Properties.*ctl->Int)) + { + f->Printf("\t%s ", ctlName); + if (ctl->Float) + { + float v = env->Properties.*ctl->Float * 1000; + int vi = int(v >= 0.0 ? v + 0.5 : v - 0.5); + f->Printf("%d.%03d\n", vi / 1000, abs(vi % 1000)); + } + else + { + f->Printf("%d\n", env->Properties.*ctl->Int); + } + } + else + { + if ((1 << ctl->Flag) & (env->Properties.Flags ^ base->Properties.Flags)) + { + f->Printf("\t%s %s\n", ctlName, ctl->Flag & env->Properties.Flags ? "true" : "false"); + } + } + } + } + f->Printf("}\n\n"); + } + delete f; + } + else + { + M_StartMessage("Save failed", 1); + } +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, GetValue) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + float v; + + if (index >= 0 && index < countof(ReverbFields)) + { + auto rev = &ReverbFields[index]; + if (rev->Int != nullptr) + { + v = float(CurrentEnv->Properties.*(rev->Int)); + } + else if (rev->Float != nullptr) + { + v = CurrentEnv->Properties.*(rev->Float); + } + else + { + v = !!(CurrentEnv->Properties.Flags & (1 << int(rev->Flag))); + } + } + ACTION_RETURN_FLOAT(v); + return 1; +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, SetValue) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + PARAM_FLOAT(v); + + if (index >= 0 && index < countof(ReverbFields)) + { + auto rev = &ReverbFields[index]; + if (rev->Int != nullptr) + { + v = CurrentEnv->Properties.*(rev->Int) = clamp(int(v), rev->Min, rev->Max); + } + else if (rev->Float != nullptr) + { + v = CurrentEnv->Properties.*(rev->Float) = clamp(float(v), rev->Min / 1000.f, rev->Max / 1000.f); + } + else + { + if (v == 0) CurrentEnv->Properties.Flags &= ~(1 << int(rev->Flag)); + else CurrentEnv->Properties.Flags |= (1 << int(rev->Flag)); + } + } + + ACTION_RETURN_FLOAT(v); + return 1; +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, GrayCheck) +{ + PARAM_PROLOGUE; + ACTION_RETURN_BOOL(CurrentEnv->Builtin); + return 1; +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, GetSelectedEnvironment) +{ + PARAM_PROLOGUE; + if (numret > 1) + { + numret = 2; + ret[1].SetInt(CurrentEnv ? CurrentEnv->ID : -1); + } + if (numret > 0) + { + ret[0].SetString(CurrentEnv ? CurrentEnv->Name : ""); + } + return numret; +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, FillSelectMenu) +{ + PARAM_PROLOGUE; + PARAM_STRING(ccmd); + PARAM_OBJECT(desc, DOptionMenuDescriptor); + desc->mItems.Clear(); + for (auto env = Environments; env != nullptr; env = env->Next) + { + FStringf text("(%d, %d) %s", HIBYTE(env->ID), LOBYTE(env->ID), env->Name); + FStringf cmd("%s \"%s\"", ccmd.GetChars(), env->Name); + PClass *cls = PClass::FindClass("OptionMenuItemCommand"); + if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem")) + { + auto func = dyn_cast(cls->FindSymbol("Init", true)); + if (func != nullptr) + { + DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); + VMValue params[] = { item, &text, FName(cmd).GetIndex(), false, true }; + VMCall(func->Variants[0].Implementation, params, 5, nullptr, 0); + desc->mItems.Push((DMenuItemBase*)item); + } + } + } + return 0; +} + +static TArray> SaveState; + +DEFINE_ACTION_FUNCTION(DReverbEdit, FillSaveMenu) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(desc, DOptionMenuDescriptor); + desc->mItems.Resize(4); + SaveState.Clear(); + for (auto env = Environments; env != nullptr; env = env->Next) + { + if (!env->Builtin) + { + int index = (int)SaveState.Push(std::make_pair(env, false)); + + FStringf text("(%d, %d) %s", HIBYTE(env->ID), LOBYTE(env->ID), env->Name); + PClass *cls = PClass::FindClass("OptionMenuItemReverbSaveSelect"); + if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem")) + { + auto func = dyn_cast(cls->FindSymbol("Init", true)); + if (func != nullptr) + { + DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); + VMValue params[] = { item, &text, index, FName("OnOff").GetIndex() }; + VMCall(func->Variants[0].Implementation, params, 4, nullptr, 0); + desc->mItems.Push((DMenuItemBase*)item); + } + } + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, GetSaveSelection) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + bool res = false; + if ((unsigned)index <= SaveState.Size()) + { + res = SaveState[index].second; + } + ACTION_RETURN_BOOL(res); +} + +DEFINE_ACTION_FUNCTION(DReverbEdit, ToggleSaveSelection) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + if ((unsigned)index <= SaveState.Size()) + { + SaveState[index].second = !SaveState[index].second; + } + return 0; +} + + +CCMD(savereverbs) +{ + if (SaveState.Size() == 0) return; + + TArray toSave; + + for (auto &p : SaveState) + { + if (p.second) toSave.Push(p.first); + } + ExportEnvironments(reverbsavename, toSave.Size(), &toSave[0]); + SaveState.Clear(); +} + +static void SelectEnvironment(const char *envname) +{ + for (auto env = Environments; env != nullptr; env = env->Next) + { + if (!strcmp(env->Name, envname)) + { + CurrentEnv = env; + SavedProperties = env->Properties; + if (eaxedit_test) ForcedEnvironment = env; + + // Set up defaults for a new environment based on this one. + int newid = FirstFreeID(env->ID, env->Builtin); + UCVarValue cv; + cv.Int = HIBYTE(newid); + reverbedit_id1.ForceSet(cv, CVAR_Int); + cv.Int = LOBYTE(newid); + reverbedit_id2.ForceSet(cv, CVAR_Int); + FString selectname = SuggestNewName(env); + cv.String = selectname.GetChars(); + reverbedit_name.ForceSet(cv, CVAR_String); + return; + } + } +} + +void InitReverbMenu() +{ + // Make sure that the editor's variables are properly initialized. + SelectEnvironment("Off"); +} + +CCMD(selectenvironment) +{ + if (argv.argc() > 1) + { + auto str = argv[1]; + SelectEnvironment(str); + } + else + InitReverbMenu(); +} + +CCMD(revertenvironment) +{ + if (CurrentEnv != nullptr) + { + CurrentEnv->Properties = SavedProperties; + } +} + +CCMD(createenvironment) +{ + if (S_FindEnvironment(reverbedit_name)) + { + M_StartMessage(FStringf("An environment with the name '%s' already exists", *reverbedit_name), 1); + return; + } + int id = (reverbedit_id1 << 8) + reverbedit_id2; + if (S_FindEnvironment(id)) + { + M_StartMessage(FStringf("An environment with the ID (%d, %d) already exists", *reverbedit_id1, *reverbedit_id2), 1); + return; + } + + auto newenv = new ReverbContainer; + newenv->Builtin = false; + newenv->ID = id; + newenv->Name = copystring(reverbedit_name); + newenv->Next = nullptr; + newenv->Properties = CurrentEnv->Properties; + S_AddEnvironment(newenv); + SelectEnvironment(newenv->Name); +} + +CCMD(reverbedit) +{ + C_DoCommand("openmenu reverbedit"); +} + diff --git a/src/win32/eaxedit.cpp b/src/win32/eaxedit.cpp deleted file mode 100644 index a5a4b81168..0000000000 --- a/src/win32/eaxedit.cpp +++ /dev/null @@ -1,1412 +0,0 @@ -/* -** -** -**--------------------------------------------------------------------------- -** Copyright 2005-2016 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT 0x0500 -#define _WIN32_IE 0x0500 -#include -#include -#include - -#include -#include -#include - -#include "resource.h" -#include "s_sound.h" -#include "templates.h" -#include "cmdlib.h" -#include "c_dispatch.h" -#include "c_cvars.h" -#include "doomstat.h" -#include "v_video.h" - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -// More w32api lackings -#ifndef TTM_SETTITLE -#define TTM_SETTITLEA (WM_USER+32) -#define TTM_SETTITLEW (WM_USER+33) -#ifdef UNICODE -#define TTM_SETTITLE TTM_SETTITLEW -#else -#define TTM_SETTITLE TTM_SETTITLEA -#endif -#endif -#ifndef TTF_TRACK -#define TTF_TRACK 0x0020 -#endif -#ifndef TTF_TRANSPARENT -#define TTF_TRANSPARENT 0x0100 -#endif - -#ifndef OFN_ENABLESIZING -#define OFN_ENABLESIZING 0x00800000 -typedef struct w32apiFixedOFNA { - DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCSTR lpstrFilter; - LPSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPSTR lpstrFile; - DWORD nMaxFile; - LPSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCSTR lpstrInitialDir; - LPCSTR lpstrTitle; - DWORD Flags; - uint16_t nFileOffset; - uint16_t nFileExtension; - LPCSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCSTR lpTemplateName; - void *pvReserved; - DWORD dwReserved; - DWORD FlagsEx; -} FIXEDOPENFILENAMEA; -#define OPENFILENAME FIXEDOPENFILENAMEA -#endif - -extern HINSTANCE g_hInst; -extern HWND Window; -extern bool ForceWindowed; -EXTERN_CVAR (Bool, fullscreen) -extern ReverbContainer *ForcedEnvironment; - -HWND EAXEditWindow; -HWND hPropList; -POINT PropListMaxSize; -LONG PropListHeightDiff; -POINT EditWindowSize; -POINT DoneLocation; -WNDPROC StdEditProc; -LONG NewLeft; -LONG SaveLeft; -LONG RevertLeft; -POINT TestLocation; - -bool SpawnEAXWindow; - -REVERB_PROPERTIES SavedProperties; -ReverbContainer *CurrentEnv; - -CUSTOM_CVAR (Bool, eaxedit_test, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) -{ - if (EAXEditWindow != 0) - { - CheckDlgButton (EAXEditWindow, IDC_TESTEAX, self ? BST_CHECKED : BST_UNCHECKED); - if (self) - { - ForcedEnvironment = CurrentEnv; - } - else - { - ForcedEnvironment = NULL; - } - } -} - -struct MySaveData -{ - const ReverbContainer *Default; - const ReverbContainer **Saves; - UINT NumSaves; - - MySaveData (const ReverbContainer *def) - : Default (def), Saves (NULL), NumSaves (0) {} - ~MySaveData () - { - if (Saves) delete[] Saves; - } -}; - -struct EnvControl -{ - const char *Name; - int EditControl; - int SliderControl; - int Min; - int Max; - float REVERB_PROPERTIES::*Float; - int REVERB_PROPERTIES::*Int; - HWND EditHWND; - HWND SliderHWND; -}; - -struct EnvFlag -{ - const char *Name; - int CheckboxControl; - unsigned int Flag; - HWND CheckboxHWND; -}; - -void PopulateEnvDropDown (HWND hCtl); -void SetupEnvControls (HWND hDlg); -void UpdateControls (const ReverbContainer *env, HWND hDlg); -void UpdateControl (const EnvControl *control, int value, bool slider); - -EnvControl EnvControls[] = -{ - { "Environment", 0, 0, 0, 25, 0, &REVERB_PROPERTIES::Environment }, - { "EnvironmentSize", IDCE_ENVIRONMENTSIZE, IDCS_ENVIRONMENTSIZE, 1000, 100000, &REVERB_PROPERTIES::EnvSize, 0 }, - { "EnvironmentDiffusion", IDCE_ENVIRONMENTDIFFUSION, IDCS_ENVIRONMENTDIFFUSION, 0, 1000, &REVERB_PROPERTIES::EnvDiffusion, 0 }, - { "Room", IDCE_ROOM, IDCS_ROOM, -10000, 0, 0, &REVERB_PROPERTIES::Room }, - { "RoomHF", IDCE_ROOMHF, IDCS_ROOMHF, -10000, 0, 0, &REVERB_PROPERTIES::RoomHF }, - { "RoomLF", IDCE_ROOMLF, IDCS_ROOMLF, -10000, 0, 0, &REVERB_PROPERTIES::RoomLF }, - { "DecayTime", IDCE_DECAYTIME, IDCS_DECAYTIME, 100, 20000, &REVERB_PROPERTIES::DecayTime, 0 }, - { "DecayHFRatio", IDCE_DECAYHFRATIO, IDCS_DECAYHFRATIO, 100, 2000, &REVERB_PROPERTIES::DecayHFRatio, 0 }, - { "DecayLFRatio", IDCE_DECAYLFRATIO, IDCS_DECAYLFRATIO, 100, 2000, &REVERB_PROPERTIES::DecayLFRatio, 0 }, - { "Reflections", IDCE_REFLECTIONS, IDCS_REFLECTIONS, -10000, 1000, 0, &REVERB_PROPERTIES::Reflections }, - { "ReflectionsDelay", IDCE_REFLECTIONSDELAY, IDCS_REFLECTIONSDELAY, 0, 300, &REVERB_PROPERTIES::ReflectionsDelay, 0 }, - { "ReflectionsPanX", IDCE_REFLECTIONSPANX, IDCS_REFLECTIONSPANX, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan0, 0 }, - { "ReflectionsPanY", IDCE_REFLECTIONSPANY, IDCS_REFLECTIONSPANY, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan1, 0 }, - { "ReflectionsPanZ", IDCE_REFLECTIONSPANZ, IDCS_REFLECTIONSPANZ, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan2, 0 }, - { "Reverb", IDCE_REVERB, IDCS_REVERB, -10000, 2000, 0, &REVERB_PROPERTIES::Reverb }, - { "ReverbDelay", IDCE_REVERBDELAY, IDCS_REVERBDELAY, 0, 100, &REVERB_PROPERTIES::ReverbDelay, 0 }, - { "ReverbPanX", IDCE_REVERBPANX, IDCS_REVERBPANX, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan0, 0 }, - { "ReverbPanY", IDCE_REVERBPANY, IDCS_REVERBPANY, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan1, 0 }, - { "ReverbPanZ", IDCE_REVERBPANZ, IDCS_REVERBPANZ, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan2, 0 }, - { "EchoTime", IDCE_ECHOTIME, IDCS_ECHOTIME, 75, 250, &REVERB_PROPERTIES::EchoTime, 0 }, - { "EchoDepth", IDCE_ECHODEPTH, IDCS_ECHODEPTH, 0, 1000, &REVERB_PROPERTIES::EchoDepth, 0 }, - { "ModulationTime", IDCE_MODULATIONTIME, IDCS_MODULATIONTIME, 40, 4000, &REVERB_PROPERTIES::ModulationTime, 0 }, - { "ModulationDepth", IDCE_MODULATIONDEPTH, IDCS_MODULATIONDEPTH, 0, 1000, &REVERB_PROPERTIES::ModulationDepth, 0 }, - { "AirAbsorptionHF", IDCE_AIRABSORPTIONHF, IDCS_AIRABSORPTIONHF, -100000, 0, &REVERB_PROPERTIES::AirAbsorptionHF, 0 }, - { "HFReference", IDCE_HFREFERENCE, IDCS_HFREFERENCE, 1000000, 20000000, &REVERB_PROPERTIES::HFReference, 0 }, - { "LFReference", IDCE_LFREFERENCE, IDCS_LFREFERENCE, 20000, 1000000, &REVERB_PROPERTIES::LFReference, 0 }, - { "RoomRolloffFactor", IDCE_ROOMROLLOFFFACTOR, IDCS_ROOMROLLOFFFACTOR, 0, 10000, &REVERB_PROPERTIES::RoomRolloffFactor, 0 }, - { "Diffusion", 0, 0, 0, 100000, &REVERB_PROPERTIES::Diffusion, 0 }, - { "Density", 0, 0, 0, 100000, &REVERB_PROPERTIES::Density, 0 }, -}; - -EnvFlag EnvFlags[] = -{ - { "bReflectionsScale", IDC_REFLECTIONSSCALE, REVERB_FLAGS_REFLECTIONSSCALE }, - { "bReflectionsDelayScale", IDC_REFLECTIONSDELAYSCALE, REVERB_FLAGS_REFLECTIONSDELAYSCALE }, - { "bDecayTimeScale", IDC_DECAYTIMESCALE, REVERB_FLAGS_DECAYTIMESCALE }, - { "bDecayHFLimit", IDC_DECAYHFLIMIT, REVERB_FLAGS_DECAYHFLIMIT }, - { "bReverbScale", IDC_REVERBSCALE, REVERB_FLAGS_REVERBSCALE }, - { "bReverbDelayScale", IDC_REVERBDELAYSCALE, REVERB_FLAGS_REVERBDELAYSCALE }, - { "bEchoTimeScale", IDC_ECHOTIMESCALE, REVERB_FLAGS_ECHOTIMESCALE }, - { "bModulationTimeScale", IDC_MODULATIONTIMESCALE, REVERB_FLAGS_MODULATIONTIMESCALE } -}; - -LRESULT AddEnvToDropDown (HWND hCtl, bool showID, const ReverbContainer *env) -{ - char buff[128]; - LRESULT i; - - if (showID) - { - mysnprintf (buff, countof(buff), "(%3d,%3d) %s", HIBYTE(env->ID), LOBYTE(env->ID), env->Name); - i = SendMessage (hCtl, CB_ADDSTRING, 0, (LPARAM)buff); - } - else - { - i = SendMessage (hCtl, CB_ADDSTRING, 0, (LPARAM)env->Name); - } - SendMessage (hCtl, CB_SETITEMDATA, i, (LPARAM)env); - return i; -} - -void PopulateEnvDropDown (HWND hCtl, bool showIDs, const ReverbContainer *defEnv) -{ - const ReverbContainer *env; - WPARAM envCount = 0; - LPARAM strCount = 0; - LRESULT i; - - for (env = Environments; env != NULL; env = env->Next) - { - envCount++; - strCount += strlen (env->Name) + 1; - } - - SendMessage (hCtl, WM_SETREDRAW, FALSE, 0); - SendMessage (hCtl, CB_RESETCONTENT, 0, 0); - SendMessage (hCtl, CB_INITSTORAGE, envCount, showIDs ? - strCount + envCount * 10 : strCount); - - for (env = Environments; env != NULL; env = env->Next) - { - AddEnvToDropDown (hCtl, showIDs, env); - } - - SendMessage (hCtl, WM_SETREDRAW, TRUE, 0); - - if (defEnv == NULL) - { - SendMessage (hCtl, CB_SETCURSEL, 0, 0); - SetFocus (hCtl); - } - else - { - for (i = 0; i < (LPARAM)envCount; ++i) - { - if ((const ReverbContainer *)SendMessage (hCtl, CB_GETITEMDATA, i, 0) - == defEnv) - { - SendMessage (hCtl, CB_SETCURSEL, i, 0); - break; - } - } - } -} - -void SetIDEdits (HWND hDlg, uint16_t id) -{ - char text[4]; - - mysnprintf (text, countof(text), "%d", HIBYTE(id)); - SendMessage (GetDlgItem (hDlg, IDC_EDITID1), WM_SETTEXT, 0, (LPARAM)text); - mysnprintf (text, countof(text), "%d", LOBYTE(id)); - SendMessage (GetDlgItem (hDlg, IDC_EDITID2), WM_SETTEXT, 0, (LPARAM)text); -} - -void PopulateEnvList (HWND hCtl, bool show, const ReverbContainer *defEnv) -{ - const ReverbContainer *env; - int i; - LVITEM item; - - SendMessage (hCtl, WM_SETREDRAW, FALSE, 0); - - item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; - item.stateMask = LVIS_SELECTED|LVIS_FOCUSED; - item.iSubItem = 0; - - for (env = Environments, i = 0; env != NULL; env = env->Next, ++i) - { - if (!env->Builtin || show) - { - item.iItem = i; - item.pszText = (LPSTR)env->Name; - item.lParam = (LPARAM)env; - item.state = env == defEnv ? LVIS_SELECTED|LVIS_FOCUSED : 0; - SendMessage (hCtl, LVM_INSERTITEM, 0, (LPARAM)&item); - } - } - - SendMessage (hCtl, WM_SETREDRAW, TRUE, 0); -} - -uint16_t FirstFreeID (uint16_t base, bool builtin) -{ - int tryCount = 0; - int priID = HIBYTE(base); - - // If the original sound is built-in, start searching for a new - // primary ID at 30. - if (builtin) - { - for (priID = 30; priID < 256; ++priID) - { - if (S_FindEnvironment (priID << 8) == NULL) - { - break; - } - } - if (priID == 256) - { // Oh well. - priID = 30; - } - } - - for (;;) - { - uint16_t lastID = Environments->ID; - const ReverbContainer *env = Environments->Next; - - // Find the lowest-numbered free ID with the same primary ID as base - // If none are available, add 100 to base's primary ID and try again. - // If that fails, then the primary ID gets incremented - // by 1 until a match is found. If all the IDs searchable by this - // algorithm are in use, then you're in trouble. - - while (env != NULL) - { - if (HIBYTE(env->ID) > priID) - { - break; - } - if (HIBYTE(env->ID) == priID) - { - if (HIBYTE(lastID) == priID) - { - if (LOBYTE(env->ID) - LOBYTE(lastID) > 1) - { - return lastID+1; - } - } - lastID = env->ID; - } - env = env->Next; - } - if (LOBYTE(lastID) == 255) - { - if (tryCount == 0) - { - base += 100*256; - tryCount = 1; - } - else - { - base += 256; - } - } - else if (builtin && lastID == 0) - { - return priID << 8; - } - else - { - return lastID+1; - } - } -} - -LRESULT CALLBACK EditControlProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - char buff[16]; - double val; - const EnvControl *env; - MSG *msg; - - switch (uMsg) - { - case WM_GETDLGCODE: - msg = (MSG *)lParam; - if (msg && LOWORD(msg->message) == WM_KEYDOWN) - { - // Do not close the dialog if Enter was pressed - // inside an edit control. - if (msg->wParam == VK_RETURN || msg->wParam == VK_ESCAPE) - { - return DLGC_WANTALLKEYS; - } - } - break; - - case WM_CHAR: - // Only allow numeric symbols. - if (wParam >= ' ' && wParam <= 127 && - (wParam < '0' || wParam > '9') && - wParam != '.' && - wParam != '-' && - wParam != '+') - { - return 0; - } - break; - - case WM_KEYDOWN: - if (wParam != VK_RETURN) - { - if (wParam == VK_ESCAPE) - { // Put the original value back in the edit control. - env = (const EnvControl *)(LONG_PTR)GetWindowLongPtr (hWnd, GWLP_USERDATA); - int vali = SendMessage (env->SliderHWND, TBM_GETPOS, 0, 0); - if (env->Float) - { - mysnprintf (buff, countof(buff), "%d.%03d", vali/1000, abs(vali%1000)); - } - else - { - mysnprintf (buff, countof(buff), "%d", vali); - } - CallWindowProc (StdEditProc, hWnd, WM_SETTEXT, 0, (LPARAM)buff); - CallWindowProc (StdEditProc, hWnd, EM_SETSEL, 0, -1); - return 0; - } - break; - } - - // intentional fallthrough - - case WM_KILLFOCUS: - // Validate the new value and update the corresponding slider. - env = (const EnvControl *)(LONG_PTR)GetWindowLongPtr (hWnd, GWLP_USERDATA); - val = 0.0; - if (CallWindowProc (StdEditProc, hWnd, WM_GETTEXT, 16, (LPARAM)buff) > 0) - { - val = atof (buff); - } - if (env->Float) - { - val *= 1000.0; - } - if (val < env->Min) val = env->Min; - else if (val > env->Max) val = env->Max; - UpdateControl (env, int(val), true); - break; - } - return CallWindowProc (StdEditProc, hWnd, uMsg, wParam, lParam); -} - -LRESULT CALLBACK EditControlProcNoDeci (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - // This is just like the above WndProc, except it only accepts integers. - if (uMsg == WM_CHAR && wParam == '.') - { - return 0; - } - return EditControlProc (hWnd, uMsg, wParam, lParam); -} - -void SetupEnvControls (HWND hDlg) -{ - size_t i; - - for (i = 0; i < countof(EnvControls); ++i) - { - if (EnvControls[i].EditControl == 0) - continue; - - EnvControls[i].EditHWND = GetDlgItem (hDlg, EnvControls[i].EditControl); - EnvControls[i].SliderHWND = GetDlgItem (hDlg, EnvControls[i].SliderControl); - SendMessage (EnvControls[i].SliderHWND, TBM_SETRANGEMIN, FALSE, EnvControls[i].Min); - SendMessage (EnvControls[i].SliderHWND, TBM_SETRANGEMAX, TRUE, EnvControls[i].Max); - SendMessage (EnvControls[i].EditHWND, EM_LIMITTEXT, 10, 0); - StdEditProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr (EnvControls[i].EditHWND, GWLP_WNDPROC, - (LONG_PTR)(EnvControls[i].Float ? EditControlProc : EditControlProcNoDeci)); - SetWindowLongPtr (EnvControls[i].EditHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]); - SetWindowLongPtr (EnvControls[i].SliderHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]); - } - for (i = 0; i < countof(EnvFlags); ++i) - { - EnvFlags[i].CheckboxHWND = GetDlgItem (hDlg, EnvFlags[i].CheckboxControl); - SetWindowLongPtr (EnvFlags[i].CheckboxHWND, GWLP_USERDATA, (LONG_PTR)&EnvFlags[i]); - } -} - -void UpdateControl (const EnvControl *control, int value, bool slider) -{ - char buff[16]; - - if (slider) - { - SendMessage (control->SliderHWND, TBM_SETPOS, TRUE, value); - } - if (control->Float) - { - mysnprintf (buff, countof(buff), "%d.%03d", value/1000, abs(value%1000)); - if (CurrentEnv != NULL) - { - CurrentEnv->Properties.*control->Float = float(value) / 1000.0; - } - } - else - { - mysnprintf (buff, countof(buff), "%d", value); - if (CurrentEnv != NULL) - { - CurrentEnv->Properties.*control->Int = value; - } - } - SendMessage (control->EditHWND, WM_SETTEXT, 0, (LPARAM)buff); - if (CurrentEnv != NULL) - { - CurrentEnv->Modified = true; - } -} - -void UpdateControls (ReverbContainer *env, HWND hDlg) -{ - char buff[4]; - size_t i; - - if (env == NULL) - return; - - CurrentEnv = NULL; - - for (i = 0; i < countof(EnvControls); ++i) - { - EnvControl *ctrl = &EnvControls[i]; - - if (ctrl->Float) - { - float v = env->Properties.*ctrl->Float * 1000; - UpdateControl (ctrl, int(v >= 0.0 ? v + 0.5 : v - 0.5), true); - } - else - { - UpdateControl (ctrl, env->Properties.*ctrl->Int, true); - } - EnableWindow (ctrl->EditHWND, !env->Builtin); - EnableWindow (ctrl->SliderHWND, !env->Builtin); - } - for (i = 0; i < countof(EnvFlags); ++i) - { - SendMessage (EnvFlags[i].CheckboxHWND, BM_SETCHECK, - (env->Properties.Flags & EnvFlags[i].Flag) ? BST_CHECKED : BST_UNCHECKED, 0); - EnableWindow (EnvFlags[i].CheckboxHWND, !env->Builtin); - } - EnableWindow (GetDlgItem (hDlg, IDC_REVERT), !env->Builtin); - - mysnprintf (buff, countof(buff), "%d", HIBYTE(env->ID)); - SendMessage (GetDlgItem (hDlg, IDC_ID1), WM_SETTEXT, 0, (LPARAM)buff); - - mysnprintf (buff, countof(buff), "%d", LOBYTE(env->ID)); - SendMessage (GetDlgItem (hDlg, IDC_ID2), WM_SETTEXT, 0, (LPARAM)buff); - - SavedProperties = env->Properties; - CurrentEnv = env; - - if (SendMessage (GetDlgItem (hDlg, IDC_TESTEAX), BM_GETCHECK, 0,0) == BST_CHECKED) - { - ForcedEnvironment = env; - } -} - -INT_PTR CALLBACK EAXProp (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - const EnvControl *env; - SCROLLINFO si; - int yPos; - - switch (uMsg) - { - case WM_INITDIALOG: - SetupEnvControls (hDlg); - return FALSE; - - case WM_VSCROLL: - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - GetScrollInfo (hDlg, SB_VERT, &si); - yPos = si.nPos; - - switch (LOWORD(wParam)) - { - case SB_TOP: si.nPos = si.nMin; break; - case SB_BOTTOM: si.nPos = si.nMax; break; - case SB_LINEUP: si.nPos -= 16; break; - case SB_LINEDOWN: si.nPos += 16; break; - case SB_PAGEUP: si.nPos -= si.nPage; break; - case SB_PAGEDOWN: si.nPos += si.nPage; break; - case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; - } - si.fMask = SIF_POS; - SetScrollInfo (hDlg, SB_VERT, &si, TRUE); - GetScrollInfo (hDlg, SB_VERT, &si); - if (si.nPos != yPos) - { - ScrollWindow (hDlg, 0, yPos - si.nPos, NULL, NULL); - UpdateWindow (hDlg); - } - return TRUE; - - case WM_HSCROLL: - env = (const EnvControl *)(LONG_PTR)GetWindowLongPtr ((HWND)lParam, GWLP_USERDATA); - UpdateControl (env, SendMessage ((HWND)lParam, TBM_GETPOS, 0, 0), false); - return TRUE; - - case WM_SIZE: - if (wParam != SIZE_MAXSHOW && wParam != SIZE_MAXHIDE) - { - si.cbSize = sizeof(si); - si.fMask = SIF_POS; - GetScrollInfo (hDlg, SB_VERT, &si); - yPos = si.nPos; - - // If we let the scroll bar disappear, then when that happens, - // it will resize the window before SetScrollInfo returns. - // Rather than checking for recursive WM_SIZE messages, I choose - // to force the scroll bar to always be present. The dialog is - // really designed with the appearance of the scroll bar in - // mind anyway, since it does nothing to resize the controls - // horizontally. - - si.fMask = SIF_POS|SIF_PAGE|SIF_DISABLENOSCROLL; - si.nPage = HIWORD(lParam); - - SetScrollInfo (hDlg, SB_VERT, &si, TRUE); - GetScrollInfo (hDlg, SB_VERT, &si); - if (si.nPos != yPos) - { - ScrollWindow (hDlg, 0, yPos - si.nPos, NULL, NULL); - UpdateWindow (hDlg); - } - } - return TRUE; - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED && CurrentEnv != NULL) - { - for (size_t i = 0; i < countof(EnvFlags); ++i) - { - if ((HWND)lParam == EnvFlags[i].CheckboxHWND) - { - if (SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED) - { - CurrentEnv->Properties.Flags |= EnvFlags[i].Flag; - } - else - { - CurrentEnv->Properties.Flags &= ~EnvFlags[i].Flag; - } - return TRUE;; - } - } - } - return FALSE; - } - return FALSE; -} - -void SuggestNewName (const ReverbContainer *env, HWND hEdit) -{ - const ReverbContainer *probe = NULL; - char text[32]; - size_t len; - int number, numdigits; - - strncpy (text, env->Name, 31); - text[31] = 0; - - len = strlen (text); - while (text[len-1] >= '0' && text[len-1] <= '9') - { - len--; - } - number = atoi (text + len); - if (number < 1) - { - number = 1; - } - - if (text[len-1] != ' ' && len < 31) - { - text[len++] = ' '; - } - - for (; number < 100000; ++number) - { - if (number < 10) numdigits = 1; - else if (number < 100) numdigits = 2; - else if (number < 1000) numdigits = 3; - else if (number < 10000)numdigits = 4; - else numdigits = 5; - if (len + numdigits > 31) - { - len = 31 - numdigits; - } - mysnprintf (text + len, countof(text) - len, "%d", number); - - probe = Environments; - while (probe != NULL) - { - if (stricmp (probe->Name, text) == 0) - break; - probe = probe->Next; - } - if (probe == NULL) - { - break; - } - } - - if (probe == NULL) - { - SetWindowText (hEdit, text); - } -} - -void ShowErrorTip (HWND ToolTip, TOOLINFO &ti, HWND hDlg, const char *title) -{ - SendMessage (ToolTip, TTM_SETTITLE, 3, (LPARAM)title); - - ti.cbSize = sizeof(ti); - ti.hinst = g_hInst; - SendMessage (ToolTip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); - GetClientRect (ti.hwnd, &ti.rect); - POINT pt = { (ti.rect.left + ti.rect.right) / 2, ti.rect.bottom - 4 }; - ClientToScreen (ti.hwnd, &pt); - SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0); - SendMessage (ToolTip, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y)); - SendMessage (ToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti); - SetFocus (ti.hwnd); - SendMessage (ti.hwnd, EM_SETSEL, 0, -1); - MessageBeep (MB_ICONEXCLAMATION); - SetTimer (hDlg, 11223, 10000, NULL); -} - -INT_PTR CALLBACK NewEAXProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - const ReverbContainer *rev; - TOOLINFO ti; - char buff[33], buff4[4]; - int id1, id2; - static HWND ToolTip; - HWND hWnd; - int i; - - switch (uMsg) - { - case WM_INITDIALOG: - hWnd = GetDlgItem (hDlg, IDC_ENVIRONMENTLIST); - PopulateEnvList (hWnd, true, (const ReverbContainer *)lParam); - SendMessage (GetDlgItem (hDlg, IDC_SPINID1), UDM_SETRANGE, 0, MAKELONG(255,0)); - SendMessage (GetDlgItem (hDlg, IDC_SPINID2), UDM_SETRANGE, 0, MAKELONG(255,0)); - SendMessage (GetDlgItem (hDlg, IDC_EDITID1), EM_LIMITTEXT, 3, 0); - SendMessage (GetDlgItem (hDlg, IDC_EDITID2), EM_LIMITTEXT, 3, 0); - - hWnd = GetDlgItem (hDlg, IDC_NEWENVNAME); - SendMessage (hWnd, EM_LIMITTEXT, 31, 0); - SuggestNewName ((const ReverbContainer *)lParam, hWnd); - SetIDEdits (hDlg, FirstFreeID (((const ReverbContainer *)lParam)->ID, - ((const ReverbContainer *)lParam)->Builtin)); - - ToolTip = CreateWindowEx (WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, - WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON|TTS_CLOSE, - 0, 0, 0, 0, - hDlg, NULL, g_hInst, NULL); - if (ToolTip) - { - char zero = '\0'; - ti.cbSize = sizeof(ti); - ti.uFlags = TTF_TRACK | TTF_TRANSPARENT; - ti.hinst = g_hInst; - ti.lpszText = &zero; - for (i = 0; i < 3; ++i) - { - ti.uId = i; - ti.hwnd = GetDlgItem (hDlg, IDC_NEWENVNAME+i); - GetClientRect (ti.hwnd, &ti.rect); - SendMessage (ToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); - } - } - - return 1; - - case WM_TIMER: - if (wParam == 11223) - { - SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0); - KillTimer (hDlg, 11223); - } - return 1; - - case WM_MOVE: - // Just hide the tool tip if the user moves the window. - SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0); - return 1; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - id1 = 256; id2 = 256; - buff[0] = 0; - if (0 == GetWindowText (GetDlgItem (hDlg, IDC_NEWENVNAME), buff, 32) || - S_FindEnvironment (buff) != NULL) - { - static CHAR text0[] = "That name is already used."; - static CHAR text1[] = "Please enter a name."; - ti.uId = 0; - ti.hwnd = GetDlgItem (hDlg, IDC_NEWENVNAME); - ti.lpszText = buff[0] ? text0 : text1; - ShowErrorTip (ToolTip, ti, hDlg, "Bad Name"); - return 0; - } - if (0 < GetWindowText (GetDlgItem (hDlg, IDC_EDITID1), buff4, 4)) - { - id1 = atoi (buff4); - } - if (0 < GetWindowText (GetDlgItem (hDlg, IDC_EDITID2), buff4, 4)) - { - id2 = atoi (buff4); - } - if (id1 > 255 || id2 > 255) - { - static CHAR text[] = "Please enter a number between 0 and 255."; - ti.uId = id1 > 255 ? 1 : 2; - ti.hwnd = GetDlgItem (hDlg, IDC_EDITID1 + ti.uId - 1); - ti.lpszText = text; - ShowErrorTip (ToolTip, ti, hDlg, "Bad Value"); - } - else if (NULL != (rev = S_FindEnvironment (MAKEWORD (id2, id1)))) - { - static char foo[80]; - ti.uId = 2; - ti.hwnd = GetDlgItem (hDlg, IDC_EDITID2); - mysnprintf (foo, countof(foo), "This ID is already used by \"%s\".", rev->Name); - ti.lpszText = foo; - ShowErrorTip (ToolTip, ti, hDlg, "Bad ID"); - } - else - { - LVITEM item; - - hWnd = GetDlgItem (hDlg, IDC_ENVIRONMENTLIST); - i = SendMessage (hWnd, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_ALL|LVNI_SELECTED); - - if (i == -1) - { - MessageBeep (MB_ICONEXCLAMATION); - return 0; - } - - item.iItem = i; - item.iSubItem = 0; - item.mask = LVIF_PARAM; - if (!SendMessage (hWnd, LVM_GETITEM, 0, (LPARAM)&item)) - { - MessageBeep (MB_ICONEXCLAMATION); - return 0; - } - - ReverbContainer *env = new ReverbContainer; - rev = (ReverbContainer *)item.lParam; - - env->Builtin = false; - env->ID = MAKEWORD (id2, id1); - env->Name = copystring (buff); - env->Next = NULL; - env->Properties = rev->Properties; - S_AddEnvironment (env); - - EndDialog (hDlg, (INT_PTR)env); - } - return 0; - - case IDCANCEL: - EndDialog (hDlg, 0); - break; - } - return 0; - - case WM_NOTIFY: - if (wParam == IDC_ENVIRONMENTLIST && ((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) - { - LPNMLISTVIEW nmlv = (LPNMLISTVIEW)lParam; - - if (nmlv->iItem != -1 && - (nmlv->uNewState & LVIS_SELECTED) && - !(nmlv->uOldState & LVIS_SELECTED)) - { - SuggestNewName ((const ReverbContainer *)nmlv->lParam, GetDlgItem (hDlg, IDC_NEWENVNAME)); - SetIDEdits (hDlg, FirstFreeID (((const ReverbContainer *)nmlv->lParam)->ID, - ((const ReverbContainer *)lParam)->Builtin)); - } - } - return 0; - } - return FALSE; -} - -UINT_PTR CALLBACK SaveHookProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static LONG ButtonsLeftOffset; - static LONG ListRightOffset; - static LONG GroupRightOffset; - - MySaveData *msd; - HWND hWnd; - LVITEM item; - int i, count; - RECT rect1, rect2; - UINT ns; - - switch (msg) - { - case WM_INITDIALOG: - GetClientRect (hDlg, &rect1); - GetWindowRect (GetDlgItem (hDlg, IDC_SELECTALL), &rect2); - ScreenToClient (hDlg, (LPPOINT)&rect2.left); - ButtonsLeftOffset = rect2.left - rect1.right; - GetWindowRect (GetDlgItem (hDlg, IDC_ENVLIST), &rect2); - ListRightOffset = (rect2.right - rect2.left) - rect1.right; - GetWindowRect (GetDlgItem (hDlg, IDC_SAVEGROUP), &rect2); - GroupRightOffset = (rect2.right - rect2.left) - rect1.right; - - hWnd = GetDlgItem (hDlg, IDC_ENVLIST); - PopulateEnvList (hWnd, false, - ((MySaveData *)(((LPOPENFILENAME)lParam)->lCustData))->Default); - SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR)((LPOPENFILENAME)lParam)->lCustData); - return 1; - - case WM_ERASEBKGND: - SetWindowLongPtr (hDlg, DWLP_MSGRESULT, 1); - return 1; - - case WM_SIZE: - if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW) - { - GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SAVEGROUP), &rect1); - SetWindowPos (hWnd, NULL, 0, 0, LOWORD(lParam) + GroupRightOffset, rect1.bottom-rect1.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_DEFERERASE); - - GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SELECTALL), &rect1); - ScreenToClient (hDlg, (LPPOINT)&rect1.left); - SetWindowPos (hWnd, NULL, LOWORD(lParam)+ButtonsLeftOffset, rect1.top, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); - - GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SELECTNONE), &rect1); - ScreenToClient (hDlg, (LPPOINT)&rect1.left); - SetWindowPos (hWnd, NULL, LOWORD(lParam)+ButtonsLeftOffset, rect1.top, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); - - GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_ENVLIST), &rect1); - SetWindowPos (hWnd, NULL, 0, 0, LOWORD(lParam) + ListRightOffset, rect1.bottom-rect1.top, SWP_DEFERERASE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER); - } - return 1; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_SELECTALL: - case IDC_SELECTNONE: - hWnd = GetDlgItem (hDlg, IDC_ENVLIST); - SendMessage (hWnd, WM_SETREDRAW, FALSE, 0); - count = ListView_GetItemCount (hWnd); - item.iSubItem = 0; - item.mask = LVIF_STATE; - item.stateMask = LVIS_SELECTED; - item.state = LOWORD(wParam)==IDC_SELECTALL ? LVIS_SELECTED : 0; - for (i = 0; i < count; ++i) - { - item.iItem = i; - ListView_SetItem (hWnd, &item); - } - if (LOWORD(wParam) == IDC_SELECTALL) - { - SetFocus (hWnd); - } - SendMessage (hWnd, WM_SETREDRAW, TRUE, 0); - return 1; - } - return 0; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) - { - case CDN_INITDONE: - hWnd = GetParent (hDlg); - GetWindowRect (hWnd, &rect1); - GetWindowRect (hDlg, &rect2); - SetWindowPos (hDlg, NULL, 0, 0, rect1.right-rect1.left, rect2.bottom-rect2.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER); - return 1; - - case CDN_FILEOK: - msd = (MySaveData *)(LONG_PTR)GetWindowLongPtr (hDlg, DWLP_USER); - hWnd = GetDlgItem (hDlg, IDC_ENVLIST); - ns = ListView_GetSelectedCount (hWnd); - if (ns == 0) - { - msd->NumSaves = 0; - if (IDNO == MessageBox (hDlg, - "You have not selected any EAX environments to save.\n" - "Do you want to cancel the save operation?", - "Nothing Selected", - MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2)) - { - SetWindowLongPtr (hDlg, DWLP_MSGRESULT, 1); - return 1; - } - } - else - { - UINT x; - msd->Saves = new const ReverbContainer *[ns]; - item.iItem = -1; - item.iSubItem = 0; - item.mask = LVIF_PARAM; - - for (x = 0; x != ns; ) - { - item.iItem = ListView_GetNextItem (hWnd, item.iItem, LVNI_SELECTED); - if (item.iItem != -1 && ListView_GetItem (hWnd, &item)) - { - msd->Saves[x++] = (const ReverbContainer *)item.lParam; - } - } - msd->NumSaves = x; - } - return 0; - } - return 0; - - default: - return 0; - } -} - -void ExportEnvironments (const char *filename, UINT count, const ReverbContainer **envs) -{ - FILE *f; - -retry: - f = fopen (filename, "w"); - - if (f != NULL) - { - for (UINT i = 0; i < count; ++i) - { - const ReverbContainer *env = envs[i]; - const ReverbContainer *base; - size_t j; - - if ((unsigned int)env->Properties.Environment < 26) - { - base = DefaultEnvironments[env->Properties.Environment]; - } - else - { - base = NULL; - } - fprintf (f, "\"%s\" %u %u\n{\n", env->Name, HIBYTE(env->ID), LOBYTE(env->ID)); - for (j = 0; j < countof(EnvControls); ++j) - { - const EnvControl *ctl = &EnvControls[j]; - if (ctl->Name && - (j == 0 || - (ctl->Float && base->Properties.*ctl->Float != env->Properties.*ctl->Float) || - (ctl->Int && base->Properties.*ctl->Int != env->Properties.*ctl->Int)) - ) - { - fprintf (f, "\t%s ", ctl->Name); - if (ctl->Float) - { - float v = env->Properties.*ctl->Float * 1000; - int vi = int(v >= 0.0 ? v + 0.5 : v - 0.5); - fprintf (f, "%d.%03d\n", vi/1000, abs(vi%1000)); - } - else - { - fprintf (f, "%d\n", env->Properties.*ctl->Int); - } - } - } - for (j = 0; j < countof(EnvFlags); ++j) - { - if (EnvFlags[j].Flag & (env->Properties.Flags ^ base->Properties.Flags)) - { - fprintf (f, "\t%s %s\n", EnvFlags[j].Name, - EnvFlags[j].Flag & env->Properties.Flags ? "true" : "false"); - } - } - fprintf (f, "}\n\n"); - } - fclose (f); - } - else - { - LPVOID lpMsgBuf; - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - if (IDRETRY == MessageBox (EAXEditWindow, (LPCTSTR)lpMsgBuf, "Save Failed!", MB_RETRYCANCEL|MB_ICONERROR)) - { - LocalFree (lpMsgBuf); - goto retry; - } - LocalFree (lpMsgBuf); - } -} - -void SaveEnvironments (HWND owner, const ReverbContainer *defEnv) -{ - MySaveData msd (defEnv); - OPENFILENAME ofn = { sizeof(ofn) }; - char filename[PATH_MAX]; - - ofn.hwndOwner = owner; - ofn.hInstance = g_hInst; - ofn.lpstrFilter = "Text Files\0*.txt\0All Files\0*.*\0"; - ofn.lpstrCustomFilter = NULL; - ofn.nMaxCustFilter = 0; - ofn.nFilterIndex = 1; - ofn.lpstrFile = filename; - ofn.nMaxFile = sizeof(filename); - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.lpstrTitle = "Save EAX Environments As..."; - ofn.Flags = OFN_ENABLEHOOK|OFN_ENABLESIZING|OFN_ENABLETEMPLATE|OFN_EXPLORER| - OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT; - ofn.nFileOffset = 0; - ofn.nFileExtension = 0; - ofn.lpstrDefExt = "txt"; - ofn.lCustData = (LPARAM)&msd; - ofn.lpfnHook = SaveHookProc; - ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEEAX); - - filename[0] = 0; - - if (GetSaveFileName ((tagOFNA *)&ofn) && msd.NumSaves != 0) - { - ExportEnvironments (filename, msd.NumSaves, msd.Saves); - } -} - -INT_PTR CALLBACK EAXProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - SCROLLINFO scrollInfo; - HWND hWnd; - RECT rect; - POINT ul; - ReverbContainer *env; - - switch (uMsg) - { - case WM_INITDIALOG: - hPropList = CreateDialog (g_hInst, MAKEINTRESOURCE(IDD_EAXPROPERTYLIST), hDlg, EAXProp); - hWnd = GetDlgItem (hDlg, IDC_DUMMY); - GetWindowRect (hPropList, &rect); - PropListMaxSize.x = rect.right - rect.left; - PropListMaxSize.y = rect.bottom - rect.top; - GetWindowRect (hWnd, &rect); - DestroyWindow (hWnd); - ul.x = rect.left; - ul.y = rect.top; - ScreenToClient (hDlg, &ul); - PropListMaxSize.x = rect.right - rect.left; - - scrollInfo.cbSize = sizeof(scrollInfo); - scrollInfo.fMask = SIF_RANGE|SIF_POS|SIF_PAGE|SIF_DISABLENOSCROLL; - scrollInfo.nMin = 0; - scrollInfo.nMax = PropListMaxSize.y; - scrollInfo.nPos = 0; - scrollInfo.nPage = rect.bottom - rect.top; - SetScrollInfo (hPropList, SB_VERT, &scrollInfo, TRUE); - - MoveWindow (hPropList, ul.x, ul.y, PropListMaxSize.x, rect.bottom - rect.top, FALSE); - ShowWindow (hPropList, SW_SHOW); - - // Windows should have a layout control like MUI so that I don't have - // to do any extra work to make the dialog resizable. - - GetClientRect (hDlg, &rect); - PropListHeightDiff = (rect.bottom - rect.top) - scrollInfo.nPage; - - // Using a scroll bar to create a size box seems like an odd way of - // doing things. - - hWnd = CreateWindow( - "Scrollbar", - (LPSTR)NULL, - WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN | WS_CLIPSIBLINGS, - 0,0,rect.right,rect.bottom, - hDlg, - (HMENU)IDC_SIZEBOX, - g_hInst, - NULL); - - TestLocation.x = DoneLocation.x = rect.right; - TestLocation.y = DoneLocation.y = rect.bottom; - GetWindowRect (GetDlgItem (hDlg, IDOK), &rect); - ScreenToClient (hDlg, (LPPOINT)&rect.left); - DoneLocation.x -= rect.left; - DoneLocation.y -= rect.top; - - GetWindowRect (GetDlgItem (hDlg, IDC_TESTEAX), &rect); - ScreenToClient (hDlg, (LPPOINT)&rect.left); - TestLocation.x -= rect.left; - TestLocation.y -= rect.top; - - GetWindowRect (hDlg, &rect); - EditWindowSize.x = rect.right - rect.left; - EditWindowSize.y = (rect.bottom - rect.top) - scrollInfo.nPage; - - GetWindowRect (GetDlgItem (hDlg, IDC_NEW), &rect); - ScreenToClient (hDlg, (LPPOINT)&rect.left); - NewLeft = rect.left; - - GetWindowRect (GetDlgItem (hDlg, IDC_SAVE), &rect); - ScreenToClient (hDlg, (LPPOINT)&rect.left); - SaveLeft = rect.left; - - GetWindowRect (GetDlgItem (hDlg, IDC_REVERT), &rect); - ScreenToClient (hDlg, (LPPOINT)&rect.left); - RevertLeft = rect.left; - - hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT); - PopulateEnvDropDown (hWnd, IsDlgButtonChecked (hDlg, IDC_SHOWIDS)==BST_CHECKED, NULL); - EAXProc (hDlg, WM_COMMAND, MAKELONG(IDC_CURRENTENVIRONMENT,CBN_SELENDOK), (LPARAM)hWnd); - - CheckDlgButton (hDlg, IDC_TESTEAX, eaxedit_test ? BST_CHECKED : BST_UNCHECKED); - return 0; - - case WM_SIZE: - if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW) - { - GetClientRect (hWnd = GetDlgItem (hDlg, IDC_SIZEBOX), &rect); - SetWindowPos (hWnd, HWND_BOTTOM, LOWORD(lParam)-rect.right, HIWORD(lParam)-rect.bottom, 0, 0, SWP_NOSIZE); - - SetWindowPos (hPropList, NULL, 0, 0, PropListMaxSize.x, HIWORD(lParam)-PropListHeightDiff, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_DEFERERASE); - SetWindowPos (GetDlgItem (hDlg, IDOK), NULL, LOWORD(lParam)-DoneLocation.x, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE); - SetWindowPos (GetDlgItem (hDlg, IDC_NEW), NULL, NewLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE); - SetWindowPos (GetDlgItem (hDlg, IDC_SAVE), NULL, SaveLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE); - SetWindowPos (GetDlgItem (hDlg, IDC_REVERT), NULL, RevertLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE); - SetWindowPos (GetDlgItem (hDlg, IDC_TESTEAX), NULL, LOWORD(lParam)-TestLocation.x, HIWORD(lParam)-TestLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE); - } - return 0; - - case WM_NCDESTROY: - EAXEditWindow = 0; - //new FS_Switcher; - ForceWindowed = false; - if (fullscreen) - { - setmodeneeded = true; - } - ForcedEnvironment = NULL; - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - case IDCANCEL: - DestroyWindow (hPropList); - DestroyWindow (hDlg); - return 1; - - case IDC_NEW: - hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT); - env = (ReverbContainer *)DialogBoxParam (g_hInst, - MAKEINTRESOURCE(IDD_NEWEAX), hDlg, NewEAXProc, - SendMessage (hWnd, CB_GETITEMDATA, - SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0)); - if (env != NULL) - { - LRESULT i = AddEnvToDropDown (hWnd, - SendMessage (GetDlgItem (hDlg, IDC_SHOWIDS), BM_GETCHECK, 0, 0)==BST_CHECKED, - env); - SendMessage (hWnd, CB_SETCURSEL, i, 0); - UpdateControls (env, hDlg); - - hWnd = GetDlgItem (hPropList, IDCE_ENVIRONMENTSIZE); - SetFocus (hWnd); - SendMessage (hWnd, EM_SETSEL, 0, -1); - } - return 0; - - case IDC_REVERT: - hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT); - env = (ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA, - SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0); - env->Properties = SavedProperties; - UpdateControls (env, hDlg); - return 0; - - case IDC_SAVE: - hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT); - SaveEnvironments (hDlg, - (ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA, - SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0)); - return 0; - - case IDC_TESTEAX: - if (HIWORD(wParam) == BN_CLICKED) - { - eaxedit_test = (SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED); - } - break; - - case IDC_SHOWIDS: - if (HIWORD(wParam) == BN_CLICKED) - { - hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT); - PopulateEnvDropDown (hWnd, - SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0)==BST_CHECKED, - (ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA, - SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0)); - EAXProc (hDlg, WM_COMMAND, MAKELONG(IDC_CURRENTENVIRONMENT,CBN_SELENDOK), - (LPARAM)hWnd); - return 0; - } - break; - - case IDC_CURRENTENVIRONMENT: - if (HIWORD(wParam) == CBN_SELENDOK) - { - env = (ReverbContainer *)SendMessage ((HWND)lParam, CB_GETITEMDATA, - SendMessage ((HWND)lParam, CB_GETCURSEL, 0, 0), 0); - UpdateControls (env, hDlg); - } - return 0; - } - return 1; - - case WM_GETMINMAXINFO: - ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = - ((MINMAXINFO *)lParam)->ptMinTrackSize.x = EditWindowSize.x; - ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = EditWindowSize.y + PropListMaxSize.y + 5; - GetClientRect (GetDlgItem (hDlg, IDOK), &rect); - ((MINMAXINFO *)lParam)->ptMinTrackSize.y = rect.bottom * 10; - return 0; - } - return FALSE; -} - -void ShowEAXEditor () -{ - EAXEditWindow = CreateDialog (g_hInst, MAKEINTRESOURCE(IDD_EAXEDIT), Window, EAXProc); -} - -extern int NewWidth, NewHeight, NewBits, DisplayBits; - -CCMD (reverbedit) -{ - if (EAXEditWindow != 0) - { - SetForegroundWindow (EAXEditWindow); - } - else - { - ForceWindowed = true; - if (fullscreen) - { - NewWidth = screen->VideoWidth; - NewHeight = screen->VideoHeight; - NewBits = DisplayBits; - setmodeneeded = true; - SpawnEAXWindow = true; - } - else - { - ShowEAXEditor (); - } - } -} diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 9289438205..84ab3ff84e 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -130,9 +130,6 @@ FJoystickCollection *JoyDevices[NUM_JOYDEVICES]; extern HINSTANCE g_hInst; extern DWORD SessionID; -extern void ShowEAXEditor (); -extern bool SpawnEAXWindow; - static HMODULE DInputDLL; bool GUICapture; @@ -141,10 +138,8 @@ extern FKeyboard *Keyboard; bool VidResizing; -extern bool SpawnEAXWindow; extern BOOL vidactive; extern HWND Window, ConWindow; -extern HWND EAXEditWindow; EXTERN_CVAR (String, language) EXTERN_CVAR (Bool, lookstrafe) @@ -500,12 +495,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_KEYDOWN: - // When the EAX editor is open, pressing Ctrl+Tab will switch to it - if (EAXEditWindow != 0 && wParam == VK_TAB && !(lParam & 0x40000000) && - (GetKeyState (VK_CONTROL) & 0x8000)) - { - SetForegroundWindow (EAXEditWindow); - } break; case WM_SYSKEYDOWN: @@ -531,11 +520,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_DISPLAYCHANGE: case WM_STYLECHANGED: - if (SpawnEAXWindow) - { - SpawnEAXWindow = false; - ShowEAXEditor (); - } return DefWindowProc(hWnd, message, wParam, lParam); case WM_GETMINMAXINFO: @@ -798,14 +782,12 @@ void I_GetEvent () { if (mess.message == WM_QUIT) exit (mess.wParam); - if (EAXEditWindow == 0 || !IsDialogMessage (EAXEditWindow, &mess)) + + if (GUICapture) { - if (GUICapture) - { - TranslateMessage (&mess); - } - DispatchMessage (&mess); + TranslateMessage (&mess); } + DispatchMessage (&mess); } if (Keyboard != NULL) diff --git a/src/win32/i_xinput.cpp b/src/win32/i_xinput.cpp index 8b967746fb..5c5e25aed9 100644 --- a/src/win32/i_xinput.cpp +++ b/src/win32/i_xinput.cpp @@ -165,7 +165,7 @@ public: bool GetDevice(); void ProcessInput(); - bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); + bool WndProcHook(HWND hWnd, uint32_t message, WPARAM wParam, LPARAM lParam, LRESULT *result); void AddAxes(float axes[NUM_JOYAXIS]); void GetDevices(TArray &sticks); IJoystickConfig *Rescan(); @@ -781,7 +781,7 @@ void FXInputManager::GetDevices(TArray &sticks) // //=========================================================================== -bool FXInputManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) +bool FXInputManager::WndProcHook(HWND hWnd, uint32_t message, WPARAM wParam, LPARAM lParam, LRESULT *result) { if (nullptr != InputEnable && message == WM_ACTIVATE) { diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 6bb5dbdc28..7b5eed9a05 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1682,6 +1682,7 @@ OPTMNU_CHANGERENDER = "Change Rendering Output"; OPTMNU_DEFAULTS = "Reset to defaults"; OPTMNU_RESETTOSAVED = "Reset to last saved"; OPTMNU_CONSOLE = "Go to console"; +OPTMNU_REVERB = "Reverb environment editor"; // Controls Menu diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index e28b6f2aa2..3c727247fa 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1630,6 +1630,8 @@ OptionMenu SoundOptions protected StaticText " " Submenu "$SNDMNU_ADVANCED", "AdvSoundOptions" Submenu "$SNDMNU_MODREPLAYER", "ModReplayerOptions" + StaticText " " + Submenu "$OPTMNU_REVERB", "ReverbEdit" } /*======================================= @@ -2214,3 +2216,90 @@ OptionMenu "OpenGLOptions" protected Slider "$GLPREFMNU_PALTONEMAPPOWER", gl_paltonemap_powtable, 0.2, 3.0, 0.1, 1 Option "$GLPREFMNU_PALTONEMAPORDER", gl_paltonemap_reverselookup, "LookupOrder" } + +OptionMenu "ReverbEdit" protected +{ + Class "ReverbEdit" + Title "$OPTMNU_REVERB" + StaticTextSwitchable "", "", "EvironmentName", 1 + StaticTextSwitchable "", "", "EvironmentID" + StaticText " " + Submenu "Select Environment", "ReverbSelect" + Option "Test Environment", "eaxedit_test", OnOff + StaticText " " + Submenu "New Environment", "ReverbNew" + Submenu "Save Environments", "ReverbSave" + Submenu "Edit Environment", "ReverbSettings" +} + +OptionMenu "ReverbSelect" protected +{ + Class "ReverbSelect" + Title "Select Environment" + // filled in by code +} + +OptionMenu "ReverbSettings" protected +{ + Title "Edit Reverb Environment" + SafeCommand "Revert settings", "revertenvironment" + StaticText " " + SliderReverbEditOption "Environment Size", 1, 100, 0.01, 3, 1 + SliderReverbEditOption "Environment Diffusion", 0, 1, 0.01, 3, 2 + SliderReverbEditOption "Room", -10000, 0, 1, 0, 3 + SliderReverbEditOption "Room HF", -10000, 0, 1, 0, 4 + SliderReverbEditOption "Room LF", -10000, 0, 1, 0, 5 + SliderReverbEditOption "Decay Time", 1, 200, 0.01, 3, 6 + SliderReverbEditOption "Decay HF Ratio", 1, 20, 0.01, 3, 7 + SliderReverbEditOption "Decay LF Ratio", 1, 20, 0.01, 3, 8 + SliderReverbEditOption "Reflections", -10000, 1000, 1, 0, 9 + SliderReverbEditOption "Reflections Delay", 0, 0.3, 1, 3, 10 + SliderReverbEditOption "Reflections Pan X", -2000, 2000, 1, 3, 11 + SliderReverbEditOption "Reflections Pan Y", -2000, 2000, 1, 3, 12 + SliderReverbEditOption "Reflections Pan Z", -2000, 2000, 1, 3, 13 + SliderReverbEditOption "Reverb", -10000, 2000, 1, 0, 14 + SliderReverbEditOption "Reverb Delay", 0, 0.1, 0.01, 3, 15 + SliderReverbEditOption "Reverb Pan X", -2000, 2000, 1, 3, 16 + SliderReverbEditOption "Reverb Pan Y", -2000, 2000, 1, 3, 17 + SliderReverbEditOption "Reverb Pan Z", -2000, 2000, 1, 3, 18 + SliderReverbEditOption "Echo Time", 0.075, 0.25, 0.005, 3, 19 + SliderReverbEditOption "Echo Depth", 0, 1, 0.01, 3, 20 + SliderReverbEditOption "Modulation Time", 0.04, 4, 0.01, 3, 21 + SliderReverbEditOption "Modulation Depth",0, 1, 0.01, 3, 22 + SliderReverbEditOption "Air Absorption HF", -100, 0, 0.01, 3, 23 + SliderReverbEditOption "HF Reference", 10000, 200000, 1, 3, 24 + SliderReverbEditOption "LF Reference",20, 10000, 0.1, 3, 25 + SliderReverbEditOption "Room Rolloff Factor",0, 10, 0.01, 3, 26 + SliderReverbEditOption "Diffusion",0, 100, 0.01, 3, 27 + SliderReverbEditOption "Density",0, 100, 0.01, 3, 28 + StaticText " " + ReverbOption "Reflections Scale", 29, OnOff + ReverbOption "Reflections Delay Scale", 30, OnOff + ReverbOption "Decay Time Scale", 31, OnOff + ReverbOption "Decay HF Limit", 32, OnOff + ReverbOption "Reverb Scale", 33, OnOff + ReverbOption "Reverb Delay Scale", 34, OnOff + ReverbOption "Echo Time Scale", 35, OnOff + ReverbOption "Modulation Time Scale", 36, OnOff +} + +OptionMenu "ReverbNew" protected +{ + Title "New Reverb Environment" + ReverbSelect "Based on", "ReverbSelect" + TextField "Name", "reverbedit_name" + NumberField "ID #1", "reverbedit_id1", 0, 255 + NumberField "ID #2", "reverbedit_id2", 0, 255 + Command "Create", "createenvironment", 0, 1 +} + +OptionMenu "ReverbSave" protected +{ + Class "ReverbSave" + Title "Save Reverb Environments" + Command "Save...", "savereverbs" + TextField "File name", "reverbsavename" + StaticText "" + StaticText "Environments to save" + // Rest is filled in by code. +} \ No newline at end of file diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 919e2f97f0..755e427dda 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -25,6 +25,7 @@ version "3.3" #include "zscript/menu/videomenu.txt" #include "zscript/menu/readthis.txt" #include "zscript/menu/conversationmenu.txt" +#include "zscript/menu/reverbedit.txt" #include "zscript/statscreen/types.txt" #include "zscript/statscreen/statscreen.txt" diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 3405ae5493..4668ea0681 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -127,11 +127,13 @@ class OptionMenuItemSubmenu : OptionMenuItem class OptionMenuItemCommand : OptionMenuItemSubmenu { private String ccmd; // do not allow access to this from the outside. + bool mCloseOnSelect; - OptionMenuItemCommand Init(String label, Name command, bool centered = false) + OptionMenuItemCommand Init(String label, Name command, bool centered = false, bool closeonselect = false) { Super.Init(label, command, 0, centered); ccmd = command; + mCloseOnSelect = closeonselect; return self; } @@ -150,6 +152,11 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu } Menu.MenuSound("menu/choose"); DoCommand(ccmd); + if (mCloseOnSelect) + { + let curmenu = Menu.GetCurrentMenu(); + if (curmenu != null) curmenu.Close(); + } return true; } @@ -245,11 +252,11 @@ class OptionMenuItemOptionBase : OptionMenuItem virtual void SetSelection(int Selection) { } - + //============================================================================= override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { - bool grayed = mGrayCheck != null && !(mGrayCheck.GetInt()); + bool grayed = isGrayed(); if (mCenter) { @@ -294,10 +301,15 @@ class OptionMenuItemOptionBase : OptionMenuItem } return true; } + + virtual bool isGrayed() + { + return mGrayCheck != null && !mGrayCheck.GetInt(); + } override bool Selectable() { - return mGrayCheck == null || mGrayCheck.GetInt(); + return !isGrayed(); } } diff --git a/wadsrc/static/zscript/menu/reverbedit.txt b/wadsrc/static/zscript/menu/reverbedit.txt new file mode 100644 index 0000000000..2f372968c6 --- /dev/null +++ b/wadsrc/static/zscript/menu/reverbedit.txt @@ -0,0 +1,259 @@ + +class ReverbEdit : OptionMenu +{ + static native double GetValue(int index); + static native double SetValue(int index, double value); + static native bool GrayCheck(); + static native string, int GetSelectedEnvironment(); + static native void FillSelectMenu(String ccmd, OptionMenuDescriptor desc); + static native void FillSaveMenu(OptionMenuDescriptor desc); + static native int GetSaveSelection(int num); + static native void ToggleSaveSelection(int num); + + override void Init(Menu parent, OptionMenuDescriptor desc) + { + super.Init(parent, desc); + OnReturn(); + } + + override void OnReturn() + { + string env; + int id; + + [env, id] = GetSelectedEnvironment(); + + let li = GetItem('EvironmentName'); + if (li != NULL) + { + if (id != -1) + { + li.SetValue(0, 1); + li.SetString(0, env); + } + else + { + li.SetValue(0, 0); + } + } + li = GetItem('EvironmentID'); + if (li != NULL) + { + if (id != -1) + { + li.SetValue(0, 1); + li.SetString(0, String.Format("%d, %d", (id >> 8) & 255, id & 255)); + } + else + { + li.SetValue(0, 0); + } + } + } +} + +class ReverbSelect : OptionMenu +{ + //============================================================================= + // + // + // + //============================================================================= + + override void Init(Menu parent, OptionMenuDescriptor desc) + { + ReverbEdit.FillSelectMenu("selectenvironment", desc); + super.Init(parent, desc); + } +} + +class ReverbSave : OptionMenu +{ + //============================================================================= + // + // + // + //============================================================================= + + override void Init(Menu parent, OptionMenuDescriptor desc) + { + ReverbEdit.FillSaveMenu(desc); + super.Init(parent, desc); + } +} + +//============================================================================= +// +// Change a CVAR, command is the CVAR name +// +//============================================================================= + +class OptionMenuItemReverbSaveSelect : OptionMenuItemOptionBase +{ + int mValIndex; + + OptionMenuItemReverbSaveSelect Init(String label, int index, Name values) + { + Super.Init(label, 'None', values, null, 0); + mValIndex = index; + return self; + } + + //============================================================================= + override int GetSelection() + { + return ReverbEdit.GetSaveSelection(mValIndex); + } + + override void SetSelection(int Selection) + { + ReverbEdit.ToggleSaveSelection(mValIndex); + } +} + + +//============================================================================= +// +// opens a submenu, command is a submenu name +// +//============================================================================= + +class OptionMenuItemReverbSelect : OptionMenuItemSubMenu +{ + OptionMenuItemReverbSelect Init(String label, Name command) + { + Super.init(label, command, 0, false); + return self; + } + + + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + int x = drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); + + String text = ReverbEdit.GetSelectedEnvironment(); + screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue, indent + CursorSpace(), y, text, DTA_CleanNoMove_1, true); + + return indent; + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemReverbOption : OptionMenuItemOptionBase +{ + int mValIndex; + + OptionMenuItemReverbOption Init(String label, int valindex, Name values) + { + Super.Init(label, "", values, null, false); + mValIndex = valindex; + return self; + } + + override bool isGrayed() + { + return ReverbEdit.GrayCheck(); + } + + override int GetSelection() + { + return int(ReverbEdit.GetValue(mValIndex)); + } + + override void SetSelection(int Selection) + { + ReverbEdit.SetValue(mValIndex, Selection); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase +{ + int mValIndex; + String mEditValue; + TextEnterMenu mEnter; + + OptionMenuItemSliderReverbEditOption Init(String label, double min, double max, double step, int showval, int valindex) + { + Super.Init(label, min, max, step, showval); + mValIndex = valindex; + mEnter = null; + return self; + } + + + override double GetSliderValue() + { + return ReverbEdit.GetValue(mValIndex); + } + + override void SetSliderValue(double val) + { + ReverbEdit.SetValue(mValIndex, val); + } + + override bool Selectable() + { + return !ReverbEdit.GrayCheck(); + } + + virtual String Represent() + { + return mEnter.GetText() .. SmallFont.GetCursor(); + } + + //============================================================================= + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) + { + drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, ReverbEdit.GrayCheck()); + + mDrawX = indent + CursorSpace(); + if (mEnter) + { + screen.DrawText(SmallFont, OptionMenuSettings.mFontColorValue, mDrawX, y, Represent(), DTA_CleanNoMove_1, true); + } + else + { + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); + } + return indent; + } + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/choose"); + mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), String.Format("%.3f", GetSliderValue()), -1, 2, fromcontroller); + mEnter.ActivateMenu(); + return true; + } + else if (mkey == Menu.MKEY_Input) + { + String val = mEnter.GetText(); + SetSliderValue(val.toDouble()); + mEnter = null; + return true; + } + else if (mkey == Menu.MKEY_Abort) + { + mEnter = null; + return true; + } + + return Super.MenuEvent(mkey, fromcontroller); + } + +} +