GUI: Add icons and scrolling enhancements

This commit is contained in:
Jeffrey Pfau 2016-01-09 00:54:18 -08:00
parent 90eca20ab2
commit 0511d0a69e
19 changed files with 360 additions and 53 deletions

BIN
res/icons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
res/icons2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -203,7 +203,7 @@ void GBAGUIRun(struct GBAGUIRunner* runner, const char* path) {
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_ALIGN_HCENTER, 0xFFFFFFFF, "Loading...");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
@ -216,7 +216,7 @@ void GBAGUIRun(struct GBAGUIRunner* runner, const char* path) {
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Load failed!");
GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_ALIGN_HCENTER, 0xFFFFFFFF, "Load failed!");
if (runner->params.guiFinish) {
runner->params.guiFinish();
}
@ -270,7 +270,7 @@ void GBAGUIRun(struct GBAGUIRunner* runner, const char* path) {
if (runner->params.guiPrepare) {
runner->params.guiPrepare();
}
GUIFontPrintf(runner->params.font, 0, GUIFontHeight(runner->params.font), GUI_TEXT_LEFT, 0x7FFFFFFF, "%.2f fps", runner->fps);
GUIFontPrintf(runner->params.font, 0, GUIFontHeight(runner->params.font), GUI_ALIGN_LEFT, 0x7FFFFFFF, "%.2f fps", runner->fps);
if (runner->params.guiFinish) {
runner->params.guiFinish();
}

View File

@ -28,6 +28,7 @@ set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE)
set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)
list(APPEND GUI_SRC
${CMAKE_CURRENT_BINARY_DIR}/icons.c
${CMAKE_CURRENT_BINARY_DIR}/font.c
${CMAKE_CURRENT_BINARY_DIR}/uishader.c
${CMAKE_CURRENT_BINARY_DIR}/uishader.h
@ -38,6 +39,7 @@ list(APPEND GUI_SRC
${CMAKE_CURRENT_SOURCE_DIR}/ctr-gpu.h)
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/icons.c
${CMAKE_CURRENT_BINARY_DIR}/font.c
${CMAKE_CURRENT_BINARY_DIR}/uishader.c
${CMAKE_CURRENT_BINARY_DIR}/uishader.h
@ -59,6 +61,10 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c
COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw
DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c
COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw
DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/uishader.vsh

View File

@ -7,8 +7,9 @@
#include "util/gui/font-metrics.h"
#include "util/png-io.h"
#include "util/vfs.h"
#include "platform/3ds/ctr-gpu.h"
#include "icons.h"
#include "font.h"
#include "ctr-gpu.h"
#define CELL_HEIGHT 16
#define CELL_WIDTH 16
@ -16,6 +17,7 @@
struct GUIFont {
struct ctrTexture texture;
struct ctrTexture icons;
};
struct GUIFont* GUIFontCreate(void) {
@ -35,11 +37,23 @@ struct GUIFont* GUIFontCreate(void) {
GX_RequestDma((u32*) font, tex->data, font_size);
gspWaitForDMA();
tex = &guiFont->icons;
ctrTexture_Init(tex);
tex->data = vramAlloc(256 * 64 * 2);
tex->format = GPU_RGBA5551;
tex->width = 256;
tex->height = 64;
GSPGPU_FlushDataCache(icons, icons_size);
GX_RequestDma((u32*) icons, tex->data, icons_size);
gspWaitForDMA();
return guiFont;
}
void GUIFontDestroy(struct GUIFont* font) {
vramFree(font->texture.data);
vramFree(font->icons.data);
free(font);
}
@ -71,3 +85,42 @@ void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint
ctrAddRect(color, x, y, u, v, CELL_WIDTH, CELL_HEIGHT);
}
void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
ctrActivateTexture(&font->icons);
if (icon >= GUI_ICON_MAX) {
return;
}
struct GUIIconMetric metric = defaultIconMetrics[icon];
switch (align & GUI_ALIGN_HCENTER) {
case GUI_ALIGN_HCENTER:
x -= metric.width / 2;
break;
case GUI_ALIGN_RIGHT:
x -= metric.width;
break;
}
switch (align & GUI_ALIGN_VCENTER) {
case GUI_ALIGN_VCENTER:
y -= metric.height / 2;
break;
case GUI_ALIGN_BOTTOM:
y -= metric.height;
break;
}
switch (orient) {
case GUI_ORIENT_HMIRROR:
ctrAddRectScaled(color, x + metric.width, y, -metric.width, metric.height, metric.x, metric.y, metric.width, metric.height);
break;
case GUI_ORIENT_VMIRROR:
ctrAddRectScaled(color, x, y + metric.height, metric.width, -metric.height, metric.x, metric.y, metric.width, metric.height);
break;
case GUI_ORIENT_0:
default:
// TODO: Rotation
ctrAddRect(color, x, y, metric.x, metric.y, metric.width, metric.height);
break;
}
}

