rnd-20140418-1-src
authorHolger Schemel <info@artsoft.org>
Fri, 18 Apr 2014 00:51:53 +0000 (02:51 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 09:01:27 +0000 (11:01 +0200)
src/conf_gfx.c
src/conf_var.c
src/conftime.h
src/events.c
src/files.c
src/libgame/system.h
src/main.h
src/screens.c

index a2406193916f55446bda0078db9d2aad31392c9b..9ac6c9089d78181c92a9729e566dd26d203bf1b0 100644 (file)
@@ -5829,6 +5829,8 @@ struct ConfigInfo image_config[] =
   { "menu.draw_yoffset.SETUP[ARTWORK]",                "0"                     },
   { "menu.draw_xoffset.SETUP[INPUT]",          "0"                     },
   { "menu.draw_yoffset.SETUP[INPUT]",          "0"                     },
+  { "menu.draw_xoffset.SETUP[TOUCH]",          "0"                     },
+  { "menu.draw_yoffset.SETUP[TOUCH]",          "0"                     },
   { "menu.draw_xoffset.SETUP[SHORTCUTS]",      "0"                     },
   { "menu.draw_yoffset.SETUP[SHORTCUTS]",      "0"                     },
   { "menu.draw_xoffset.SETUP[SHORTCUTS_1]",    "0"                     },
index 03ab11dd55ae577483766f92e8a8696af065bd02..635fd08a32b35f7b60652ed961821cfd1525edd6 100644 (file)
@@ -1300,6 +1300,14 @@ struct TokenIntPtrInfo image_config_vars[] =
     "menu.draw_yoffset.SETUP[INPUT]",
     &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_INPUT]
   },
