shithub: choc

Download patch

ref: 0a29eddd798e0722b74d0653fcd293b977cb5704
parent: b4082e71fc70f9295952b8c8c5cd77b85d602671
author: Simon Howard <fraggle@gmail.com>
date: Thu Aug 31 14:13:40 EDT 2006

Add key and mouse input widgets for selecting keys and mouse buttons.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 583

--- a/setup/keyboard.c
+++ b/setup/keyboard.c
@@ -1,7 +1,52 @@
 #include "textscreen.h"
 
-int dummy;
+#include "txt_keyinput.h"
 
+int key_left = KEY_LEFTARROW;
+int key_right = KEY_RIGHTARROW;
+int key_up = KEY_UPARROW;
+int key_down = KEY_DOWNARROW;
+int key_strafeleft = ',';
+int key_straferight = '.';
+int key_fire = KEY_RCTRL;
+int key_use = ' ';
+int key_strafe = KEY_RALT;
+int key_speed = KEY_RSHIFT;
+
+static int *allkeys[] = {&key_left, &key_right, &key_up, &key_down, 
+                         &key_strafeleft, &key_straferight, &key_fire, 
+                         &key_use, &key_strafe, &key_speed};
+
+// Callback invoked when a key control is set
+
+static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable))
+{
+    TXT_CAST_ARG(int, variable);
+    int i;
+
+    for (i=0; i<sizeof(allkeys) / sizeof(*allkeys); ++i)
+    {
+        if (*variable == *allkeys[i] && allkeys[i] != variable)
+        {
+            // A different key has the same value.  Clear the existing
+            // value. This ensures that no two keys can have the same
+            // value.
+
+            *allkeys[i] = 0;
+        }
+    }
+}
+
+static void AddKeyControl(txt_table_t *table, char *name, int *var)
+{
+    txt_key_input_t *key_input;
+
+    TXT_AddWidget(table, TXT_NewLabel(name));
+    key_input = TXT_NewKeyInput(var);
+    TXT_AddWidget(table, key_input);
+    TXT_SignalConnect(key_input, "set", KeySetCallback, var);
+}
+
 void ConfigKeyboard(void)
 {
     txt_window_t *window;
@@ -12,25 +57,16 @@
     TXT_AddWidget(window, TXT_NewSeparator("Movement"));
 
     table = TXT_NewTable(2);
-    TXT_AddWidget(table, TXT_NewStrut(20, 0));
-    TXT_AddWidget(table, TXT_NewStrut(8, 0));
+    TXT_SetColumnWidths(table, 20, 8);
 
-    TXT_AddWidget(table, TXT_NewLabel("Move Forward"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Move Backward"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Turn Left"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Turn Right"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Strafe Left"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Strafe Right"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Speed On"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Strafe On"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
+    AddKeyControl(table, "Move Forward", &key_up);
+    AddKeyControl(table, "Move Backward", &key_down);
+    AddKeyControl(table, "Turn Left", &key_left);
+    AddKeyControl(table, "Turn Right", &key_right);
+    AddKeyControl(table, "Strafe Left", &key_strafeleft);
+    AddKeyControl(table, "Strafe Right", &key_straferight);
+    AddKeyControl(table, "Speed On", &key_speed);
+    AddKeyControl(table, "Strafe On", &key_strafe);
 
     TXT_AddWidget(window, table);
 
@@ -37,13 +73,10 @@
     TXT_AddWidget(window, TXT_NewSeparator("Action"));
 
     table = TXT_NewTable(2);
-    TXT_AddWidget(table, TXT_NewStrut(20, 0));
-    TXT_AddWidget(table, TXT_NewStrut(8, 0));
+    TXT_SetColumnWidths(table, 20, 8);
 
-    TXT_AddWidget(table, TXT_NewLabel("Use"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
-    TXT_AddWidget(table, TXT_NewLabel("Fire"));
-    TXT_AddWidget(table, TXT_NewIntInputBox(&dummy, 7));
+    AddKeyControl(table, "Use", &key_use);
+    AddKeyControl(table, "Fire", &key_fire);
 
     TXT_AddWidget(window, table);
 }
--- a/setup/mouse.c
+++ b/setup/mouse.c
@@ -2,11 +2,50 @@
 #include <stdlib.h>
 #include "textscreen.h"
 
+#include "txt_mouseinput.h"
+
 int novert;
 int speed;
 int accel;
 int threshold;
 
+int mouseb_fire;
+int mouseb_strafe;
+int mouseb_forward;
+
+static int *all_mouse_buttons[] = {&mouseb_fire, &mouseb_strafe, 
+                                   &mouseb_forward};
+
+static void MouseSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable))
+{
+    TXT_CAST_ARG(int, variable);
+    int i;
+
+    // Check if the same mouse button is used for a different action
+    // If so, set the other action(s) to -1 (unset)
+
+    for (i=0; i<sizeof(all_mouse_buttons) / sizeof(*all_mouse_buttons); ++i)
+    {
+        if (*all_mouse_buttons[i] == *variable
+         && all_mouse_buttons[i] != variable)
+        {
+            *all_mouse_buttons[i] = -1;
+        }
+    }
+}
+
+static void AddMouseControl(txt_table_t *table, char *label, int *var)
+{
+    txt_mouse_input_t *mouse_input;
+
+    TXT_AddWidget(table, TXT_NewLabel(label));
+
+    mouse_input = TXT_NewMouseInput(var);
+    TXT_AddWidget(table, mouse_input);
+
+    TXT_SignalConnect(mouse_input, "set", MouseSetCallback, var);
+}
+
 void ConfigMouse(void)
 {
     txt_window_t *window;
@@ -18,19 +57,32 @@
 
     table = TXT_NewTable(2);
 
-    TXT_AddWidget(table, TXT_NewLabel("Speed: "));
+    TXT_SetColumnWidths(table, 25, 10);
+    TXT_AddWidget(table, TXT_NewLabel("Speed"));
     TXT_AddWidget(table, TXT_NewIntInputBox(&speed, 8));
-    TXT_AddWidget(table, TXT_NewLabel("Acceleration: "));
+    TXT_AddWidget(table, TXT_NewLabel("Acceleration"));
     TXT_AddWidget(table, TXT_NewIntInputBox(&accel, 8));
-    TXT_AddWidget(table, TXT_NewLabel("Acceleration threshold: "));
+    TXT_AddWidget(table, TXT_NewLabel("Acceleration threshold"));
     TXT_AddWidget(table, TXT_NewIntInputBox(&threshold, 8));
+
+    TXT_AddWidget(window, table);
     
+    TXT_AddWidget(window, TXT_NewSeparator("Mouse buttons"));
+
+    table = TXT_NewTable(2);
+
+    TXT_SetColumnWidths(table, 25, 10);
+    AddMouseControl(table, "Fire weapon", &mouseb_fire);
+    AddMouseControl(table, "Move forward", &mouseb_forward);
+    AddMouseControl(table, "Strafe on", &mouseb_strafe);
+    
     TXT_AddWidget(window, table);
     
     TXT_AddWidget(window, TXT_NewSeparator(NULL));
 
     TXT_AddWidget(window, 
-                  TXT_NewInvertedCheckBox("Allow vertical mouse movement", &novert));
+                  TXT_NewInvertedCheckBox("Allow vertical mouse movement", 
+                                          &novert));
 
 }
 
--- /dev/null
+++ b/setup/txt_keyinput.c
@@ -1,0 +1,151 @@
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomkeys.h"
+
+#include "txt_keyinput.h"
+#include "txt_io.h"
+#include "txt_label.h"
+#include "txt_window.h"
+
+#define KEY_INPUT_WIDTH 10
+
+static int KeyPressCallback(txt_window_t *window, int key, 
+                            TXT_UNCAST_ARG(key_input))
+{
+    TXT_CAST_ARG(txt_key_input_t, key_input);
+
+    if (key != KEY_ESCAPE)
+    {
+        // Got the key press.  Save to the variable and close the window.
+
+        *key_input->variable = key;
+        TXT_EmitSignal(key_input, "set");
+        TXT_CloseWindow(window);
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static void OpenPromptWindow(txt_key_input_t *key_input)
+{
+    txt_window_t *window;
+    txt_label_t *label;
+
+    window = TXT_NewWindow(NULL);
+    TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
+    TXT_SetWindowAction(window, TXT_HORIZ_CENTER, 
+                        TXT_NewWindowAbortAction(window));
+    TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
+    
+    label = TXT_NewLabel("Press the new key...");
+
+    TXT_AddWidget(window, label);
+    TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER);
+
+    TXT_SetKeyListener(window, KeyPressCallback, key_input);
+}
+
+static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input))
+{
+    TXT_CAST_ARG(txt_key_input_t, key_input);
+
+    // All keyinputs are the same size.
+
+    key_input->widget.w = KEY_INPUT_WIDTH;
+    key_input->widget.h = 1;
+}
+
+
+static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input), int selected)
+{
+    TXT_CAST_ARG(txt_key_input_t, key_input);
+    char buf[20];
+    int i;
+
+    if (*key_input->variable == 0)
+    {
+        strcpy(buf, "");
+    }
+    else
+    {
+        TXT_GetKeyDescription(*key_input->variable, buf);
+    }
+
+    if (selected)
+    {
+        TXT_BGColor(TXT_COLOR_GREY, 0);
+    }
+    else
+    {
+        TXT_BGColor(TXT_COLOR_BLUE, 0);
+    }
+
+    TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+    
+    TXT_DrawString(buf);
+    
+    for (i=strlen(buf); i<KEY_INPUT_WIDTH; ++i)
+    {
+        TXT_DrawString(" ");
+    }
+}
+
+static void TXT_KeyInputDestructor(TXT_UNCAST_ARG(key_input))
+{
+    TXT_CAST_ARG(txt_key_input_t, key_input);
+}
+
+static int TXT_KeyInputKeyPress(TXT_UNCAST_ARG(key_input), int key)
+{
+    TXT_CAST_ARG(txt_key_input_t, key_input);
+
+    if (key == KEY_ENTER)
+    {
+        // Open a window to prompt for the new key press
+
+        OpenPromptWindow(key_input);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+static void TXT_KeyInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
+{
+    TXT_CAST_ARG(txt_key_input_t, widget);
+            
+    // Clicking is like pressing enter
+
+    if (b == TXT_MOUSE_LEFT)
+    {
+        TXT_KeyInputKeyPress(widget, KEY_ENTER);
+    }
+}
+
+txt_widget_class_t txt_key_input_class =
+{
+    TXT_KeyInputSizeCalc,
+    TXT_KeyInputDrawer,
+    TXT_KeyInputKeyPress,
+    TXT_KeyInputDestructor,
+    TXT_KeyInputMousePress,
+};
+
+txt_key_input_t *TXT_NewKeyInput(int *variable)
+{
+    txt_key_input_t *key_input;
+
+    key_input = malloc(sizeof(txt_key_input_t));
+
+    TXT_InitWidget(key_input, &txt_key_input_class);
+    key_input->variable = variable;
+
+    return key_input;
+}
+
--- /dev/null
+++ b/setup/txt_keyinput.h
@@ -1,0 +1,47 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// $Id$
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2006 Simon Howard
+//
+// 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., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+
+#ifndef TXT_KEY_INPUT_H
+#define TXT_KEY_INPUT_H
+
+typedef struct txt_key_input_s txt_key_input_t;
+
+#include "txt_widget.h"
+
+//
+// A key input is like an input box.  When selected, a box pops up
+// allowing a key to be selected.
+//
+
+struct txt_key_input_s
+{
+    txt_widget_t widget;
+    int *variable;
+};
+
+txt_key_input_t *TXT_NewKeyInput(int *variable);
+
+#endif /* #ifndef TXT_KEY_INPUT_H */
+
+
--- /dev/null
+++ b/setup/txt_mouseinput.c
@@ -1,0 +1,180 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomkeys.h"
+
+#include "txt_mouseinput.h"
+#include "txt_io.h"
+#include "txt_label.h"
+#include "txt_window.h"
+
+#define MOUSE_INPUT_WIDTH 10
+
+static int MouseButtonToSetting(int b)
+{
+    switch (b)
+    {
+        case TXT_MOUSE_LEFT:
+            return 0;
+        case TXT_MOUSE_RIGHT:
+            return 1;
+        case TXT_MOUSE_MIDDLE:
+            return 2;
+        default:
+            return -1;
+    }
+}
+
+static int MousePressCallback(txt_window_t *window, 
+                              int x, int y, int b,
+                              TXT_UNCAST_ARG(mouse_input))
+{
+    TXT_CAST_ARG(txt_mouse_input_t, mouse_input);
+
+    // Got the mouse press.  Save to the variable and close the window.
+
+    *mouse_input->variable = MouseButtonToSetting(b);
+    TXT_EmitSignal(mouse_input, "set");
+    TXT_CloseWindow(window);
+
+    return 1;
+}
+
+static void OpenPromptWindow(txt_mouse_input_t *mouse_input)
+{
+    txt_window_t *window;
+    txt_label_t *label;
+
+    window = TXT_NewWindow(NULL);
+    TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
+    TXT_SetWindowAction(window, TXT_HORIZ_CENTER, 
+                        TXT_NewWindowAbortAction(window));
+    TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
+    
+    label = TXT_NewLabel("Press the new mouse button...");
+
+    TXT_AddWidget(window, label);
+    TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER);
+
+    TXT_SetMouseListener(window, MousePressCallback, mouse_input);
+}
+
+static void TXT_MouseInputSizeCalc(TXT_UNCAST_ARG(mouse_input))
+{
+    TXT_CAST_ARG(txt_mouse_input_t, mouse_input);
+
+    // All mouseinputs are the same size.
+
+    mouse_input->widget.w = MOUSE_INPUT_WIDTH;
+    mouse_input->widget.h = 1;
+}
+
+static void GetMouseButtonDescription(int button, char *buf)
+{
+    switch (button)
+    {
+        case 0:
+            strcpy(buf, "LEFT");
+            break;
+        case 1:
+            strcpy(buf, "RIGHT");
+            break;
+        case 2:
+            strcpy(buf, "MID");
+            break;
+        default:
+            sprintf(buf, "BUTTON #%i", button);
+            break;
+    }
+}
+
+static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input), int selected)
+{
+    TXT_CAST_ARG(txt_mouse_input_t, mouse_input);
+    char buf[20];
+    int i;
+
+    if (*mouse_input->variable == -1)
+    {
+        strcpy(buf, "");
+    }
+    else
+    {
+        GetMouseButtonDescription(*mouse_input->variable, buf);
+    }
+
+    if (selected)
+    {
+        TXT_BGColor(TXT_COLOR_GREY, 0);
+    }
+    else
+    {
+        TXT_BGColor(TXT_COLOR_BLUE, 0);
+    }
+
+    TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+    
+    TXT_DrawString(buf);
+    
+    for (i=strlen(buf); i<MOUSE_INPUT_WIDTH; ++i)
+    {
+        TXT_DrawString(" ");
+    }
+}
+
+static void TXT_MouseInputDestructor(TXT_UNCAST_ARG(mouse_input))
+{
+    TXT_CAST_ARG(txt_mouse_input_t, mouse_input);
+}
+
+static int TXT_MouseInputKeyPress(TXT_UNCAST_ARG(mouse_input), int mouse)
+{
+    TXT_CAST_ARG(txt_mouse_input_t, mouse_input);
+
+    if (mouse == KEY_ENTER)
+    {
+        // Open a window to prompt for the new mouse press
+
+        OpenPromptWindow(mouse_input);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+static void TXT_MouseInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
+{
+    TXT_CAST_ARG(txt_mouse_input_t, widget);
+            
+    // Clicking is like pressing enter
+
+    if (b == TXT_MOUSE_LEFT)
+    {
+        TXT_MouseInputKeyPress(widget, KEY_ENTER);
+    }
+}
+
+txt_widget_class_t txt_mouse_input_class =
+{
+    TXT_MouseInputSizeCalc,
+    TXT_MouseInputDrawer,
+    TXT_MouseInputKeyPress,
+    TXT_MouseInputDestructor,
+    TXT_MouseInputMousePress,
+};
+
+txt_mouse_input_t *TXT_NewMouseInput(int *variable)
+{
+    txt_mouse_input_t *mouse_input;
+
+    mouse_input = malloc(sizeof(txt_mouse_input_t));
+
+    TXT_InitWidget(mouse_input, &txt_mouse_input_class);
+    mouse_input->variable = variable;
+
+    return mouse_input;
+}
+
--- /dev/null
+++ b/setup/txt_mouseinput.h
@@ -1,0 +1,47 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// $Id$
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2006 Simon Howard
+//
+// 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., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+
+#ifndef TXT_MOUSE_INPUT_H
+#define TXT_MOUSE_INPUT_H
+
+typedef struct txt_mouse_input_s txt_mouse_input_t;
+
+#include "txt_widget.h"
+
+//
+// A mouse input is like an input box.  When selected, a box pops up
+// allowing a mouse to be selected.
+//
+
+struct txt_mouse_input_s
+{
+    txt_widget_t widget;
+    int *variable;
+};
+
+txt_mouse_input_t *TXT_NewMouseInput(int *variable);
+
+#endif /* #ifndef TXT_MOUSE_INPUT_H */
+
+