-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathnuklear_console_input.h
More file actions
249 lines (216 loc) · 8.66 KB
/
nuklear_console_input.h
File metadata and controls
249 lines (216 loc) · 8.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#ifndef NK_CONSOLE_INPUT_H__
#define NK_CONSOLE_INPUT_H__
/**
* Data specifically used for the input widget.
*
* @see nk_console_input()
*/
typedef struct nk_console_input_data {
struct nk_console_button_data button_data; /** Inherited from button */
int gamepad_number; /** The gamepad number of which to expect input from. Provied -1 for any gamepad. */
int* out_gamepad_number; /** A pointer for where to store the gamepad number the button is associated with. */
enum nk_gamepad_button* out_gamepad_button; /** A pointer to where to store the gamepad button. */
float timer; /** A countdown timer to prompt the user with. @see NK_CONSOLE_INPUT_TIMER */
} nk_console_input_data;
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Create a new input widget to get a gamepad button.
*
* @param parent The parent console of where to add the widget.
* @param label The label to display.
* @param gamepad_number The gamepad number to expect input from. Provide -1 for any gamepad.
* @param out_gamepad_number When the user enters a button, this is where the gamepad number that was used to press the button.
* @param out_gamepad_button When the user enters a button, this is where the gamepad button will be stored.
*
* @todo Input: Add Keyboard support?
*
* @return The new input widget.
*/
NK_API nk_console* nk_console_input(nk_console* parent, const char* label, int gamepad_number, int* out_gamepad_number, enum nk_gamepad_button* out_gamepad_button);
NK_API struct nk_rect nk_console_input_render(nk_console* widget);
#if defined(__cplusplus)
}
#endif
#endif // NK_CONSOLE_INPUT_H__
#if defined(NK_CONSOLE_IMPLEMENTATION) && !defined(NK_CONSOLE_HEADER_ONLY)
#ifndef NK_CONSOLE_INPUT_IMPLEMENTATION_ONCE
#define NK_CONSOLE_INPUT_IMPLEMENTATION_ONCE
#ifndef NK_CONSOLE_INPUT_TIMER
/**
* The amount of time to wait for input before timing out, in seconds.
*/
#define NK_CONSOLE_INPUT_TIMER 6.0f
#endif
#if defined(__cplusplus)
extern "C" {
#endif
NK_API struct nk_rect nk_console_input_render(nk_console* console) {
if (console == NULL || console->data == NULL) {
return nk_rect(0, 0, 0, 0);
}
nk_console_input_data* data = (nk_console_input_data*)console->data;
if (data->out_gamepad_button == NULL) {
return nk_rect(0, 0, 0, 0);
}
// Set up the layout
nk_console_layout_widget(console);
// Display the label
if (console->label != NULL && console->label[0] != '\0') {
if (!nk_console_is_active_widget(console)) {
nk_widget_disable_begin(console->ctx);
}
if (console->label_length > 0) {
nk_text(console->ctx, console->label, console->label_length, NK_TEXT_LEFT);
}
else {
nk_label(console->ctx, console->label, NK_TEXT_LEFT);
}
if (!nk_console_is_active_widget(console)) {
nk_widget_disable_end(console->ctx);
}
}
// Display the mocked button
switch (*data->out_gamepad_button) {
case NK_GAMEPAD_BUTTON_UP:
nk_console_button_set_symbol(console, NK_SYMBOL_TRIANGLE_UP);
break;
case NK_GAMEPAD_BUTTON_DOWN:
nk_console_button_set_symbol(console, NK_SYMBOL_TRIANGLE_DOWN);
break;
case NK_GAMEPAD_BUTTON_LEFT:
nk_console_button_set_symbol(console, NK_SYMBOL_TRIANGLE_LEFT);
break;
case NK_GAMEPAD_BUTTON_RIGHT:
nk_console_button_set_symbol(console, NK_SYMBOL_TRIANGLE_RIGHT);
break;
case NK_GAMEPAD_BUTTON_START:
nk_console_button_set_symbol(console, NK_SYMBOL_PLUS);
break;
case NK_GAMEPAD_BUTTON_BACK:
nk_console_button_set_symbol(console, NK_SYMBOL_MINUS);
break;
default:
nk_console_button_set_symbol(console, NK_SYMBOL_NONE);
break;
}
// Switch the values to have the widget display as a button.
int swap_columns = console->columns;
const char* swap_label = console->label;
int swap_label_length = console->label_length;
console->columns = 0;
console->label = (*data->out_gamepad_button < 0) ? "<None>" : nk_gamepad_button_name(nk_console_get_gamepads(console), *data->out_gamepad_button);
if (console->label == NULL) {
console->label = "Unknown";
}
console->label_length = 0;
struct nk_rect widget_bounds = nk_console_button_render(console);
console->columns = swap_columns;
console->label = swap_label;
console->label_length = swap_label_length;
return widget_bounds;
}
/**
* Go back as a post-render hook so that it handles the events safely afterwards.
*/
static void nk_console_input_back_post_render(nk_console* console, void* user_data) {
NK_UNUSED(user_data);
nk_console_button_back(console, NULL);
}
/**
* Render the "Press a Button" prompt.
*
* @param console The console to render the prompt for.
*
* @return An empty rectangle, because there isn't a widget to interact with.
*/
static struct nk_rect nk_console_input_active_render(nk_console* console) {
if (console == NULL) {
return nk_rect(0, 0, 0, 0);
}
// Get the parent input widget.
nk_console* input = console->parent;
nk_console_input_data* data = (nk_console_input_data*)input->data;
if (data == NULL) {
return nk_rect(0, 0, 0, 0);
}
nk_console* top = nk_console_get_top(console);
// Set up the layout
nk_console_layout_widget(console);
// Display the label for the input
if (input->label != NULL && input->label[0] != '\0') {
if (input->label_length > 0) {
nk_text(console->ctx, input->label, input->label_length, NK_TEXT_CENTERED);
}
else {
nk_label(console->ctx, input->label, NK_TEXT_CENTERED);
}
}
// Give a timer to the user.
data->timer += console->ctx->delta_time_seconds;
nk_bool finished = nk_false;
// Handle the timeout
if (data->timer >= NK_CONSOLE_INPUT_TIMER) {
finished = nk_true;
}
// Only display the timer if delta time is provided.
if (data->timer > 0.0f) {
// Display a progressbar, scaling the time to milliseconds.
nk_prog(console->ctx, (size_t)(data->timer * 1000), (size_t)(NK_CONSOLE_INPUT_TIMER * 1000), nk_false);
}
// Blinking press a button instructions
if (((int)(data->timer * 2)) % 2 == 0) {
nk_label(console->ctx, "Press a Button", NK_TEXT_CENTERED);
}
else {
nk_spacer(console->ctx);
}
// Check for input.
nk_console_top_data* top_data = (nk_console_top_data*)top->data;
if (top_data->input_processed == nk_false) {
// Gamepad button released.
if (nk_gamepad_any_button_released((struct nk_gamepads*)nk_console_get_gamepads(top), data->gamepad_number, data->out_gamepad_number, data->out_gamepad_button)) {
// Trigger the onchange event and exit.
nk_console_trigger_event(input, NK_CONSOLE_EVENT_CHANGED);
finished = nk_true;
}
// Any other input.
else if (nk_input_is_key_released(&console->ctx->input, NK_KEY_BACKSPACE) || nk_input_is_key_released(&console->ctx->input, NK_KEY_ENTER) || nk_input_is_mouse_released(&console->ctx->input, NK_BUTTON_LEFT) || nk_input_is_mouse_released(&console->ctx->input, NK_BUTTON_RIGHT)) {
finished = nk_true;
}
}
if (finished == nk_true) {
top_data->input_processed = nk_true;
data->timer = 0.0f;
nk_console_add_event(console, NK_CONSOLE_EVENT_POST_RENDER_ONCE, &nk_console_input_back_post_render);
}
return nk_rect(0, 0, 0, 0);
}
NK_API nk_console* nk_console_input(nk_console* parent, const char* label, int gamepad_number, int* out_gamepad_number, enum nk_gamepad_button* out_gamepad_button) {
if (parent == NULL) {
return NULL;
}
// Create the widget data.
nk_console_input_data* data = (nk_console_input_data*)NK_CONSOLE_MALLOC(nk_handle_id(0), NULL, sizeof(nk_console_input_data));
nk_zero(data, sizeof(nk_console_input_data));
data->gamepad_number = gamepad_number;
data->out_gamepad_number = out_gamepad_number;
data->out_gamepad_button = out_gamepad_button;
nk_console* widget = nk_console_label(parent, label);
widget->type = NK_CONSOLE_INPUT;
widget->columns = label == NULL ? 1 : 2;
widget->render = nk_console_input_render;
widget->selectable = nk_true;
widget->data = data;
// Set up the input state child.
nk_console* active_state = nk_console_label(widget, NULL);
active_state->type = NK_CONSOLE_INPUT_ACTIVE;
active_state->render = nk_console_input_active_render;
return widget;
}
#if defined(__cplusplus)
}
#endif
#endif // NK_CONSOLE_INPUT_IMPLEMENTATION_ONCE
#endif // NK_CONSOLE_IMPLEMENTATION