about summary refs log tree commit diff
path: root/src/engine/client/input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/client/input.cpp')
-rw-r--r--src/engine/client/input.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp
new file mode 100644
index 00000000..9f546226
--- /dev/null
+++ b/src/engine/client/input.cpp
@@ -0,0 +1,208 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include "SDL.h"
+
+#include <base/system.h>
+#include <engine/shared/config.h>
+#include <engine/graphics.h>
+#include <engine/input.h>
+#include <engine/keys.h>
+
+#include "input.h"
+
+//print >>f, "int inp_key_code(const char *key_name) { int i; if (!strcmp(key_name, \"-?-\")) return -1; else for (i = 0; i < 512; i++) if (!strcmp(key_strings[i], key_name)) return i; return -1; }"
+
+// this header is protected so you don't include it from anywere
+#define KEYS_INCLUDE
+#include "keynames.h"
+#undef KEYS_INCLUDE
+
+void CInput::AddEvent(int Unicode, int Key, int Flags)
+{
+	if(m_NumEvents != INPUT_BUFFER_SIZE)
+	{
+		m_aInputEvents[m_NumEvents].m_Unicode = Unicode;
+		m_aInputEvents[m_NumEvents].m_Key = Key;
+		m_aInputEvents[m_NumEvents].m_Flags = Flags;
+		m_NumEvents++;
+	}
+}
+
+CInput::CInput()
+{
+	mem_zero(m_aInputCount, sizeof(m_aInputCount));
+	mem_zero(m_aInputState, sizeof(m_aInputState));
+	mem_zero(m_Keys, sizeof(m_Keys));
+
+	m_InputCurrent = 0;
+	m_InputGrabbed = 0;
+
+	m_LastRelease = 0;
+	m_ReleaseDelta = -1;
+
+	m_NumEvents = 0;
+}
+
+void CInput::Init()
+{
+	m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
+	SDL_EnableUNICODE(1);
+	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+}
+
+void CInput::MouseRelative(int *x, int *y)
+{
+	int nx = 0, ny = 0;
+	float Sens = g_Config.m_InpMousesens/100.0f;
+
+	if(g_Config.m_InpGrab)
+		SDL_GetRelativeMouseState(&nx, &ny);
+	else
+	{
+		if(m_InputGrabbed)
+		{
+			SDL_GetMouseState(&nx,&ny);
+			SDL_WarpMouse(Graphics()->ScreenWidth()/2,Graphics()->ScreenHeight()/2);
+			nx -= Graphics()->ScreenWidth()/2; ny -= Graphics()->ScreenHeight()/2;
+		}
+	}
+
+	*x = nx*Sens;
+	*y = ny*Sens;
+}
+
+void CInput::MouseModeAbsolute()
+{
+	SDL_ShowCursor(1);
+	m_InputGrabbed = 0;
+	if(g_Config.m_InpGrab)
+		SDL_WM_GrabInput(SDL_GRAB_OFF);
+}
+
+void CInput::MouseModeRelative()
+{
+	SDL_ShowCursor(0);
+	m_InputGrabbed = 1;
+	if(g_Config.m_InpGrab)
+		SDL_WM_GrabInput(SDL_GRAB_ON);
+}
+
+int CInput::MouseDoubleClick()
+{
+	return m_ReleaseDelta < (time_freq() >> 2);
+}
+
+void CInput::ClearKeyStates()
+{
+	mem_zero(m_aInputState, sizeof(m_aInputState));
+	mem_zero(m_aInputCount, sizeof(m_aInputCount));
+}
+
+int CInput::KeyState(int Key)
+{
+	return m_aInputState[m_InputCurrent][Key];
+}
+
+void CInput::Update()
+{
+	if(m_InputGrabbed && !Graphics()->WindowActive())
+		MouseModeAbsolute();
+
+	/*if(!input_grabbed && Graphics()->WindowActive())
+		Input()->MouseModeRelative();*/
+
+	// clear and begin count on the other one
+	m_InputCurrent^=1;
+	mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
+	mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+
+	{
+		int i;
+		Uint8 *pState = SDL_GetKeyState(&i);
+		if(i >= KEY_LAST)
+			i = KEY_LAST-1;
+		mem_copy(m_aInputState[m_InputCurrent], pState, i);
+	}
+
+	// these states must always be updated manually because they are not in the GetKeyState from SDL
+	int i = SDL_GetMouseState(NULL, NULL);
+	if(i&SDL_BUTTON(1)) m_aInputState[m_InputCurrent][KEY_MOUSE_1] = 1; // 1 is left
+	if(i&SDL_BUTTON(3)) m_aInputState[m_InputCurrent][KEY_MOUSE_2] = 1; // 3 is right
+	if(i&SDL_BUTTON(2)) m_aInputState[m_InputCurrent][KEY_MOUSE_3] = 1; // 2 is middle
+	if(i&SDL_BUTTON(4)) m_aInputState[m_InputCurrent][KEY_MOUSE_4] = 1;
+	if(i&SDL_BUTTON(5)) m_aInputState[m_InputCurrent][KEY_MOUSE_5] = 1;
+	if(i&SDL_BUTTON(6)) m_aInputState[m_InputCurrent][KEY_MOUSE_6] = 1;
+	if(i&SDL_BUTTON(7)) m_aInputState[m_InputCurrent][KEY_MOUSE_7] = 1;
+	if(i&SDL_BUTTON(8)) m_aInputState[m_InputCurrent][KEY_MOUSE_8] = 1;
+
+	{
+		SDL_Event Event;
+
+		while(SDL_PollEvent(&Event))
+		{
+			int Key = -1;
+			int Action = IInput::FLAG_PRESS;
+			switch (Event.type)
+			{
+				// handle keys
+				case SDL_KEYDOWN:
+					AddEvent(Event.key.keysym.unicode, 0, 0); // ignore_convention
+                    if(Event.key.keysym.unicode != 0 && Event.key.keysym.unicode < 256) // ignore_convention
+                    {
+                        Key = Event.key.keysym.unicode;  // ignore_convention
+                        m_Keys[Event.key.keysym.sym] = Event.key.keysym.unicode; // ignore_convention
+                    }
+                    else
+                        Key = Event.key.keysym.sym;  // ignore_convention
+					break;
+				case SDL_KEYUP:
+					Action = IInput::FLAG_RELEASE;
+					if(m_Keys[Event.key.keysym.sym] != 0) // ignore_convention
+                        Key = m_Keys[Event.key.keysym.sym]; // ignore_convention
+                    else
+                        Key = Event.key.keysym.sym; // ignore_convention
+					break;
+
+				// handle mouse buttons
+				case SDL_MOUSEBUTTONUP:
+					Action = IInput::FLAG_RELEASE;
+
+					if(Event.button.button == 1) // ignore_convention
+					{
+						m_ReleaseDelta = time_get() - m_LastRelease;
+						m_LastRelease = time_get();
+					}
+
+					// fall through
+				case SDL_MOUSEBUTTONDOWN:
+					if(Event.button.button == SDL_BUTTON_LEFT) Key = KEY_MOUSE_1; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_RIGHT) Key = KEY_MOUSE_2; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_MIDDLE) Key = KEY_MOUSE_3; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_WHEELUP) Key = KEY_MOUSE_WHEEL_UP; // ignore_convention
+					if(Event.button.button == SDL_BUTTON_WHEELDOWN) Key = KEY_MOUSE_WHEEL_DOWN; // ignore_convention
+					if(Event.button.button == 6) Key = KEY_MOUSE_6; // ignore_convention
+					if(Event.button.button == 7) Key = KEY_MOUSE_7; // ignore_convention
+					if(Event.button.button == 8) Key = KEY_MOUSE_8; // ignore_convention
+					break;
+
+				// other messages
+				case SDL_QUIT:
+					// TODO: cleaner exit
+					exit(0); // ignore_convention
+					break;
+			}
+
+			//
+			if(Key != -1)
+			{
+				m_aInputCount[m_InputCurrent][Key].m_Presses++;
+				if(Action == IInput::FLAG_PRESS)
+					m_aInputState[m_InputCurrent][Key] = 1;
+				AddEvent(0, Key, Action);
+			}
+
+		}
+	}
+}
+
+
+IEngineInput *CreateEngineInput() { return new CInput; }