diff options
author | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
commit | 75e8452b6e6a2bf4fb2f588aa00b428a60d873b5 (patch) | |
tree | f29541d55309487a94bd1d38e8b53bb3dde9aec6 /engines/sword25/input | |
parent | 48ee83b88957dab86bc763e9ef21a70179fa8679 (diff) | |
parent | e9f50882ea5b6beeefa994040be9d3bab6a1f107 (diff) | |
download | scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.gz scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.bz2 scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.zip |
OPENGL: Merged from trunk, from rev 52105 to 53396.
This includes an rather hacky attempt to merge all the recent gp2x backend
changes into the branch. I suppose the gp2x backend and probably all new
backends, i.e. gph, dingux etc., might not compile anymore.
Since I have no way of testing those it would be nice if porters could look
into getting those up to speed in this branch.
svn-id: r53399
Diffstat (limited to 'engines/sword25/input')
-rw-r--r-- | engines/sword25/input/inputengine.cpp | 399 | ||||
-rw-r--r-- | engines/sword25/input/inputengine.h | 333 | ||||
-rw-r--r-- | engines/sword25/input/inputengine_script.cpp | 355 |
3 files changed, 1087 insertions, 0 deletions
diff --git a/engines/sword25/input/inputengine.cpp b/engines/sword25/input/inputengine.cpp new file mode 100644 index 0000000000..a57af23e6b --- /dev/null +++ b/engines/sword25/input/inputengine.cpp @@ -0,0 +1,399 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +#define BS_LOG_PREFIX "INPUTENGINE" + +#include "common/algorithm.h" +#include "common/events.h" +#include "common/system.h" +#include "common/util.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/callbackregistry.h" +#include "sword25/kernel/inputpersistenceblock.h" +#include "sword25/kernel/outputpersistenceblock.h" +#include "sword25/input/inputengine.h" + +namespace Sword25 { + +#define DOUBLE_CLICK_TIME 500 +#define DOUBLE_CLICK_RECT_SIZE 4 + +InputEngine::InputEngine(Kernel *pKernel) : + Service(pKernel), + m_CurrentState(0), + m_LeftMouseDown(false), + m_RightMouseDown(false), + m_MouseX(0), + m_MouseY(0), + m_LeftDoubleClick(false), + m_DoubleClickTime(DOUBLE_CLICK_TIME), + m_DoubleClickRectWidth(DOUBLE_CLICK_RECT_SIZE), + m_DoubleClickRectHeight(DOUBLE_CLICK_RECT_SIZE), + m_LastLeftClickTime(0), + m_LastLeftClickMouseX(0), + m_LastLeftClickMouseY(0) { + 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; + + if (!registerScriptBindings()) + BS_LOG_ERRORLN("Script bindings could not be registered."); + else + BS_LOGLN("Script bindings registered."); +} + +Service *InputEngine_CreateObject(Kernel *pKernel) { + return new InputEngine(pKernel); +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::Init() { + // No initialisation needed + return true; +} + +// ----------------------------------------------------------------------------- + +void InputEngine::Update() { + Common::Event event; + m_CurrentState ^= 1; + + // Loop through processing any pending events + bool handleEvents = true; + while (handleEvents && g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + m_LeftMouseDown = event.type == Common::EVENT_LBUTTONDOWN; + m_MouseX = event.mouse.x; + m_MouseY = event.mouse.y; + handleEvents = false; + break; + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_RBUTTONUP: + m_RightMouseDown = event.type == Common::EVENT_RBUTTONDOWN; + m_MouseX = event.mouse.x; + m_MouseY = event.mouse.y; + handleEvents = false; + break; + + case Common::EVENT_MOUSEMOVE: + m_MouseX = event.mouse.x; + m_MouseY = event.mouse.y; + break; + + case Common::EVENT_KEYDOWN: + case Common::EVENT_KEYUP: + AlterKeyboardState(event.kbd.keycode, (event.type == Common::EVENT_KEYDOWN) ? 0x80 : 0); + break; + + case Common::EVENT_QUIT: + Kernel::GetInstance()->GetWindow()->SetWindowAlive(false); + break; + + default: + break; + } + } + + m_LeftMouseState[m_CurrentState] = m_LeftMouseDown; + m_RightMouseState[m_CurrentState] = m_RightMouseDown; + + TestForLeftDoubleClick(); +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::IsLeftMouseDown() { + return m_LeftMouseDown; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::IsRightMouseDown() { + return m_RightMouseDown; +} + +// ----------------------------------------------------------------------------- + +void InputEngine::TestForLeftDoubleClick() { + m_LeftDoubleClick = false; + + // Only bother checking for a double click if the left mouse button was clicked + if (WasLeftMouseDown()) { + // Get the time now + uint Now = Kernel::GetInstance()->GetMilliTicks(); + + // A double click is signalled if + // 1. The two clicks are close enough together + // 2. The mouse cursor hasn't moved much + 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; + + // Reset the time and position of the last click, so that clicking is not + // interpreted as the first click of a further double-click + m_LastLeftClickTime = 0; + m_LastLeftClickMouseX = 0; + m_LastLeftClickMouseY = 0; + } else { + // There is no double click. Remember the position and time of the click, + // in case it's the first click of a double-click sequence + m_LastLeftClickTime = Now; + m_LastLeftClickMouseX = m_MouseX; + m_LastLeftClickMouseY = m_MouseY; + } + } +} + +// ----------------------------------------------------------------------------- + +void InputEngine::AlterKeyboardState(int keycode, byte newState) { + m_KeyboardState[m_CurrentState][keycode] = newState; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::IsLeftDoubleClick() { + return m_LeftDoubleClick; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::WasLeftMouseDown() { + return (m_LeftMouseState[m_CurrentState] == false) && (m_LeftMouseState[m_CurrentState ^ 1] == true); +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::WasRightMouseDown() { + return (m_RightMouseState[m_CurrentState] == false) && (m_RightMouseState[m_CurrentState ^ 1] == true); +} + +// ----------------------------------------------------------------------------- + +int InputEngine::GetMouseX() { + return m_MouseX; +} + +// ----------------------------------------------------------------------------- + +int InputEngine::GetMouseY() { + return m_MouseY; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::IsKeyDown(uint KeyCode) { + return (m_KeyboardState[m_CurrentState][KeyCode] & 0x80) != 0; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::WasKeyDown(uint KeyCode) { + return ((m_KeyboardState[m_CurrentState][KeyCode] & 0x80) == 0) && + ((m_KeyboardState[m_CurrentState ^ 1][KeyCode] & 0x80) != 0); +} + +// ----------------------------------------------------------------------------- + +void InputEngine::SetMouseX(int PosX) { + m_MouseX = PosX; + g_system->warpMouse(m_MouseX, m_MouseY); +} + +// ----------------------------------------------------------------------------- + +void InputEngine::SetMouseY(int PosY) { + m_MouseY = PosY; + g_system->warpMouse(m_MouseX, m_MouseY); +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::RegisterCharacterCallback(CharacterCallback Callback) { + if (Common::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 InputEngine::UnregisterCharacterCallback(CharacterCallback Callback) { + Common::List<CharacterCallback>::iterator CallbackIter = Common::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 InputEngine::RegisterCommandCallback(CommandCallback Callback) { + if (Common::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 InputEngine::UnregisterCommandCallback(CommandCallback Callback) { + Common::List<CommandCallback>::iterator CallbackIter = + Common::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 InputEngine::ReportCharacter(byte Character) { + Common::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. + Common::List<CharacterCallback>::const_iterator CurCallbackIter = CallbackIter; + ++CallbackIter; + + (*CurCallbackIter)(Character); + } +} + +// ----------------------------------------------------------------------------- + +void InputEngine::ReportCommand(KEY_COMMANDS Command) { + Common::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. + Common::List<CommandCallback>::const_iterator CurCallbackIter = CallbackIter; + ++CallbackIter; + + (*CurCallbackIter)(Command); + } +} + +// ----------------------------------------------------------------------------- +// Persistenz +// ----------------------------------------------------------------------------- + +bool InputEngine::persist(OutputPersistenceBlock &writer) { + // Anzahl an Command-Callbacks persistieren. + writer.write(m_CommandCallbacks.size()); + + // Alle Command-Callbacks einzeln persistieren. + { + Common::List<CommandCallback>::const_iterator It = m_CommandCallbacks.begin(); + while (It != m_CommandCallbacks.end()) { + writer.write(CallbackRegistry::getInstance().resolveCallbackPointer(*It)); + ++It; + } + } + + // Anzahl an Character-Callbacks persistieren. + writer.write(m_CharacterCallbacks.size()); + + // Alle Character-Callbacks einzeln persistieren. + { + Common::List<CharacterCallback>::const_iterator It = m_CharacterCallbacks.begin(); + while (It != m_CharacterCallbacks.end()) { + writer.write(CallbackRegistry::getInstance().resolveCallbackPointer(*It)); + ++It; + } + } + + return true; +} + +// ----------------------------------------------------------------------------- + +bool InputEngine::unpersist(InputPersistenceBlock &reader) { + // Command-Callbackliste leeren. + m_CommandCallbacks.clear(); + + // Anzahl an Command-Callbacks lesen. + uint CommandCallbackCount; + reader.read(CommandCallbackCount); + + // Alle Command-Callbacks wieder herstellen. + for (uint i = 0; i < CommandCallbackCount; ++i) { + Common::String CallbackFunctionName; + reader.read(CallbackFunctionName); + + m_CommandCallbacks.push_back(reinterpret_cast<CommandCallback>( + CallbackRegistry::getInstance().resolveCallbackFunction(CallbackFunctionName))); + } + + // Character-Callbackliste leeren. + m_CharacterCallbacks.clear(); + + // Anzahl an Character-Callbacks lesen. + uint CharacterCallbackCount; + reader.read(CharacterCallbackCount); + + // Alle Character-Callbacks wieder herstellen. + for (uint i = 0; i < CharacterCallbackCount; ++i) { + Common::String CallbackFunctionName; + reader.read(CallbackFunctionName); + + m_CharacterCallbacks.push_back(reinterpret_cast<CharacterCallback>(CallbackRegistry::getInstance().resolveCallbackFunction(CallbackFunctionName))); + } + + return reader.isGood(); +} + +} // End of namespace Sword25 diff --git a/engines/sword25/input/inputengine.h b/engines/sword25/input/inputengine.h new file mode 100644 index 0000000000..540817b5ce --- /dev/null +++ b/engines/sword25/input/inputengine.h @@ -0,0 +1,333 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +/* + * BS_InputEngine + * ------------- + * This is the input interface engine that contains all the methods that an + * input source must implement. + * All input engines must be derived from this class. + * + * Autor: Alex Arnst + */ + +#ifndef SWORD25_INPUTENGINE_H +#define SWORD25_INPUTENGINE_H + +/// Includes +#include "sword25/kernel/common.h" +#include "sword25/kernel/service.h" +#include "sword25/kernel/persistable.h" +#include "sword25/kernel/callbackregistry.h" + +namespace Sword25 { + +/// Class definitions + +class InputEngine : public Service, public Persistable { +public: + InputEngine(Kernel *pKernel); + ~InputEngine() {}; + + // NOTE: These codes are registered in inputengine_script.cpp + // Any changes to these enums must also adjust the above file. + 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 + }; + + // NOTE: These codes are registered in inputengine_script.cpp. + // Any changes to these enums must also adjust the above file. + 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 + }; + + /// -------------------------------------------------------------- + /// THESE METHODS MUST BE IMPLEMENTED BY THE INPUT ENGINE + /// -------------------------------------------------------------- + + /** + * Initialises the input engine + * @return Returns a true on success, otherwise false. + */ + bool Init(); + + /** + * Performs a "tick" of the input engine. + * + * This method should be called once per frame. It can be used by implementations + * of the input engine that are not running in their own thread, or to perform + * additional administrative tasks that are needed. + */ + void Update(); + + /** + * Returns true if the left mouse button is pressed + */ + bool IsLeftMouseDown(); + + /** + * Returns true if the right mouse button is pressed. + */ + bool IsRightMouseDown(); + + /** + * Returns true if the left mouse button was pressed and released. + * + * The difference between this and IsLeftMouseDown() is that this only returns + * true when the left mouse button is released. + */ + bool WasLeftMouseDown(); + + /** + * Returns true if the right mouse button was pressed and released. + * + * The difference between this and IsRightMouseDown() is that this only returns + * true when the right mouse button is released. + */ + bool WasRightMouseDown(); + + /** + * Returns true if the left mouse button double click was done + */ + bool IsLeftDoubleClick(); + + /** + * Returns the X position of the cursor in pixels + */ + int GetMouseX(); + + /** + * Returns the Y position of the cursor in pixels + */ + int GetMouseY(); + + /** + * Sets the X position of the cursor in pixels + */ + void SetMouseX(int PosX); + + /** + * Sets the Y position of the cursor in pixels + */ + void SetMouseY(int PosY); + + /** + * Returns true if a given key was pressed + * @param KeyCode The key code to be checked + * @return Returns true if the given key is done, otherwise false. + */ + bool IsKeyDown(uint KeyCode); + + /** + * Returns true if a certain key was pushed and released. + * + * The difference between IsKeyDown() is that this only returns true after the key + * has been released. This method facilitates the retrieval of keys, and reading + * strings that users type. + * @param KeyCode The key code to be checked + */ + bool WasKeyDown(uint KeyCode); + + typedef CallbackPtr CharacterCallback; + + /** + * Registers a callback function for keyboard input. + * + * The callbacks that are registered with this function will be called whenever an + * input key is pressed. A letter entry is different from the query using the + * methods IsKeyDown () and WasKeyDown () in the sense that are treated instead + * of actual scan-coded letters. These were taken into account, among other things: + * the keyboard layout, the condition the Shift and Caps Lock keys and the repetition + * of longer holding the key. + * The input of strings by the user through use of callbacks should be implemented. + * @return Returns true if the function was registered, otherwise false. + */ + bool RegisterCharacterCallback(CallbackPtr Callback); + + /** + * De-registeres a previously registered callback function. + * @return Returns true if the function could be de-registered, otherwise false. + */ + bool UnregisterCharacterCallback(CallbackPtr Callback); + + typedef CallbackPtr CommandCallback; + + /** + * Registers a callback function for the input of commands that can have influence on the string input + * + * The callbacks that are registered with this function will be called whenever the input service + * has a key that affects the character string input. This could be the following keys: + * Enter, End, Left, Right, ... + * The input of strings by the user through the use of callbacks should be implemented. + * @return Returns true if the function was registered, otherwise false. + */ + bool RegisterCommandCallback(CallbackPtr Callback); + + /** + * Un-register a callback function for the input of commands that can have an influence on the string input. + * @return Returns true if the function could be de-registered, otherwise false. + */ + bool UnregisterCommandCallback(CommandCallback Callback); + + void ReportCharacter(byte Character); + void ReportCommand(KEY_COMMANDS Command); + + bool persist(OutputPersistenceBlock &writer); + bool unpersist(InputPersistenceBlock &reader); + +private: + bool registerScriptBindings(); + +private: + void TestForLeftDoubleClick(); + void AlterKeyboardState(int keycode, byte newState); + + byte m_KeyboardState[2][256]; + bool m_LeftMouseState[2]; + bool m_RightMouseState[2]; + uint m_CurrentState; + int m_MouseX; + int m_MouseY; + bool m_LeftMouseDown; + bool m_RightMouseDown; + bool m_LeftDoubleClick; + uint m_DoubleClickTime; + int m_DoubleClickRectWidth; + int m_DoubleClickRectHeight; + uint m_LastLeftClickTime; + int m_LastLeftClickMouseX; + int m_LastLeftClickMouseY; + Common::List<CommandCallback> m_CommandCallbacks; + Common::List<CharacterCallback> m_CharacterCallbacks; +}; + +} // End of namespace Sword25 + +#endif diff --git a/engines/sword25/input/inputengine_script.cpp b/engines/sword25/input/inputengine_script.cpp new file mode 100644 index 0000000000..38ecc3cf56 --- /dev/null +++ b/engines/sword25/input/inputengine_script.cpp @@ -0,0 +1,355 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "common/ptr.h" +#include "common/str.h" +#include "sword25/kernel/common.h" +#include "sword25/kernel/kernel.h" +#include "sword25/kernel/callbackregistry.h" +#include "sword25/script/script.h" +#include "sword25/script/luabindhelper.h" +#include "sword25/script/luacallback.h" + +#include "sword25/input/inputengine.h" + +#define BS_LOG_PREFIX "INPUTENGINE" + +namespace Sword25 { + +using namespace Lua; + +// ----------------------------------------------------------------------------- +// Callback-Objekte +// ----------------------------------------------------------------------------- + +static void TheCharacterCallback(int Character); +static void TheCommandCallback(int Command); + +namespace { +class CharacterCallbackClass : public LuaCallback { +public: + CharacterCallbackClass(lua_State *L) : LuaCallback(L) {}; + + Common::String Character; + +protected: + int PreFunctionInvokation(lua_State *L) { + lua_pushstring(L, Character.c_str()); + return 1; + } +}; +Common::SharedPtr<CharacterCallbackClass> CharacterCallbackPtr; + +// ----------------------------------------------------------------------------- + +class CommandCallbackClass : public LuaCallback { +public: + CommandCallbackClass(lua_State *L) : LuaCallback(L) { + Command = InputEngine::KEY_COMMAND_BACKSPACE; + } + + InputEngine::KEY_COMMANDS Command; + +protected: + int PreFunctionInvokation(lua_State *L) { + lua_pushnumber(L, Command); + return 1; + } +}; +Common::SharedPtr<CommandCallbackClass> CommandCallbackPtr; + +// ------------------------------------------------------------------------- + +struct CallbackfunctionRegisterer { + CallbackfunctionRegisterer() { + CallbackRegistry::getInstance().registerCallbackFunction("LuaCommandCB", TheCommandCallback); + CallbackRegistry::getInstance().registerCallbackFunction("LuaCharacterCB", TheCharacterCallback); + } +}; +static CallbackfunctionRegisterer Instance; +} + +// ----------------------------------------------------------------------------- + +static InputEngine *GetIE() { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + InputEngine *pIE = static_cast<InputEngine *>(pKernel->GetService("input")); + BS_ASSERT(pIE); + return pIE; +} + +// ----------------------------------------------------------------------------- + +static int Init(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->Init()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int Update(lua_State *L) { + 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) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->IsLeftMouseDown()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int IsRightMouseDown(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->IsRightMouseDown()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int WasLeftMouseDown(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->WasLeftMouseDown()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int WasRightMouseDown(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->WasRightMouseDown()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int IsLeftDoubleClick(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->IsLeftDoubleClick()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetMouseX(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushnumber(L, pIE->GetMouseX()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int GetMouseY(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushnumber(L, pIE->GetMouseY()); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int IsKeyDown(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->IsKeyDown((uint) luaL_checknumber(L, 1))); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int WasKeyDown(lua_State *L) { + InputEngine *pIE = GetIE(); + + lua_pushbooleancpp(L, pIE->WasKeyDown((uint) luaL_checknumber(L, 1))); + return 1; +} + +// ----------------------------------------------------------------------------- + +static int SetMouseX(lua_State *L) { + InputEngine *pIE = GetIE(); + + pIE->SetMouseX((int) luaL_checknumber(L, 1)); + return 0; +} + +// ----------------------------------------------------------------------------- + +static int SetMouseY(lua_State *L) { + InputEngine *pIE = GetIE(); + + pIE->SetMouseY((int) luaL_checknumber(L, 1)); + return 0; +} + +// ----------------------------------------------------------------------------- + +static void TheCharacterCallback(int Character) { + CharacterCallbackPtr->Character = static_cast<byte>(Character); + lua_State *L = static_cast<lua_State *>(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(int Command) { + CommandCallbackPtr->Command = static_cast<InputEngine::KEY_COMMANDS>(Command); + lua_State *L = static_cast<lua_State *>(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, InputEngine::KEY_##k} +#define Y(k) {"KEY_COMMAND_" #k, 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 InputEngine::registerScriptBindings() { + Kernel *pKernel = Kernel::GetInstance(); + BS_ASSERT(pKernel); + ScriptEngine *pScript = static_cast<ScriptEngine *>(pKernel->GetService("script")); + BS_ASSERT(pScript); + lua_State *L = static_cast<lua_State *>(pScript->getScriptObject()); + BS_ASSERT(L); + + if (!LuaBindhelper::addFunctionsToLib(L, PACKAGE_LIBRARY_NAME, PACKAGE_FUNCTIONS)) return false; + if (!LuaBindhelper::addConstantsToLib(L, PACKAGE_LIBRARY_NAME, PACKAGE_CONSTANTS)) return false; + + CharacterCallbackPtr = Common::SharedPtr<CharacterCallbackClass>(new CharacterCallbackClass(L)); + CommandCallbackPtr = Common::SharedPtr<CommandCallbackClass>(new CommandCallbackClass(L)); + + return true; +} + +} // End of namespace Sword25 |