comparison nuklear_ui/blastem_nuklear.c @ 2317:e836cf11783b

Make deadzones configurable and bump up the default value
author Michael Pavone <pavone@retrodev.com>
date Sun, 02 Apr 2023 23:21:39 -0700
parents ef5dc4d02d27
children ab3d8759da08
comparison
equal deleted inserted replaced
2316:523ab225815b 2317:e836cf11783b
1042 void view_controller_bindings(struct nk_context *context) 1042 void view_controller_bindings(struct nk_context *context)
1043 { 1043 {
1044 if (nk_begin(context, "Controller Bindings", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { 1044 if (nk_begin(context, "Controller Bindings", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) {
1045 if (!bindings) { 1045 if (!bindings) {
1046 bindings = calloc(1, sizeof(*bindings)); 1046 bindings = calloc(1, sizeof(*bindings));
1047 tern_node *pad = get_binding_node_for_pad(selected_controller); 1047 tern_node *pad = get_binding_node_for_pad(selected_controller, &selected_controller_info);
1048 if (pad) { 1048 if (pad) {
1049 tern_foreach(tern_find_node(pad, "buttons"), button_iter, bindings); 1049 tern_foreach(tern_find_node(pad, "buttons"), button_iter, bindings);
1050 tern_foreach(tern_find_node(pad, "axes"), axis_iter, bindings); 1050 tern_foreach(tern_find_node(pad, "axes"), axis_iter, bindings);
1051 tern_node *dpad = tern_find_path(pad, "dpads\0" "0\0", TVAL_NODE).ptrval; 1051 tern_node *dpad = tern_find_path(pad, "dpads\0" "0\0", TVAL_NODE).ptrval;
1052 const char *dir_keys[] = {"up", "down", "right", "left"}; 1052 const char *dir_keys[] = {"up", "down", "right", "left"};
1486 "WiiU", "Switch" 1486 "WiiU", "Switch"
1487 }, 2); 1487 }, 2);
1488 nk_end(context); 1488 nk_end(context);
1489 } 1489 }
1490 } 1490 }
1491 static uint8_t stick_nav_disabled;
1492 static SDL_GameController *current_controller;
1493 static uint8_t deadzones_dirty;
1494 void stick_deadzone_widget(float left, float top, float size, SDL_GameControllerAxis x_axis)
1495 {
1496 float crosshair_size = context->style.font->height;
1497 nk_stroke_rect(&context->current->buffer, nk_rect(left, top, size, size), context->style.window.rounding, context->style.window.border, nk_rgb(255, 255, 255));
1498 float deadzone_size = selected_controller_info.stick_deadzone * size / 65535.0f;
1499 int16_t raw_x = SDL_GameControllerGetAxis(current_controller, x_axis);
1500 int16_t raw_y = SDL_GameControllerGetAxis(current_controller, x_axis + 1);
1501 if (raw_x > selected_controller_info.stick_deadzone) {
1502 float points[] = {
1503 left + size * 0.5f + deadzone_size, top + size * 0.5f - deadzone_size,
1504 left + size, top,
1505 left + size, top + size,
1506 left + size * 0.5f + deadzone_size, top + size * 0.5f + deadzone_size,
1507 };
1508 nk_fill_polygon(&context->current->buffer, points, sizeof(points)/(2 * sizeof(float)), context->style.checkbox.cursor_normal.data.color);
1509 } else if (raw_x < -selected_controller_info.stick_deadzone) {
1510 float points[] = {
1511 left, top,
1512 left + size * 0.5f - deadzone_size, top + size * 0.5f - deadzone_size,
1513 left + size * 0.5f - deadzone_size, top + size * 0.5f + deadzone_size,
1514 left, top + size,
1515 };
1516 nk_fill_polygon(&context->current->buffer, points, sizeof(points)/(2 * sizeof(float)), context->style.checkbox.cursor_normal.data.color);
1517 }
1518 if (raw_y > selected_controller_info.stick_deadzone) {
1519 float points[] = {
1520 left, top + size,
1521 left + size, top + size,
1522 left + size * 0.5f + deadzone_size, top + size * 0.5f + deadzone_size,
1523 left + size * 0.5f - deadzone_size, top + size * 0.5f + deadzone_size,
1524 };
1525 nk_fill_polygon(&context->current->buffer, points, sizeof(points)/(2 * sizeof(float)), context->style.checkbox.cursor_normal.data.color);
1526 } else if (raw_y < -selected_controller_info.stick_deadzone) {
1527 float points[] = {
1528 left, top,
1529 left + size, top,
1530 left + size * 0.5f + deadzone_size, top + size * 0.5f - deadzone_size,
1531 left + size * 0.5f - deadzone_size, top + size * 0.5f - deadzone_size,
1532 };
1533 nk_fill_polygon(&context->current->buffer, points, sizeof(points)/(2 * sizeof(float)), context->style.checkbox.cursor_normal.data.color);
1534 }
1535 nk_stroke_rect(&context->current->buffer, nk_rect(left + 0.5f * size - deadzone_size, top + 0.5f * size - deadzone_size, 2 * deadzone_size, 2 * deadzone_size), context->style.window.rounding, 0.5f * context->style.window.border, nk_rgb(200, 200, 200));
1536 //nk_layout_space_push(context, nk_rect(left, top, size, size));
1537 float x = raw_x * size / 65535.0f + size / 2.0f - crosshair_size / 2.0f;
1538 float y = raw_y * size / 65535.0f + size / 2.0f - crosshair_size / 2.0f;
1539 nk_draw_symbol(&context->current->buffer, NK_SYMBOL_X, nk_rect(left + x, top + y, crosshair_size, crosshair_size), nk_rgb(0, 0, 0), nk_rgb(255, 255, 255), 1, context->style.font);
1540 }
1541
1542 void trigger_deadzone_widget(float left, float top, float size, SDL_GameControllerAxis axis)
1543 {
1544 float crosshair_size = context->style.font->height;
1545 nk_stroke_rect(&context->current->buffer, nk_rect(left, top, size, crosshair_size * 1.5f), context->style.window.rounding, context->style.window.border, nk_rgb(255, 255, 255));
1546 float deadzone_size = selected_controller_info.trigger_deadzone * size / 32767.0f;
1547 int16_t raw = SDL_GameControllerGetAxis(current_controller, axis);
1548 if (raw < 0) {
1549 raw = 0;
1550 }
1551 if (raw > selected_controller_info.trigger_deadzone) {
1552 nk_fill_rect(&context->current->buffer, nk_rect(left + deadzone_size, top, size - deadzone_size, 1.5f * crosshair_size), context->style.window.rounding, context->style.checkbox.cursor_normal.data.color);
1553 }
1554 nk_stroke_line(&context->current->buffer, left + deadzone_size, top, left + deadzone_size, top + 1.5f * crosshair_size, 0.5f * context->style.window.border, nk_rgb(200, 200, 200));
1555 float x = raw * size / 32767.0f - crosshair_size / 2.0f;
1556 nk_draw_symbol(&context->current->buffer, NK_SYMBOL_X, nk_rect(left + x, top + 0.25f * crosshair_size, crosshair_size, crosshair_size), nk_rgb(0, 0, 0), nk_rgb(255, 255, 255), 1, context->style.font);
1557 }
1558
1559 void view_deadzones(struct nk_context *context)
1560 {
1561 if (nk_begin(context, "Deadzones", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) {
1562 nk_layout_space_begin(context, NK_STATIC, render_height() - 3 * context->style.font->height, 4);
1563
1564 float left = render_width() / 8.0f, top = render_height() / 8.0f;
1565 float size = render_height() / 3.0f;
1566 stick_deadzone_widget(left, top, size, SDL_CONTROLLER_AXIS_LEFTX);
1567 stick_deadzone_widget(left + 1.25f * size, top, size, SDL_CONTROLLER_AXIS_RIGHTX);
1568
1569 top += size + context->style.font->height;
1570 nk_layout_space_push(context, nk_rect(left, top, size * 2, context->style.font->height));
1571 int val = selected_controller_info.stick_deadzone;
1572 nk_property_int(context, "Stick Deadzone", 250, &val, 32000, 250, 1.0f);
1573 if (val != selected_controller_info.stick_deadzone) {
1574 selected_controller_info.stick_deadzone = val;
1575 deadzones_dirty = 1;
1576 }
1577
1578 top += 2.0f * context->style.font->height;
1579 trigger_deadzone_widget(left, top, size, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
1580 trigger_deadzone_widget(left + 1.25f * size, top, size, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
1581
1582 top += context->style.font->height * 2.5f;
1583 nk_layout_space_push(context, nk_rect(left, top, size * 2, context->style.font->height));
1584 val = selected_controller_info.trigger_deadzone;
1585 nk_property_int(context, "Trigger Deadzone", 250, &val, 32000, 250, 1.0f);
1586 if (val != selected_controller_info.trigger_deadzone) {
1587 selected_controller_info.trigger_deadzone = val;
1588 deadzones_dirty = 1;
1589 }
1590
1591 nk_layout_space_end(context);
1592
1593 nk_layout_row_static(context, context->style.font->height, (render_width() - 2 * context->style.font->height) / 2, 2);
1594 if (nk_button_label(context, "Back")) {
1595 stick_nav_disabled = 0;
1596 if (current_controller) {
1597 SDL_GameControllerClose(current_controller);
1598 current_controller = NULL;
1599 }
1600 if (deadzones_dirty) {
1601 save_controller_info(selected_controller, &selected_controller_info);
1602 }
1603 pop_view();
1604 }
1605 nk_end(context);
1606 }
1607 }
1491 1608
1492 void view_controllers(struct nk_context *context) 1609 void view_controllers(struct nk_context *context)
1493 { 1610 {
1494 if (nk_begin(context, "Controllers", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { 1611 if (nk_begin(context, "Controllers", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) {
1495 int height = (render_height() - 2*context->style.font->height) / 5; 1612 int height = (render_height() - 2*context->style.font->height) / 5;
1496 int inner_height = height - context->style.window.spacing.y; 1613 int inner_height = height - context->style.window.spacing.y;
1497 const struct nk_user_font *font = context->style.font; 1614 const struct nk_user_font *font = context->style.font;
1498 int bindings_width = font->width(font->userdata, font->height, "Bindings", strlen("Bindings")) + context->style.button.padding.x * 2; 1615 int bindings_width = font->width(font->userdata, font->height, "Bindings", strlen("Bindings")) + context->style.button.padding.x * 2;
1499 int remap_width = font->width(font->userdata, font->height, "Remap", strlen("Remap")) + context->style.button.padding.x * 2; 1616 int remap_width = font->width(font->userdata, font->height, "Remap", strlen("Remap")) + context->style.button.padding.x * 2;
1500 int change_type_width = font->width(font->userdata, font->height, "Change Type", strlen("Change Type")) + context->style.button.padding.x * 2; 1617 int change_type_width = font->width(font->userdata, font->height, "Change Type", strlen("Change Type")) + context->style.button.padding.x * 2;
1501 int total = bindings_width + remap_width + change_type_width; 1618 int deadzones_width = font->width(font->userdata, font->height, "Deadzones", strlen("Deadzones")) + context->style.button.padding.x * 2;
1619 int total = bindings_width + remap_width + change_type_width + deadzones_width;
1502 float bindings_ratio = (float)bindings_width / total; 1620 float bindings_ratio = (float)bindings_width / total;
1503 float remap_ratio = (float)remap_width / total; 1621 float remap_ratio = (float)remap_width / total;
1504 float change_type_ratio = (float)change_type_width / total; 1622 float change_type_ratio = (float)change_type_width / total;
1623 float deadzones_ratio = (float)deadzones_width / total;
1505 1624
1506 1625
1507 uint8_t found_controller = 0; 1626 uint8_t found_controller = 0;
1508 for (int i = 0; i < MAX_JOYSTICKS; i++) 1627 for (int i = 0; i < MAX_JOYSTICKS; i++)
1509 { 1628 {
1561 selected_controller = i; 1680 selected_controller = i;
1562 selected_controller_info = info; 1681 selected_controller_info = info;
1563 initial_controller_config = 0; 1682 initial_controller_config = 0;
1564 push_view(view_controller_type); 1683 push_view(view_controller_type);
1565 } 1684 }
1685 button_start += change_type_width + context->style.window.spacing.x;
1686 deadzones_width = deadzones_ratio * button_area_width;
1687 nk_layout_space_push(context, nk_rect(button_start, height/2, deadzones_width, inner_height/2));
1688 if (nk_button_label(context, "Deadzones")) {
1689 selected_controller = i;
1690 selected_controller_info = info;
1691 current_controller = render_get_controller(i);
1692 stick_nav_disabled = 1;
1693 deadzones_dirty = 0;
1694 push_view(view_deadzones);
1695 }
1566 } 1696 }
1567 //nk_layout_row_end(context); 1697 nk_layout_space_end(context);
1568 } 1698 }
1569 } 1699 }
1570 if (!found_controller) { 1700 if (!found_controller) {
1571 nk_layout_row_static(context, context->style.font->height, render_width() - 2 * context->style.font->height, 1); 1701 nk_layout_row_static(context, context->style.font->height, render_width() - 2 * context->style.font->height, 1);
1572 nk_label(context, "No controllers detected", NK_TEXT_CENTERED); 1702 nk_label(context, "No controllers detected", NK_TEXT_CENTERED);
2320 } else if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == 0) { 2450 } else if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == 0) {
2321 click = 1; 2451 click = 1;
2322 } else if (event->type == SDL_MOUSEBUTTONUP && event->button.button == 0) { 2452 } else if (event->type == SDL_MOUSEBUTTONUP && event->button.button == 0) {
2323 click = 0; 2453 click = 0;
2324 } 2454 }
2455 if (stick_nav_disabled && event->type == SDL_CONTROLLERAXISMOTION) {
2456 return;
2457 }
2325 nk_sdl_handle_event(event); 2458 nk_sdl_handle_event(event);
2326 } 2459 }
2327 2460
2328 static void context_destroyed(void) 2461 static void context_destroyed(void)
2329 { 2462 {