[olofsonprojects] kobodeluxe patch to allow menu control with touchscreen

  • From: Robert Schuster <theBohemian@xxxxxxx>
  • To: olofsonprojects@xxxxxxxxxxxxx
  • Date: Mon, 11 Feb 2008 03:52:47 +0100

Hi David,
thanks you liked my last patch. Here comes the first one which makes
kobo deluxe usuable on more platforms! (especially those without keys :) )

What it does:
One can optionally compile touchscreen support in. If done it will
enable code which calculates a pointer border from a given (hard-coded)
percentage and the actual display size. Clicks in this border are not
translated into BTN_FIRE but into BTN_LEFT, BTN_RIGHT etc. Additionally
the upper right corner translates to BTN_PAUSE and the lower right to
BTN_EXIT.

There are also some tiny changes which are not directly related to the
above:
 - mouse click is only translated to BTN_FIRE in menu mode when the
mouse movement option is set
 - in the MOUSEBUTTONDOWN and MOUSEBUTTONUP code ev.motion was used,
that should be ev.button instead

The next two are neccessary for the touchscreen code but affect the
other variant, too:
 - BTN_FIRE in the new_player state is handled regardless of whether
joystick control has been set

I thought it would not to bad if someone presses the button to confirm
the player name.

 - main() prints whether touchscreen support is compiled in and while at
   it I added 'gcc --version' style copyright notices.

It may make sense to move the setup_pointer_border() method (and the
variables it uses) into gfxengine and enable the setup code in all
compilation variants since it does not cause a big overhead. What should
not be enabled on non-touchscreen targets is the if-else stuff in the
MOUSEBUTTONDOWN handler.

However feel free to implement the feature in a different way (Please
send me your patch then to integrate it into OE).

I am also open to suggestions to make this patch better!

Furthermore it would be nice if the game could somehow show the pointer
borders. I haven't looked into the graphics routines but the following
might be a possibility which you (with more knowledge about the game)
can implement quickly I think: When switching between the menus some
kind of distortion effect you could be painted along the border lines.
The idea is that the learns how big it is by seeing it sometimes.

Regards
Robert
Index: KoboDeluxe-0.5.1/README
===================================================================
--- KoboDeluxe-0.5.1.orig/README        2008-02-11 01:10:23.000000000 +0100
+++ KoboDeluxe-0.5.1/README     2008-02-11 01:17:30.000000000 +0100
@@ -39,6 +39,12 @@
        key  diagonals.  Escape enters the meny system, from where it is possi-
        ble to change settings, start a new game or exit the game.
 
+       In case the touchscreen support has been compiled in, the menu  can  be
+       controlled by clicking the frame borders. Touching the  inner  part  of
+       the  screen is like a button  press. In the game  mode a  click in  the
+       upper right corner activates pause mode and the lower right  corner es-
+       capes to the menu.
+
 OPTIONS
        Note that all relevant options can be also  configured  in  the  config
        file,  which  can be edited directly, or using the options menus in the