+  {
+    "menu.draw_xoffset.SETUP[TOUCH]",
+    &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_TOUCH]
+  },
+  {
+    "menu.draw_yoffset.SETUP[TOUCH]",
+    &menu.draw_yoffset_setup[GFX_SPECIAL_ARG_SETUP_TOUCH]
+  },
   {
     "menu.draw_xoffset.SETUP[SHORTCUTS]",
     &menu.draw_xoffset_setup[GFX_SPECIAL_ARG_SETUP_SHORTCUTS]
index eb9a7af8c5b5ac9e4b2cbf76c45b07e2ba1ae639..5aca865a438a9cca8e9dea64f3fe73815c5be1ef 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "2014-03-31 21:28"
+#define COMPILE_DATE_STRING "2014-04-18 02:47"
index f1d9ad1125046821b51c8e390a320825be948b80..17c39c0407a887342dbdca3060dcaaf5dc1af68c 100644 (file)
@@ -539,10 +539,12 @@ void HandleFingerEvent(FingerEvent *event)
   static Key button_key = KSYM_UNDEFINED;
   static float motion_x1, motion_y1;
   static float button_x1, button_y1;
-  static SDL_FingerID motion_id = 0;
-  static SDL_FingerID button_id = 0;
-  int trigger_distance_percent = 1;    // percent of touchpad width/height
-  float trigger_distance = (float)trigger_distance_percent / 100;
+  static SDL_FingerID motion_id = -1;
+  static SDL_FingerID button_id = -1;
+  int move_trigger_distance_percent = 2;   // percent of touchpad width/height
+  int drop_trigger_distance_percent = 5;   // percent of touchpad width/height
+  float move_trigger_distance = (float)move_trigger_distance_percent / 100;
+  float drop_trigger_distance = (float)drop_trigger_distance_percent / 100;
   float event_x = event->x;
   float event_y = event->y;
 
@@ -562,7 +564,13 @@ void HandleFingerEvent(FingerEvent *event)
   if (game_status != GAME_MODE_PLAYING)
     return;
 
-  if (1)
+#if 1
+  if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+#else
+  boolean use_virtual_button_control = FALSE;
+
+  if (use_virtual_button_control)
+#endif
   {
     int key_status = (event->type == EVENT_FINGERRELEASE ? KEY_RELEASED :
                      KEY_PRESSED);
@@ -714,6 +722,8 @@ void HandleFingerEvent(FingerEvent *event)
     return;
   }
 
+  // use touch direction control
+
   if (event->type == EVENT_FINGERPRESS)
   {
     if (event_x > 1.0 / 3.0)
@@ -750,7 +760,7 @@ void HandleFingerEvent(FingerEvent *event)
   {
     if (event->fingerId == motion_id)
     {
-      motion_id = 0;
+      motion_id = -1;
 
       if (motion_key_x != KSYM_UNDEFINED)
        HandleKey(motion_key_x, KEY_RELEASED);
@@ -764,7 +774,7 @@ void HandleFingerEvent(FingerEvent *event)
     }
     else if (event->fingerId == button_id)
     {
-      button_id = 0;
+      button_id = -1;
 
       if (button_key != KSYM_UNDEFINED)
        HandleKey(button_key, KEY_RELEASED);
@@ -787,16 +797,16 @@ void HandleFingerEvent(FingerEvent *event)
                              event_y > motion_y1 ? setup.input[0].key.down :
                              KSYM_UNDEFINED);
 
-      if (distance_x < trigger_distance / 2 ||
+      if (distance_x < move_trigger_distance / 2 ||
          distance_x < distance_y)
        new_motion_key_x = KSYM_UNDEFINED;
 
-      if (distance_y < trigger_distance / 2 ||
+      if (distance_y < move_trigger_distance / 2 ||
          distance_y < distance_x)
        new_motion_key_y = KSYM_UNDEFINED;
 
-      if (distance_x > trigger_distance ||
-         distance_y > trigger_distance)
+      if (distance_x > move_trigger_distance ||
+         distance_y > move_trigger_distance)
       {
        if (new_motion_key_x != motion_key_x)
        {
@@ -828,8 +838,8 @@ void HandleFingerEvent(FingerEvent *event)
       float distance_x = ABS(event_x - button_x1);
       float distance_y = ABS(event_y - button_y1);
 
-      if (distance_x < trigger_distance / 2 &&
-         distance_y > trigger_distance)
+      if (distance_x < drop_trigger_distance / 2 &&
+         distance_y > drop_trigger_distance)
       {
        if (button_key == setup.input[0].key.snap)
          HandleKey(button_key, KEY_RELEASED);
index f20c215596e58b88a2b4d5a1ab1020c43e1ada67..2f396591f4dc6dc5bf40961d2e73ad75b865a81d 100644 (file)
@@ -11365,8 +11365,11 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_VOLUME_SIMPLE              35
 #define SETUP_TOKEN_VOLUME_LOOPS               36
 #define SETUP_TOKEN_VOLUME_MUSIC               37
+#define SETUP_TOKEN_TOUCH_CONTROL_TYPE         38
+#define SETUP_TOKEN_TOUCH_MOVE_DISTANCE                39
+#define SETUP_TOKEN_TOUCH_DROP_DISTANCE                40
 
-#define NUM_GLOBAL_SETUP_TOKENS                        38
+#define NUM_GLOBAL_SETUP_TOKENS                        41
 
 /* editor setup */
 #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH      0
@@ -11514,6 +11517,9 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_INTEGER,&si.volume_simple,           "volume_simple"          },
   { TYPE_INTEGER,&si.volume_loops,            "volume_loops"           },
   { TYPE_INTEGER,&si.volume_music,            "volume_music"           },
+  { TYPE_STRING, &si.touch.control_type,      "touch.control_type"     },
+  { TYPE_INTEGER,&si.touch.move_distance,     "touch.move_distance"    },
+  { TYPE_INTEGER,&si.touch.drop_distance,     "touch.drop_distance"    },
 };
 
 static boolean not_used = FALSE;
@@ -11686,9 +11692,13 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->override_level_sounds = FALSE;
   si->override_level_music = FALSE;
 
-  si->volume_simple = 100;     /* percent */
-  si->volume_loops = 100;      /* percent */
-  si->volume_music = 100;      /* percent */
+  si->volume_simple = 100;             /* percent */
+  si->volume_loops = 100;              /* percent */
+  si->volume_music = 100;              /* percent */
+
+  si->touch.control_type = getStringCopy(TOUCH_CONTROL_DEFAULT);
+  si->touch.move_distance = TOUCH_MOVE_DISTANCE_DEFAULT;       /* percent */
+  si->touch.drop_distance = TOUCH_DROP_DISTANCE_DEFAULT;       /* percent */
 
   si->editor.el_boulderdash            = TRUE;
   si->editor.el_emerald_mine           = TRUE;
@@ -11957,7 +11967,8 @@ void SaveSetup()
     /* just to make things nicer :) */
     if (i == SETUP_TOKEN_PLAYER_NAME + 1 ||
        i == SETUP_TOKEN_GRAPHICS_SET ||
-       i == SETUP_TOKEN_VOLUME_SIMPLE)
+       i == SETUP_TOKEN_VOLUME_SIMPLE ||
+       i == SETUP_TOKEN_TOUCH_CONTROL_TYPE)
       fprintf(file, "\n");
 
     fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
index b9c74003365e64ead0319b70879c65caeabc8e4c..90e8bca7af8f4d39dff18f6ab32a2d26bd6e5b39 100644 (file)
 
 #define SCALING_QUALITY_DEFAULT                SCALING_QUALITY_LINEAR
 
+/* values for touch control */
+#define TOUCH_CONTROL_VIRTUAL_BUTTONS  "virtual_buttons"
+#define TOUCH_CONTROL_WIPE_GESTURES    "wipe_gestures"
+
+#define TOUCH_CONTROL_DEFAULT          TOUCH_CONTROL_VIRTUAL_BUTTONS
+
+#define TOUCH_MOVE_DISTANCE_DEFAULT    2
+#define TOUCH_DROP_DISTANCE_DEFAULT    5
+
+
 /* default input keys */
 #define DEFAULT_KEY_LEFT               KSYM_Left
 #define DEFAULT_KEY_RIGHT              KSYM_Right
@@ -868,6 +878,13 @@ struct SetupKeyboardInfo
   Key snap, drop;
 };
 
+struct SetupTouchInfo
+{
+  char *control_type;
+  int move_distance;
+  int drop_distance;
+};
+
 struct SetupInputInfo
 {
   boolean use_joystick;
@@ -999,6 +1016,7 @@ struct SetupInfo
   struct SetupEditorCascadeInfo editor_cascade;
   struct SetupShortcutInfo shortcut;
   struct SetupInputInfo input[MAX_PLAYERS];
+  struct SetupTouchInfo touch;
   struct SetupSystemInfo system;
   struct OptionInfo options;
 };
index 2a335bbade494560f7f7ef708ff67ecce5f5f042..29f84f2f5ee393b46b710c5caff3a39c39a69432 100644 (file)
 #define GFX_SPECIAL_ARG_SETUP_SOUND            4
 #define GFX_SPECIAL_ARG_SETUP_ARTWORK          5
 #define GFX_SPECIAL_ARG_SETUP_INPUT            6
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS                7
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1      8
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2      9
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3      10
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4      11
-#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_5      12
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK   13
-#define GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER     14
-
-#define NUM_SPECIAL_GFX_SETUP_ARGS             15
+#define GFX_SPECIAL_ARG_SETUP_TOUCH            7
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS                8
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_1      9
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_2      10
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_3      11
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_4      12
+#define GFX_SPECIAL_ARG_SETUP_SHORTCUTS_5      13
+#define GFX_SPECIAL_ARG_SETUP_CHOOSE_ARTWORK   14
+#define GFX_SPECIAL_ARG_SETUP_CHOOSE_OTHER     15
+
+#define NUM_SPECIAL_GFX_SETUP_ARGS             16
 
 
 /* values for image configuration suffixes */
index 47c66fb3ffed37b5c66506196117519bb54d7799..95b6706f5f0c8beb3257fcf833781def1a44b4af 100644 (file)
 #define SETUP_MODE_SOUND               4
 #define SETUP_MODE_ARTWORK             5
 #define SETUP_MODE_INPUT               6
-#define SETUP_MODE_SHORTCUTS           7
-#define SETUP_MODE_SHORTCUTS_1         8
-#define SETUP_MODE_SHORTCUTS_2         9
-#define SETUP_MODE_SHORTCUTS_3         10
-#define SETUP_MODE_SHORTCUTS_4         11
-#define SETUP_MODE_SHORTCUTS_5         12
+#define SETUP_MODE_TOUCH               7
+#define SETUP_MODE_SHORTCUTS           8
+#define SETUP_MODE_SHORTCUTS_1         9
+#define SETUP_MODE_SHORTCUTS_2         10
+#define SETUP_MODE_SHORTCUTS_3         11
+#define SETUP_MODE_SHORTCUTS_4         12
+#define SETUP_MODE_SHORTCUTS_5         13
 
 /* sub-screens on the setup screen (generic) */
-#define SETUP_MODE_CHOOSE_ARTWORK      13
-#define SETUP_MODE_CHOOSE_OTHER                14
+#define SETUP_MODE_CHOOSE_ARTWORK      14
+#define SETUP_MODE_CHOOSE_OTHER                15
 
 /* sub-screens on the setup screen (specific) */
-#define SETUP_MODE_CHOOSE_GAME_SPEED   15
-#define SETUP_MODE_CHOOSE_SCROLL_DELAY 16
-#define SETUP_MODE_CHOOSE_SCREEN_MODE  17
-#define SETUP_MODE_CHOOSE_WINDOW_SIZE  18
-#define SETUP_MODE_CHOOSE_SCALING_TYPE 19
-#define SETUP_MODE_CHOOSE_GRAPHICS     20
-#define SETUP_MODE_CHOOSE_SOUNDS       21
-#define SETUP_MODE_CHOOSE_MUSIC                22
-#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        23
-#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 24
-#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 25
-
-#define MAX_SETUP_MODES                        26
+#define SETUP_MODE_CHOOSE_GAME_SPEED   16
+#define SETUP_MODE_CHOOSE_SCROLL_DELAY 17
+#define SETUP_MODE_CHOOSE_SCREEN_MODE  18
+#define SETUP_MODE_CHOOSE_WINDOW_SIZE  19
+#define SETUP_MODE_CHOOSE_SCALING_TYPE 20
+#define SETUP_MODE_CHOOSE_GRAPHICS     21
+#define SETUP_MODE_CHOOSE_SOUNDS       22
+#define SETUP_MODE_CHOOSE_MUSIC                23
+#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        24
+#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 25
+#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 26
+#define SETUP_MODE_CHOOSE_TOUCH_CONTROL        27
+#define SETUP_MODE_CHOOSE_MOVE_DISTANCE        28
+#define SETUP_MODE_CHOOSE_DROP_DISTANCE        29
+
+#define MAX_SETUP_MODES                        30
 
 /* for input setup functions */
 #define SETUPINPUT_SCREEN_POS_START    0
@@ -171,6 +175,7 @@ static void CalibrateJoystick(int);
 static void execSetupGame(void);
 static void execSetupGraphics(void);
 static void execSetupSound(void);
+static void execSetupTouch(void);
 static void execSetupArtwork(void);
 static void HandleChooseTree(int, int, int, int, int, TreeInfo **);
 
@@ -225,6 +230,15 @@ static TreeInfo *volume_loops_current = NULL;
 static TreeInfo *volumes_music = NULL;
 static TreeInfo *volume_music_current = NULL;
 
+static TreeInfo *touch_controls = NULL;
+static TreeInfo *touch_control_current = NULL;
+
+static TreeInfo *move_distances = NULL;
+static TreeInfo *move_distance_current = NULL;
+
+static TreeInfo *drop_distances = NULL;
+static TreeInfo *drop_distance_current = NULL;
+
 static TreeInfo *level_number = NULL;
 static TreeInfo *level_number_current = NULL;
 
@@ -334,6 +348,37 @@ static struct
   {    -1,     NULL                            },
 };
 
+static struct
+{
+  char *value;
+  char *text;
+} touch_controls_list[] =
+{
+  {    TOUCH_CONTROL_VIRTUAL_BUTTONS,  "Virtual Buttons"       },
+  {    TOUCH_CONTROL_WIPE_GESTURES,    "Wipe Gestures"         },
+
+  {    NULL,                           NULL                    },
+};
+
+static struct
+{
+  int value;
+  char *text;
+} distances_list[] =
+{
+  {    1,      "1 %"                           },
+  {    2,      "2 %"                           },
+  {    3,      "3 %"                           },
+  {    4,      "4 %"                           },
+  {    5,      "5 %"                           },
+  {    10,     "10 %"                          },
+  {    15,     "15 %"                          },
+  {    20,     "20 %"                          },
+  {    25,     "25 %"                          },
+
+  {    -1,     NULL                            },
+};
+
 #define DRAW_MODE(s)           ((s) >= GAME_MODE_MAIN &&               \
                                 (s) <= GAME_MODE_SETUP ? (s) :         \
                                 (s) == GAME_MODE_PSEUDO_TYPENAME ?     \
@@ -3734,6 +3779,10 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
               setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
               setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
        execSetupSound();
+      else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL ||
+              setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE ||
+              setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+       execSetupTouch();
       else
        execSetupArtwork();
     }
@@ -3975,6 +4024,10 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
            execSetupSound();
+         else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL ||
+                  setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE ||
+                  setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+           execSetupTouch();
          else
            execSetupArtwork();
        }
@@ -4262,6 +4315,9 @@ static char *music_set_name;
 static char *volume_simple_text;
 static char *volume_loops_text;
 static char *volume_music_text;
+static char *touch_controls_text;
+static char *move_distance_text;
+static char *drop_distance_text;
 
 static void execSetupMain()
 {
@@ -4825,6 +4881,173 @@ static void execSetupSound()
   DrawSetupScreen();
 }
 
+static void execSetupChooseTouchControls()
+{
+  setup_mode = SETUP_MODE_CHOOSE_TOUCH_CONTROL;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseMoveDistance()
+{
+  setup_mode = SETUP_MODE_CHOOSE_MOVE_DISTANCE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupChooseDropDistance()
+{
+  setup_mode = SETUP_MODE_CHOOSE_DROP_DISTANCE;
+
+  DrawSetupScreen();
+}
+
+static void execSetupTouch()
+{
+#if 1
+  if (touch_controls == NULL)
+  {
+    int i;
+
+    for (i = 0; touch_controls_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = touch_controls_list[i].value;
+      char *text = touch_controls_list[i].text;
+
+      ti->node_top = &touch_controls;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Control Type");
+
+      pushTreeInfo(&touch_controls, ti);
+    }
+
+    /* sort touch control values to start with lowest touch control value */
+    sortTreeInfo(&touch_controls);
+
+    /* set current touch control value to configured touch control value */
+    touch_control_current =
+      getTreeInfoFromIdentifier(touch_controls, setup.touch.control_type);
+
+    /* if that fails, set current touch control to reliable default value */
+    if (touch_control_current == NULL)
+      touch_control_current =
+       getTreeInfoFromIdentifier(touch_controls, TOUCH_CONTROL_DEFAULT);
+
+    /* if that also fails, set current touch control to first available value */
+    if (touch_control_current == NULL)
+      touch_control_current = touch_controls;
+  }
+
+  if (move_distances == NULL)
+  {
+    int i;
+
+    for (i = 0; distances_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = distances_list[i].value;
+      char *text = distances_list[i].text;
+
+      ti->node_top = &move_distances;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Move Distance");
+
+      pushTreeInfo(&move_distances, ti);
+    }
+
+    /* sort distance values to start with lowest distance value */
+    sortTreeInfo(&move_distances);
+
+    /* set current distance value to configured distance value */
+    move_distance_current =
+      getTreeInfoFromIdentifier(move_distances,
+                               i_to_a(setup.touch.move_distance));
+
+    /* if that fails, set current distance to reliable default value */
+    if (move_distance_current == NULL)
+      move_distance_current =
+       getTreeInfoFromIdentifier(move_distances, i_to_a(1));
+
+    /* if that also fails, set current distance to first available value */
+    if (move_distance_current == NULL)
+      move_distance_current = move_distances;
+  }
+
+  if (drop_distances == NULL)
+  {
+    int i;
+
+    for (i = 0; distances_list[i].value != -1; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      int value = distances_list[i].value;
+      char *text = distances_list[i].text;
+
+      ti->node_top = &drop_distances;
+      ti->sort_priority = value;
+
+      sprintf(identifier, "%d", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, "Drop Distance");
+
+      pushTreeInfo(&drop_distances, ti);
+    }
+
+    /* sort distance values to start with lowest distance value */
+    sortTreeInfo(&drop_distances);
+
+    /* set current distance value to configured distance value */
+    drop_distance_current =
+      getTreeInfoFromIdentifier(drop_distances,
+                               i_to_a(setup.touch.drop_distance));
+
+    /* if that fails, set current distance to reliable default value */
+    if (drop_distance_current == NULL)
+      drop_distance_current =
+       getTreeInfoFromIdentifier(drop_distances, i_to_a(1));
+
+    /* if that also fails, set current distance to first available value */
+    if (drop_distance_current == NULL)
+      drop_distance_current = drop_distances;
+  }
+
+  setup.touch.control_type = touch_control_current->identifier;
+  setup.touch.move_distance = atoi(move_distance_current->identifier);
+  setup.touch.drop_distance = atoi(drop_distance_current->identifier);
+
+  /* needed for displaying volume text instead of identifier */
+  touch_controls_text = touch_control_current->name;
+  move_distance_text = move_distance_current->name;
+  drop_distance_text = drop_distance_current->name;
+#endif
+
+  setup_mode = SETUP_MODE_TOUCH;
+
+  DrawSetupScreen();
+}
+
 static void execSetupArtwork()
 {
 #if 0
@@ -4941,7 +5164,12 @@ static struct TokenInfo setup_info_main[] =
   { TYPE_ENTER_MENU,   execSetupGraphics,      "Graphics"              },
   { TYPE_ENTER_MENU,   execSetupSound,         "Sound & Music"         },
   { TYPE_ENTER_MENU,   execSetupArtwork,       "Custom Artwork"        },
+#if !defined(PLATFORM_ANDROID)
   { TYPE_ENTER_MENU,   execSetupInput,         "Input Devices"         },
+  { TYPE_ENTER_MENU,   execSetupTouch,         "Touch Controls"        },
+#else
+  { TYPE_ENTER_MENU,   execSetupTouch,         "Touch Controls"        },
+#endif
   { TYPE_ENTER_MENU,   execSetupShortcuts,     "Key Shortcuts"         },
   { TYPE_EMPTY,                NULL,                   ""                      },
   { TYPE_LEAVE_MENU,   execExitSetup,          "Exit"                  },
@@ -5113,6 +5341,21 @@ static struct TokenInfo setup_info_input[] =
   { 0,                 NULL,                   NULL                    }
 };
 
+static struct TokenInfo setup_info_touch[] =
+{
+  { TYPE_ENTER_LIST,   execSetupChooseTouchControls, "Touch Control Type:" },
+  { TYPE_STRING,       &touch_controls_text,   ""                      },
+  { TYPE_EMPTY,                NULL,                   ""                      },
+  { TYPE_ENTER_LIST,   execSetupChooseMoveDistance, "Move Trigger Distance:" },
+  { TYPE_STRING,       &move_distance_text,    ""                      },
+  { TYPE_ENTER_LIST,   execSetupChooseDropDistance, "Drop Trigger Distance:" },
+  { TYPE_STRING,       &drop_distance_text,    ""                      },
+  { TYPE_EMPTY,                NULL,                   ""                      },
+  { TYPE_LEAVE_MENU,   execSetupMain,          "Back"                  },
+
+  { 0,                 NULL,                   NULL                    }
+};
+
 static struct TokenInfo setup_info_shortcuts[] =
 {
   { TYPE_ENTER_MENU,   execSetupShortcuts1,    "Various Keys"          },
@@ -5738,6 +5981,11 @@ static void DrawSetupScreen_Generic()
     setup_info = setup_info_artwork;
     title_string = "Custom Artwork";
   }
+  else if (setup_mode == SETUP_MODE_TOUCH)
+  {
+    setup_info = setup_info_touch;
+    title_string = "Setup Touch Ctrls";
+  }
   else if (setup_mode == SETUP_MODE_SHORTCUTS)
   {
     setup_info = setup_info_shortcuts;
@@ -6901,6 +7149,12 @@ void DrawSetupScreen()
     DrawChooseTree(&volume_loops_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
     DrawChooseTree(&volume_music_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL)
+    DrawChooseTree(&touch_control_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE)
+    DrawChooseTree(&move_distance_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+    DrawChooseTree(&drop_distance_current);
   else
     DrawSetupScreen_Generic();
 
@@ -6951,6 +7205,12 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     HandleChooseTree(mx, my, dx, dy, button, &volume_loops_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC)
     HandleChooseTree(mx, my, dx, dy, button, &volume_music_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL)
+    HandleChooseTree(mx, my, dx, dy, button, &touch_control_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE)
+    HandleChooseTree(mx, my, dx, dy, button, &move_distance_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE)
+    HandleChooseTree(mx, my, dx, dy, button, &drop_distance_current);
   else
     HandleSetupScreen_Generic(mx, my, dx, dy, button);