diff mde/input/Input.d @ 99:5de5810e3516

Implemented an editable TextContent widget; it's now possible to edit text options using the GUI. The widget supports moving the text entry-point using arrows and home/end, but there's no visual indicator or edit-point setting using the mouse.
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 14 Nov 2008 12:44:32 +0000
parents 97e6dce08037
children 20f7d813bb0f
line wrap: on
line diff
--- a/mde/input/Input.d	Wed Nov 12 13:18:51 2008 +0000
+++ b/mde/input/Input.d	Fri Nov 14 12:44:32 2008 +0000
@@ -25,58 +25,79 @@
 
 // sdl imports
 import derelict.sdl.events;
+import derelict.sdl.keyboard;
 import derelict.sdl.types;	// only SDL_PRESSED
 import derelict.sdl.joystick;	// SDL_HAT_*
 
+import Utf = tango.text.convert.Utf;
 import tango.util.log.Log : Log, Logger;
 
-/** Class encapsulating all input functionality.
+/**************************************************************************************************
+ * Class encapsulating all input functionality.
+ *
+ * This class has several modes which affect output: interaction mode (default), text input mode,
+ * mouse gui mode and axis/button binding modes.
+ *
+ * TODO: Gui mode and button capture and axis capture modes for key binding, disabling all
+ * other modes (except gui-type mouse info?).
+ * TODO: Possible revisions: remove by-index lookup, only providing callbacks?
+ * TODO: Make callbacks send the time of the event?
+ * TODO: Adjusters, e.g. double-press, hold/click differences. Axis output: via short or double?
+ * TODO: add an Axis1Callback similar to getAxis1? Or remove getAxis1 and provide a conversion function?
+ * TODO: allow callbacks to be removed. Currently not needed.
+ * TODO: modifiers in text-input mode: shortcut handling? Global shortcuts - either mode?
  *
- * The following methods are provided for Gui mouse input:
+ * The primary mode is the interaction mode, mapping each button and axis to a configurable index,
+ * and allowing event callback functions to be bound per index as well as allowing the state to be
+ * looked up directly.
+ * ---
+ * // For keyboard, joystick and mouse button input
+ * bool getButton (inputID id);
+ * void addButtonCallback (inputID id, ButtonCallback dg);  // callback receives both up and down events
+ *
+ * // For joystick axis input
+ * short getAxis (inputID id);      // range: -32767 .. 32767
+ * double getAxis1 (inputID id);    // range: -1.0 .. 1.0
+ * void addAxisCallback (inputID id, AxisCallback dg);
+ *
+ * // For mouse (and joystick ball) relative motion input
+ * void getRelMotion (inputID id, out double x, out double y);
+ * void addRelMotionCallback (inputID id, RelMotionCallback dg);
+ * ---
+ *
+ * The keyboard can be put in text input mode, disabling interaction-mode keyboard access and
+ * providing a callback called on each letter press with it's UTF-8 code. Setting a LetterCallback
+ * activates text input mode and removing it disables this mode; only one may be active at once.
+ * ---
+ * void setLetterCallback (LetterCallback dg);
+ * ---
+ *
+ * Mouse input can be recieved via gui-oriented click/coordinate callbacks in both interaction
+ * mode and gui mode, however interaction-mode button and relative motion input is not received in
+ * gui mode.
  * ---
  * void getMouseScreenPos (out uint x, out uint y);
  * void addMouseClickCallback (MouseClickCallback dg);
  * void addMouseMotionCallback (MouseMotionCallback dg);
  * ---
  *
- * The following methods are provided for mouse (and joystick ball) relative motion input:
- * ---
- * void getRelMotion (inputID id, out real x = 0.0, out real y = 0.0);
- * void addRelMotionCallback (inputID id, RelMotionCallback dg);
- * ---
- *
- * The following methods are provided for joystick axis input:
- * ---
- * short getAxis (inputID id);
- * real getAxis1 (inputID id);
- * void addAxisCallback (inputID id, AxisCallback dg);
- * ---
- *
- * The following methods are provided for keyboard, joystick and mouse button input:
- * ---
- * bool getButton (inputID id);
- * void addButtonCallback (inputID id, ButtonCallback dg)
- * ---
- *
  * The following methods are provided for setup & posting events:
  * ---
- * bool opCall (ref SDL_Event event);
- * void frameReset ();
- * void loadConfig (char[] profile = "Default");
+ * bool opCall (ref SDL_Event event);   // Handles an event, making all the above work
+ * void frameReset ();  // Needs to be called once per frame for correct relative input
+ * void loadConfig (char[] profile = "Default");    // Configuration for interaction-mode indexes
  * ---
  ***************************************************/
