diff options
author | Eugene Sandulenko | 2010-07-29 19:53:02 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 21:38:20 +0000 |
commit | a683a420a9e43705c972b5e74d55e319729e1a81 (patch) | |
tree | bde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/input | |
parent | 7723d91c957d07205c51be32498d45cd0a78568f (diff) | |
download | scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.gz scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.bz2 scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.zip |
SWORD25: Importing original sources
svn-id: r53171
Diffstat (limited to 'engines/sword25/input')
-rwxr-xr-x | engines/sword25/input/inputengine.cpp | 36 | ||||
-rwxr-xr-x | engines/sword25/input/inputengine.h | 291 | ||||
-rwxr-xr-x | engines/sword25/input/inputengine_script.cpp | 364 | ||||
-rwxr-xr-x | engines/sword25/input/stdwininput.cpp | 401 | ||||
-rwxr-xr-x | engines/sword25/input/stdwininput.h | 88 |
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 |