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 */
+
+