- added ZDoom's keybinding class and some needed support code.

Not hooked up yet with the game.
This commit is contained in:
Christoph Oelckers 2019-11-03 18:19:29 +01:00
parent 12a02cb456
commit 73e64ff0b2
11 changed files with 1809 additions and 0 deletions

View file

@ -782,7 +782,11 @@ set (PCH_SOURCES
common/fonts/fontchars.cpp common/fonts/fontchars.cpp
common/console/c_cvars.cpp common/console/c_cvars.cpp
common/console/c_bind.cpp
common/console/c_commandline.cpp
common/console/d_event.cpp
common/utility/i_time.cpp
common/utility/name.cpp common/utility/name.cpp
common/utility/cmdlib.cpp common/utility/cmdlib.cpp
common/utility/m_argv.cpp common/utility/m_argv.cpp

View file

@ -0,0 +1,792 @@
/*
** c_bind.cpp
** Functions for using and maintaining key bindings
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 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.
**---------------------------------------------------------------------------
**
*/
#include <stdint.h>
//#include "doomtype.h"
#include "keydef.h"
#include "c_commandline.h"
#include "c_bind.h"
//#include "g_level.h"
//#include "hu_stuff.h"
#include "configfile.h"
//#include "d_event.h"
#include "filesystem.h"
#include "templates.h"
#include "i_time.h"
//#include "menu/menu.h"
#include "printf.h"
#include "v_text.h"
#include "d_event.h"
const char *KeyNames[NUM_KEYS] =
{
// This array is dependant on the particular keyboard input
// codes generated in i_input.c. If they change there, they
// also need to change here. In this case, we use the
// DirectInput codes and assume a qwerty keyboard layout.
// See <dinput.h> for the DIK_* codes
nullptr, "Escape", "1", "2", "3", "4", "5", "6", //00
"7", "8", "9", "0", "-", "=", "Backspace","Tab", //08
"Q", "W", "E", "R", "T", "Y", "U", "I", //10
"O", "P", "[", "]", "Enter", "Ctrl", "A", "S", //18
"D", "F", "G", "H", "J", "K", "L", ";", //20
"'", "`", "Shift", "\\", "Z", "X", "C", "V", //28
"B", "N", "M", ",", ".", "/", "RShift", "KP*", //30
"Alt", "Space", "CapsLock", "F1", "F2", "F3", "F4", "F5", //38
"F6", "F7", "F8", "F9", "F10", "NumLock", "Scroll", "KP7", //40
"KP8", "KP9", "KP-", "KP4", "KP5", "KP6", "KP+", "KP1", //48
"KP2", "KP3", "KP0", "KP.", nullptr, nullptr, "OEM102", "F11", //50
"F12", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //58
nullptr, nullptr, nullptr, nullptr, "F13", "F14", "F15", "F16", //60
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //68
"Kana", nullptr, nullptr, "Abnt_C1", nullptr, nullptr, nullptr, nullptr, //70
nullptr, "Convert", nullptr, "NoConvert",nullptr, "Yen", "Abnt_C2", nullptr, //78
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //80
nullptr, nullptr, nullptr, nullptr, nullptr, "KP=", nullptr, nullptr, //88
"Circumflex","@", ":", "_", "Kanji", "Stop", "Ax", "Unlabeled",//90
nullptr, "PrevTrack",nullptr, nullptr, "KP-Enter", "RCtrl", nullptr, nullptr, //98
"Mute", "Calculator","Play", nullptr, "Stop", nullptr, nullptr, nullptr, //A0
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "VolDown", nullptr, //A8
"VolUp", nullptr, "WebHome", "KP,", nullptr, "KP/", nullptr, "SysRq", //B0
"RAlt", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //B8
nullptr, nullptr, nullptr, nullptr, nullptr, "Pause", nullptr, "Home", //C0
"UpArrow", "PgUp", nullptr, "LeftArrow",nullptr, "RightArrow",nullptr, "End", //C8
"DownArrow","PgDn", "Ins", "Del", nullptr, nullptr, nullptr, nullptr, //D0
#ifdef __APPLE__
nullptr, nullptr, nullptr, "Command", nullptr, "Apps", "Power", "Sleep", //D8
#else // !__APPLE__
nullptr, nullptr, nullptr, "LWin", "RWin", "Apps", "Power", "Sleep", //D8
#endif // __APPLE__
nullptr, nullptr, nullptr, "Wake", nullptr, "Search", "Favorites","Refresh", //E0
"WebStop", "WebForward","WebBack", "MyComputer","Mail", "MediaSelect",nullptr, nullptr, //E8
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //F0
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //F8
// non-keyboard buttons that can be bound
"Mouse1", "Mouse2", "Mouse3", "Mouse4", // 8 mouse buttons
"Mouse5", "Mouse6", "Mouse7", "Mouse8",
"Joy1", "Joy2", "Joy3", "Joy4", // 128 joystick buttons!
"Joy5", "Joy6", "Joy7", "Joy8",
"Joy9", "Joy10", "Joy11", "Joy12",
"Joy13", "Joy14", "Joy15", "Joy16",
"Joy17", "Joy18", "Joy19", "Joy20",
"Joy21", "Joy22", "Joy23", "Joy24",
"Joy25", "Joy26", "Joy27", "Joy28",
"Joy29", "Joy30", "Joy31", "Joy32",
"Joy33", "Joy34", "Joy35", "Joy36",
"Joy37", "Joy38", "Joy39", "Joy40",
"Joy41", "Joy42", "Joy43", "Joy44",
"Joy45", "Joy46", "Joy47", "Joy48",
"Joy49", "Joy50", "Joy51", "Joy52",
"Joy53", "Joy54", "Joy55", "Joy56",
"Joy57", "Joy58", "Joy59", "Joy60",
"Joy61", "Joy62", "Joy63", "Joy64",
"Joy65", "Joy66", "Joy67", "Joy68",
"Joy69", "Joy70", "Joy71", "Joy72",
"Joy73", "Joy74", "Joy75", "Joy76",
"Joy77", "Joy78", "Joy79", "Joy80",
"Joy81", "Joy82", "Joy83", "Joy84",
"Joy85", "Joy86", "Joy87", "Joy88",
"Joy89", "Joy90", "Joy91", "Joy92",
"Joy93", "Joy94", "Joy95", "Joy96",
"Joy97", "Joy98", "Joy99", "Joy100",
"Joy101", "Joy102", "Joy103", "Joy104",
"Joy105", "Joy106", "Joy107", "Joy108",
"Joy109", "Joy110", "Joy111", "Joy112",
"Joy113", "Joy114", "Joy115", "Joy116",
"Joy117", "Joy118", "Joy119", "Joy120",
"Joy121", "Joy122", "Joy123", "Joy124",
"Joy125", "Joy126", "Joy127", "Joy128",
"POV1Up", "POV1Right","POV1Down", "POV1Left", // First POV hat
"POV2Up", "POV2Right","POV2Down", "POV2Left", // Second POV hat
"POV3Up", "POV3Right","POV3Down", "POV3Left", // Third POV hat
"POV4Up", "POV4Right","POV4Down", "POV4Left", // Fourth POV hat
"MWheelUp", "MWheelDown", // the mouse wheel
"MWheelRight", "MWheelLeft",
"Axis1Plus","Axis1Minus","Axis2Plus","Axis2Minus", // joystick axes as buttons
"Axis3Plus","Axis3Minus","Axis4Plus","Axis4Minus",
"Axis5Plus","Axis5Minus","Axis6Plus","Axis6Minus",
"Axis7Plus","Axis7Minus","Axis8Plus","Axis8Minus",
"LStickRight","LStickLeft","LStickDown","LStickUp", // Gamepad axis-based buttons
"RStickRight","RStickLeft","RStickDown","RStickUp",
"DPadUp","DPadDown","DPadLeft","DPadRight", // Gamepad buttons
"Pad_Start","Pad_Back","LThumb","RThumb",
"LShoulder","RShoulder","LTrigger","RTrigger",
"Pad_A", "Pad_B", "Pad_X", "Pad_Y"
};
FKeyBindings Bindings;
FKeyBindings DoubleBindings;
FKeyBindings AutomapBindings; // this is currently not in use but may be added later.
static unsigned int DClickTime[NUM_KEYS];
static FixedBitArray<NUM_KEYS> DClicked;
//=============================================================================
//
//
//
//=============================================================================
static int GetKeyFromName (const char *name)
{
int i;
// Names of the form #xxx are translated to key xxx automatically
if (name[0] == '#' && name[1] != 0)
{
return atoi (name + 1);
}
// Otherwise, we scan the KeyNames[] array for a matching name
for (i = 0; i < NUM_KEYS; i++)
{
if (KeyNames[i] && !stricmp (KeyNames[i], name))
return i;
}
return 0;
}
//=============================================================================
//
//
//
//=============================================================================
static int GetConfigKeyFromName (const char *key)
{
int keynum = GetKeyFromName(key);
if (keynum == 0)
{
if (stricmp (key, "LeftBracket") == 0)
{
keynum = GetKeyFromName ("[");
}
else if (stricmp (key, "RightBracket") == 0)
{
keynum = GetKeyFromName ("]");
}
else if (stricmp (key, "Equals") == 0)
{
keynum = GetKeyFromName ("=");
}
else if (stricmp (key, "KP-Equals") == 0)
{
keynum = GetKeyFromName ("kp=");
}
}
return keynum;
}
//=============================================================================
//
//
//
//=============================================================================
static const char *KeyName (int key)
{
static char name[5];
if (KeyNames[key])
return KeyNames[key];
snprintf (name, countof(name), "Key_%d", key);
return name;
}
//=============================================================================
//
//
//
//=============================================================================
static const char *ConfigKeyName(int keynum)
{
const char *name = KeyName(keynum);
if (name[1] == 0) // Make sure given name is config-safe
{
if (name[0] == '[')
return "LeftBracket";
else if (name[0] == ']')
return "RightBracket";
else if (name[0] == '=')
return "Equals";
else if (strcmp (name, "kp=") == 0)
return "KP-Equals";
}
return name;
}
//=============================================================================
//
//
//
//=============================================================================
void C_NameKeys (char *str, int first, int second)
{
int c = 0;
*str = 0;
if (second == first) second = 0;
if (first)
{
c++;
strcpy (str, KeyName (first));
if (second)
strcat (str, TEXTCOLOR_BLACK ", " TEXTCOLOR_NORMAL);
}
if (second)
{
c++;
strcat (str, KeyName (second));
}
if (!c)
*str = '\0';
}
//=============================================================================
//
//
//
//=============================================================================
FString C_NameKeys (int *keys, int count)
{
FString result;
for (int i = 0; i < count; i++)
{
int key = keys[i];
if (key == 0) continue;
for (int j = 0; j < count; j++)
{
if (key == keys[j])
{
key = 0;
break;
}
}
if (key == 0) continue;
if (result.IsNotEmpty()) result += TEXTCOLOR_BLACK ", " TEXTCOLOR_NORMAL;
result += KeyName(key);
}
return result;
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::DoBind (const char *key, const char *bind)
{
int keynum = GetConfigKeyFromName (key);
if (keynum != 0)
{
Binds[keynum] = bind;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindAll ()
{
for (int i = 0; i < NUM_KEYS; ++i)
{
Binds[i] = "";
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindKey(const char *key)
{
int i;
if ( (i = GetKeyFromName (key)) )
{
Binds[i] = "";
}
else
{
Printf ("Unknown key \"%s\"\n", key);
return;
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::PerformBind(FCommandLine &argv, const char *msg)
{
int i;
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], Binds[i].GetChars());
}
else
{
Binds[i] = argv[2];
}
}
else
{
Printf ("%s:\n", msg);
for (i = 0; i < NUM_KEYS; i++)
{
if (!Binds[i].IsEmpty())
Printf ("%s \"%s\"\n", KeyName (i), Binds[i].GetChars());
}
}
}
//=============================================================================
//
// This function is first called for functions in custom key sections.
// In this case, matchcmd is non-nullptr, and only keys bound to that command
// are stored. If a match is found, its binding is set to "\1".
// After all custom key sections are saved, it is called one more for the
// normal Bindings and DoubleBindings sections for this game. In this case
// matchcmd is nullptr and all keys will be stored. The config section was not
// previously cleared, so all old bindings are still in place. If the binding
// for a key is empty, the corresponding key in the config is removed as well.
// If a binding is "\1", then the binding itself is cleared, but nothing
// happens to the entry in the config.
//
//=============================================================================
void FKeyBindings::ArchiveBindings(FConfigFile *f, const char *matchcmd)
{
int i;
for (i = 0; i < NUM_KEYS; i++)
{
if (Binds[i].IsEmpty())
{
if (matchcmd == nullptr)
{
f->ClearKey(ConfigKeyName(i));
}
}
else if (matchcmd == nullptr || stricmp(Binds[i], matchcmd) == 0)
{
if (Binds[i][0] == '\1')
{
Binds[i] = "";
continue;
}
f->SetValueForKey(ConfigKeyName(i), Binds[i]);
if (matchcmd != nullptr)
{ // If saving a specific command, set a marker so that
// it does not get saved in the general binding list.
Binds[i] = "\1";
}
}
}
}
//=============================================================================
//
//
//
//=============================================================================
TArray<int> FKeyBindings::GetKeysForCommand (const char *cmd)
{
int i = 0;
TArray<int> result;
while (i < NUM_KEYS)
{
if (stricmp (cmd, Binds[i]) == 0)
{
result.Push(i);
}
i++;
}
return result;
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::UnbindACommand (const char *str)
{
int i;
for (i = 0; i < NUM_KEYS; i++)
{
if (!stricmp (str, Binds[i]))
{
Binds[i] = "";
}
}
}
//=============================================================================
//
//
//
//=============================================================================
void FKeyBindings::DefaultBind(const char *keyname, const char *cmd)
{
int key = GetKeyFromName (keyname);
if (key == 0)
{
Printf ("Unknown key \"%s\"\n", keyname);
return;
}
if (!Binds[key].IsEmpty())
{ // This key is already bound.
return;
}
for (int i = 0; i < NUM_KEYS; ++i)
{
if (!Binds[i].IsEmpty() && stricmp (Binds[i], cmd) == 0)
{ // This command is already bound to a key.
return;
}
}
// It is safe to do the bind, so do it.
Binds[key] = cmd;
}
//=============================================================================
//
//
//
//=============================================================================
void C_UnbindAll ()
{
Bindings.UnbindAll();
DoubleBindings.UnbindAll();
AutomapBindings.UnbindAll();
}
#if 0
CCMD (unbindall)
{
C_UnbindAll ();
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (unbind)
{
if (argv.argc() > 1)
{
Bindings.UnbindKey(argv[1]);
}
}
CCMD (undoublebind)
{
if (argv.argc() > 1)
{
DoubleBindings.UnbindKey(argv[1]);
}
}
CCMD (unmapbind)
{
if (argv.argc() > 1)
{
AutomapBindings.UnbindKey(argv[1]);
}
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (bind)
{
Bindings.PerformBind(argv, "Current key bindings");
}
CCMD (doublebind)
{
DoubleBindings.PerformBind(argv, "Current key doublebindings");
}
CCMD (mapbind)
{
AutomapBindings.PerformBind(argv, "Current automap key bindings");
}
//==========================================================================
//
// CCMD defaultbind
//
// Binds a command to a key if that key is not already bound and if
// that command is not already bound to another key.
//
//==========================================================================
CCMD (defaultbind)
{
if (argv.argc() < 3)
{
Printf ("Usage: defaultbind <key> <command>\n");
}
else
{
Bindings.DefaultBind(argv[1], argv[2]);
}
}
//=============================================================================
//
//
//
//=============================================================================
CCMD (rebind)
{
FKeyBindings *bindings;
if (key == 0)
{
Printf ("Rebind cannot be used from the console\n");
return;
}
if (key & KEY_DBLCLICKED)
{
bindings = &DoubleBindings;
key &= KEY_DBLCLICKED-1;
}
else
{
bindings = &Bindings;
}
if (argv.argc() > 1)
{
bindings->SetBind(key, argv[1]);
}
}
#endif
//=============================================================================
//
//
//
//=============================================================================
void C_BindDefaults ()
{
#if 0
int lump, lastlump = 0;
while ((lump = Wads.FindLump("DEFBINDS", &lastlump)) != -1)
{
FScanner sc(lump);
while (sc.GetString())
{
FKeyBindings *dest = &Bindings;
int key;
// bind destination is optional and is the same as the console command
if (sc.Compare("bind"))
{
sc.MustGetString();
}
else if (sc.Compare("doublebind"))
{
dest = &DoubleBindings;
sc.MustGetString();
}
else if (sc.Compare("mapbind"))
{
dest = &AutomapBindings;
sc.MustGetString();
}
key = GetConfigKeyFromName(sc.String);
sc.MustGetString();
dest->SetBind(key, sc.String);
}
}
#endif
}
#if 0
CCMD(binddefaults)
{
C_BindDefaults ();
}
#endif
void C_SetDefaultBindings ()
{
C_UnbindAll ();
C_BindDefaults ();
}
void AddCommandString (const char *copy, int keynum);
//=============================================================================
//
//
//
//=============================================================================
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
{
FString binding;
bool dclick;
unsigned int nowtime;
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
return false;
if ((unsigned int)ev->data1 >= NUM_KEYS)
return false;
dclick = false;
nowtime = (unsigned)I_msTime();
if (doublebinds != nullptr && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown)
{
// Key pressed for a double click
binding = doublebinds->GetBinding(ev->data1);
DClicked.Set(ev->data1);
dclick = true;
}
else
{
if (ev->type == EV_KeyDown)
{ // Key pressed for a normal press
binding = binds->GetBinding(ev->data1);
DClickTime[ev->data1] = nowtime + 571;
}
else if (doublebinds != nullptr && DClicked[ev->data1])
{ // Key released from a double click
binding = doublebinds->GetBinding(ev->data1);
DClicked.Clear(ev->data1);
DClickTime[ev->data1] = 0;
dclick = true;
}
else
{ // Key released from a normal press
binding = binds->GetBinding(ev->data1);
}
}
if (binding.IsEmpty())
{
binding = binds->GetBinding(ev->data1);
dclick = false;
}
if (!binding.IsEmpty())// && (chatmodeon == 0 || ev->data1 < 256))
{
if (ev->type == EV_KeyUp && binding[0] != '+')
{
return false;
}
char *copy = binding.LockBuffer();
if (ev->type == EV_KeyUp)
{
copy[0] = '-';
}
AddCommandString (copy, dclick ? ev->data1 | KEY_DBLCLICKED : ev->data1);
return true;
}
return false;
}
#include "osd.h"
void AddCommandString(const char* copy, int keynum)
{
if (*copy == '+')
{
}
else if (*copy == '-')
{
}
else OSD_Dispatch(copy);
}

View file

@ -0,0 +1,109 @@
/*
** c_bind.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 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.
**---------------------------------------------------------------------------
**
*/
#ifndef __C_BINDINGS_H__
#define __C_BINDINGS_H__
#include "keydef.h"
#include "zstring.h"
#include "tarray.h"
struct event_t;
class FConfigFile;
class FCommandLine;
void C_NameKeys (char *str, int first, int second);
FString C_NameKeys (int *keys, int count);
class FKeyBindings
{
FString Binds[NUM_KEYS];
public:
void PerformBind(FCommandLine &argv, const char *msg);
bool DoKey(event_t *ev);
void ArchiveBindings(FConfigFile *F, const char *matchcmd = NULL);
TArray<int> GetKeysForCommand (const char *cmd);
void UnbindACommand (const char *str);
void UnbindAll ();
void UnbindKey(const char *key);
void DoBind (const char *key, const char *bind);
void DefaultBind(const char *keyname, const char *cmd);
void SetBind(unsigned int key, const char *bind)
{
if (key < NUM_KEYS) Binds[key] = bind;
}
const FString &GetBinding(unsigned int index) const
{
return Binds[index];
}
const char *GetBind(unsigned int index) const
{
if (index < NUM_KEYS) return Binds[index].GetChars();
else return NULL;
}
};
extern FKeyBindings Bindings;
extern FKeyBindings DoubleBindings;
extern FKeyBindings AutomapBindings;
extern FKeyBindings MenuBindings;
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds);
// Stuff used by the customize controls menu
void C_SetDefaultBindings ();
void C_UnbindAll ();
extern const char *KeyNames[];
struct FKeyAction
{
FString mTitle;
FString mAction;
};
struct FKeySection
{
FString mTitle;
FString mSection;
TArray<FKeyAction> mActions;
};
extern TArray<FKeySection> KeySections;
#endif //__C_BINDINGS_H__

View file

@ -0,0 +1,204 @@
/*
** c_dispatch.cpp
** Functions for executing console commands and aliases
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 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.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "c_commandline.h"
#include "c_cvars.h"
#include "v_text.h"
// ParseCommandLine
//
// Parse a command line (passed in args). If argc is non-NULL, it will
// be set to the number of arguments. If argv is non-NULL, it will be
// filled with pointers to each argument; argv[0] should be initialized
// to point to a buffer large enough to hold all the arguments. The
// return value is the necessary size of this buffer.
//
// Special processing:
// Inside quoted strings, \" becomes just "
// \\ becomes just a single backslash
// \c becomes just TEXTCOLOR_ESCAPE
// $<cvar> is replaced by the contents of <cvar>
static long ParseCommandLine(const char* args, int* argc, char** argv, bool no_escapes)
{
int count;
char* buffplace;
count = 0;
buffplace = NULL;
if (argv != NULL)
{
buffplace = argv[0];
}
for (;;)
{
while (*args <= ' ' && *args)
{ // skip white space
args++;
}
if (*args == 0)
{
break;
}
else if (*args == '\"')
{ // read quoted string
char stuff;
if (argv != NULL)
{
argv[count] = buffplace;
}
count++;
args++;
do
{
stuff = *args++;
if (!no_escapes && stuff == '\\' && *args == '\"')
{
stuff = '\"', args++;
}
else if (!no_escapes && stuff == '\\' && *args == '\\')
{
args++;
}
else if (!no_escapes && stuff == '\\' && *args == 'c')
{
stuff = TEXTCOLOR_ESCAPE, args++;
}
else if (stuff == '\"')
{
stuff = 0;
}
else if (stuff == 0)
{
args--;
}
if (argv != NULL)
{
*buffplace = stuff;
}
buffplace++;
} while (stuff);
}
else
{ // read unquoted string
const char* start = args++, * end;
FBaseCVar* var;
UCVarValue val;
while (*args && *args > ' ' && *args != '\"')
args++;
if (*start == '$' && (var = FindCVarSub(start + 1, int(args - start - 1))))
{
val = var->GetGenericRep(CVAR_String);
start = val.String;
end = start + strlen(start);
}
else
{
end = args;
}
if (argv != NULL)
{
argv[count] = buffplace;
while (start < end)
*buffplace++ = *start++;
*buffplace++ = 0;
}
else
{
buffplace += end - start + 1;
}
count++;
}
}
if (argc != NULL)
{
*argc = count;
}
return (long)(buffplace - (char*)0);
}
FCommandLine::FCommandLine (const char *commandline, bool no_escapes)
{
cmd = commandline;
_argc = -1;
_argv = NULL;
noescapes = no_escapes;
}
FCommandLine::~FCommandLine ()
{
if (_argv != NULL)
{
delete[] _argv;
}
}
void FCommandLine::Shift()
{
// Only valid after _argv has been filled.
for (int i = 1; i < _argc; ++i)
{
_argv[i - 1] = _argv[i];
}
}
int FCommandLine::argc ()
{
if (_argc == -1)
{
argsize = ParseCommandLine (cmd, &_argc, NULL, noescapes);
}
return _argc;
}
char *FCommandLine::operator[] (int i)
{
if (_argv == NULL)
{
int count = argc();
_argv = new char *[count + (argsize+sizeof(char*)-1)/sizeof(char*)];
_argv[0] = (char *)_argv + count*sizeof(char *);
ParseCommandLine (cmd, NULL, _argv, noescapes);
}
return _argv[i];
}

View file

@ -0,0 +1,60 @@
/*
** c_dispatch.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 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.
**---------------------------------------------------------------------------
**
*/
#ifndef __C_DISPATCH_H__
#define __C_DISPATCH_H__
class FConfigFile;
const int KEY_DBLCLICKED = 0x8000;
// Class that can parse command lines
class FCommandLine
{
public:
FCommandLine (const char *commandline, bool no_escapes = false);
~FCommandLine ();
int argc ();
char *operator[] (int i);
const char *args () { return cmd; }
void Shift();
private:
const char *cmd;
int _argc;
char **_argv;
long argsize;
bool noescapes;
};
#endif //__C_DISPATCH_H__

View file

@ -0,0 +1,233 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//
//-----------------------------------------------------------------------------
#include "c_bind.h"
#include "d_event.h"
#include "d_gui.h"
int eventhead;
int eventtail;
event_t events[MAXEVENTS];
//==========================================================================
//
// G_Responder
// Process the event for the game
//
//==========================================================================
bool G_Responder (event_t *ev)
{
#if 0
// any other key pops up menu if in demos
// [RH] But only if the key isn't bound to a "special" command
if (gameaction == ga_nothing &&
(demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL))
{
const char *cmd = Bindings.GetBind (ev->data1);
if (ev->type == EV_KeyDown)
{
if (!cmd || (
strnicmp (cmd, "menu_", 5) &&
stricmp (cmd, "toggleconsole") &&
stricmp (cmd, "sizeup") &&
stricmp (cmd, "sizedown") &&
stricmp (cmd, "togglemap") &&
stricmp (cmd, "spynext") &&
stricmp (cmd, "spyprev") &&
stricmp (cmd, "chase") &&
stricmp (cmd, "+showscores") &&
stricmp (cmd, "bumpgamma") &&
stricmp (cmd, "screenshot")))
{
M_StartControlPanel(true);
M_SetMenu(NAME_Mainmenu, -1);
return true;
}
else
{
return C_DoKey (ev, &Bindings, &DoubleBindings);
}
}
if (cmd && cmd[0] == '+')
return C_DoKey (ev, &Bindings, &DoubleBindings);
return false;
}
#endif
#if 0
if (gamestate == GS_LEVEL)
{
if (ST_Responder (ev))
return true; // status window ate it
if (!viewactive && primaryLevel->automap->Responder (ev, false))
return true; // automap ate it
}
else if (gamestate == GS_FINALE)
{
if (F_Responder (ev))
return true; // finale ate the event
}
#endif
switch (ev->type)
{
case EV_KeyDown:
if (C_DoKey (ev, &Bindings, &DoubleBindings))
return true;
break;
case EV_KeyUp:
C_DoKey (ev, &Bindings, &DoubleBindings);
break;
#if 0
// [RH] mouse buttons are sent as key up/down events
case EV_Mouse:
mousex = (int)(ev->x * mouse_sensitivity);
mousey = (int)(ev->y * mouse_sensitivity);
break;
#endif
}
// [RH] If the view is active, give the automap a chance at
// the events *last* so that any bound keys get precedence.
#if 0
if (gamestate == GS_LEVEL && viewactive && primaryLevel->automap)
return primaryLevel->automap->Responder (ev, true);
#endif
return (ev->type == EV_KeyDown ||
ev->type == EV_Mouse);
}
//==========================================================================
//
// D_ProcessEvents
//
// Send all the events of the given timestamp down the responder chain.
// Events are asynchronous inputs generally generated by the game user.
// Events can be discarded if no responder claims them
//
//==========================================================================
void D_ProcessEvents (void)
{
event_t *ev;
for (; eventtail != eventhead ; eventtail = (eventtail+1)&(MAXEVENTS-1))
{
ev = &events[eventtail];
if (ev->type == EV_None)
continue;
if (ev->type == EV_DeviceChange)
(void)0;//UpdateJoystickMenu(I_UpdateDeviceList());
#if 0
if (C_Responder (ev))
continue; // console ate the event
if (M_Responder (ev))
continue; // menu ate the event
#endif
G_Responder (ev);
}
}
//==========================================================================
//
// D_PostEvent
//
// Called by the I/O functions when input is detected.
//
//==========================================================================
void D_PostEvent (const event_t *ev)
{
// Do not post duplicate consecutive EV_DeviceChange events.
if (ev->type == EV_DeviceChange && events[eventhead].type == EV_DeviceChange)
{
return;
}
events[eventhead] = *ev;
#if 0
if (ev->type == EV_Mouse && menuactive == MENU_Off && ConsoleState != c_down && ConsoleState != c_falling && !primaryLevel->localEventManager->Responder(ev) && !paused)
{
if (Button_Mlook.bDown || freelook)
{
int look = int(ev->y * m_pitch * mouse_sensitivity * 16.0);
if (invertmouse)
look = -look;
G_AddViewPitch (look, true);
events[eventhead].y = 0;
}
if (!Button_Strafe.bDown && !lookstrafe)
{
G_AddViewAngle (int(ev->x * m_yaw * mouse_sensitivity * 8.0), true);
events[eventhead].x = 0;
}
if ((events[eventhead].x | events[eventhead].y) == 0)
{
return;
}
}
#endif
eventhead = (eventhead+1)&(MAXEVENTS-1);
}
//==========================================================================
//
// D_RemoveNextCharEvent
//
// Removes the next EV_GUI_Char event in the input queue. Used by the menu,
// since it (generally) consumes EV_GUI_KeyDown events and not EV_GUI_Char
// events, and it needs to ensure that there is no left over input when it's
// done. If there are multiple EV_GUI_KeyDowns before the EV_GUI_Char, then
// there are dead chars involved, so those should be removed, too. We do
// this by changing the message type to EV_None rather than by actually
// removing the event from the queue.
//
//==========================================================================
void D_RemoveNextCharEvent()
{
assert(events[eventtail].type == EV_GUI_Event && events[eventtail].subtype == EV_GUI_KeyDown);
for (int evnum = eventtail; evnum != eventhead; evnum = (evnum+1) & (MAXEVENTS-1))
{
event_t *ev = &events[evnum];
if (ev->type != EV_GUI_Event)
break;
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_Char)
{
ev->type = EV_None;
if (ev->subtype == EV_GUI_Char)
break;
}
else
{
break;
}
}
}

View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
#ifndef __D_EVENT_H__
#define __D_EVENT_H__
#include <functional>
//
// Event handling.
//
// Input event types.
enum EGenericEvent
{
EV_None,
EV_KeyDown, // data1: scan code, data2: Qwerty ASCII code
EV_KeyUp, // same
EV_Mouse, // x, y: mouse movement deltas
EV_GUI_Event, // subtype specifies actual event
EV_DeviceChange,// a device has been connected or removed
};
// Event structure.
struct event_t
{
uint8_t type;
uint8_t subtype;
int16_t data1; // keys / mouse/joystick buttons
int16_t data2;
int16_t data3;
int x; // mouse/joystick x move
int y; // mouse/joystick y move
};
// Called by IO functions when input is detected.
void D_PostEvent (const event_t* ev);
void D_RemoveNextCharEvent();
//
// GLOBAL VARIABLES
//
#define MAXEVENTS 128
extern event_t events[MAXEVENTS];
#endif

View file

@ -0,0 +1,115 @@
/*
** d_gui.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 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.
**---------------------------------------------------------------------------
**
** So when do I get a real UT-like windowing system?
*/
#ifndef __D_GUI_H__
#define __D_GUI_H__
// For a GUIEvent, x and y specify absolute location of mouse pointer
enum EGUIEvent
{
EV_GUI_None,
EV_GUI_KeyDown, // data1: unshifted ASCII, data2: shifted ASCII, data3: modifiers
EV_GUI_KeyRepeat, // same
EV_GUI_KeyUp, // same
EV_GUI_Char, // data1: translated character (for user text input), data2: alt down?
EV_GUI_FirstMouseEvent,
EV_GUI_MouseMove,
EV_GUI_LButtonDown,
EV_GUI_LButtonUp,
EV_GUI_LButtonDblClick,
EV_GUI_MButtonDown,
EV_GUI_MButtonUp,
EV_GUI_MButtonDblClick,
EV_GUI_RButtonDown,
EV_GUI_RButtonUp,
EV_GUI_RButtonDblClick,
EV_GUI_WheelUp, // data3: shift/ctrl/alt
EV_GUI_WheelDown, // "
EV_GUI_WheelRight, // "
EV_GUI_WheelLeft, // "
EV_GUI_BackButtonDown,
EV_GUI_BackButtonUp,
EV_GUI_FwdButtonDown,
EV_GUI_FwdButtonUp,
EV_GUI_LastMouseEvent,
};
enum GUIKeyModifiers
{
GKM_SHIFT = 1,
GKM_CTRL = 2,
GKM_ALT = 4,
GKM_META = 8,
GKM_LBUTTON = 16
};
// Special codes for some GUI keys, including a few real ASCII codes.
enum ESpecialGUIKeys
{
GK_PGDN = 1,
GK_PGUP = 2,
GK_HOME = 3,
GK_END = 4,
GK_LEFT = 5,
GK_RIGHT = 6,
GK_ALERT = 7, // ASCII bell
GK_BACKSPACE= 8, // ASCII
GK_TAB = 9, // ASCII
GK_LINEFEED = 10, // ASCII
GK_DOWN = 10,
GK_VTAB = 11, // ASCII
GK_UP = 11,
GK_FORMFEED = 12, // ASCII
GK_RETURN = 13, // ASCII
GK_F1 = 14,
GK_F2 = 15,
GK_F3 = 16,
GK_F4 = 17,
GK_F5 = 18,
GK_F6 = 19,
GK_F7 = 20,
GK_F8 = 21,
GK_F9 = 22,
GK_F10 = 23,
GK_F11 = 24,
GK_F12 = 25,
GK_DEL = 26,
GK_ESCAPE = 27, // ASCII
GK_FREE1 = 28,
GK_FREE2 = 29,
GK_BACK = 30, // browser back key
GK_CESCAPE = 31 // color escape
};
#endif //__D_GUI_H__

View file

@ -0,0 +1,136 @@
#pragma once
#include <stdio.h>
#include <string.h>
//
// Keyboard definition. Everything below = 0x100 matches
// a mode 1 keyboard scan code.
//
enum EKeyCodes
{
KEY_PAUSE = 0xc5, // DIK_PAUSE
KEY_RIGHTARROW = 0xcd, // DIK_RIGHT
KEY_LEFTARROW = 0xcb, // DIK_LEFT
KEY_UPARROW = 0xc8, // DIK_UP
KEY_DOWNARROW = 0xd0, // DIK_DOWN
KEY_ESCAPE = 0x01, // DIK_ESCAPE
KEY_ENTER = 0x1c, // DIK_RETURN
KEY_SPACE = 0x39, // DIK_SPACE
KEY_TAB = 0x0f, // DIK_TAB
KEY_F1 = 0x3b, // DIK_F1
KEY_F2 = 0x3c, // DIK_F2
KEY_F3 = 0x3d, // DIK_F3
KEY_F4 = 0x3e, // DIK_F4
KEY_F5 = 0x3f, // DIK_F5
KEY_F6 = 0x40, // DIK_F6
KEY_F7 = 0x41, // DIK_F7
KEY_F8 = 0x42, // DIK_F8
KEY_F9 = 0x43, // DIK_F9
KEY_F10 = 0x44, // DIK_F10
KEY_F11 = 0x57, // DIK_F11
KEY_F12 = 0x58, // DIK_F12
KEY_GRAVE = 0x29, // DIK_GRAVE
KEY_BACKSPACE = 0x0e, // DIK_BACK
KEY_EQUALS = 0x0d, // DIK_EQUALS
KEY_MINUS = 0x0c, // DIK_MINUS
KEY_LSHIFT = 0x2A, // DIK_LSHIFT
KEY_LCTRL = 0x1d, // DIK_LCONTROL
KEY_LALT = 0x38, // DIK_LMENU
KEY_RSHIFT = 0x36,
KEY_RCTRL = 0x9d,
KEY_RALT = 0xb8,
KEY_INS = 0xd2, // DIK_INSERT
KEY_DEL = 0xd3, // DIK_DELETE
KEY_END = 0xcf, // DIK_END
KEY_HOME = 0xc7, // DIK_HOME
KEY_PGUP = 0xc9, // DIK_PRIOR
KEY_PGDN = 0xd1, // DIK_NEXT
KEY_MOUSE1 = 0x100,
KEY_MOUSE2 = 0x101,
KEY_MOUSE3 = 0x102,
KEY_MOUSE4 = 0x103,
KEY_MOUSE5 = 0x104,
KEY_MOUSE6 = 0x105,
KEY_MOUSE7 = 0x106,
KEY_MOUSE8 = 0x107,
KEY_FIRSTJOYBUTTON = 0x108,
KEY_JOY1 = KEY_FIRSTJOYBUTTON+0,
KEY_JOY2,
KEY_JOY3,
KEY_JOY4,
KEY_JOY5,
KEY_JOY6,
KEY_JOY7,
KEY_JOY8,
KEY_LASTJOYBUTTON = 0x187,
KEY_JOYPOV1_UP = 0x188,
KEY_JOYPOV1_RIGHT = 0x189,
KEY_JOYPOV1_DOWN = 0x18a,
KEY_JOYPOV1_LEFT = 0x18b,
KEY_JOYPOV2_UP = 0x18c,
KEY_JOYPOV3_UP = 0x190,
KEY_JOYPOV4_UP = 0x194,
KEY_MWHEELUP = 0x198,
KEY_MWHEELDOWN = 0x199,
KEY_MWHEELRIGHT = 0x19A,
KEY_MWHEELLEFT = 0x19B,
KEY_JOYAXIS1PLUS = 0x19C,
KEY_JOYAXIS1MINUS = 0x19D,
KEY_JOYAXIS2PLUS = 0x19E,
KEY_JOYAXIS2MINUS = 0x19F,
KEY_JOYAXIS3PLUS = 0x1A0,
KEY_JOYAXIS3MINUS = 0x1A1,
KEY_JOYAXIS4PLUS = 0x1A2,
KEY_JOYAXIS4MINUS = 0x1A3,
KEY_JOYAXIS5PLUS = 0x1A4,
KEY_JOYAXIS5MINUS = 0x1A5,
KEY_JOYAXIS6PLUS = 0x1A6,
KEY_JOYAXIS6MINUS = 0x1A7,
KEY_JOYAXIS7PLUS = 0x1A8,
KEY_JOYAXIS7MINUS = 0x1A9,
KEY_JOYAXIS8PLUS = 0x1AA,
KEY_JOYAXIS8MINUS = 0x1AB,
KEY_PAD_LTHUMB_RIGHT = 0x1AC,
KEY_PAD_LTHUMB_LEFT = 0x1AD,
KEY_PAD_LTHUMB_DOWN = 0x1AE,
KEY_PAD_LTHUMB_UP = 0x1AF,
KEY_PAD_RTHUMB_RIGHT = 0x1B0,
KEY_PAD_RTHUMB_LEFT = 0x1B1,
KEY_PAD_RTHUMB_DOWN = 0x1B2,
KEY_PAD_RTHUMB_UP = 0x1B3,
KEY_PAD_DPAD_UP = 0x1B4,
KEY_PAD_DPAD_DOWN = 0x1B5,
KEY_PAD_DPAD_LEFT = 0x1B6,
KEY_PAD_DPAD_RIGHT = 0x1B7,
KEY_PAD_START = 0x1B8,
KEY_PAD_BACK = 0x1B9,
KEY_PAD_LTHUMB = 0x1BA,
KEY_PAD_RTHUMB = 0x1BB,
KEY_PAD_LSHOULDER = 0x1BC,
KEY_PAD_RSHOULDER = 0x1BD,
KEY_PAD_LTRIGGER = 0x1BE,
KEY_PAD_RTRIGGER = 0x1BF,
KEY_PAD_A = 0x1C0,
KEY_PAD_B = 0x1C1,
KEY_PAD_X = 0x1C2,
KEY_PAD_Y = 0x1C3,
NUM_KEYS = 0x1C4,
NUM_JOYAXISBUTTONS = 8,
};

View file

@ -0,0 +1,75 @@
/*
** i_time.cpp
** Implements the timer
**
**---------------------------------------------------------------------------
** Copyright 1998-2016 Randy Heit
** Copyright 2017 Magnus Norddahl
** 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.
**---------------------------------------------------------------------------
**
*/
#include <chrono>
#include <thread>
#include "i_time.h"
#include "c_cvars.h"
#include "printf.h"
//==========================================================================
//
// Tick time functions
//
//==========================================================================
static double TimeScale = 1.0;
static uint64_t GetClockTimeNS()
{
using namespace std::chrono;
return (uint64_t)((duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count()) * (uint64_t)(TimeScale * 1000));
}
static uint64_t MSToNS(unsigned int ms)
{
return static_cast<uint64_t>(ms) * 1'000'000;
}
static uint64_t NSToMS(uint64_t ns)
{
return static_cast<uint64_t>(ns / 1'000'000);
}
uint64_t I_nsTime()
{
return GetClockTimeNS();
}
uint64_t I_msTime()
{
return NSToMS(I_nsTime());
}

View file

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
// [RH] Returns millisecond-accurate time
uint64_t I_msTime();
// Nanosecond-accurate time
uint64_t I_nsTime();