View File

@ -410,7 +410,7 @@ static uint32_t _pollInput(void) {
return keys;
}
static enum GUICursorState _pollCursor(int* x, int* y) {
static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
hidScanInput();
if (!(hidKeysHeld() & KEY_TOUCH)) {
return GUI_CURSOR_NOT_PRESENT;

View File

@ -19,8 +19,14 @@ set(OBJCOPY_CMD ${OBJCOPY} -I binary -O elf32-littlearm -B arm)
list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/font.o ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o PROPERTIES GENERATED ON)
add_executable(${BINARY_NAME}.elf ${PLATFORM_SRC} ${GUI_SRC} ${CMAKE_CURRENT_BINARY_DIR}/font.o ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o main.c)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/icons.o
${CMAKE_CURRENT_BINARY_DIR}/font.o
${CMAKE_CURRENT_BINARY_DIR}/backdrop.o
PROPERTIES GENERATED ON)
add_executable(${BINARY_NAME}.elf ${PLATFORM_SRC} ${GUI_SRC} main.c
${CMAKE_CURRENT_BINARY_DIR}/icons.o
${CMAKE_CURRENT_BINARY_DIR}/font.o
${CMAKE_CURRENT_BINARY_DIR}/backdrop.o)
set_target_properties(${BINARY_NAME}.elf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${OS_LIB})
@ -28,6 +34,10 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.o
COMMAND ${OBJCOPY_CMD} font2x.png ${CMAKE_CURRENT_BINARY_DIR}/font.o
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/res)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.o
COMMAND ${OBJCOPY_CMD} icons2x.png ${CMAKE_CURRENT_BINARY_DIR}/icons.o
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/res)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o
COMMAND ${OBJCOPY_CMD} backdrop.png ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -13,9 +13,11 @@
#define GLYPH_HEIGHT 24
extern const uint8_t _binary_font2x_png_start[];
extern const uint8_t _binary_icons2x_png_start[];
struct GUIFont {
vita2d_texture* tex;
vita2d_texture* icons;
};
struct GUIFont* GUIFontCreate(void) {
@ -24,11 +26,13 @@ struct GUIFont* GUIFontCreate(void) {
return 0;
}
font->tex = vita2d_load_PNG_buffer(_binary_font2x_png_start);
font->icons = vita2d_load_PNG_buffer(_binary_icons2x_png_start);
return font;
}
void GUIFontDestroy(struct GUIFont* font) {
vita2d_free_texture(font->tex);
vita2d_free_texture(font->icons);
free(font);
}
@ -57,3 +61,49 @@ void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color,
CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2,
1, 1, color);
}
void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
if (icon >= GUI_ICON_MAX) {
return;
}
struct GUIIconMetric metric = defaultIconMetrics[icon];
switch (align & GUI_ALIGN_HCENTER) {
case GUI_ALIGN_HCENTER:
x -= metric.width;
break;
case GUI_ALIGN_RIGHT:
x -= metric.width * 2;
break;
}
switch (align & GUI_ALIGN_VCENTER) {
case GUI_ALIGN_VCENTER:
y -= metric.height;
break;
case GUI_ALIGN_BOTTOM:
y -= metric.height * 2;
break;
}
switch (orient) {
case GUI_ORIENT_HMIRROR:
vita2d_draw_texture_tint_part_scale(font->icons, x, y,
metric.x * 2, metric.y * 2,
metric.width * 2, metric.height * 2,
-1, 1, color);
return;
case GUI_ORIENT_VMIRROR:
vita2d_draw_texture_tint_part_scale(font->icons, x, y,
metric.x * 2, metric.y * 2,
metric.width * 2, metric.height * 2,
1, -1, color);
return;
case GUI_ORIENT_0:
default:
// TOOD: Rotate
vita2d_draw_texture_tint_part(font->icons, x, y,
metric.x * 2, metric.y * 2,
metric.width * 2, metric.height * 2,
color);
break;
}
}