Index: KoboDeluxe-0.5.1/config.h
===================================================================
--- KoboDeluxe-0.5.1.orig/config.h      2008-02-11 00:23:20.000000000 +0100
+++ KoboDeluxe-0.5.1/config.h   2008-02-11 02:01:17.000000000 +0100
@@ -95,6 +95,15 @@
 #define MARGIN 8
 
 /*
+ * Fraction of the screen size in which clicks are not considered
+ * clicks but movements in that direction (as regarded from the
+ * center of the screen) or other special things (pause & exit).
+ *
+ * Used only in touchscreen mode.
+ */
+#define POINTER_MARGIN_PERCENT 10
+
+/*
  * (In XKobo, WSIZE was used where this is
  * used now; in the game logic code.)
  *
Index: KoboDeluxe-0.5.1/configure.in
===================================================================
--- KoboDeluxe-0.5.1.orig/configure.in  2008-02-11 00:37:18.000000000 +0100
+++ KoboDeluxe-0.5.1/configure.in       2008-02-11 00:48:59.000000000 +0100
@@ -195,6 +195,16 @@
        CXXFLAGS="$CXXFLAGS -DHAVE_OPENGL"
 fi
 
+AC_ARG_ENABLE(
+  touchscreen,
+  [AS_HELP_STRING(
+    [--enable-touchscreen],
+    [Compile menu control support suitable for touchscreens (default is no)])],
+  AC_DEFINE(
+    [ENABLE_TOUCHSCREEN],
+    [1],
+    [Set to 1 if the menusystem should support touchscreen input]),
+    [])
 
 dnl-------------------------------------------------------
 dnl Checks for header files.
Index: KoboDeluxe-0.5.1/kobo.cpp
===================================================================
--- KoboDeluxe-0.5.1.orig/kobo.cpp      2008-02-11 00:24:57.000000000 +0100
+++ KoboDeluxe-0.5.1/kobo.cpp   2008-02-11 03:45:05.000000000 +0100
@@ -28,6 +28,8 @@
 // Use this to benchmark and create a new percentage table!
 #undef TIME_PROGRESS
 
+#include <aconfig.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -671,6 +673,10 @@
                gh = dh;
        }
 
+#if ENABLE_TOUCHSCREEN
+       gengine->setup_pointer_margin(dw, dh);
+#endif
+
        // Scaling has 16ths granularity, so tiles scale properly!
        gengine->scale((int)((gw * 16 + 8) / SCREEN_WIDTH) / 16.f,
                        (int)((gh * 16 + 8) / SCREEN_HEIGHT) / 16.f);
@@ -1599,6 +1605,23 @@
 {
 }
 
+#ifdef ENABLE_TOUCHSCREEN
+void kobo_gfxengine_t::setup_pointer_margin(int dw, int dh)
+{
+       // Precalculates the border ranges. Mouse clicks outside these are 
handled
+  // specially.
+       pointer_margin_width_min = dw * POINTER_MARGIN_PERCENT / 100;
+       pointer_margin_width_max = dw - dw * POINTER_MARGIN_PERCENT / 100;
+       pointer_margin_height_min = dh * POINTER_MARGIN_PERCENT / 100;
+       pointer_margin_height_max = dh - dh * POINTER_MARGIN_PERCENT / 100;
+
+       log_printf(VLOG, "Pointer margin range [%d, %d, %d, %d]\n",
+                                                pointer_margin_width_min,
+                                                pointer_margin_width_max,
+                                                pointer_margin_height_min,
+                                                pointer_margin_height_max);
+}
+#endif
 
 void kobo_gfxengine_t::frame()
 {
@@ -1800,11 +1823,57 @@
                                                mouse_y - MARGIN - WSIZE/2);
                        break;
                  case SDL_MOUSEBUTTONDOWN:
-                       mouse_x = (int)(ev.motion.x / gengine->xscale()) - 
km.xoffs;
-                       mouse_y = (int)(ev.motion.y / gengine->yscale()) - 
km.yoffs;
-                       gsm.press(BTN_FIRE);
+                       mouse_x = (int)(ev.button.x / gengine->xscale()) - 
km.xoffs;
+                       mouse_y = (int)(ev.button.y / gengine->yscale()) - 
km.yoffs;
                        if(prefs->use_mouse)
                        {
+#if ENABLE_TOUCHSCREEN
+                               if (ev.motion.x <= pointer_margin_width_min)
+                               {
+                                       gsm.press(BTN_LEFT);
+                                       pointer_margin_used = true;
+                               } else if (ev.motion.x >= 
pointer_margin_width_max)
+                               {
+                                       // Upper right corner invokes pause.
+          // Lower right corner invokes exit.
+          // Otherwise it is just 'right'. :)
+                                       if (ev.motion.y <= 
pointer_margin_height_min)
+                                       {
+                                               gsm.press(BTN_PAUSE);
+                                               gamecontrol.press(BTN_PAUSE);
+                                       }
+                                       else
+                                               gsm.press((ev.motion.y >= 
pointer_margin_height_max
+                       ? BTN_EXIT
+                       : BTN_RIGHT));
+
+                                       pointer_margin_used = true;
+
+                               }
+
+                               if (ev.motion.y <= pointer_margin_height_min)
+                               {
+                                       // Handle as 'up' only if it was not in 
the 'pause' area.
+                                       // Still handle as clicked, so 'fire' 
will not kick in.
+                                       if (ev.motion.x < 
pointer_margin_width_max)
+                                               gsm.press(BTN_UP);
+                                       pointer_margin_used = true;
+                               } else if (ev.motion.y >= 
pointer_margin_height_max)
+                               {
+                                       // Handle as 'down' only if it was not 
in the 'exit' area.
+                                       // Still handle as clicked, so 'fire' 
will not kick in.
+                                       if (ev.motion.x < 
pointer_margin_width_max)
+                                               gsm.press(BTN_DOWN);
+
+                                       pointer_margin_used = true;
+                               }
+
+                               if (!pointer_margin_used)
+                                       gsm.press(BTN_FIRE);
+#else
+                               gsm.press(BTN_FIRE);
+#endif
+
                                gamecontrol.mouse_position(
                                                mouse_x - 8 - MARGIN - WSIZE/2,
                                                mouse_y - MARGIN - WSIZE/2);
@@ -1824,10 +1893,24 @@
                        }
                        break;
                  case SDL_MOUSEBUTTONUP:
-                       mouse_x = (int)(ev.motion.x / gengine->xscale()) - 
km.xoffs;
-                       mouse_y = (int)(ev.motion.y / gengine->yscale()) - 
km.yoffs;
+                       mouse_x = (int)(ev.button.x / gengine->xscale()) - 
km.xoffs;
+                       mouse_y = (int)(ev.button.y / gengine->yscale()) - 
km.yoffs;
                        if(prefs->use_mouse)
                        {
+#if ENABLE_TOUCHSCREEN
+                               // Resets all kinds of buttons that might have 
been activated by
+                               // clicking in the pointer margin.
+                               if (pointer_margin_used)
+                               {
+                                       gsm.release(BTN_EXIT);
+                                       gsm.release(BTN_LEFT);
+                                       gsm.release(BTN_RIGHT);
+                                       gsm.release(BTN_UP);
+                                       gsm.release(BTN_DOWN);
+                                       pointer_margin_used = false;
+                               }
+#endif
+
                                gamecontrol.mouse_position(
                                                mouse_x - 8 - MARGIN - WSIZE/2,
                                                mouse_y - MARGIN - WSIZE/2);
@@ -2078,6 +2161,19 @@
 int main(int argc, char *argv[])
 {
        int cmd_exit = 0;
+
+       printf(PACKAGE " - " VERSION " (touchscreen support: %s)\n",
+                               (ENABLE_TOUCHSCREEN ? "yes" : "no"));
+       puts("Copyright (c) 1995, 1996 Akira Higuchi\n"
+       "Copyright (C) 1997 Masanao Izumo\n"
+       "Copyright (C) 1999-2001 Simon Peter\n"
+       "Copyright (C) 2002 Florian Schulze\n"
+       "Copyright (C) 2002 Jeremy Sheeley\n"
+       "Copyright (C) 2005 Erik Auerswald\n"
+       "Copyright (c) 1999-2007 David Olofson\n"
+       "This is free software; see the source for copying conditions. There is 
NO\n"
+       "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.\n");
+
        atexit(emergency_close);
        signal(SIGTERM, breakhandler);
        signal(SIGINT, breakhandler);
Index: KoboDeluxe-0.5.1/kobo.h
===================================================================
--- KoboDeluxe-0.5.1.orig/kobo.h        2008-02-11 00:31:23.000000000 +0100
+++ KoboDeluxe-0.5.1/kobo.h     2008-02-11 02:19:29.000000000 +0100
@@ -23,6 +23,8 @@
 #ifndef _KOBO_H_
 #define _KOBO_H_
 
+#include <aconfig.h>
+
 #include "gfxengine.h"
 #include "window.h"
 #include "display.h"
@@ -45,11 +47,25 @@
 
 class kobo_gfxengine_t : public gfxengine_t
 {
+#if ENABLE_TOUCHSCREEN
+       bool pointer_margin_used;
+
+       int pointer_margin_width_min;
+       int pointer_margin_width_max;
+       int pointer_margin_height_min;
+       int pointer_margin_height_max;
+#endif
+
        void frame();
        void pre_render();
        void post_render();
   public:
        kobo_gfxengine_t();
+
+#if ENABLE_TOUCHSCREEN
+       void setup_pointer_margin(int, int);
+#endif
+
 };
 
 extern kobo_gfxengine_t                *gengine;
Index: KoboDeluxe-0.5.1/states.cpp
===================================================================
--- KoboDeluxe-0.5.1.orig/states.cpp    2008-02-11 03:06:41.000000000 +0100
+++ KoboDeluxe-0.5.1/states.cpp 2008-02-11 03:06:49.000000000 +0100
@@ -963,8 +963,6 @@
                        break;
 
                  case BTN_FIRE:
-                       if(!prefs->use_joystick)
-                               break;
                  case BTN_START:
                  case BTN_SELECT:
                        sound.ui_ok();

Other related posts: