Sirikata
|
00001 /* Sirikata Input Plugin -- plugins/input 00002 * InputDevice.hpp 00003 * 00004 * Copyright (c) 2009, Patrick Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifndef SIRIKATA_INPUT_InputDevice_HPP__ 00034 #define SIRIKATA_INPUT_InputDevice_HPP__ 00035 00036 #include <sirikata/ogre/Platform.hpp> 00037 #include <sirikata/core/util/Time.hpp> 00038 #include <sirikata/core/util/Timer.hpp> 00039 00040 namespace Sirikata { 00041 namespace Input { 00042 00043 /* 00044 00045 ==== AVATAR IS FOCUSED ==== 00046 00047 Walk Forward/Backward: <Axis Type> 00048 Mouse X [Edit] "M/0/x" 00049 Mouse Y [Edit] "M/0/y" 00050 Joystick Axis 0 [Edit] "J/0/0" 00051 Joystick Axis 1 [Edit] "J/0/1" 00052 Joystick Axis 2 [Edit] "J/0/2" 00053 Tablet/Touchscreen [Edit] "MA/0/x" 00054 Up/Down arrow keys [Edit] "KA/0" 00055 [Keyboard/Hatswitch] 00056 [New Tablet Mode] 00057 Walk Left/Right: <A/D> 00058 Turn Left/Right: <Mouse X> 00059 Turn Up/Down: <W/S> 00060 00061 Jump: [Space] 00062 Select: [Type or pick key] 00063 Mouse up [Edit] 00064 [Make new analog Hatswitch / key from axis.] 00065 00066 00067 ==== SCENE HAS FOCUS (or null) ==== 00068 00069 Absolute pointer 0: [Mouse 1 Cursor] 00070 Absolute pointer 1: [Touchpad] 00071 Absolute pointer 2: [Joystick Axis 1+2] 00072 Absolute pointer 3: [Keyboard Axis "Up/Down arrow keys"/"Left/Right arrow keys"] 00073 Return from UI: [ESCAPE] 00074 00075 Key bindings: 00076 [Not implemented, but you can bind buttons to individual keys if you want] 00077 00078 ==== FLASH GAME IS FOCUSED ==== 00079 Choose two analog inputs and one keyboard/joystick->key bindings 00080 00081 */ 00082 00083 struct AxisValue { 00084 float value; 00085 float get01() const { 00086 return (value + 1.0f)/2.0f; 00087 } 00088 float getCentered() const { 00089 return value; 00090 } 00091 static AxisValue fromCentered(float val) { 00092 AxisValue ret = {val}; 00093 return ret; 00094 } 00095 static AxisValue from01(float val) { 00096 AxisValue ret = {(val-0.5f)*2.0f}; 00097 return ret; 00098 } 00099 static AxisValue null() { 00100 return fromCentered(0.0f); 00101 } 00102 00103 bool isNegative() const { 00104 return value < 0; 00105 } 00106 bool isPositive() const { 00107 return value > 0; 00108 } 00109 00110 void clip() { 00111 if (value > 1.0) { 00112 value = 1.0; 00113 } 00114 if (value < -1.0) { 00115 value = -1.0; 00116 } 00117 } 00118 bool operator == (const AxisValue &other) const { 00119 return value == other.value; 00120 } 00121 AxisValue operator - () const { 00122 return fromCentered(-getCentered()); 00123 } 00124 bool operator != (const AxisValue &other) const { 00125 return value != other.value; 00126 } 00127 00128 friend std::ostream &operator <<(std::ostream &os, const AxisValue &val) { 00129 return os << (int)(100*val.getCentered()) << '%'; 00130 } 00131 }; 00132 00133 class InputManager; 00134 00135 class InputDevice; 00136 typedef std::tr1::shared_ptr<InputDevice> InputDevicePtr; 00137 typedef std::tr1::weak_ptr<InputDevice> InputDeviceWPtr; 00138 00139 class PointerDevice; 00140 typedef std::tr1::shared_ptr<PointerDevice> PointerDevicePtr; 00141 00142 /* SDL Defines these on some platforms */ 00143 #ifdef MOD_SHIFT 00144 #undef MOD_SHIFT 00145 #endif 00146 #ifdef MOD_CTRL 00147 #undef MOD_CTRL 00148 #endif 00149 #ifdef MOD_GUI 00150 #undef MOD_GUI 00151 #endif 00152 #ifdef MOD_ALT 00153 #undef MOD_ALT 00154 #endif 00155 00156 typedef uint32 Modifier; 00157 enum KeyboardModifiers { 00158 MOD_NONE = 0, 00159 MOD_SHIFT = 1, 00160 MOD_CTRL = 2, 00161 MOD_ALT = 4, 00162 MOD_GUI = 8 00163 }; 00164 enum PointerModifiers { 00165 //POINTER_STYLUS = 0, // default 00166 POINTER_ERASER = (1<<0), 00167 POINTER_CURSOR = (1<<1) 00168 }; 00169 00170 enum Axes { 00171 AXIS_CURSORX, 00172 AXIS_CURSORY, 00173 AXIS_RELX, 00174 AXIS_RELY, 00175 NUM_POINTER_AXES 00176 }; 00177 00178 typedef uint32 AxisIndex; 00179 00180 typedef int32 MouseButton; 00181 00182 typedef int32 KeyButton; 00183 00184 enum KeyEvent { 00185 KEY_PRESSED, 00186 KEY_DOWN, 00187 KEY_RELEASED, 00188 KEY_REPEATED 00189 }; 00190 00199 enum MouseDragType { 00200 DRAG_DEADBAND, // Have not yet started an actual drag 00201 DRAG_START, 00202 DRAG_DRAG, 00203 DRAG_END 00204 }; 00205 00206 enum WindowEventType { 00207 WindowShown, 00208 WindowHidden, 00209 WindowExposed, 00210 WindowMoved, 00211 WindowResized, 00212 WindowMinimized, 00213 WindowMaximized, 00214 WindowRestored, 00215 WindowMouseEnter, 00216 WindowMouseLeave, 00217 WindowFocusGained, 00218 WindowFocusLost, 00219 WindowQuit 00220 }; 00221 00222 class SIRIKATA_OGRE_EXPORT InputDevice { 00223 protected: 00224 std::string mName; 00225 InputManager *mManager; 00226 00227 struct ButtonState { 00228 Modifier mod; 00229 Time initialTime; 00230 Time lastTime; 00231 }; 00232 typedef std::tr1::unordered_map<unsigned int, ButtonState> ButtonSet; 00233 typedef std::vector<AxisValue> AxisVector; 00234 00235 ButtonSet buttonState; 00236 AxisVector axisState; 00237 00238 bool changeButton(unsigned int button, bool newState, Modifier &mod); 00239 bool changeAxis(unsigned int axis, AxisValue newValue); 00240 00241 public: 00242 const std::string &getName() const { 00243 return mName; 00244 } 00245 void setName(const std::string &newName) { 00246 mName = newName; 00247 } 00248 InputManager *getInputManager() { 00249 return mManager; 00250 } 00251 void setInputManager(InputManager *man) { 00252 mManager = man; 00253 } 00254 00255 InputDevice() : mManager(0) {} 00256 virtual ~InputDevice() {} 00257 00258 virtual std::string getButtonName(unsigned int button) const = 0; 00259 virtual int getNumButtons() const = 0; 00260 00261 virtual std::string getAxisName(unsigned int axis) const = 0; 00262 virtual unsigned int getNumAxes() const = 0; 00263 00264 virtual bool isKeyboard() { return false; } 00265 00266 bool fireButton(const InputDevicePtr &thisptr, 00267 unsigned int button, bool newState, Modifier mod = 0); 00268 bool fireAxis(const InputDevicePtr &thisptr, 00269 unsigned int axis, AxisValue newState); 00270 00271 inline AxisValue getAxis(unsigned int axis) const { 00272 if (axisState.size() <= axis) { 00273 return AxisValue::null(); 00274 } 00275 return axisState[axis]; 00276 } 00277 inline bool getButton(unsigned int button, Modifier mod) const { 00278 ButtonSet::const_iterator iter = buttonState.find(button); 00279 if (iter != buttonState.end()) { 00280 return (*iter).second.mod == mod; 00281 } else { 00282 return false; 00283 } 00284 } 00285 inline const Modifier *getButton(unsigned int button) const { 00286 ButtonSet::const_iterator iter = buttonState.find(button); 00287 if (iter != buttonState.end()) { 00288 return &((*iter).second.mod); 00289 } else { 00290 return NULL; 00291 } 00292 } 00293 }; 00294 00295 00296 class SIRIKATA_OGRE_EXPORT PointerDevice : public InputDevice { 00297 struct DragInfo { 00298 int mButton; 00299 bool mIsDragging; 00300 float mDragStartX; 00301 float mDragStartY; 00302 float mDragX; 00303 float mDragY; 00304 float mOffsetX; 00305 float mOffsetY; 00306 }; 00307 typedef std::list<DragInfo> DragMap; 00308 DragMap mDragInfo; 00309 protected: 00310 float mDeadband; 00311 unsigned int mRelativeMode; 00312 00313 virtual void setRelativeMode(bool enabled) = 0; 00314 00315 public: 00316 PointerDevice() : mDeadband(0.0), mRelativeMode(0) { 00317 } 00318 void setDragDeadband(float deadband) { 00319 mDeadband = deadband; 00320 } 00321 00322 void pushRelativeMode() { 00323 if (mRelativeMode++ == 0) { 00324 setRelativeMode(true); 00325 } 00326 } 00327 00328 void popRelativeMode() { 00329 if (mRelativeMode > 0) { 00330 if (--mRelativeMode == 0) { 00331 setRelativeMode(false); 00332 } 00333 } 00334 } 00335 bool getRelativeMode() const { 00336 return mRelativeMode ? true : false; 00337 } 00338 00339 void firePointerMotion(const PointerDevicePtr &thisptr, 00340 float xPixel, 00341 float yPixel, 00342 int cursorType, 00343 int pressure, int pressmin, int pressmax); 00344 void firePointerClick(const PointerDevicePtr &thisptr, 00345 float xPixel, 00346 float yPixel, 00347 int cursor, 00348 int button, 00349 bool state); 00350 }; 00351 00352 } 00353 } 00354 00355 #endif