aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/input
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sword25/input')
-rwxr-xr-xengines/sword25/input/inputengine.cpp36
-rwxr-xr-xengines/sword25/input/inputengine.h291
-rwxr-xr-xengines/sword25/input/inputengine_script.cpp364
-rwxr-xr-xengines/sword25/input/stdwininput.cpp401
-rwxr-xr-xengines/sword25/input/stdwininput.h88
5 files changed, 1180 insertions, 0 deletions
diff --git a/engines/sword25/input/inputengine.cpp b/engines/sword25/input/inputengine.cpp
new file mode 100755
index 0000000000..85164447ce
--- /dev/null
+++ b/engines/sword25/input/inputengine.cpp
@@ -0,0 +1,36 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 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.
+//
+// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#define BS_LOG_PREFIX "INPUTENGINE"
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "inputengine.h"
+
+// -----------------------------------------------------------------------------
+
+BS_InputEngine::BS_InputEngine(BS_Kernel * pKernel) : BS_Service(pKernel)
+{
+ if (!_RegisterScriptBindings())
+ BS_LOG_ERRORLN("Script bindings could not be registered.");
+ else
+ BS_LOGLN("Script bindings registered.");
+}
diff --git a/engines/sword25/input/inputengine.h b/engines/sword25/input/inputengine.h
new file mode 100755
index 0000000000..d2c4c92c5d
--- /dev/null
+++ b/engines/sword25/input/inputengine.h
@@ -0,0 +1,291 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 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.
+//
+// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+/**
+ BS_InputEngine
+ -------------
+ Dies ist das Inputengine Interface, dass alle Methoden enthält, die eine Inputengine implementieren muss.
+ Implementationen der Inputengine müssen von dieser Klasse abgeleitet werden.
+
+ Autor: Alex Arnst
+**/
+
+#ifndef BS_INPUTENGINE_H
+#define BS_INPUTENGINE_H
+
+/// Includes
+#include "kernel/common.h"
+#include "kernel/service.h"
+#include "kernel/persistable.h"
+
+/// Klassendefinition
+class BS_InputEngine : public BS_Service, public BS_Persistable
+{
+public:
+ BS_InputEngine(BS_Kernel* pKernel);
+ virtual ~BS_InputEngine(){};
+
+ // ACHTUNG: Diese Codes werden in inputengine_script.cpp beim Skript-Service registriert. Bei Änderungen an diesem Enum muss auch diese
+ // Datei angepasst werden.
+ enum KEY_CODES
+ {
+ KEY_BACKSPACE = 0x08,
+ KEY_TAB = 0x09,
+ KEY_CLEAR = 0x0C,
+ KEY_RETURN = 0x0D,
+ KEY_PAUSE = 0x13,
+ KEY_CAPSLOCK = 0x14,
+ KEY_ESCAPE = 0x1B,
+ KEY_SPACE = 0x20,
+ KEY_PAGEUP = 0x21,
+ KEY_PAGEDOWN = 0x22,
+ KEY_END = 0x23,
+ KEY_HOME = 0x24,
+ KEY_LEFT = 0x25,
+ KEY_UP = 0x26,
+ KEY_RIGHT = 0x27,
+ KEY_DOWN = 0x28,
+ KEY_PRINTSCREEN = 0x2C,
+ KEY_INSERT = 0x2D,
+ KEY_DELETE = 0x2E,
+ KEY_0 = 0x30,
+ KEY_1 = 0x31,
+ KEY_2 = 0x32,
+ KEY_3 = 0x33,
+ KEY_4 = 0x34,
+ KEY_5 = 0x35,
+ KEY_6 = 0x36,
+ KEY_7 = 0x37,
+ KEY_8 = 0x38,
+ KEY_9 = 0x39,
+ KEY_A = 0x41,
+ KEY_B = 0x42,
+ KEY_C = 0x43,
+ KEY_D = 0x44,
+ KEY_E = 0x45,
+ KEY_F = 0x46,
+ KEY_G = 0x47,
+ KEY_H = 0x48,
+ KEY_I = 0x49,
+ KEY_J = 0x4A,
+ KEY_K = 0x4B,
+ KEY_L = 0x4C,
+ KEY_M = 0x4D,
+ KEY_N = 0x4E,
+ KEY_O = 0x4F,
+ KEY_P = 0x50,
+ KEY_Q = 0x51,
+ KEY_R = 0x52,
+ KEY_S = 0x53,
+ KEY_T = 0x54,
+ KEY_U = 0x55,
+ KEY_V = 0x56,
+ KEY_W = 0x57,
+ KEY_X = 0x58,
+ KEY_Y = 0x59,
+ KEY_Z = 0x5A,
+ KEY_NUMPAD0 = 0x60,
+ KEY_NUMPAD1 = 0x61,
+ KEY_NUMPAD2 = 0x62,
+ KEY_NUMPAD3 = 0x63,
+ KEY_NUMPAD4 = 0x64,
+ KEY_NUMPAD5 = 0x65,
+ KEY_NUMPAD6 = 0x66,
+ KEY_NUMPAD7 = 0x67,
+ KEY_NUMPAD8 = 0x68,
+ KEY_NUMPAD9 = 0x69,
+ KEY_MULTIPLY = 0x6A,
+ KEY_ADD = 0x6B,
+ KEY_SEPARATOR = 0x6C,
+ KEY_SUBTRACT = 0x6D,
+ KEY_DECIMAL = 0x6E,
+ KEY_DIVIDE = 0x6F,
+ KEY_F1 = 0x70,
+ KEY_F2 = 0x71,
+ KEY_F3 = 0x72,
+ KEY_F4 = 0x73,
+ KEY_F5 = 0x74,
+ KEY_F6 = 0x75,
+ KEY_F7 = 0x76,
+ KEY_F8 = 0x77,
+ KEY_F9 = 0x78,
+ KEY_F10 = 0x79,
+ KEY_F11 = 0x7A,
+ KEY_F12 = 0x7B,
+ KEY_NUMLOCK = 0x90,
+ KEY_SCROLL = 0x91,
+ KEY_LSHIFT = 0xA0,
+ KEY_RSHIFT = 0xA1,
+ KEY_LCONTROL = 0xA2,
+ KEY_RCONTROL = 0xA3,
+ };
+
+ // ACHTUNG: Diese Codes werden in inputengine_script.cpp beim Skript-Service registriert. Bei Änderungen an diesem Enum muss auch diese
+ // Datei angepasst werden.
+ enum KEY_COMMANDS
+ {
+ KEY_COMMAND_ENTER = 1,
+ KEY_COMMAND_LEFT = 2,
+ KEY_COMMAND_RIGHT = 3,
+ KEY_COMMAND_HOME = 4,
+ KEY_COMMAND_END = 5,
+ KEY_COMMAND_BACKSPACE = 6,
+ KEY_COMMAND_TAB = 7,
+ KEY_COMMAND_INSERT = 8,
+ KEY_COMMAND_DELETE = 9,
+ };
+
+ /// --------------------------------------------------------------
+ /// DIESE METHODEN MÜSSEN VON DER INPUTENGINE IMPLEMENTIERT WERDEN
+ /// --------------------------------------------------------------
+
+ /**
+ @brief Initialisiert die Inputengine
+ @return Gibt bei Erfolg true zurück, ansonsten false.
+ */
+ virtual bool Init() = 0;
+
+ /**
+ @brief Führt einen "Tick" der Input-Engine aus
+
+ Diese Methode sollte mindestens ein mal pro Frame aufgerufen werden. Sie dient dazu Implementationen der
+ Input-Engine zu ermöglichen, die nicht in einem eigenen Thread laufen oder zusätzliche Verwaltungsaufgaben
+ durchführen müssen.
+ */
+ virtual void Update() = 0;
+
+ /**
+ @brief Gibt true zurück, wenn die linke Maustaste gedrückt ist.
+ */
+ virtual bool IsLeftMouseDown() = 0;
+
+ /**
+ @brief Gibt true zurück, wenn die rechte Maustaste gedrückt ist.
+ */
+ virtual bool IsRightMouseDown() = 0;
+
+ /**
+ @brief Gibt true zurück, wenn die linke Maustaste gedrückt und losgelassen wurde.
+
+ Der Unterschied zu IsLeftMouseDown() besteht darin, dass erst true zurückgegegen wird, wenn der Tastendruck beendet ist, die Taste also
+ wieder losgelassen wurde.
+ */
+ virtual bool WasLeftMouseDown() = 0;
+
+ /**
+ @brief Gibt true zurück, wenn die linke Maustaste gedrückt und losgelassen wurde.
+
+ Der Unterschied zu IsRightMouseDown() besteht darin, dass erst true zurückgegegen wird, wenn der Tastendruck beendet ist, die Taste also
+ wieder losgelassen wurde.
+ */
+ virtual bool WasRightMouseDown() = 0;
+
+ /**
+ @brief Gibt true zurück wenn mit der linken Maustaste ein Doppelklick ausgelöst wurde.
+ */
+ virtual bool IsLeftDoubleClick() = 0;
+
+ /**
+ @brief Gibt die Position des Mauszeigers auf der X-Achse in Pixeln zurück.
+ */
+ virtual int GetMouseX() = 0;
+
+ /**
+ @brief Gibt die Position des Mauszeigers auf der Y-Achse in Pixeln zurück.
+ */
+ virtual int GetMouseY() = 0;
+
+ /**
+ @brief Setzt die Position des Mauszeigers auf der X-Achse in Pixeln.
+ */
+ virtual void SetMouseX(int PosX) = 0;
+
+ /**
+ @brief Setzt die Position des Mauszeigers auf der Y-Achse in Pixeln.
+ */
+ virtual void SetMouseY(int PosY) = 0;
+
+ /**
+ @brief Gibt true zurück wenn eine bestimmte Taste gedrückt ist.
+ @param KeyCode der Key-Code der zu testenden Taste
+ @return Gibt true zurück, wenn die Taste mit dem übergebenen Key-Code gedrückt ist, ansonsten false.
+ */
+ virtual bool IsKeyDown(unsigned int KeyCode) = 0;
+
+ /**
+ @brief Gibt true zurück wenn eine bestimmte Taste gerückt und losgelassen wurde.
+
+ Der Unterschied zu IsKeyDown() besteht darin, dass erst true zurückgegegen wird, wenn der Tastendruck beendet ist, die Taste also
+ wieder losgelassen wurde. Diese Methode erleichtert das Abfragen von Funktionstasten und das Einlesen von Zeichenketten, die vom
+ Benutzer getippt werden.
+
+ @param KeyCode der Key-Code der zu testenden Taste
+ */
+ virtual bool WasKeyDown(unsigned int KeyCode) = 0;
+
+ typedef void (*CharacterCallback)(unsigned char Character);
+
+ /**
+ @brief Registriert eine Callbackfunktion für die Eingabe von Buchstaben.
+
+ Die Callbacks, die mit dieser Funktion registriert werden, werden immer dann aufgerufen, wenn der Input-Service eine Buchstabeneingabe
+ feststellt. Eine Buchstabeneingabe unterscheidet sich von der Abfrage mittels der Methoden IsKeyDown() und WasKeyDown() in der Hinsicht,
+ dass statt Scan-Coded tatsächliche Buchstaben behandelt werden. Dabei wurden unter anderem Berücksichtigt:des Tastaturlayout, der Zustand
+ der Shift und Caps Lock Tasten und die Wiederholung durch längeres Halten der Taste.<br>
+ Die Eingabe von Zeichenketten durch den Benutzer sollte durch Benutzung dieses Callbacks realisiert werden.
+
+ @return Gibt true zurück, wenn die Funktion registriert werden konnte, ansonsten false.
+ */
+ virtual bool RegisterCharacterCallback(CharacterCallback Callback) = 0;
+
+ /**
+ @brief Deregistriert eine Callbackfunktion für die Eingabe von Buchstaben.
+
+ @return Gibt true zurück, wenn die Funktion deregistriert werden konnte, ansonsten false.
+ */
+ virtual bool UnregisterCharacterCallback(CharacterCallback Callback) = 0;
+
+ typedef void (*CommandCallback)(KEY_COMMANDS Command);
+
+ /**
+ @brief Registriert eine Callbackfunktion für die Eingabe von Kommandos, die auf die Zeichenketteneingabe Einfluss haben können.
+
+ Die Callbacks, die mit dieser Funktion registriert werden , werden immer dann aufgerufen, wenn der Input-Service einen Tastendruck
+ feststellt, der die Zeichenketteneingabe beeinflussen kann. Dies könnten folgende Tasten sein: Enter, Pos 1, Ende, Links, Rechts, ...<br>
+ Die Eingabe von Zeichenketten durch den Benutzer sollte durch Benutzung dieses Callbacks realisiert werden.
+
+ @return Gibt true zurück, wenn die Funktion registriert werden konnte, ansonsten false.
+ */
+ virtual bool RegisterCommandCallback(CommandCallback Callback) = 0;
+
+ /**
+ @brief Deregistriert eine Callbackfunktion für die Eingabe von Kommandos, die auf die Zeichenketteneingabe Einfluss haben können.
+
+ @return Gibt true zurück, wenn die Funktion deregistriert werden konnte, ansonsten false.
+ */
+ virtual bool UnregisterCommandCallback(CommandCallback Callback) = 0;
+
+ virtual void ReportCharacter(unsigned char Character) = 0;
+ virtual void ReportCommand(KEY_COMMANDS Command) = 0;
+
+private:
+ bool _RegisterScriptBindings();
+};
+
+#endif
diff --git a/engines/sword25/input/inputengine_script.cpp b/engines/sword25/input/inputengine_script.cpp
new file mode 100755
index 0000000000..7c2868186b
--- /dev/null
+++ b/engines/sword25/input/inputengine_script.cpp
@@ -0,0 +1,364 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 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.
+//
+// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include <string>
+#include <algorithm>
+
+#include "kernel/common.h"
+#include "kernel/kernel.h"
+#include "kernel/callbackregistry.h"
+#include "script/script.h"
+#include "script/luabindhelper.h"
+#include "script/luacallback.h"
+
+#include "inputengine.h"
+
+#define BS_LOG_PREFIX "INPUTENGINE"
+
+// -----------------------------------------------------------------------------
+// Callback-Objekte
+// -----------------------------------------------------------------------------
+
+static void TheCharacterCallback(unsigned char Character);
+static void TheCommandCallback(BS_InputEngine::KEY_COMMANDS Command);
+
+namespace
+{
+ class CharacterCallbackClass : public BS_LuaCallback
+ {
+ public:
+ CharacterCallbackClass(lua_State * L) : BS_LuaCallback(L) {};
+
+ std::string Character;
+
+ protected:
+ int PreFunctionInvokation(lua_State * L)
+ {
+ lua_pushstring(L, Character.c_str());
+ return 1;
+ }
+ };
+ std::auto_ptr<CharacterCallbackClass> CharacterCallbackPtr;
+
+ // -----------------------------------------------------------------------------
+
+ class CommandCallbackClass : public BS_LuaCallback
+ {
+ public:
+ CommandCallbackClass(lua_State * L) : BS_LuaCallback(L) { Command = BS_InputEngine::KEY_COMMAND_BACKSPACE; }
+
+ BS_InputEngine::KEY_COMMANDS Command;
+
+ protected:
+ int PreFunctionInvokation(lua_State * L)
+ {
+ lua_pushnumber(L, Command);
+ return 1;
+ }
+ };
+ std::auto_ptr<CommandCallbackClass> CommandCallbackPtr;
+
+ // -------------------------------------------------------------------------
+
+ struct CallbackfunctionRegisterer
+ {
+ CallbackfunctionRegisterer()
+ {
+ BS_CallbackRegistry::GetInstance().RegisterCallbackFunction("LuaCommandCB", TheCommandCallback);
+ BS_CallbackRegistry::GetInstance().RegisterCallbackFunction("LuaCharacterCB", TheCharacterCallback);
+ }
+ };
+ static CallbackfunctionRegisterer Instance;
+}
+
+// -----------------------------------------------------------------------------
+
+static BS_InputEngine * GetIE()
+{
+ BS_Kernel * pKernel = BS_Kernel::GetInstance();
+ BS_ASSERT(pKernel);
+ BS_InputEngine * pIE = static_cast<BS_InputEngine *>(pKernel->GetService("input"));
+ BS_ASSERT(pIE);
+ return pIE;
+}
+
+// -----------------------------------------------------------------------------
+
+static int Init(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->Init());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int Update(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ // Beim ersten Aufruf der Update()-Methode werden die beiden Callbacks am Input-Objekt registriert.
+ // Dieses kann nicht in _RegisterScriptBindings() passieren, da diese Funktion vom Konstruktor der abstrakten Basisklasse aufgerufen wird und die
+ // Register...()-Methoden abstrakt sind, im Konstruktor der Basisklasse also nicht aufgerufen werden können.
+ static bool FirstCall = true;
+ if (FirstCall)
+ {
+ FirstCall = false;
+ pIE->RegisterCharacterCallback(TheCharacterCallback);
+ pIE->RegisterCommandCallback(TheCommandCallback);
+ }
+
+ pIE->Update();
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static int IsLeftMouseDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->IsLeftMouseDown());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int IsRightMouseDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->IsRightMouseDown());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int WasLeftMouseDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->WasLeftMouseDown());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int WasRightMouseDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->WasRightMouseDown());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int IsLeftDoubleClick(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->IsLeftDoubleClick());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int GetMouseX(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushnumber(L, pIE->GetMouseX());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int GetMouseY(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushnumber(L, pIE->GetMouseY());
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int IsKeyDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->IsKeyDown((unsigned int) luaL_checknumber(L, 1)));
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int WasKeyDown(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ lua_pushbooleancpp(L, pIE->WasKeyDown((unsigned int) luaL_checknumber(L, 1)));
+ return 1;
+}
+
+// -----------------------------------------------------------------------------
+
+static int SetMouseX(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ pIE->SetMouseX((int) luaL_checknumber(L, 1));
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static int SetMouseY(lua_State * L)
+{
+ BS_InputEngine * pIE = GetIE();
+
+ pIE->SetMouseY((int) luaL_checknumber(L, 1));
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static void TheCharacterCallback(unsigned char Character)
+{
+ CharacterCallbackPtr->Character = Character;
+ lua_State * L = static_cast<lua_State *>(BS_Kernel::GetInstance()->GetScript()->GetScriptObject());
+ CharacterCallbackPtr->InvokeCallbackFunctions(L, 1);
+}
+
+// -----------------------------------------------------------------------------
+
+static int RegisterCharacterCallback(lua_State * L)
+{
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ CharacterCallbackPtr->RegisterCallbackFunction(L, 1);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static int UnregisterCharacterCallback(lua_State * L)
+{
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ CharacterCallbackPtr->UnregisterCallbackFunction(L, 1);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static void TheCommandCallback(BS_InputEngine::KEY_COMMANDS Command)
+{
+ CommandCallbackPtr->Command = Command;
+ lua_State * L = static_cast<lua_State *>(BS_Kernel::GetInstance()->GetScript()->GetScriptObject());
+ CommandCallbackPtr->InvokeCallbackFunctions(L, 1);
+}
+
+// -----------------------------------------------------------------------------
+
+static int RegisterCommandCallback(lua_State * L)
+{
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ CommandCallbackPtr->RegisterCallbackFunction(L, 1);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static int UnregisterCommandCallback(lua_State * L)
+{
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ CommandCallbackPtr->UnregisterCallbackFunction(L, 1);
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+static const char * PACKAGE_LIBRARY_NAME = "Input";
+
+static const luaL_reg PACKAGE_FUNCTIONS[] =
+{
+ "Init", Init,
+ "Update", Update,
+ "IsLeftMouseDown", IsLeftMouseDown,
+ "IsRightMouseDown", IsRightMouseDown,
+ "WasLeftMouseDown", WasLeftMouseDown,
+ "WasRightMouseDown", WasRightMouseDown,
+ "IsLeftDoubleClick", IsLeftDoubleClick,
+ "GetMouseX", GetMouseX,
+ "GetMouseY", GetMouseY,
+ "SetMouseX", SetMouseX,
+ "SetMouseY", SetMouseY,
+ "IsKeyDown", IsKeyDown,
+ "WasKeyDown", WasKeyDown,
+ "RegisterCharacterCallback", RegisterCharacterCallback,
+ "UnregisterCharacterCallback", UnregisterCharacterCallback,
+ "RegisterCommandCallback", RegisterCommandCallback,
+ "UnregisterCommandCallback", UnregisterCommandCallback,
+ 0, 0,
+};
+
+#define X(k) "KEY_" #k, BS_InputEngine::KEY_##k
+#define Y(k) "KEY_COMMAND_" #k, BS_InputEngine::KEY_COMMAND_##k
+static const lua_constant_reg PACKAGE_CONSTANTS[] =
+{
+ X(BACKSPACE), X(TAB), X(CLEAR), X(RETURN), X(PAUSE), X(CAPSLOCK), X(ESCAPE), X(SPACE), X(PAGEUP), X(PAGEDOWN), X(END), X(HOME), X(LEFT),
+ X(UP), X(RIGHT), X(DOWN), X(PRINTSCREEN), X(INSERT), X(DELETE), X(0), X(1), X(2), X(3), X(4), X(5), X(6), X(7), X(8), X(9), X(A), X(B),
+ X(C), X(D), X(E), X(F), X(G), X(H), X(I), X(J), X(K), X(L), X(M), X(N), X(O), X(P), X(Q), X(R), X(S), X(T), X(U), X(V), X(W), X(X), X(Y),
+ X(Z), X(NUMPAD0), X(NUMPAD1), X(NUMPAD2), X(NUMPAD3), X(NUMPAD4), X(NUMPAD5), X(NUMPAD6), X(NUMPAD7), X(NUMPAD8), X(NUMPAD9), X(MULTIPLY),
+ X(ADD), X(SEPARATOR), X(SUBTRACT), X(DECIMAL), X(DIVIDE), X(F1), X(F2), X(F3), X(F4), X(F5), X(F6), X(F7), X(F8), X(F9), X(F10), X(F11),
+ X(F12), X(NUMLOCK), X(SCROLL), X(LSHIFT), X(RSHIFT), X(LCONTROL), X(RCONTROL),
+ Y(ENTER), Y(LEFT), Y(RIGHT), Y(HOME), Y(END), Y(BACKSPACE), Y(TAB), Y(INSERT), Y(DELETE),
+ 0, 0,
+};
+#undef X
+#undef Y
+
+// -----------------------------------------------------------------------------
+
+bool BS_InputEngine::_RegisterScriptBindings()
+{
+ BS_Kernel * pKernel = BS_Kernel::GetInstance();
+ BS_ASSERT(pKernel);
+ BS_ScriptEngine * pScript = static_cast<BS_ScriptEngine *>(pKernel->GetService("script"));
+ BS_ASSERT(pScript);
+ lua_State * L = static_cast<lua_State *>(pScript->GetScriptObject());
+ BS_ASSERT(L);
+
+ if (!BS_LuaBindhelper::AddFunctionsToLib(L, PACKAGE_LIBRARY_NAME, PACKAGE_FUNCTIONS)) return false;
+ if (!BS_LuaBindhelper::AddConstantsToLib(L, PACKAGE_LIBRARY_NAME, PACKAGE_CONSTANTS)) return false;
+
+ CharacterCallbackPtr.reset(new CharacterCallbackClass(L));
+ CommandCallbackPtr.reset(new CommandCallbackClass(L));
+
+ return true;
+}
diff --git a/engines/sword25/input/stdwininput.cpp b/engines/sword25/input/stdwininput.cpp
new file mode 100755
index 0000000000..16e3832b67
--- /dev/null
+++ b/engines/sword25/input/stdwininput.cpp
@@ -0,0 +1,401 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 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.
+//
+// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#include "kernel/kernel.h"
+#include "kernel/callbackregistry.h"
+#include "kernel/inputpersistenceblock.h"
+#include "kernel/outputpersistenceblock.h"
+#include "stdwininput.h"
+
+#include <algorithm>
+using namespace std;
+
+#define BS_LOG_PREFIX "WININPUT"
+
+// -----------------------------------------------------------------------------
+// Konstruktion / Destruktion
+// -----------------------------------------------------------------------------
+
+BS_StdWinInput::BS_StdWinInput(BS_Kernel* pKernel) :
+ m_CurrentState(0),
+ m_LeftMouseDown(false),
+ m_RightMouseDown(false),
+ m_MouseX(0),
+ m_MouseY(0),
+ m_LeftDoubleClick(false),
+ m_DoubleClickTime(GetDoubleClickTime()),
+ m_DoubleClickRectWidth(GetSystemMetrics(SM_CXDOUBLECLK)),
+ m_DoubleClickRectHeight(GetSystemMetrics(SM_CYDOUBLECLK)),
+ m_LastLeftClickTime(0),
+ m_LastLeftClickMouseX(0),
+ m_LastLeftClickMouseY(0),
+ BS_InputEngine(pKernel)
+{
+ memset(m_KeyboardState[0], 0, sizeof(m_KeyboardState[0]));
+ memset(m_KeyboardState[1], 0, sizeof(m_KeyboardState[1]));
+ m_LeftMouseState[0] = false;
+ m_LeftMouseState[1] = false;
+ m_RightMouseState[0] = false;
+ m_RightMouseState[1] = false;
+}
+
+BS_StdWinInput::~BS_StdWinInput()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+BS_Service * BS_StdWinInput_CreateObject(BS_Kernel* pKernel) { return new BS_StdWinInput(pKernel); }
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::Init()
+{
+ // Keine Inialisierung notwendig
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::Update()
+{
+ // Der Status wird nur aktualisiert, wenn das Applikationsfenster den Fokus hat, so wird verhindert, dass
+ // Eingaben verarbeitet werden, die eigentlich für eine andere Applikation gedacht waren.
+ if (BS_Kernel::GetInstance()->GetWindow()->HasFocus())
+ {
+ m_CurrentState ^= 1;
+
+ // Der Status der Eingabegeräte wird nur einmal pro Frame ausgelesen, damit für
+ // jeden Frame gleiche Anfragen die gleiche Antwort erhalten.
+
+ POINT MousePos;
+ if (GetCursorPos(&MousePos))
+ {
+ m_MouseX = MousePos.x - BS_Kernel::GetInstance()->GetWindow()->GetClientX();
+ m_MouseY = MousePos.y - BS_Kernel::GetInstance()->GetWindow()->GetClientY();
+ }
+ else
+ {
+ BS_LOG_ERRORLN("Call to GetCursorPos() failed.");
+ m_MouseX = 0;
+ m_MouseY = 0;
+ }
+
+ GetKeyboardState(m_KeyboardState[m_CurrentState]);
+
+ m_LeftMouseDown = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0;
+ m_RightMouseDown = (GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0;
+ m_LeftMouseState[m_CurrentState] = m_LeftMouseDown;
+ m_RightMouseState[m_CurrentState] = m_RightMouseDown;
+
+ TestForLeftDoubleClick();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::IsLeftMouseDown()
+{
+ return m_LeftMouseDown;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::IsRightMouseDown()
+{
+ return m_RightMouseDown;
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::TestForLeftDoubleClick()
+{
+ // Das Doppelklick-Flag wird gelöscht, für den Fall, dass im letzten Frame ein Doppelklick ausgetreten ist.
+ m_LeftDoubleClick = false;
+
+ // Die linke Maustaste wurde geklickt, also muss getestet werden, ob ein Doppelklick vorliegt.
+ if (WasLeftMouseDown())
+ {
+ // Die Zeit auslesen.
+ unsigned int Now = BS_Kernel::GetInstance()->GetMilliTicks();
+
+ // Ein Doppelklick wird erkannt, wenn:
+ // 1. Die zwei Klicks liegen nah genug zusammen.
+ // 2. Der Mauscursor wurde zwischen den Klicks nicht zu viel bewegt.
+ if (Now - m_LastLeftClickTime <= m_DoubleClickTime &&
+ abs(m_MouseX - m_LastLeftClickMouseX) <= m_DoubleClickRectWidth / 2 &&
+ abs(m_MouseY - m_LastLeftClickMouseY) <= m_DoubleClickRectHeight / 2)
+ {
+ m_LeftDoubleClick = true;
+
+ // Die Zeit und Position des letzten Linksklicks zurücksetzen, damit dieser Klick nicht als erster Klick eines weiteren Doppelklicks
+ // interpretiert wird.
+ m_LastLeftClickTime = 0;
+ m_LastLeftClickMouseX = 0;
+ m_LastLeftClickMouseY = 0;
+ }
+ else
+ {
+ // Es liegt kein Doppelklick vor, die Zeit und die Position dieses Klicks merken, für den Fall das dies der erste Klick eines
+ // zukünftigen Doppelklicks wird.
+ m_LastLeftClickTime = Now;
+ m_LastLeftClickMouseX = m_MouseX;
+ m_LastLeftClickMouseY = m_MouseY;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::IsLeftDoubleClick()
+{
+ return m_LeftDoubleClick;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::WasLeftMouseDown()
+{
+ return (m_LeftMouseState[m_CurrentState] == false) && (m_LeftMouseState[m_CurrentState ^ 1] == true);
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::WasRightMouseDown()
+{
+ return (m_RightMouseState[m_CurrentState] == false) && (m_RightMouseState[m_CurrentState ^ 1] == true);
+}
+
+// -----------------------------------------------------------------------------
+
+int BS_StdWinInput::GetMouseX()
+{
+ return m_MouseX;
+}
+
+// -----------------------------------------------------------------------------
+
+int BS_StdWinInput::GetMouseY()
+{
+ return m_MouseY;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::IsKeyDown(unsigned int KeyCode)
+{
+ return (m_KeyboardState[m_CurrentState][KeyCode] & 0x80) != 0;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::WasKeyDown(unsigned int KeyCode)
+{
+ return ((m_KeyboardState[m_CurrentState][KeyCode] & 0x80) == 0) && ((m_KeyboardState[m_CurrentState ^ 1][KeyCode] & 0x80) != 0);
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::SetMouseX(int PosX)
+{
+ m_MouseX = PosX;
+ SetCursorPos(m_MouseX + BS_Kernel::GetInstance()->GetWindow()->GetClientX(), m_MouseY + BS_Kernel::GetInstance()->GetWindow()->GetClientY());
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::SetMouseY(int PosY)
+{
+ m_MouseY = PosY;
+ SetCursorPos(m_MouseX + BS_Kernel::GetInstance()->GetWindow()->GetClientX(), m_MouseY + BS_Kernel::GetInstance()->GetWindow()->GetClientY());
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::RegisterCharacterCallback(CharacterCallback Callback)
+{
+ if (find(m_CharacterCallbacks.begin(), m_CharacterCallbacks.end(), Callback) == m_CharacterCallbacks.end())
+ {
+ m_CharacterCallbacks.push_back(Callback);
+ return true;
+ }
+ else
+ {
+ BS_LOG_WARNINGLN("Tried to register an CharacterCallback that was already registered.");
+ return false;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::UnregisterCharacterCallback(CharacterCallback Callback)
+{
+ list<CharacterCallback>::iterator CallbackIter = find(m_CharacterCallbacks.begin(), m_CharacterCallbacks.end(), Callback);
+ if (CallbackIter != m_CharacterCallbacks.end())
+ {
+ m_CharacterCallbacks.erase(CallbackIter);
+ return true;
+ }
+ else
+ {
+ BS_LOG_WARNINGLN("Tried to unregister an CharacterCallback that was not previously registered.");
+ return false;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::RegisterCommandCallback(CommandCallback Callback)
+{
+ if (find(m_CommandCallbacks.begin(), m_CommandCallbacks.end(), Callback) == m_CommandCallbacks.end())
+ {
+ m_CommandCallbacks.push_back(Callback);
+ return true;
+ }
+ else
+ {
+ BS_LOG_WARNINGLN("Tried to register an CommandCallback that was already registered.");
+ return false;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::UnregisterCommandCallback(CommandCallback Callback)
+{
+ list<CommandCallback>::iterator CallbackIter = find(m_CommandCallbacks.begin(), m_CommandCallbacks.end(), Callback);
+ if (CallbackIter != m_CommandCallbacks.end())
+ {
+ m_CommandCallbacks.erase(CallbackIter);
+ return true;
+ }
+ else
+ {
+ BS_LOG_WARNINGLN("Tried to unregister an CommandCallback that was not previously registered.");
+ return false;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::ReportCharacter(unsigned char Character)
+{
+ list<CharacterCallback>::const_iterator CallbackIter = m_CharacterCallbacks.begin();
+ while (CallbackIter != m_CharacterCallbacks.end())
+ {
+ // Iterator vor dem Aufruf erhöhen und im Folgendem auf einer Kopie arbeiten.
+ // Dieses Vorgehen ist notwendig da der Iterator möglicherweise von der Callbackfunktion durch das Deregistrieren des Callbacks
+ // invalidiert wird.
+ list<CharacterCallback>::const_iterator CurCallbackIter = CallbackIter;
+ ++CallbackIter;
+
+ (*CurCallbackIter)(Character);
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void BS_StdWinInput::ReportCommand(KEY_COMMANDS Command)
+{
+ list<CommandCallback>::const_iterator CallbackIter = m_CommandCallbacks.begin();
+ while (CallbackIter != m_CommandCallbacks.end())
+ {
+ // Iterator vor dem Aufruf erhöhen und im Folgendem auf einer Kopie arbeiten.
+ // Dieses Vorgehen ist notwendig da der Iterator möglicherweise von der Callbackfunktion durch das Deregistrieren des Callbacks
+ // invalidiert wird.
+ list<CommandCallback>::const_iterator CurCallbackIter = CallbackIter;
+ ++CallbackIter;
+
+ (*CurCallbackIter)(Command);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Persistenz
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::Persist(BS_OutputPersistenceBlock & Writer)
+{
+ // Anzahl an Command-Callbacks persistieren.
+ Writer.Write(m_CommandCallbacks.size());
+
+ // Alle Command-Callbacks einzeln persistieren.
+ {
+ list<CommandCallback>::const_iterator It = m_CommandCallbacks.begin();
+ while (It != m_CommandCallbacks.end())
+ {
+ Writer.Write(BS_CallbackRegistry::GetInstance().ResolveCallbackPointer(*It));
+ ++It;
+ }
+ }
+
+ // Anzahl an Character-Callbacks persistieren.
+ Writer.Write(m_CharacterCallbacks.size());
+
+ // Alle Character-Callbacks einzeln persistieren.
+ {
+ list<CharacterCallback>::const_iterator It = m_CharacterCallbacks.begin();
+ while (It != m_CharacterCallbacks.end())
+ {
+ Writer.Write(BS_CallbackRegistry::GetInstance().ResolveCallbackPointer(*It));
+ ++It;
+ }
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_StdWinInput::Unpersist(BS_InputPersistenceBlock & Reader)
+{
+ // Command-Callbackliste leeren.
+ m_CommandCallbacks.clear();
+
+ // Anzahl an Command-Callbacks lesen.
+ unsigned int CommandCallbackCount;
+ Reader.Read(CommandCallbackCount);
+
+ // Alle Command-Callbacks wieder herstellen.
+ for (unsigned int i = 0; i < CommandCallbackCount; ++i)
+ {
+ std::string CallbackFunctionName;
+ Reader.Read(CallbackFunctionName);
+
+ m_CommandCallbacks.push_back(reinterpret_cast<CommandCallback>(BS_CallbackRegistry::GetInstance().ResolveCallbackFunction(CallbackFunctionName)));
+ }
+
+ // Character-Callbackliste leeren.
+ m_CharacterCallbacks.clear();
+
+ // Anzahl an Character-Callbacks lesen.
+ unsigned int CharacterCallbackCount;
+ Reader.Read(CharacterCallbackCount);
+
+ // Alle Character-Callbacks wieder herstellen.
+ for (unsigned int i = 0; i < CharacterCallbackCount; ++i)
+ {
+ std::string CallbackFunctionName;
+ Reader.Read(CallbackFunctionName);
+
+ m_CharacterCallbacks.push_back(reinterpret_cast<CharacterCallback>(BS_CallbackRegistry::GetInstance().ResolveCallbackFunction(CallbackFunctionName)));
+ }
+
+ return Reader.IsGood();
+}
diff --git a/engines/sword25/input/stdwininput.h b/engines/sword25/input/stdwininput.h
new file mode 100755
index 0000000000..20e02fdd11
--- /dev/null
+++ b/engines/sword25/input/stdwininput.h
@@ -0,0 +1,88 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 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.
+//
+// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#ifndef BS_STDWININPUT_H
+#define BS_STDWININPUT_H
+
+/// Includes
+#include "kernel/memlog_off.h"
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <list>
+#include "kernel/memlog_on.h"
+
+#include "kernel/common.h"
+#include "inputengine.h"
+
+/// Klassendefinitionen
+class BS_Kernel;
+
+/// Klassendefinition
+class BS_StdWinInput : public BS_InputEngine
+{
+public:
+ BS_StdWinInput(BS_Kernel* pKernel);
+ virtual ~BS_StdWinInput();
+
+ virtual bool Init();
+ virtual void Update();
+ virtual bool IsLeftMouseDown();
+ virtual bool IsRightMouseDown();
+ virtual bool WasLeftMouseDown();
+ virtual bool WasRightMouseDown();
+ virtual bool IsLeftDoubleClick();
+ virtual int GetMouseX();
+ virtual int GetMouseY();
+ virtual bool IsKeyDown(unsigned int KeyCode);
+ virtual bool WasKeyDown(unsigned int KeyCode);
+ virtual void SetMouseX(int PosX);
+ virtual void SetMouseY(int PosY);
+ virtual bool RegisterCharacterCallback(CharacterCallback Callback);
+ virtual bool UnregisterCharacterCallback(CharacterCallback Callback);
+ virtual bool RegisterCommandCallback(CommandCallback Callback);
+ virtual bool UnregisterCommandCallback(CommandCallback Callback);
+ virtual void ReportCharacter(unsigned char Character);
+ virtual void ReportCommand(KEY_COMMANDS Command);
+
+ bool Persist(BS_OutputPersistenceBlock & Writer);
+ bool Unpersist(BS_InputPersistenceBlock & Reader);
+
+private:
+ void TestForLeftDoubleClick();
+
+ BYTE m_KeyboardState[2][256];
+ bool m_LeftMouseState[2];
+ bool m_RightMouseState[2];
+ unsigned int m_CurrentState;
+ int m_MouseX;
+ int m_MouseY;
+ bool m_LeftMouseDown;
+ bool m_RightMouseDown;
+ bool m_LeftDoubleClick;
+ unsigned int m_DoubleClickTime;
+ int m_DoubleClickRectWidth;
+ int m_DoubleClickRectHeight;
+ unsigned int m_LastLeftClickTime;
+ int m_LastLeftClickMouseX;
+ int m_LastLeftClickMouseY;
+ std::list<CommandCallback> m_CommandCallbacks;
+ std::list<CharacterCallback> m_CharacterCallbacks;
+};
+
+#endif