From 00e96fd53b8e738c12af641594086e594dde4ac9 Mon Sep 17 00:00:00 2001 From: Steven Mattera Date: Mon, 30 Jul 2018 17:23:34 -0400 Subject: [PATCH] Added touch controls. (#41) * Added touch controls. --- common/common.h | 1 + common/menu-list.c | 1 + common/menu.c | 11 ++-- common/menu.h | 6 +- common/message-box.c | 13 ++-- common/message-box.h | 15 +++++ nx_main/main.c | 2 + nx_main/nx_touch.c | 141 +++++++++++++++++++++++++++++++++++++++++++ nx_main/nx_touch.h | 15 +++++ 9 files changed, 186 insertions(+), 19 deletions(-) create mode 100644 common/message-box.h create mode 100644 nx_main/nx_touch.c create mode 100644 nx_main/nx_touch.h diff --git a/common/common.h b/common/common.h index c837087..4457ab5 100644 --- a/common/common.h +++ b/common/common.h @@ -57,6 +57,7 @@ typedef union { #include "nanojpeg.h" #include "math.h" #include "theme.h" +#include "message-box.h" void menuStartup(); void menuLoop(); diff --git a/common/menu-list.c b/common/menu-list.c index ba7aacd..ff74afc 100644 --- a/common/menu-list.c +++ b/common/menu-list.c @@ -30,6 +30,7 @@ static void menuAddEntry(menuEntry_s* me) { m->firstEntry = me; m->lastEntry = me; } + m->xPos = 0; m->nEntries ++; } diff --git a/common/menu.c b/common/menu.c index e10730e..e5eae5f 100644 --- a/common/menu.c +++ b/common/menu.c @@ -410,17 +410,16 @@ void menuLoop() { } else { - static int x = 0; static int v = 0; if (menu->nEntries > 7) { int wanted_x = clamp(-menu->curEntry * (140 + 30), -(menu->nEntries - 7) * (140 + 30), 0); - x += v; - v += (wanted_x - x) / 3; + menu->xPos += v; + v += (wanted_x - menu->xPos) / 3; v /= 2; } else { - x = v = 0; + menu->xPos = v = 0; } menuEntry_s *active_entry = NULL; @@ -430,7 +429,7 @@ void menuLoop() { int entry_start_x = 29 + i * (140 + 30); int screen_width = 1280; - if (entry_start_x >= (screen_width - x)) + if (entry_start_x >= (screen_width - menu->xPos)) break; int is_active = i==menu->curEntry; @@ -438,7 +437,7 @@ void menuLoop() { if (is_active) active_entry = me; - drawEntry(me, entry_start_x + x, is_active); + drawEntry(me, entry_start_x + menu->xPos, is_active); } if(active_entry != NULL) { diff --git a/common/menu.h b/common/menu.h index 9b4a17e..baae21e 100644 --- a/common/menu.h +++ b/common/menu.h @@ -29,6 +29,7 @@ struct menu_s_tag menuEntry_s *firstEntry, *lastEntry; int nEntries; int curEntry; + int xPos; char dirname[PATH_MAX+1]; }; @@ -73,11 +74,6 @@ double menuTimer; extern "C" { #endif -void menuCreateMsgBox(int width, int height, const char *text); -void menuCloseMsgBox(); -bool menuIsMsgBoxOpen(); -void menuDrawMsgBox(void); - void menuEntryInit(menuEntry_s* me, MenuEntryType type); void menuEntryFree(menuEntry_s* me); bool fileExists(const char* path); diff --git a/common/message-box.c b/common/message-box.c index cd826ef..d5bee7d 100644 --- a/common/message-box.c +++ b/common/message-box.c @@ -1,12 +1,5 @@ #include "common.h" - -typedef struct -{ - uint32_t width; - uint32_t height; - color_t *bg; - char *text; -} MessageBox; +#include "message-box.h" MessageBox currMsgBox; @@ -177,3 +170,7 @@ void menuCloseMsgBox() { currMsgBox.text = NULL; } } + +MessageBox menuGetCurrentMsgBox() { + return currMsgBox; +} diff --git a/common/message-box.h b/common/message-box.h new file mode 100644 index 0000000..7c62304 --- /dev/null +++ b/common/message-box.h @@ -0,0 +1,15 @@ +#pragma once + +typedef struct +{ + uint32_t width; + uint32_t height; + color_t *bg; + char *text; +} MessageBox; + +void menuCreateMsgBox(int width, int height, const char *text); +void menuCloseMsgBox(); +bool menuIsMsgBoxOpen(); +void menuDrawMsgBox(void); +MessageBox menuGetCurrentMsgBox(); diff --git a/nx_main/main.c b/nx_main/main.c index cf6c2bf..c519f3e 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -3,6 +3,7 @@ #include #include "../common/common.h" +#include "nx_touch.h" uint8_t* g_framebuf; u32 g_framebuf_width; @@ -110,6 +111,7 @@ bool menuUpdate(void) { bool exitflag = 0; menu_s* menu = menuGetCurrent(); u32 down = hidKeysDown(CONTROLLER_P1_AUTO); + handleTouch(menu); if (down & KEY_Y) { diff --git a/nx_main/nx_touch.c b/nx_main/nx_touch.c new file mode 100644 index 0000000..2d499c9 --- /dev/null +++ b/nx_main/nx_touch.c @@ -0,0 +1,141 @@ +#include "nx_touch.h" + +#define TAP_MOVEMENT_GAP 20 +#define VERTICAL_SWIPE_HORIZONTAL_PLAY 250 +#define VERTICAL_SWIPE_MINIMUM_DISTANCE 300 +#define LISTING_START_Y 475 +#define LISTING_END_Y 647 +#define BUTTON_START_Y 672 +#define BUTTON_END_Y 704 +#define BACK_BUTTON_START_X 966 +#define BACK_BUTTON_END_X 1048 +#define LAUNCH_BUTTON_START_X 1092 +#define LAUNCH_BUTTON_END_X 1200 + +#define distance(x1, y1, x2, y2) (int) sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)) + +struct touchInfo_s touchInfo; + +void touchInit() { + touchInfo.gestureInProgress = false; + touchInfo.isTap = true; + touchInfo.initMenuXPos = 0; + touchInfo.initMenuIndex = 0; +} + +void handleTappingOnApp(menu_s* menu, int px) { + int i = 0; + menuEntry_s *me = NULL; + + for (me = menu->firstEntry, i = 0; me; me = me->next, i ++) { + int entry_start_x = 29 + i * (140 + 30); + + int screen_width = 1280; + if (entry_start_x >= (screen_width - menu->xPos)) + break; + + if (px >= (entry_start_x + menu->xPos) && px <= (entry_start_x + menu->xPos) + 140 ) { + launchMenuEntryTask(me); + break; + } + } +} + +void handleTappingOnOpenLaunch(menu_s* menu) { + if (menu->nEntries > 0) + { + int i; + menuEntry_s* me; + for (i = 0, me = menu->firstEntry; i != menu->curEntry; i ++, me = me->next); + launchMenuEntryTask(me); + } +} + +void handleTouch(menu_s* menu) { + touchPosition currentTouch; + u32 touches = hidTouchCount(); + + // On touch start. + if (touches == 1 && !touchInfo.gestureInProgress) { + hidTouchRead(¤tTouch, 0); + + touchInfo.gestureInProgress = true; + touchInfo.firstTouch = currentTouch; + touchInfo.prevTouch = currentTouch; + touchInfo.isTap = true; + touchInfo.initMenuXPos = menu->xPos; + touchInfo.initMenuIndex = menu->curEntry; + } + // On touch moving. + else if (touches >= 1 && touchInfo.gestureInProgress) { + hidTouchRead(¤tTouch, 0); + + touchInfo.prevTouch = currentTouch; + + if (touchInfo.isTap && (abs(touchInfo.firstTouch.px - currentTouch.px) > TAP_MOVEMENT_GAP || abs(touchInfo.firstTouch.py - currentTouch.py) > TAP_MOVEMENT_GAP)) { + touchInfo.isTap = false; + } + if (!menuIsMsgBoxOpen() && touchInfo.firstTouch.py > LISTING_START_Y && touchInfo.firstTouch.py < LISTING_END_Y && !touchInfo.isTap && menu->nEntries > 7) { + menu->xPos = touchInfo.initMenuXPos + (currentTouch.px - touchInfo.firstTouch.px); + menu->curEntry = touchInfo.initMenuIndex + ((int) (touchInfo.firstTouch.px - currentTouch.px) / 170); + + if (menu->curEntry < 0) + menu->curEntry = 0; + + if (menu->curEntry >= menu->nEntries - 6) + menu->curEntry = menu->nEntries - 7; + } + } + // On touch end. + else if (touchInfo.gestureInProgress) { + int x1 = touchInfo.firstTouch.px; + int y1 = touchInfo.firstTouch.py; + int x2 = touchInfo.prevTouch.px; + int y2 = touchInfo.prevTouch.py; + + if (menuIsMsgBoxOpen()) { + MessageBox currMsgBox = menuGetCurrentMsgBox(); + int start_x = 1280 / 2 - currMsgBox.width / 2; + int start_y = (720 / 2 - currMsgBox.height / 2) + (currMsgBox.height - 80); + int end_x = start_x + currMsgBox.width; + int end_y = start_y + 80; + + if (x1 > start_x && x1 < end_x && y1 > start_y && y1 < end_y && touchInfo.isTap) { + menuCloseMsgBox(); + } + } else if (touchInfo.isTap) { + // App Icons + if (y1 > LISTING_START_Y && y1 < LISTING_END_Y) { + handleTappingOnApp(menu, touchInfo.prevTouch.px); + } + // Bottom Buttons + else if (y1 > BUTTON_START_Y && y1 < BUTTON_END_Y) { + // Back Button for non-empty directory + if (menu->nEntries != 0 && x1 > BACK_BUTTON_START_X && x1 < BACK_BUTTON_END_X) { + launchMenuBackTask(); + } + // Open/Launch Button / Back Button for empty directories + else if (x1 > LAUNCH_BUTTON_START_X && x1 < LAUNCH_BUTTON_END_X) { + if (menu->nEntries == 0) { + launchMenuBackTask(); + } else { + handleTappingOnOpenLaunch(menu); + } + } + } + } + // Vertical Swipe + else if (abs(x1 - x2) < VERTICAL_SWIPE_HORIZONTAL_PLAY && distance(x1, y1, x2, y2) > VERTICAL_SWIPE_MINIMUM_DISTANCE) { + // Swipe up to go back + if (y1 - y2 > 0) { + launchMenuBackTask(); + } + // Swipe down to go into netloader + else if (y1 - y2 < 0) { + launchMenuNetloaderTask(); + } + } + + touchInfo.gestureInProgress = false; + } +} \ No newline at end of file diff --git a/nx_main/nx_touch.h b/nx_main/nx_touch.h new file mode 100644 index 0000000..cea6010 --- /dev/null +++ b/nx_main/nx_touch.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "../common/common.h" + +struct touchInfo_s { + bool gestureInProgress; + touchPosition firstTouch; + touchPosition prevTouch; + bool isTap; + int initMenuXPos; + int initMenuIndex; +}; + +void handleTouch(menu_s* menu); \ No newline at end of file