102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
gui_tab_gamepad.c
Go to the documentation of this file.
1#include "gui_internal.h"
2
3static const char *const GAMEPAD_AXIS_TOOLTIPS[] = {
4 "Disables this gamepad axis mapping.",
5 "Left stick horizontal axis.",
6 "Left stick vertical axis.",
7 "Right stick horizontal axis.",
8 "Right stick vertical axis.",
9 "Left trigger axis.",
10 "Right trigger axis.",
11};
12
13static const char *TOOLTIP_GAMEPAD_ENABLED = "Enable controller input. Default: true.";
14static const char *TOOLTIP_GAMEPAD_INDEX = "Controller index, starting at 0. Default: 0.";
15static const char *TOOLTIP_GAMEPAD_AXIS = "SDL axis for this DttR control. Default: "
16 "movement uses the left stick; camera RZ "
17 "uses the right stick X axis.";
18static const char *TOOLTIP_GAMEPAD_DEADZONE = "Per-axis deadzone in scaled axis units. "
19 "Default: 700.";
20static const char *TOOLTIP_GAMEPAD_BUTTONS = "Map controller inputs to game actions. "
21 "Bind waits for a button; Clear leaves the "
22 "action unused.";
23static const char *TOOLTIP_GAMEPAD_SOUTH = "Default menu confirm action.";
24static const char *TOOLTIP_GAMEPAD_EAST = "Default menu back action.";
25static const char *TOOLTIP_GAMEPAD_START = "Default start/pause action.";
26static const char *TOOLTIP_BIND_BUTTON = "Click, then press a gamepad button or "
27 "trigger to remap this SDL source row.";
28static const char *TOOLTIP_CLEAR_BUTTON = "Set this SDL input mapping to none.";
29static const char *TOOLTIP_RESET_BUTTON = "Reset this game action to its default "
30 "controller input.";
31static const char *const GAMEPAD_SOURCE_UNKNOWN = "Unknown";
32
33typedef struct {
34 const char *label;
35 const char *id;
38
40 {"Stick X Axis", "##axis_stick_x", DTTR_GAMEPAD_AXIS_IDX_STICK_X},
41 {"Stick Y Axis", "##axis_stick_y", DTTR_GAMEPAD_AXIS_IDX_STICK_Y},
42 {"Camera RZ Axis", "##axis_camera_rz", DTTR_GAMEPAD_AXIS_IDX_CAMERA_RZ},
43};
44
46 {"Stick X Deadzone", "##deadzone_stick_x", DTTR_GAMEPAD_AXIS_IDX_STICK_X},
47 {"Stick Y Deadzone", "##deadzone_stick_y", DTTR_GAMEPAD_AXIS_IDX_STICK_Y},
48 {"Camera RZ Deadzone", "##deadzone_camera_rz", DTTR_GAMEPAD_AXIS_IDX_CAMERA_RZ},
49};
50
53 const int *saved_values,
54 const int *default_values,
55 int axis_index
56) {
58 state->config.gamepad_axes[axis_index] != saved_values[axis_index],
59 state->config.gamepad_axes[axis_index] != default_values[axis_index]
60 );
61}
62
65 const int *saved_values,
66 const int *default_values,
67 int axis_index
68) {
70 state->config.gamepad_axis_deadzone[axis_index] != saved_values[axis_index],
71 state->config.gamepad_axis_deadzone[axis_index] != default_values[axis_index]
72 );
73}
74
78 const char *label,
79 const char *id,
80 int axis_index
81) {
83 ctx,
84 label,
85 id,
86 &state->config.gamepad_axes[axis_index],
91 state,
92 state->saved_config.gamepad_axes,
93 state->defaults.gamepad_axes,
94 axis_index
95 )
96 );
97}
98
102 const char *label,
103 const char *id,
104 int axis_index
105) {
107 ctx,
108 label,
109 id,
110 &state->config.gamepad_axis_deadzone[axis_index],
111 10,
112 100,
115 state,
116 state->saved_config.gamepad_axis_deadzone,
117 state->defaults.gamepad_axis_deadzone,
118 axis_index
119 )
120 );
121}
122
123const char *source_label(int source) {
124 switch (source) {
126 return "none";
128 return "left_trigger";
130 return "right_trigger";
131 default:
132 break;
133 }
134
135 if (source < 0 || source >= SDL_GAMEPAD_BUTTON_COUNT) {
137 }
138
139 const char *label = SDL_GetGamepadStringForButton((SDL_GamepadButton)source);
140 return label ? label : GAMEPAD_SOURCE_UNKNOWN;
141}
142
143const char *source_tooltip(int source) {
144 switch (source) {
146 return "No controller input is bound to this game action.";
147 case SDL_GAMEPAD_BUTTON_SOUTH:
149 case SDL_GAMEPAD_BUTTON_EAST:
151 case SDL_GAMEPAD_BUTTON_START:
153 default:
155 }
156}
157
159 switch (event->type) {
160 case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
161 return event->gbutton.button;
162 case SDL_EVENT_GAMEPAD_AXIS_MOTION:
163 if (event->gaxis.value < DTTR_GAMEPAD_TRIGGER_THRESHOLD) {
164 return -1;
165 }
166
167 switch (event->gaxis.axis) {
168 case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
170 case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
172 default:
173 return -1;
174 }
175
176 default:
177 return -1;
178 }
179}
180
183 ctx,
184 "##gamepad_axes_table",
187 )) {
188 return;
189 }
190
192 ctx,
193 "Enable Gamepad",
194 "##gamepad_enabled",
195 &state->config.gamepad_enabled,
197 FIELD_LABEL_STATE(state, gamepad_enabled)
198 );
200 ctx,
201 "Gamepad Index",
202 "##gamepad_index",
203 &state->config.gamepad_index,
204 1,
205 1,
207 FIELD_LABEL_STATE(state, gamepad_index)
208 );
209
210 for (int i = 0; i < (int)SDL_arraysize(GAMEPAD_AXIS_FIELDS); i++) {
212 ctx,
213 state,
214 GAMEPAD_AXIS_FIELDS[i].label,
216 GAMEPAD_AXIS_FIELDS[i].axis_index
217 );
218 }
219
220 for (int i = 0; i < (int)SDL_arraysize(GAMEPAD_DEADZONE_FIELDS); i++) {
222 ctx,
223 state,
226 GAMEPAD_DEADZONE_FIELDS[i].axis_index
227 );
228 }
229
231}
232
236 int row
237) {
238 igPushID_Int(row);
239
240 const int action = state->button_actions[row];
241 const int source = state->button_sources[row];
242
244 igTableNextColumn();
245 igAlignTextToFramePadding();
248 game_action_tooltip(action),
250 );
251
252 igTableNextColumn();
253 igAlignTextToFramePadding();
254 igText("%s", source_label(source));
256
257 igTableNextColumn();
258
259 if (themed_row_button(ctx, "##bind", "Bind", DTTR_CONFIG_UI_GAMEPAD_BUTTON_W)) {
260 state->binding_row = row;
261 set_status(state, "Press a gamepad button or trigger. Press Esc to cancel.");
262 }
263
265
266 igTableNextColumn();
267
268 if (themed_row_button(ctx, "##clear", "Clear", DTTR_CONFIG_UI_GAMEPAD_BUTTON_W)) {
269 state->button_sources[row] = DTTR_GAMEPAD_MAPPING_NONE;
270 }
271
273
274 igTableNextColumn();
275
276 if (themed_row_button(ctx, "##reset", "Reset", DTTR_CONFIG_UI_GAMEPAD_BUTTON_W)) {
277 state->button_sources[row] = gamepad_default_source_for_action(state, action);
278 }
279
281
282 igPopID();
283}
284
288) {
290 igSeparatorText("Button Mappings");
292
293 if (state->binding_row >= 0) {
294 igText(
295 "Waiting for input for %s...",
296 gamepad_button_row_label(state->binding_row)
297 );
298 }
299
301 return;
302 }
303
304 for (int i = 0; i < gamepad_button_row_count(); i++) {
306 }
307
309}
310
312 if (!igBeginChild_Str(
313 "##gamepad_scroll",
314 (ImVec2_c){0.0f, 0.0f},
315 ImGuiChildFlags_None,
316 ImGuiWindowFlags_None
317 )) {
318 igEndChild();
319 return;
320 }
321
324 igEndChild();
325}
const DTTR_BackendState * state
void void * ctx
void void DWORD HANDLE event
#define DTTR_GAMEPAD_SOURCE_TRIGGER_RIGHT
Definition dttr_config.h:52
#define DTTR_GAMEPAD_AXIS_IDX_STICK_Y
Definition dttr_config.h:61
#define DTTR_GAMEPAD_AXIS_IDX_CAMERA_RZ
Definition dttr_config.h:62
#define DTTR_GAMEPAD_TRIGGER_THRESHOLD
Definition dttr_config.h:49
#define DTTR_GAMEPAD_MAPPING_NONE
Definition dttr_config.h:48
#define DTTR_GAMEPAD_SOURCE_TRIGGER_LEFT
Definition dttr_config.h:51
@ DTTR_CONFIG_CHOICES_GAMEPAD_AXIS
#define DTTR_GAMEPAD_AXIS_IDX_STICK_X
Definition dttr_config.h:60
union SDL_Event SDL_Event
Definition dttr_mods.h:19
static game_data_source source
Definition game_data.c:21
int gamepad_default_source_for_action(const config_ui_state *state, int action)
Definition gui_state.c:88
config_label_state
bool themed_row_button(const DTTR_ImGuiDialogContext *ctx, const char *id, const char *label, float width)
config_label_state make_config_label_state(bool unsaved_changed, bool default_changed)
Definition gui_state.c:246
bool begin_gamepad_button_table(const DTTR_ImGuiDialogContext *ctx)
const char * gamepad_button_row_label(int row)
Definition gui_state.c:83
bool labeled_input_int(const DTTR_ImGuiDialogContext *ctx, const char *label, const char *id, int *value, int step, int step_fast, const char *tooltip, config_label_state label_state)
bool labeled_checkbox(const DTTR_ImGuiDialogContext *ctx, const char *label, const char *id, bool *value, const char *tooltip, config_label_state label_state)
bool begin_settings_table(const DTTR_ImGuiDialogContext *ctx, const char *id, float label_width, float input_width)
void draw_config_label(const char *label, const char *tooltip, config_label_state label_state)
void show_tooltip(const char *text)
void add_scaled_vertical_spacing(const DTTR_ImGuiDialogContext *ctx, float height)
Definition gui_widgets.c:12
#define DTTR_CONFIG_UI_SECTION_SPACING
void begin_config_table_row()
void end_settings_table()
#define DTTR_CONFIG_UI_LABEL_W
#define DTTR_CONFIG_UI_GAMEPAD_BUTTON_W
#define FIELD_LABEL_STATE(state, field)
#define DTTR_CONFIG_UI_INPUT_W
int gamepad_button_row_count()
Definition gui_state.c:65
config_label_state gamepad_button_label_state(const config_ui_state *state, int source, int action)
Definition gui_state.c:269
bool labeled_choice_combo(const DTTR_ImGuiDialogContext *ctx, const char *label, const char *id, int *value, DTTR_ConfigChoiceList choices, const char *const *tooltips, const char *tooltip, config_label_state label_state)
void set_status(config_ui_state *state, const char *status)
Definition gui_state.c:96
const char * game_action_tooltip(int action)
Definition gui_state.c:26
const char * source_tooltip(int source)
static const char * TOOLTIP_GAMEPAD_SOUTH
static const char * TOOLTIP_GAMEPAD_INDEX
static const gamepad_axis_field GAMEPAD_DEADZONE_FIELDS[]
static const char * TOOLTIP_RESET_BUTTON
static config_label_state gamepad_axis_label_state(const config_ui_state *state, const int *saved_values, const int *default_values, int axis_index)
static const char *const GAMEPAD_SOURCE_UNKNOWN
const char * source_label(int source)
static const char * TOOLTIP_GAMEPAD_AXIS
static void draw_gamepad_deadzone_input(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state, const char *label, const char *id, int axis_index)
static const gamepad_axis_field GAMEPAD_AXIS_FIELDS[]
static void draw_gamepad_button_row(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state, int row)
static const char * TOOLTIP_CLEAR_BUTTON
static const char * TOOLTIP_BIND_BUTTON
static void draw_gamepad_axis_choice(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state, const char *label, const char *id, int axis_index)
static const char * TOOLTIP_GAMEPAD_ENABLED
static const char * TOOLTIP_GAMEPAD_EAST
static const char * TOOLTIP_GAMEPAD_DEADZONE
static const char * TOOLTIP_GAMEPAD_BUTTONS
static void draw_gamepad_axes(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state)
int source_from_event(const SDL_Event *event)
void draw_gamepad_tab(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state)
static config_label_state gamepad_deadzone_label_state(const config_ui_state *state, const int *saved_values, const int *default_values, int axis_index)
static const char *const GAMEPAD_AXIS_TOOLTIPS[]
static void draw_gamepad_buttons(const DTTR_ImGuiDialogContext *ctx, config_ui_state *state)
static const char * TOOLTIP_GAMEPAD_START