View File

@ -72,7 +72,7 @@ static uint32_t _pollInput(void) {
return input;
}
static enum GUICursorState _pollCursor(int* x, int* y) {
static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
SceTouchData touch;
sceTouchPeek(0, &touch, 1);
if (touch.reportNum < 1) {

View File

@ -15,7 +15,7 @@ source_group("Wii-specific code" FILES ${OS_SRC})
set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE)
set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE)
list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)
list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/icons.c ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/font.c PROPERTIES GENERATED ON)
add_executable(${BINARY_NAME}.elf ${GUI_SRC} main.c)
@ -24,7 +24,12 @@ target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${OS_LIB})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c
COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/wii/font.tpl
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/src/platform/wii/font.tpl
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/src/platform/wii/font.tpl
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c
COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/wii/icons.tpl
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/src/platform/wii/icons.tpl
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(${BINARY_NAME}.dol ALL

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "util/gui/font.h"
#include "util/gui/font-metrics.h"
#include "icons.h"
#include "font.h"
#include <malloc.h>
@ -16,6 +17,7 @@
struct GUIFont {
TPLFile tdf;
TPLFile iconsTdf;
};
struct GUIFont* GUIFontCreate(void) {
@ -32,11 +34,21 @@ struct GUIFont* GUIFontCreate(void) {
}
memcpy(fontTpl, font, font_size);
TPL_OpenTPLFromMemory(&guiFont->tdf, fontTpl, font_size);
void* iconsTpl = memalign(32, icons_size);
if (!iconsTpl) {
TPL_CloseTPLFile(&guiFont->tdf);
free(guiFont);
return 0;
}
memcpy(iconsTpl, icons, icons_size);
TPL_OpenTPLFromMemory(&guiFont->iconsTdf, iconsTpl, icons_size);
return guiFont;
}
void GUIFontDestroy(struct GUIFont* font) {
TPL_CloseTPLFile(&font->tdf);
TPL_CloseTPLFile(&font->iconsTdf);
free(font);
}
@ -89,3 +101,82 @@ void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color,
GX_TexCoord2f32(tx / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
GX_End();
}
void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
if (icon >= GUI_ICON_MAX) {
return;
}
color = (color >> 24) | (color << 8);
GXTexObj tex;
struct GUIFont* ncfont = font;
TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
GX_LoadTexObj(&tex, GX_TEXMAP0);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
struct GUIIconMetric metric = defaultIconMetrics[icon];
switch (align & GUI_ALIGN_HCENTER) {
case GUI_ALIGN_HCENTER:
x -= metric.width;
break;
case GUI_ALIGN_RIGHT:
x -= metric.width * 2;
break;
}
switch (align & GUI_ALIGN_VCENTER) {
case GUI_ALIGN_VCENTER:
y -= metric.height;
break;
case GUI_ALIGN_BOTTOM:
y -= metric.height * 2;
break;
}
float u[4];
float v[4];
switch (orient) {
case GUI_ORIENT_0:
default:
// TODO: Rotations
u[0] = u[3] = metric.x / 256.f;
u[1] = u[2] = (metric.x + metric.width) / 256.f;
v[0] = v[1] = (metric.y + metric.height) / 64.f;
v[2] = v[3] = metric.y / 64.f;
break;
case GUI_ORIENT_HMIRROR:
u[0] = u[3] = (metric.x + metric.width) / 256.f;
u[1] = u[2] = metric.x / 256.f;
v[0] = v[1] = (metric.y + metric.height) / 64.f;
v[2] = v[3] = metric.y / 64.f;
break;
case GUI_ORIENT_VMIRROR:
u[0] = u[3] = metric.x / 256.f;
u[1] = u[2] = (metric.x + metric.width) / 256.f;
v[0] = v[1] = metric.y / 64.f;
v[2] = v[3] = (metric.y + metric.height) / 64.f;
break;
}
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(x, y + metric.height * 2);
GX_Color1u32(color);
GX_TexCoord2f32(u[0], v[0]);
GX_Position2s16(x + metric.width * 2, y + metric.height * 2);
GX_Color1u32(color);
GX_TexCoord2f32(u[1], v[1]);
GX_Position2s16(x + metric.width * 2, y);
GX_Color1u32(color);
GX_TexCoord2f32(u[2], v[2]);
GX_Position2s16(x, y);
GX_Color1u32(color);
GX_TexCoord2f32(u[3], v[3]);
GX_End();
}

