GUI: Support for touch/cursor

This commit is contained in:
Jeffrey Pfau 2015-09-04 22:50:20 -07:00
parent 2dcefe8fa5
commit 4cf016d442
7 changed files with 121 additions and 18 deletions

View File

@ -235,6 +235,18 @@ static uint32_t _pollInput(void) {
return keys;
}
static enum GUICursorState _pollCursor(int* x, int* y) {
hidScanInput();
if (!(hidKeysHeld() & KEY_TOUCH)) {
return GUI_CURSOR_UP;
}
touchPosition pos;
hidTouchRead(&pos);
*x = pos.px;
*y = pos.py;
return GUI_CURSOR_DOWN;
}
static void _sampleRotation(struct GBARotationSource* source) {
struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
// Work around ctrulib getting the entries wrong
@ -322,7 +334,8 @@ int main() {
.params = {
320, 240,
font, "/",
_drawStart, _drawEnd, _pollInput,
_drawStart, _drawEnd,
_pollInput, _pollCursor,
0, 0,
GUI_PARAMS_TRAIL

View File

@ -5,7 +5,7 @@ source_group("PS Vita-specific code" FILES ${OS_SRC})
list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sce-vfs.c)
set(VFS_SRC ${VFS_SRC} PARENT_SCOPE)
set(OS_LIB -lvita2d -lSceCtrl_stub -lSceRtc_stub -lSceGxm_stub -lSceDisplay_stub -lSceAudio_stub -lSceMotion_stub -lScePower_stub -lpng -lz -l${M_LIBRARY})
set(OS_LIB -lvita2d -lSceCtrl_stub -lSceRtc_stub -lSceGxm_stub -lSceDisplay_stub -lSceAudio_stub -lSceMotion_stub -lScePower_stub -lSceTouch_stub -lpng -lz -l${M_LIBRARY})
set(OBJCOPY_CMD ${OBJCOPY} -I binary -O elf32-littlearm -B arm)
list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)

View File

@ -15,6 +15,7 @@
#include <psp2/kernel/processmgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/moduleinfo.h>
#include <psp2/touch.h>
#include <vita2d.h>
@ -63,15 +64,27 @@ static uint32_t _pollInput(void) {
return input;
}
int main() {
printf("%s initializing", projectName);
static enum GUICursorState _pollCursor(int* x, int* y) {
SceTouchData touch;
sceTouchPeek(0, &touch, 1);
if (touch.reportNum < 1) {
return GUI_CURSOR_UP;
}
*x = touch.report[0].x / 2;
*y = touch.report[0].y / 2;
return GUI_CURSOR_DOWN;
}
int main() {
vita2d_init();
struct GUIFont* font = GUIFontCreate();
struct GBAGUIRunner runner = {
.params = {
PSP2_HORIZONTAL_PIXELS, PSP2_VERTICAL_PIXELS,
font, "cache0:", _drawStart, _drawEnd, _pollInput, 0, 0,
font, "cache0:", _drawStart, _drawEnd,
_pollInput, _pollCursor,
0, 0,
GUI_PARAMS_TRAIL
},

View File

@ -34,6 +34,7 @@ static int32_t _readGyroZ(struct GBARotationSource* source);
static void _drawStart(void);
static void _drawEnd(void);
static uint32_t _pollInput(void);
static enum GUICursorState _pollCursor(int* x, int* y);
static void _guiPrepare(void);
static void _guiFinish(void);
@ -68,6 +69,7 @@ int main() {
VIDEO_Init();
PAD_Init();
WPAD_Init();
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
AUDIO_Init(0);
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback(_audioDMA);
@ -159,7 +161,8 @@ int main() {
.params = {
352, 230,
font, "/",
_drawStart, _drawEnd, _pollInput,
_drawStart, _drawEnd,
_pollInput, _pollCursor,
_guiPrepare, _guiFinish,
GUI_PARAMS_TRAIL
@ -254,7 +257,7 @@ static uint32_t _pollInput(void) {
((ext == WPAD_EXP_CLASSIC) && (wiiPad & (WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_Y)))) {
keys |= 1 << GUI_INPUT_SELECT;
}
if ((padkeys & PAD_BUTTON_B) || (wiiPad & WPAD_BUTTON_1) ||
if ((padkeys & PAD_BUTTON_B) || (wiiPad & WPAD_BUTTON_1) || (wiiPad & WPAD_BUTTON_B) ||
((ext == WPAD_EXP_CLASSIC) && (wiiPad & (WPAD_CLASSIC_BUTTON_B | WPAD_CLASSIC_BUTTON_X)))) {
keys |= 1 << GUI_INPUT_BACK;
}
@ -281,6 +284,22 @@ static uint32_t _pollInput(void) {
return keys;
}
static enum GUICursorState _pollCursor(int* x, int* y) {
ir_t ir;
WPAD_IR(0, &ir);
if (!ir.smooth_valid) {
return GUI_CURSOR_NOT_PRESENT;
}
*x = ir.sx;
*y = ir.sy;
WPAD_ScanPads();
u32 wiiPad = WPAD_ButtonsHeld(0);
if (wiiPad & WPAD_BUTTON_A) {
return GUI_CURSOR_DOWN;
}
return GUI_CURSOR_UP;
}
void _guiPrepare(void) {
Mtx44 proj;
guOrtho(proj, -20, 240, 0, 352, 0, 300);
@ -324,7 +343,6 @@ void _gameUnloaded(struct GBAGUIRunner* runner) {
}
void _gameLoaded(struct GBAGUIRunner* runner) {
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC);
if (runner->context.gba->memory.hw.devices & HW_GYRO) {
int i;
for (i = 0; i < 6; ++i) {

View File

@ -31,6 +31,37 @@ void GUIPollInput(struct GUIParams* params, uint32_t* newInputOut, uint32_t* hel
}
}
enum GUICursorState GUIPollCursor(struct GUIParams* params, int* x, int* y) {
if (!params->pollCursor) {
return GUI_CURSOR_NOT_PRESENT;
}
enum GUICursorState state = params->pollCursor(x, y);
if (params->cursorState == GUI_CURSOR_DOWN) {
int dragX = *x - params->cx;
int dragY = *y - params->cy;
if (dragX * dragX + dragY * dragY > 25) {
params->cursorState = GUI_CURSOR_DRAGGING;
return GUI_CURSOR_DRAGGING;
}
if (state == GUI_CURSOR_UP) {
params->cursorState = GUI_CURSOR_UP;
return GUI_CURSOR_CLICKED;
}
} else {
params->cx = *x;
params->cy = *y;
}
if (params->cursorState == GUI_CURSOR_DRAGGING) {
if (state == GUI_CURSOR_UP || state == GUI_CURSOR_NOT_PRESENT) {
params->cursorState = GUI_CURSOR_UP;
return GUI_CURSOR_UP;
}
return GUI_CURSOR_DRAGGING;
}
params->cursorState = state;
return params->cursorState;
}
void GUIInvalidateKeys(struct GUIParams* params) {
for (int i = 0; i < GUI_INPUT_MAX; ++i) {
params->inputHistory[i] = 0;

View File

@ -28,6 +28,14 @@ enum GUIInput {
GUI_INPUT_MAX = 0x20
};
enum GUICursorState {
GUI_CURSOR_NOT_PRESENT,
GUI_CURSOR_UP,
GUI_CURSOR_DOWN,
GUI_CURSOR_CLICKED,
GUI_CURSOR_DRAGGING
};
struct GUIBackground {
void (*draw)(struct GUIBackground*, void* context);
};
@ -41,21 +49,25 @@ struct GUIParams {
void (*drawStart)(void);
void (*drawEnd)(void);
uint32_t (*pollInput)(void);
enum GUICursorState (*pollCursor)(int* x, int* y);
void (*guiPrepare)(void);
void (*guiFinish)(void);
// State
int inputHistory[GUI_INPUT_MAX];
enum GUICursorState cursorState;
int cx, cy;
// Directories
char currentPath[PATH_MAX];
size_t fileIndex;
};
#define GUI_PARAMS_TRAIL {}, "", 0
#define GUI_PARAMS_TRAIL {}, GUI_CURSOR_NOT_PRESENT, 0, 0, "", 0
void GUIInit(struct GUIParams* params);
void GUIPollInput(struct GUIParams* params, uint32_t* newInput, uint32_t* heldInput);
enum GUICursorState GUIPollCursor(struct GUIParams* params, int* x, int* y);
void GUIInvalidateKeys(struct GUIParams* params);
#endif

View File

@ -12,17 +12,21 @@ DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem);
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem* item) {
size_t start = 0;
size_t pageSize = params->height / GUIFontHeight(params->font);
size_t lineHeight = GUIFontHeight(params->font);
size_t pageSize = params->height / lineHeight;
if (pageSize > 4) {
pageSize -= 4;
} else {
pageSize = 1;
}
int cursorOverItem = 0;
GUIInvalidateKeys(params);
while (true) {
uint32_t newInput = 0;
GUIPollInput(params, &newInput, 0);
int cx, cy;
enum GUICursorState cursor = GUIPollCursor(params, &cx, &cy);
if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) {
--menu->index;
@ -44,17 +48,28 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
menu->index = GUIMenuItemListSize(&menu->items) - 1;
}
}
if (cursor != GUI_CURSOR_NOT_PRESENT) {
int index = (cy / lineHeight) - 2;
if (index >= 0 && index + start < GUIMenuItemListSize(&menu->items)) {
if (menu->index != index + start || !cursorOverItem) {
cursorOverItem = 1;
}
menu->index = index + start;
} else {
cursorOverItem = 0;
}
}
if (menu->index < start) {
start = menu->index;
}
while ((menu->index - start + 4) * GUIFontHeight(params->font) > params->height) {
while ((menu->index - start + 4) * lineHeight > params->height) {
++start;
}
if (newInput & (1 << GUI_INPUT_CANCEL)) {
break;
}
if (newInput & (1 << GUI_INPUT_SELECT)) {
if (newInput & (1 << GUI_INPUT_SELECT) || (cursorOverItem == 2 && cursor == GUI_CURSOR_CLICKED)) {
*item = *GUIMenuItemListGetPointer(&menu->items, menu->index);
if (item->submenu) {
enum GUIMenuExitReason reason = GUIShowMenu(params, item->submenu, item);
@ -65,6 +80,9 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
return GUI_MENU_EXIT_ACCEPT;
}
}
if ((cursorOverItem == 1 && cursor == GUI_CURSOR_UP)) {
cursorOverItem = 2;
}
if (newInput & (1 << GUI_INPUT_BACK)) {
return GUI_MENU_EXIT_BACK;
}
@ -76,9 +94,9 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
if (params->guiPrepare) {
params->guiPrepare();
}
unsigned y = GUIFontHeight(params->font);
unsigned y = lineHeight;
GUIFontPrint(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, menu->title);
y += 2 * GUIFontHeight(params->font);
y += 2 * lineHeight;
size_t i;
for (i = start; i < GUIMenuItemListSize(&menu->items); ++i) {
int color = 0xE0A0A0A0;
@ -88,16 +106,14 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
bullet = '>';
}
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, GUIMenuItemListGetPointer(&menu->items, i)->title);
y += GUIFontHeight(params->font);
if (y + GUIFontHeight(params->font) > params->height) {
y += lineHeight;
if (y + lineHeight > params->height) {
break;
}
}
if (params->guiFinish) {
params->guiFinish();
}
y += GUIFontHeight(params->font) * 2;
params->drawEnd();
}
return GUI_MENU_EXIT_CANCEL;