Skip to content

Commit 0647509

Browse files
authored
Add Key selector (#154)
1 parent df58097 commit 0647509

14 files changed

Lines changed: 395 additions & 75 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ if (NOT nuklear_gamepad_FOUND)
1414
FetchContent_Declare(
1515
nuklear_gamepad
1616
GIT_REPOSITORY https://github.com/RobLoach/nuklear_gamepad.git
17-
GIT_TAG 625d716
17+
GIT_TAG 82056c3
1818
)
1919
FetchContent_GetProperties(nuklear_gamepad)
2020
if (NOT nuklear_gamepad_POPULATED)

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ int main() {
4444

4545
## Widgets
4646

47-
Buttons, Checkboxes, Color Select, Comboboxes, Files, Directories, Gamepad Input Buttons, Labels, Properties, Sliders, Knobs, Radio Options, Images, Knob, Rows, TextEdit, Tree, Rule Horizontal, List View, Messages.
47+
Buttons, Checkboxes, Color Select, Comboboxes, Files, Directories, Gamepad Input Buttons, Labels, Properties, Sliders, Knobs, Radio Options, Images, Knob, Rows, TextEdit, Tree, Rule Horizontal, Keyboard Key, List View, Messages.
4848

4949
## API
5050

@@ -95,13 +95,14 @@ void nk_console_set_active_widget(nk_console* widget);
9595
9696
## Configuration
9797
98-
| Define | Description |
99-
| ------ | ----------- |
100-
| `NK_BUTTON_TRIGGER_ON_RELEASE` | When enabled, will allow for touch and drag to scroll the window |
101-
| `NK_CONSOLE_DRAG_THRESHOLD` | When using touch and drag to scroll, the amount of threshold movement needed to consider it a scroll |
102-
| `NK_CONSOLE_AXIS_DEADZONE` | The amount of movement the axis needs prior to moving the cursor |
103-
| `NK_CONSOLE_AXIS_REPEAT_INTERVAL` | When using the gamepad axis to move, how frequently the cursor will move |
104-
| `NK_CONSOLE_FILE_ADD_FILES` | The function callback used to enumerate files, see `nk_console_file_add_files_tinydir()` |
98+
Define | Description
99+
------ | -----------
100+
`NK_BUTTON_TRIGGER_ON_RELEASE` | Required in order to ensure events are triggered in the correct order
101+
`NK_CONSOLE_KEY_BACK` | The `nk_keys` enumeration that will be used to go back in the menu heirarchy. Defaults to ESC.
102+
`NK_CONSOLE_DRAG_THRESHOLD` | The amount of threshold mouse movement needed to consider it a scroll
103+
`NK_CONSOLE_AXIS_DEADZONE` | The amount of movement the gamepad axis needs prior to moving the cursor
104+
`NK_CONSOLE_AXIS_REPEAT_INTERVAL` | When using the gamepad axis to move, how frequently the cursor will move
105+
`NK_CONSOLE_FILE_ADD_FILES` | The function callback used to enumerate files, see `nk_console_file_add_files_tinydir()`
105106
106107
## Development
107108

demo/common/nuklear_console_demo.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ static char textedit_password_buffer[256] = "12345";
8484
static int gamepad_number = 0;
8585
static enum nk_gamepad_button gamepad_button = NK_GAMEPAD_BUTTON_A;
8686

87+
// Key
88+
static nk_rune key_binding = NK_KEY_ENTER;
89+
8790
// Color
8891
static struct nk_colorf color = {0.31f, 1.0f, 0.48f, 1.0f};
8992

@@ -350,12 +353,17 @@ struct nk_console* nuklear_console_demo_init(struct nk_context* ctx, void* user_
350353
struct nk_console* progressbar = nk_console_button(widgets, "Progress Bar");
351354
{
352355
nk_console_progress(progressbar, "Progress", &progressValue, 100);
356+
nk_console_progress(progressbar, "Progress (Disabled)", &progressValue, 100)
357+
->disabled = nk_true;
353358
nk_console_button_onclick(progressbar, "Back", &nk_console_button_back);
354359
}
355360

356361
// Input: From any gamepad (-1)
357362
nk_console_input(widgets, "Input Button", -1, &gamepad_number, &gamepad_button);
358363

364+
// Key: Capture a keyboard key binding
365+
nk_console_key(widgets, "Key Binding", &key_binding);
366+
359367
// Combobox
360368
nk_console_combobox(widgets, "ComboBox", "Fists;Chainsaw;Pistol;Shotgun;Chaingun", ';', &weapon)
361369
->tooltip = "Choose a weapon! The chainsaw is the best!";
@@ -375,6 +383,8 @@ struct nk_console* nuklear_console_demo_init(struct nk_context* ctx, void* user_
375383
{
376384
nk_console_slider_float(sliders, "Slider Float", 0.0f, &slider_float_test, 2.0f, 0.1f)->tooltip = "Slider float is cool! It's what you want to use.";
377385
nk_console_slider_int(sliders, "Slider Int", 0, &slider_int_test, 20, 1);
386+
nk_console_slider_int(sliders, "Slider Disabled", 0, &slider_int_test, 20, 1)
387+
->disabled = nk_true;
378388
nk_console_button_onclick(sliders, "Back", &nk_console_button_back);
379389
}
380390

demo/glfw/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define NK_IMPLEMENTATION
2323
#define NK_GLFW_GL3_IMPLEMENTATION
2424
#define NK_KEYSTATE_BASED_INPUT
25+
#define NK_BUTTON_TRIGGER_ON_RELEASE
2526
#include "../../vendor/Nuklear/nuklear.h"
2627
#include "../../vendor/Nuklear/demo/glfw_opengl3/nuklear_glfw_gl3.h"
2728

demo/raylib/main.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ void UpdateDrawFrame(void);
1616

1717
struct nk_context *ctx;
1818
nk_bool closeWindow = nk_false;
19-
struct nk_rect lastWindowSize;
2019

2120
int main() {
2221
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
@@ -32,7 +31,6 @@ int main() {
3231
Texture texture = LoadTexture("resources/image.png");
3332

3433
console = nuklear_console_demo_init(ctx, NULL, TextureToNuklearImage(texture));
35-
lastWindowSize = nk_rect(0, 0, (float)GetScreenWidth() * 0.80f, (float)GetScreenHeight());
3634

3735
#if defined(PLATFORM_WEB)
3836
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
@@ -62,20 +60,8 @@ void UpdateDrawFrame(void) {
6260

6361
nk_gamepad_update(nk_console_get_gamepads(console));
6462

65-
int flags = NK_WINDOW_SCROLL_AUTO_HIDE;
66-
67-
// Center the window using the previous frame's rendered size, capped to screen
68-
float windowW = lastWindowSize.w < GetScreenWidth() ? lastWindowSize.w : GetScreenWidth();
69-
float windowH = lastWindowSize.h < GetScreenHeight() ? lastWindowSize.h : GetScreenHeight();
70-
struct nk_rect centered = nk_rect(
71-
(GetScreenWidth() - windowW) / 2.0f,
72-
(GetScreenHeight() - windowH) / 2.0f,
73-
windowW,
74-
windowH
75-
);
76-
7763
// Nuklear GUI Code
78-
lastWindowSize = nk_console_render_window(console, "nuklear_console", centered, flags);
64+
nk_console_render_window(console, "nuklear_console", nk_rect(0, 0, (float)GetScreenWidth(), (float)GetScreenHeight()), NK_WINDOW_SCROLL_AUTO_HIDE | NK_WINDOW_TITLE);
7965

8066
// Render
8167
BeginDrawing();

demo/sdl3_renderer/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define NK_INCLUDE_DEFAULT_FONT
2222
#define NK_INCLUDE_COMMAND_USERDATA
2323
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
24+
#define NK_BUTTON_TRIGGER_ON_RELEASE
2425
#define NK_IMPLEMENTATION
2526
#include "../../vendor/Nuklear/nuklear.h"
2627

@@ -176,6 +177,8 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
176177
SDL_RenderClear(app->renderer);
177178

178179
nk_sdl_render(ctx, NK_ANTI_ALIASING_ON);
180+
181+
// The SDL Renderer allows handling SDL_StartTextInput()
179182
nk_console_sdl_update_text_input(app->console, app->window);
180183

181184
SDL_RenderPresent(app->renderer);

demo/sdl_renderer/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define NK_INCLUDE_COMMAND_USERDATA
2121
#define NK_IMPLEMENTATION
2222
#define NK_SDL_RENDERER_IMPLEMENTATION
23+
#define NK_BUTTON_TRIGGER_ON_RELEASE
2324
#include "../../vendor/Nuklear/nuklear.h"
2425
#include "../../vendor/Nuklear/demo/sdl_renderer/nuklear_sdl_renderer.h"
2526

@@ -112,7 +113,7 @@ int main(int argc, char *argv[]) {
112113
nk_input_begin(ctx);
113114

114115
nk_gamepad_update(nk_console_get_gamepads(console));
115-
116+
116117
while (SDL_PollEvent(&evt)) {
117118
if (evt.type == SDL_QUIT) goto cleanup;
118119
if (evt.type == SDL_KEYUP && evt.key.keysym.scancode == SDL_SCANCODE_ESCAPE) running = 0;
@@ -137,6 +138,8 @@ int main(int argc, char *argv[]) {
137138
SDL_RenderClear(renderer);
138139

139140
nk_sdl_render(NK_ANTI_ALIASING_ON);
141+
142+
// The SDL Renderer allows handling SDL_StartTextInput()
140143
nk_console_sdl_update_text_input(console, win);
141144

142145
SDL_RenderPresent(renderer);

nuklear_console.h

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ typedef enum {
6969
NK_CONSOLE_COLOR,
7070
NK_CONSOLE_INPUT,
7171
NK_CONSOLE_INPUT_ACTIVE,
72+
NK_CONSOLE_KEY,
73+
NK_CONSOLE_KEY_ACTIVE,
7274
NK_CONSOLE_RADIO,
7375
NK_CONSOLE_KNOB_INT,
7476
NK_CONSOLE_KNOB_FLOAT,
@@ -284,6 +286,7 @@ NK_API nk_bool nk_console_navigate_to_path(nk_console* console, const char* path
284286
#include "nuklear_console_file_system.h"
285287
#include "nuklear_console_image.h"
286288
#include "nuklear_console_input.h"
289+
#include "nuklear_console_key.h"
287290
#include "nuklear_console_knob.h"
288291
#include "nuklear_console_label.h"
289292
#include "nuklear_console_list_view.h"
@@ -309,6 +312,28 @@ NK_API nk_bool nk_console_navigate_to_path(nk_console* console, const char* path
309312
#ifndef NK_CONSOLE_IMPLEMENTATION_ONCE
310313
#define NK_CONSOLE_IMPLEMENTATION_ONCE
311314

315+
#ifndef NK_BUTTON_TRIGGER_ON_RELEASE
316+
/**
317+
* Define NK_BUTTON_TRIGGER_ON_RELEASE prior to nuklear.h.
318+
*
319+
* This is required because the input events are triggered incorrectly otherwise, resulting in undesirable behavior.
320+
*
321+
* @code
322+
* #define NK_BUTTON_TRIGGER_ON_RELEASE
323+
* #define NK_IMPLEMENTATION
324+
* #include "nuklear.h"
325+
*
326+
* #define NK_CONSOLE_IMPLEMENTATION
327+
* #include "nuklear_console.h"
328+
* @endcode
329+
*
330+
* You are able to ignore this warning by using #define NK_CONSOLE_IGNORE_BUTTON_TRIGGER_ON_RELEASE
331+
*/
332+
#ifndef NK_CONSOLE_IGNORE_BUTTON_TRIGGER_ON_RELEASE
333+
#warning "nuklear_console requires NK_BUTTON_TRIGGER_ON_RELEASE. Add #define NK_BUTTON_TRIGGER_ON_RELEASE prior to #define NK_IMPLEMENTATION ."
334+
#endif
335+
#endif
336+
312337
#ifndef NK_CONSOLE_AXIS_DEADZONE
313338
#define NK_CONSOLE_AXIS_DEADZONE 0.22f
314339
#endif
@@ -319,6 +344,15 @@ NK_API nk_bool nk_console_navigate_to_path(nk_console* console, const char* path
319344
#define NK_CONSOLE_DRAG_THRESHOLD 8.0f
320345
#endif
321346

347+
#ifndef NK_CONSOLE_KEY_BACK
348+
/**
349+
* The Nuklear `enum nk_keys` used to go back in the menu heirarchy.
350+
*
351+
* @see nk_console_button_pushed()
352+
*/
353+
#define NK_CONSOLE_KEY_BACK NK_KEY_TEXT_RESET_MODE
354+
#endif // NK_CONSOLE_KEY_BACK
355+
322356
// NK_CONSOLE_MALLOC
323357
#ifndef NK_CONSOLE_MALLOC
324358
#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
@@ -378,6 +412,7 @@ extern "C" {
378412
#include "nuklear_console_file_system.h"
379413
#include "nuklear_console_image.h"
380414
#include "nuklear_console_input.h"
415+
#include "nuklear_console_key.h"
381416
#include "nuklear_console_knob.h"
382417
#include "nuklear_console_label.h"
383418
#include "nuklear_console_list_view.h"
@@ -876,10 +911,6 @@ static void nk_console_axis_update(nk_console* console) {
876911
* Handles the Touch and Drag Scrolling.
877912
*/
878913
static void nk_console_window_touch_drag(nk_console* console, nk_console_top_data* top_data) {
879-
#ifndef NK_BUTTON_TRIGGER_ON_RELEASE
880-
NK_UNUSED(console);
881-
NK_UNUSED(top_data);
882-
#else
883914
struct nk_input* in = &console->ctx->input;
884915
if (nk_window_is_hovered(console->ctx) && nk_input_is_mouse_pressed(in, NK_BUTTON_LEFT)) {
885916
top_data->drag_scroll_origin = in->mouse.pos;
@@ -890,7 +921,7 @@ static void nk_console_window_touch_drag(nk_console* console, nk_console_top_dat
890921
float dy = top_data->drag_scroll_origin.y - in->mouse.pos.y;
891922
float dx = top_data->drag_scroll_origin.x - in->mouse.pos.x;
892923
if (!top_data->drag_scroll_active &&
893-
(dy * dy + dx * dx) > NK_CONSOLE_DRAG_THRESHOLD * NK_CONSOLE_DRAG_THRESHOLD) {
924+
(dy * dy + dx * dx) > NK_CONSOLE_DRAG_THRESHOLD * NK_CONSOLE_DRAG_THRESHOLD) {
894925
top_data->drag_scroll_active = nk_true;
895926
}
896927
if (top_data->drag_scroll_active) {
@@ -899,10 +930,10 @@ static void nk_console_window_touch_drag(nk_console* console, nk_console_top_dat
899930
nk_window_set_scroll(console->ctx, sx, sy);
900931
top_data->input_processed = nk_true;
901932
}
902-
} else {
933+
}
934+
else {
903935
top_data->drag_scroll_active = nk_false;
904936
}
905-
#endif
906937
}
907938

908939
NK_API void nk_console_render(nk_console* console) {
@@ -973,6 +1004,15 @@ NK_API void nk_console_render(nk_console* console) {
9731004
cvector_clear(console->events);
9741005
}
9751006
}
1007+
1008+
// Update drag scroll bounds so they're valid when nk_console_render is called directly (e.g. SDL/GLFW demos) rather than via nk_console_render_window.
1009+
if (console->ctx->current != NULL) {
1010+
struct nk_rect content = nk_window_get_content_region(console->ctx);
1011+
float rendered_h = console->ctx->current->layout->at_y - console->ctx->current->layout->bounds.y + console->ctx->current->layout->row.height;
1012+
data->drag_scroll_max_y = (nk_uint)NK_MAX(0.0f, rendered_h - content.h);
1013+
data->drag_scroll_max_x = (nk_uint)NK_MAX(0.0f, console->ctx->current->layout->max_x - console->ctx->current->layout->bounds.x - content.w);
1014+
}
1015+
9761016
return;
9771017
}
9781018

@@ -1109,10 +1149,8 @@ NK_API struct nk_rect nk_console_render_window(nk_console* console, const char*
11091149
float rendered_h = console->ctx->current->layout->at_y - console->ctx->current->layout->bounds.y + console->ctx->current->layout->row.height;
11101150
window_bounds = nk_window_get_bounds(console->ctx);
11111151
window_bounds.h = window_bounds.h - content.h + rendered_h;
1112-
#ifdef NK_BUTTON_TRIGGER_ON_RELEASE
11131152
top_data->drag_scroll_max_y = (nk_uint)NK_MAX(0.0f, rendered_h - content.h);
11141153
top_data->drag_scroll_max_x = (nk_uint)NK_MAX(0.0f, console->ctx->current->layout->max_x - console->ctx->current->layout->bounds.x - content.w);
1115-
#endif
11161154
}
11171155

11181156
// Finish the window processing.
@@ -1333,8 +1371,8 @@ NK_API nk_console* nk_console_find_by_path(nk_console* console, const char* path
13331371
continue;
13341372
}
13351373
int label_len = child->label_length > 0
1336-
? child->label_length
1337-
: (int)nk_strlen(child->label);
1374+
? child->label_length
1375+
: (int)nk_strlen(child->label);
13381376
if (label_len == copy_len &&
13391377
strncmp(child->label, segment, (size_t)copy_len) == 0) {
13401378
found = child;
@@ -1397,9 +1435,9 @@ NK_API nk_bool nk_console_button_pushed(nk_console* console, int button) {
13971435
case NK_GAMEPAD_BUTTON_A: return nk_input_is_key_released(&console->ctx->input, NK_KEY_ENTER);
13981436
case NK_GAMEPAD_BUTTON_B:
13991437
// Escape Key
1400-
return nk_input_is_key_released(&console->ctx->input, NK_KEY_TEXT_RESET_MODE) ||
1401-
// Mouse Back Button
1402-
(nk_input_is_mouse_pressed(&console->ctx->input, NK_BUTTON_X1) && nk_window_is_hovered(console->ctx));
1438+
return nk_input_is_key_released(&console->ctx->input, NK_CONSOLE_KEY_BACK) ||
1439+
// Mouse Back Button
1440+
(nk_input_is_mouse_pressed(&console->ctx->input, NK_BUTTON_X1) && nk_window_is_hovered(console->ctx));
14031441
// case NK_GAMEPAD_BUTTON_X: return nk_input_is_key_pressed(&console->ctx->input, NK_KEY_A);
14041442
// case NK_GAMEPAD_BUTTON_Y: return nk_input_is_key_pressed(&console->ctx->input, NK_KEY_S);
14051443
case NK_GAMEPAD_BUTTON_LB: return nk_input_is_key_released(&console->ctx->input, NK_KEY_UP) && nk_input_is_key_down(&console->ctx->input, NK_KEY_SHIFT);

0 commit comments

Comments
 (0)