View File

@ -59,7 +59,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 enum GUICursorState _pollCursor(unsigned* x, unsigned* y);
static void _guiPrepare(void);
static void _guiFinish(void);
@ -467,7 +467,7 @@ static uint32_t _pollInput(void) {
return keys;
}
static enum GUICursorState _pollCursor(int* x, int* y) {
static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
ir_t ir;
WPAD_IR(0, &ir);
if (!ir.smooth_valid) {

View File

@ -59,7 +59,7 @@ struct GUIParams {
void (*drawStart)(void);
void (*drawEnd)(void);
uint32_t (*pollInput)(void);
enum GUICursorState (*pollCursor)(int* x, int* y);
enum GUICursorState (*pollCursor)(unsigned* x, unsigned* y);
int (*batteryState)(void);
void (*guiPrepare)(void);
void (*guiFinish)(void);
@ -78,7 +78,7 @@ struct GUIParams {
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);
enum GUICursorState GUIPollCursor(struct GUIParams* params, unsigned* x, unsigned* y);
void GUIInvalidateKeys(struct GUIParams* params);
#endif

View File

@ -71,8 +71,8 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
if (params->guiPrepare) {
params->guiPrepare();
}
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font), GUI_TEXT_LEFT, 0xFFFFFFFF, "(scanning for items: %zu)", i);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font) * 2, GUI_TEXT_LEFT, 0xFFFFFFFF, "%s", currentPath);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font), GUI_ALIGN_LEFT, 0xFFFFFFFF, "(scanning for items: %zu)", i);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font) * 2, GUI_ALIGN_LEFT, 0xFFFFFFFF, "%s", currentPath);
if (params->guiFinish) {
params->guiFinish();
}
@ -109,8 +109,8 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
if (params->guiPrepare) {
params->guiPrepare();
}
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font), GUI_TEXT_LEFT, 0xFFFFFFFF, "(scanning item %zu of %zu)", i, items);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font) * 2, GUI_TEXT_LEFT, 0xFFFFFFFF, "%s", currentPath);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font), GUI_ALIGN_LEFT, 0xFFFFFFFF, "(scanning item %zu of %zu)", i, items);
GUIFontPrintf(params->font, 0, GUIFontHeight(params->font) * 2, GUI_ALIGN_LEFT, 0xFFFFFFFF, "%s", currentPath);
if (params->guiFinish) {
params->guiFinish();
}

View File