-// FIXME: remove getMouseScreenPos (no use)?
-// FIXME: add an Axis1Callback similar to getAxis1? Or remove getAxis1 and provide a conversion
-// function?
 class Input
 {
     /// Typedef for all indexes (type is uint).
     typedef uint				inputID;
     alias void delegate(inputID, bool)		ButtonCallback;
     alias void delegate(inputID, short)		AxisCallback;
-    alias void delegate(inputID, real,real)	RelMotionCallback;
-    alias void delegate(ushort, ushort, ubyte, bool)    MouseClickCallback;
-    alias void delegate(ushort, ushort)                 MouseMotionCallback;
+    alias void delegate(inputID, double,double)	RelMotionCallback;
+    alias void delegate(ushort, ushort, ubyte, bool)	MouseClickCallback;
+    alias void delegate(ushort, ushort)		MouseMotionCallback;
+    alias void delegate(ushort, char[])		LetterCallback;
 
     /** Get key status at this ID.
     *
@@ -97,38 +118,27 @@
     }
     /** Get axis status at this ID.
     *
-    * Returns: value (real; range roughly -1.0 .. 1.0) or 0 if no value at this ID. */
-    real getAxis1 (inputID id) {
+    * Returns: value (double; range roughly -1.0 .. 1.0) or 0 if no value at this ID. */
+    double getAxis1 (inputID id) {
         short* retp = id in axis;
         if (retp) return (*retp) * 3.0518509475997192e-05;
         else return 0.0;
     }
-            
+    
     /** Get the relative motion of the mouse or a joystick ball (since last frameReset() call).
     *
-    * Future: Converts to a real via sensitivity settings (defaults may be set and overriden per item).
+    * Future: Converts to a double via sensitivity settings (defaults may be set and overriden per item).
     *
     * To avoid confusion over the ID here, the idea is for the input-layer upward to support
     * multiple mice, in case future platforms do.
     * Also joystick balls (supported by SDL) can be used in the same way as a mouse for relative
     * positions. */
-    void getRelMotion (inputID id, out real x = 0.0, out real y = 0.0) {
+    void getRelMotion (inputID id, out double x = 0.0, out double y = 0.0) {
         RelPair* rp = id in relMotion;
         if (rp) {
             x = rp.x;	y = rp.y;
         }
     }
-    /** Get mouse pointer position in screen coordinates.
-    *
-    * Window managers only support one mouse, so there will only be one screen coordinate.
-    * Unlike nearly everything else, this is not configurable.
-    *
-    * Also see addMouseMotionCallback. */
-    void getMouseScreenPos (out uint x, out uint y) {
-        x = mouse_x;	y = mouse_y;
-    }
-    // /// Is this modifier on?
-    //bool modifierStatus (inputID id);
 
     /** Adds a callback delegate for key events (both DOWN and UP) with this ID.
     *
@@ -176,6 +186,24 @@
     void addMouseMotionCallback (MouseMotionCallback dg) {
         mouseMotionCallbacks ~= dg;
     }
+    
+    /** Sets a callback delegate to recieve key presses as a Utf-8 char[].
+    *
+    * Since it is normal to type into only one location at once, setting a new LetterCallback
+    * removes the last set one (however active ButtonCallbacks will still receive events).
+    * Supplying a null delegate will turn off the slight overhead of unicode conversion.
+    * 
+    * The char[] received by the delegate must be copied and not stored or edited directly. */
+    void setLetterCallback (LetterCallback dg = null) {
+        if (dg) {
+	    SDL_EnableUNICODE (1);
+	    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+	} else {
+	    SDL_EnableUNICODE (0);
+	    SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
+	}
+        letterCallback = dg;
+    }
 
     /** Feed an SDL_Event struct (only uses if it's a key, mouse or joystick event).
     *
@@ -207,9 +235,6 @@
                 break;
             
             case SDL_MOUSEMOTION:
-                mouse_x = event.motion.x;
-                mouse_y = event.motion.y;
-                
                 foreach (dg; mouseMotionCallbacks) {
                     try
                         dg (event.motion.x, event.motion.y);
@@ -229,7 +254,10 @@
         switch (event.type) {
             // Keyboard events:
             case SDL_KEYDOWN:
+                if (letterCallback)
+		    letterCallback (event.key.keysym.sym, Utf.toString ([cast(wchar)event.key.keysym.unicode], cast(char[])utfBuf));
             case SDL_KEYUP:
+		if (letterCallback) break;	// text input mode; no keyboard input from mappings
                 outQueue[]* p = (Config.B.SDLKEY | event.key.keysym.sym) in config.button;
                 if (p) foreach (outQueue q; *p) {
                     bEvent (this, event.key.state == SDL_PRESSED, readOutQueue(q));
@@ -370,8 +398,8 @@
     }
     
     struct RelPair {	// for mouse/joystick ball motion
-        real x, y;
-        static RelPair opCall (real a, real b) {
+        double x, y;
+        static RelPair opCall (double a, double b) {
             RelPair ret;
             ret.x = a;	ret.y = b;
             return ret;
@@ -382,12 +410,12 @@
     
     static Logger logger;
 
-    Config config;			// Configuration
+    Config config;		// Configuration
+    char[6] utfBuf;		// Buffer for Utf.toString; reallocates if less than 5.
     
-    bool[inputID] button;		// Table of button states
-    short[inputID] axis;		// Table of axes states
-    ushort mouse_x, mouse_y;		// Current screen coords of the window manager mouse
-    RelPair[inputID] relMotion;		// Table of relative mouse / joystick ball motions
+    bool[inputID] button;	// Table of button states
+    short[inputID] axis;	// Table of axes states
+    RelPair[inputID] relMotion;	// Table of relative mouse / joystick ball motions
     
     // NOTE: currently no means of removal
     ButtonCallback[][inputID]	buttonCallbacks;
@@ -395,7 +423,8 @@
     RelMotionCallback[][inputID] relMotionCallbacks;
     MouseClickCallback[]	mouseClickCallbacks;
     MouseMotionCallback[]	mouseMotionCallbacks;
-        
+    LetterCallback              letterCallback;
+    
     //BEGIN Event stream functionality
     /* This section contains functions called on an event, which may modify the event (adjuster
     * functions), and finally output to one (or more) of the state tables (the event stream).
@@ -578,7 +607,7 @@
             assert (x == (counters[3] ? 0 : 32767));
             counters[3] += 1;
         });
-        ut.addRelMotionCallback (0x11F0, delegate void(inputID id, real x, real y) {
+        ut.addRelMotionCallback (0x11F0, delegate void(inputID id, double x, double y) {
             assert (x == 14.0);
             assert (y == -1.0);
             counters[4] += 1;
@@ -660,7 +689,7 @@
         assert (ut.getAxis(0x21F0) == -32767);
         assert (ut.getAxis1(0x22F0) == 0.0);
             
-        real s,t;
+        double s,t;
         ut.getRelMotion(0x10F0, s,t);
         assert (s == 14.0);
         assert (t == -1.0);