@ -135,3 +135,21 @@ struct GUIFontGlyphMetric defaultFontMetrics[128] = {
{ 10, 5, { 5, 3, 6, 3 }}, // 0x7E "}"
{ 0, 0, { 0, 0, 0, 0 }}, // 0x7F
};
struct GUIIconMetric defaultIconMetrics[] = {
[GUI_ICON_BATTERY_FULL] = { 0, 0, 32, 16 },
[GUI_ICON_BATTERY_HIGH] = { 32, 0, 32, 16 },
[GUI_ICON_BATTERY_HALF] = { 64, 0, 32, 16 },
[GUI_ICON_BATTERY_LOW] = { 96, 0, 32, 16 },
[GUI_ICON_BATTERY_EMPTY] = { 128, 0, 32, 16 },
[GUI_ICON_SCROLLBAR_BUTTON] = { 6, 16, 4, 5 },
[GUI_ICON_SCROLLBAR_TRACK] = { 23, 16, 2, 16 },
[GUI_ICON_SCROLLBAR_THUMB] = { 38, 16, 4, 16 },
[GUI_ICON_CURSOR] = { 48, 16, 16, 16 },
[GUI_ICON_POINTER] = { 68, 20, 8, 8 },
[GUI_ICON_BUTTON_CIRCLE] = { 2, 34, 12, 11 },
[GUI_ICON_BUTTON_CROSS] = { 18, 34, 12, 11 },
[GUI_ICON_BUTTON_TRIANGLE] = { 34, 34, 12, 11 },
[GUI_ICON_BUTTON_SQUARE] = { 50, 34, 12, 11 },
[GUI_ICON_BUTTON_HOME] = { 66, 34, 16, 16 },
};

View File

@ -9,5 +9,6 @@
#include "util/gui/font.h"
extern struct GUIFontGlyphMetric defaultFontMetrics[];
extern struct GUIIconMetric defaultIconMetrics[];
#endif

View File

@ -15,12 +15,12 @@ unsigned GUIFontSpanWidth(const struct GUIFont* font, const char* text) {
return width;
}
void GUIFontPrint(const struct GUIFont* font, int x, int y, enum GUITextAlignment align, uint32_t color, const char* text) {
switch (align) {
case GUI_TEXT_CENTER:
void GUIFontPrint(const struct GUIFont* font, int x, int y, enum GUIAlignment align, uint32_t color, const char* text) {
switch (align & GUI_ALIGN_HCENTER) {
case GUI_ALIGN_HCENTER:
x -= GUIFontSpanWidth(font, text) / 2;
break;
case GUI_TEXT_RIGHT:
case GUI_ALIGN_RIGHT:
x -= GUIFontSpanWidth(font, text);
break;
default:
@ -34,7 +34,7 @@ void GUIFontPrint(const struct GUIFont* font, int x, int y, enum GUITextAlignmen
}
}
void GUIFontPrintf(const struct GUIFont* font, int x, int y, enum GUITextAlignment align, uint32_t color, const char* text, ...) {
void GUIFontPrintf(const struct GUIFont* font, int x, int y, enum GUIAlignment align, uint32_t color, const char* text, ...) {
char buffer[256];
va_list args;
va_start(args, text);

View File

@ -12,10 +12,46 @@ struct GUIFont;
struct GUIFont* GUIFontCreate(void);
void GUIFontDestroy(struct GUIFont*);
enum GUITextAlignment {
GUI_TEXT_LEFT = 0,
GUI_TEXT_CENTER,
GUI_TEXT_RIGHT
enum GUIAlignment {
GUI_ALIGN_LEFT = 1,
GUI_ALIGN_HCENTER = 3,
GUI_ALIGN_RIGHT = 2,
GUI_ALIGN_TOP = 4,
GUI_ALIGN_VCENTER = 12,
GUI_ALIGN_BOTTOM = 8,
};
enum GUIOrientation {
GUI_ORIENT_0,
GUI_ORIENT_90_CCW,
GUI_ORIENT_180,
GUI_ORIENT_270_CCW,
GUI_ORIENT_VMIRROR,
GUI_ORIENT_HMIRROR,
GUI_ORIENT_90_CW = GUI_ORIENT_270_CCW,
GUI_ORIENT_270_CW = GUI_ORIENT_90_CCW
};
enum GUIIcon {
GUI_ICON_BATTERY_FULL,
GUI_ICON_BATTERY_HIGH,
GUI_ICON_BATTERY_HALF,
GUI_ICON_BATTERY_LOW,
GUI_ICON_BATTERY_EMPTY,
GUI_ICON_SCROLLBAR_THUMB,
GUI_ICON_SCROLLBAR_TRACK,
GUI_ICON_SCROLLBAR_BUTTON,
GUI_ICON_CURSOR,
GUI_ICON_POINTER,
GUI_ICON_BUTTON_CIRCLE,
GUI_ICON_BUTTON_CROSS,
GUI_ICON_BUTTON_TRIANGLE,
GUI_ICON_BUTTON_SQUARE,
GUI_ICON_BUTTON_HOME,
GUI_ICON_MAX,
};
struct GUIFontGlyphMetric {
@ -29,13 +65,21 @@ struct GUIFontGlyphMetric {
} padding;
};
struct GUIIconMetric {
int x;
int y;
int width;
int height;
};
unsigned GUIFontHeight(const struct GUIFont*);
unsigned GUIFontGlyphWidth(const struct GUIFont*, uint32_t glyph);
unsigned GUIFontSpanWidth(const struct GUIFont*, const char* text);
ATTRIBUTE_FORMAT(printf, 6, 7)
void GUIFontPrintf(const struct GUIFont*, int x, int y, enum GUITextAlignment, uint32_t color, const char* text, ...);
void GUIFontPrint(const struct GUIFont*, int x, int y, enum GUITextAlignment, uint32_t color, const char* text);
void GUIFontPrintf(const struct GUIFont*, int x, int y, enum GUIAlignment, uint32_t color, const char* text, ...);
void GUIFontPrint(const struct GUIFont*, int x, int y, enum GUIAlignment, uint32_t color, const char* text);
void GUIFontDrawGlyph(const struct GUIFont*, int x, int y, uint32_t color, uint32_t glyph);
void GUIFontDrawIcon(const struct GUIFont*, int x, int y, enum GUIAlignment, enum GUIOrientation, uint32_t color, enum GUIIcon);
#endif

View File

@ -25,7 +25,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
while (true) {
uint32_t newInput = 0;
GUIPollInput(params, &newInput, 0);
int cx, cy;
unsigned cx, cy;
enum GUICursorState cursor = GUIPollCursor(params, &cx, &cy);
if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) {
@ -71,14 +71,26 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
}
}
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;
if (cx < params->width - 16) {
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;
}
} else if (cursor == GUI_CURSOR_DOWN || cursor == GUI_CURSOR_DRAGGING) {
if (cy <= 2 * lineHeight && cy > lineHeight && menu->index > 0) {
--menu->index;
} else if (cy <= params->height && cy > params->height - lineHeight && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
++menu->index;
} else if (cy <= params->height - lineHeight && cy > 2 * lineHeight) {
size_t location = cy - 2 * lineHeight;
location *= GUIMenuItemListSize(&menu->items);
menu->index = location / (params->height - 3 * lineHeight);
}
menu->index = index + start;
} else {
cursorOverItem = 0;
}
}
@ -117,23 +129,23 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
params->guiPrepare();
}
unsigned y = lineHeight;
GUIFontPrint(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, menu->title);
GUIFontPrint(params->font, 0, y, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->title);
if (menu->subtitle) {
GUIFontPrint(params->font, 0, y * 2, GUI_TEXT_LEFT, 0xFFFFFFFF, menu->subtitle);
GUIFontPrint(params->font, 0, y * 2, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->subtitle);
}
y += 2 * lineHeight;
size_t itemsPerScreen = (params->height - y) / lineHeight;
size_t i;
for (i = start; i < GUIMenuItemListSize(&menu->items); ++i) {
int color = 0xE0A0A0A0;
char bullet = ' ';
if (i == menu->index) {
color = 0xFFFFFFFF;
bullet = '>';
GUIFontDrawIcon(params->font, 2, y, GUI_ALIGN_BOTTOM | GUI_ALIGN_LEFT, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_POINTER);
}
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, i);
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, item->title);
GUIFontPrintf(params->font, 0, y, GUI_ALIGN_LEFT, color, " %s", item->title);
if (item->validStates && item->validStates[item->state]) {
GUIFontPrintf(params->font, params->width, y, GUI_TEXT_RIGHT, color, "%s ", item->validStates[item->state]);
GUIFontPrintf(params->font, params->width, y, GUI_ALIGN_RIGHT, color, "%s ", item->validStates[item->state]);
}
y += lineHeight;
if (y + lineHeight > params->height) {
@ -141,9 +153,26 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
}
}
if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) {
y = 2 * lineHeight;
GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
for (; y < params->height - 16; y += 16) {
GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK);
}
GUIFontDrawIcon(params->font, params->width - 8, y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
size_t top = 2 * lineHeight;
y = menu->index * (y - top - 16) / GUIMenuItemListSize(&menu->items);
GUIFontDrawIcon(params->font, params->width - 8, top + y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_THUMB);
}
GUIDrawBattery(params);
GUIDrawClock(params);
if (cursor != GUI_CURSOR_NOT_PRESENT) {
GUIFontDrawIcon(params->font, cx, cy, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_CURSOR);
}
if (params->guiFinish) {
params->guiFinish();
}
@ -152,7 +181,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
return GUI_MENU_EXIT_CANCEL;
}
enum GUICursorState GUIPollCursor(struct GUIParams* params, int* x, int* y) {
enum GUICursorState GUIPollCursor(struct GUIParams* params, unsigned* x, unsigned* y) {
if (!params->pollCursor) {
return GUI_CURSOR_NOT_PRESENT;
}
@ -207,29 +236,29 @@ void GUIDrawBattery(struct GUIParams* params) {
color |= 0x3030FF;
}
const char* batteryText;
enum GUIIcon batteryIcon;
switch (state & ~BATTERY_CHARGING) {
case BATTERY_EMPTY:
batteryText = "[ ]";
batteryIcon = GUI_ICON_BATTERY_EMPTY;
break;
case BATTERY_LOW:
batteryText = "[I ]";
batteryIcon = GUI_ICON_BATTERY_LOW;
break;
case BATTERY_HALF:
batteryText = "[II ]";
batteryIcon = GUI_ICON_BATTERY_HALF;
break;
case BATTERY_HIGH:
batteryText = "[III ]";
batteryIcon = GUI_ICON_BATTERY_HIGH;
break;
case BATTERY_FULL:
batteryText = "[IIII]";
batteryIcon = GUI_ICON_BATTERY_FULL;
break;
default:
batteryText = "[????]";
batteryIcon = GUI_ICON_BATTERY_EMPTY;
break;
}
GUIFontPrint(params->font, params->width, GUIFontHeight(params->font), GUI_TEXT_RIGHT, color, batteryText);
GUIFontDrawIcon(params->font, params->width, 0, GUI_ALIGN_RIGHT, GUI_ORIENT_0, color, batteryIcon);
}
void GUIDrawClock(struct GUIParams* params) {
@ -238,5 +267,5 @@ void GUIDrawClock(struct GUIParams* params) {
struct tm tm;
localtime_r(&t, &tm);
strftime(buffer, sizeof(buffer), "%H:%M:%S", &tm);
GUIFontPrint(params->font, params->width / 2, GUIFontHeight(params->font), GUI_TEXT_CENTER, 0xFFFFFFFF, buffer);
GUIFontPrint(params->font, params->width / 2, GUIFontHeight(params->font), GUI_ALIGN_HCENTER, 0xFFFFFFFF, buffer);
}