mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-26 00:31:44 +00:00
Refactor HUD model to allow scaling font glyphs
- Should be less pixelation of touch keyboard on large tablet screens
This commit is contained in:
parent
a54a69efcc
commit
f5bbda4c6e
@ -12,6 +12,106 @@
|
||||
#include "glhudmodel.h"
|
||||
#include "glvideo.h"
|
||||
|
||||
// . . .
|
||||
// . x .
|
||||
// . . .
|
||||
typedef struct EightPatchArgs_s {
|
||||
GLModel *parent;
|
||||
unsigned int pixelSize;
|
||||
unsigned int glyphScale;
|
||||
unsigned int fb_h;
|
||||
unsigned int fb_w;
|
||||
unsigned int srcIdx;
|
||||
unsigned int dstIdx;
|
||||
} EightPatchArgs_s;
|
||||
|
||||
// Generates a semi-opaque halo effect around each glyph
|
||||
static void _eightpatch_opaquePixelHaloFilter(const EightPatchArgs_s args) {
|
||||
|
||||
#if USE_RGBA4444
|
||||
# define SEMI_OPAQUE (0x0C << SHIFT_A)
|
||||
#else
|
||||
# define SEMI_OPAQUE (0xC0 << SHIFT_A)
|
||||
#endif
|
||||
|
||||
const unsigned int pixelSize = args.pixelSize;
|
||||
const unsigned int glyphScale = args.glyphScale;
|
||||
const unsigned int fb_w = args.fb_w;
|
||||
const unsigned int fb_h = args.fb_h;
|
||||
const unsigned int srcIdx = args.srcIdx;
|
||||
const unsigned int srcCol = (srcIdx % fb_w);
|
||||
const unsigned int lastCol = (fb_w-1);
|
||||
const unsigned int dstPointStride = pixelSize * glyphScale;
|
||||
const unsigned int dstRowStride = fb_w * dstPointStride;
|
||||
const unsigned int texRowStride = ((fb_w * glyphScale) * (glyphScale/*1 row*/ * glyphScale) * pixelSize);
|
||||
const unsigned int lastPoint = ((fb_w * glyphScale) * (fb_h * glyphScale) * pixelSize);
|
||||
|
||||
uint8_t *texPixels = args.parent->texPixels;
|
||||
const int dstIdx0 = (int)args.dstIdx;
|
||||
const int dstPre0 = dstIdx0 - texRowStride; // negative is okay
|
||||
const int dstPost0 = dstIdx0 + texRowStride;
|
||||
|
||||
// scale glyph data 1x, 2x, ...
|
||||
|
||||
// north pixels
|
||||
if (dstPre0 >= 0) {
|
||||
int dstPre = dstPre0;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstPre+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstPre+=pixelSize) {
|
||||
if (srcCol != 0) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstPre - dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
*((PIXEL_TYPE*)(texPixels + dstPre)) |= SEMI_OPAQUE;
|
||||
if (srcCol < lastCol) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstPre + dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
}
|
||||
dstPre -= dstPointStride;
|
||||
}
|
||||
}
|
||||
|
||||
// west pixel
|
||||
if (srcCol != 0) {
|
||||
int dstIdx = dstIdx0;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstIdx+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstIdx+=pixelSize) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstIdx - dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
dstIdx -= dstPointStride;
|
||||
}
|
||||
}
|
||||
|
||||
// east pixel
|
||||
if (srcCol < lastCol) {
|
||||
int dstIdx = dstIdx0;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstIdx+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstIdx+=pixelSize) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstIdx + dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
dstIdx -= dstPointStride;
|
||||
}
|
||||
}
|
||||
|
||||
// south pixels
|
||||
if (dstPost0 < lastPoint) {
|
||||
int dstPost = dstPost0;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstPost+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstPost+=pixelSize) {
|
||||
if (srcCol != 0) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstPost - dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
*((PIXEL_TYPE*)(texPixels + dstPost)) |= SEMI_OPAQUE;
|
||||
if (srcCol < lastCol) {
|
||||
*((PIXEL_TYPE*)(texPixels + dstPost + dstPointStride)) |= SEMI_OPAQUE;
|
||||
}
|
||||
}
|
||||
dstPost -= dstPointStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void *glhud_createDefault(void) {
|
||||
return glhud_createCustom(sizeof(GLModelHUDElement));
|
||||
}
|
||||
@ -20,6 +120,7 @@ void *glhud_createCustom(unsigned int sizeofModel) {
|
||||
assert(sizeof(GLModelHUDElement) <= sizeofModel);
|
||||
GLModelHUDElement *hudElement = (GLModelHUDElement *)CALLOC(sizeofModel, 1);
|
||||
if (hudElement) {
|
||||
hudElement->glyphMultiplier = 1;
|
||||
hudElement->colorScheme = RED_ON_BLACK;
|
||||
}
|
||||
return hudElement;
|
||||
@ -28,6 +129,8 @@ void *glhud_createCustom(unsigned int sizeofModel) {
|
||||
void glhud_setupDefault(GLModel *parent) {
|
||||
|
||||
GLModelHUDElement *hudElement = (GLModelHUDElement *)parent->custom;
|
||||
assert(hudElement->glyphMultiplier > 0);
|
||||
|
||||
char *submenu = (char *)(hudElement->tpl);
|
||||
const unsigned int cols = hudElement->tplWidth;
|
||||
const unsigned int rows = hudElement->tplHeight;
|
||||
@ -36,71 +139,68 @@ void glhud_setupDefault(GLModel *parent) {
|
||||
// render template into indexed fb
|
||||
interface_plotMessage(fb, hudElement->colorScheme, submenu, cols, rows);
|
||||
|
||||
// Generate OpenGL color from indexed color
|
||||
// generate OpenGL texture/color from indexed color
|
||||
const unsigned int fb_w = hudElement->pixWidth;
|
||||
const unsigned int fb_h = hudElement->pixHeight;
|
||||
const unsigned int count = fb_w * fb_h;
|
||||
const unsigned int countOut = count * sizeof(PIXEL_TYPE);
|
||||
for (unsigned int srcIdx=0, dstIdx=0; srcIdx<count; srcIdx++, dstIdx+=sizeof(PIXEL_TYPE)) {
|
||||
uint8_t index = *(fb + srcIdx);
|
||||
PIXEL_TYPE rgb = (((PIXEL_TYPE)(colormap[index].red) << SHIFT_R) |
|
||||
((PIXEL_TYPE)(colormap[index].green) << SHIFT_G) |
|
||||
((PIXEL_TYPE)(colormap[index].blue) << SHIFT_B));
|
||||
if (rgb == 0 && hudElement->blackIsTransparent) {
|
||||
// make black transparent
|
||||
} else {
|
||||
rgb |= ((PIXEL_TYPE)MAX_SATURATION << SHIFT_A);
|
||||
const unsigned int pixelSize = sizeof(PIXEL_TYPE);
|
||||
const unsigned int glyphScale = hudElement->glyphMultiplier;
|
||||
const unsigned int dstPointStride = pixelSize * glyphScale;
|
||||
const unsigned int dstRowStride = fb_w * dstPointStride;
|
||||
const unsigned int texSubRowStride = dstRowStride * (glyphScale-1);
|
||||
|
||||
LOG("fb_h:%u, fb_w:%u -- texH:%u texW:%u", fb_h, fb_w, parent->texHeight, parent->texWidth);
|
||||
|
||||
do {
|
||||
unsigned int srcIdx = 0;
|
||||
unsigned int texIdx = 0;
|
||||
for (unsigned int i=0; i<fb_h; i++, texIdx+=texSubRowStride) {
|
||||
for (unsigned int j=0; j<fb_w; j++, srcIdx++, texIdx+=dstPointStride) {
|
||||
uint8_t value = *(fb + srcIdx);
|
||||
PIXEL_TYPE rgba = (((PIXEL_TYPE)(colormap[value].red) << SHIFT_R) |
|
||||
((PIXEL_TYPE)(colormap[value].green) << SHIFT_G) |
|
||||
((PIXEL_TYPE)(colormap[value].blue) << SHIFT_B));
|
||||
if (rgba == 0 && hudElement->blackIsTransparent) {
|
||||
// black remains transparent
|
||||
} else {
|
||||
rgba |= ((PIXEL_TYPE)MAX_SATURATION << SHIFT_A);
|
||||
}
|
||||
|
||||
// scale glyph data 1x, 2x, ...
|
||||
unsigned int dstIdx = texIdx;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstIdx+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstIdx+=pixelSize) {
|
||||
*( (PIXEL_TYPE *)(parent->texPixels + dstIdx) ) = rgba;
|
||||
}
|
||||
dstIdx -= dstPointStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
*( (PIXEL_TYPE*)(parent->texPixels + dstIdx) ) = rgb;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
// Second pass to generate a semi-opaque halo effect around each glyph
|
||||
if (hudElement->opaquePixelHalo) {
|
||||
for (int // -negative index values allowed here ...
|
||||
srcIdx=0, dstPre=-((fb_w+1)*sizeof(PIXEL_TYPE)), dstIdx=0, dstPost=((fb_w-1)*sizeof(PIXEL_TYPE));
|
||||
srcIdx<count;
|
||||
srcIdx++, dstPre+=sizeof(PIXEL_TYPE), dstIdx+=sizeof(PIXEL_TYPE), dstPost+=sizeof(PIXEL_TYPE))
|
||||
{
|
||||
uint8_t index = *(fb + srcIdx);
|
||||
PIXEL_TYPE rgb = (((PIXEL_TYPE)(colormap[index].red) << SHIFT_R) |
|
||||
((PIXEL_TYPE)(colormap[index].green) << SHIFT_G) |
|
||||
((PIXEL_TYPE)(colormap[index].blue) << SHIFT_B));
|
||||
if (!rgb) {
|
||||
continue;
|
||||
}
|
||||
unsigned int srcIdx = 0;
|
||||
unsigned int texIdx = 0;
|
||||
for (unsigned int i=0; i<fb_h; i++, texIdx+=texSubRowStride) {
|
||||
for (unsigned int j=0; j<fb_w; j++, srcIdx++, texIdx+=dstPointStride) {
|
||||
uint8_t value = *(fb + srcIdx);
|
||||
PIXEL_TYPE rgb = (((PIXEL_TYPE)(colormap[value].red) << SHIFT_R) |
|
||||
((PIXEL_TYPE)(colormap[value].green) << SHIFT_G) |
|
||||
((PIXEL_TYPE)(colormap[value].blue) << SHIFT_B));
|
||||
|
||||
#if USE_RGBA4444
|
||||
#define SEMI_OPAQUE (0x0C << SHIFT_A)
|
||||
#else
|
||||
#define SEMI_OPAQUE (0xC0 << SHIFT_A)
|
||||
#endif
|
||||
const unsigned int col = (srcIdx % fb_w);
|
||||
unsigned int dstIdx = texIdx;
|
||||
|
||||
if (dstPre >= 0) { // north pixels
|
||||
if (col != 0) {
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPre)) |= SEMI_OPAQUE;
|
||||
}
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPre + sizeof(PIXEL_TYPE) )) |= SEMI_OPAQUE;
|
||||
if (col < fb_w-1) {
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPre + (2*sizeof(PIXEL_TYPE)) )) |= SEMI_OPAQUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (col != 0) { // west pixel
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstIdx - sizeof(PIXEL_TYPE) )) |= SEMI_OPAQUE;
|
||||
}
|
||||
|
||||
if (col < fb_w-1) { // east pixel
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstIdx + sizeof(PIXEL_TYPE) )) |= SEMI_OPAQUE;
|
||||
}
|
||||
|
||||
if (dstPost < countOut) { // south pixels
|
||||
if (col != 0) {
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPost)) |= SEMI_OPAQUE;
|
||||
}
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPost + sizeof(PIXEL_TYPE) )) |= SEMI_OPAQUE;
|
||||
if (col < fb_w-1) {
|
||||
*((PIXEL_TYPE*)(parent->texPixels + dstPost + (2*sizeof(PIXEL_TYPE)) )) |= SEMI_OPAQUE;
|
||||
// perform "eight patch" on adjacent pixels
|
||||
if (rgb) {
|
||||
EightPatchArgs_s args = {
|
||||
.parent = parent,
|
||||
.pixelSize = pixelSize,
|
||||
.glyphScale = glyphScale,
|
||||
.fb_h = fb_h,
|
||||
.fb_w = fb_w,
|
||||
.srcIdx = srcIdx,
|
||||
.dstIdx = dstIdx,
|
||||
};
|
||||
_eightpatch_opaquePixelHaloFilter(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,9 @@
|
||||
unsigned int tplHeight; /* template height */ \
|
||||
\
|
||||
uint8_t *pixels; /* raw indexed data */ \
|
||||
unsigned int pixWidth; /* FB width -- FIXME TODO : this is really the same as GLModel.texWidth */ \
|
||||
unsigned int pixHeight; /* FB height -- FIXME TODO : this is really the same as GLModel.texHeight */ \
|
||||
unsigned int pixWidth; /* FB width -- this is the same as GLModel.texWidth if glyphMultiplier is 1 */ \
|
||||
unsigned int pixHeight; /* FB height -- this is the same as GLModel.texHeight if glyphMultiplier is 1 */ \
|
||||
unsigned int glyphMultiplier; \
|
||||
\
|
||||
interface_colorscheme_t colorScheme; \
|
||||
bool blackIsTransparent; \
|
||||
|
@ -37,8 +37,8 @@
|
||||
#define MAINROW 4 // main keyboard row offset
|
||||
#define SWITCHCOL 0
|
||||
|
||||
#define KBD_FB_WIDTH (KBD_TEMPLATE_COLS * FONT80_WIDTH_PIXELS)
|
||||
#define KBD_FB_HEIGHT (KBD_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS)
|
||||
#define KBD_FB_WIDTH (KBD_TEMPLATE_COLS * FONT80_WIDTH_PIXELS) // 10 * 7 == 70
|
||||
#define KBD_FB_HEIGHT (KBD_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS) // 8 * 16 == 128
|
||||
|
||||
#define KBD_OBJ_W 2.0
|
||||
#define KBD_OBJ_H 2.0
|
||||
@ -129,27 +129,34 @@ static struct {
|
||||
|
||||
bool ctrlPressed;
|
||||
|
||||
unsigned int glyphMultiplier;
|
||||
|
||||
struct timespec timingBegin;
|
||||
} kbd = { 0 };
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Misc internal methods
|
||||
|
||||
#warning FIXME TODO ... make this a generic GLModelHUDElement function
|
||||
static void _rerender_character(int col, int row) {
|
||||
GLModelHUDKeyboard *hudKeyboard = (GLModelHUDKeyboard *)(kbd.model->custom);
|
||||
|
||||
// re-generate texture from indexed color
|
||||
const unsigned int colCount = 1;
|
||||
const unsigned int pixCharsWidth = FONT80_WIDTH_PIXELS*colCount;
|
||||
const unsigned int rowStride = hudKeyboard->pixWidth - pixCharsWidth;
|
||||
unsigned int srcIdx = (row * hudKeyboard->pixWidth * FONT_HEIGHT_PIXELS) + (col * FONT80_WIDTH_PIXELS);
|
||||
unsigned int dstIdx = srcIdx * sizeof(PIXEL_TYPE);
|
||||
// In English, this changes one glyph within the keyboard texture data to be the (un)selected color. It handles
|
||||
// scaling from indexed color to RGBA8888 (4x) and then possibly scaling to 2x or greater.
|
||||
|
||||
for (unsigned int i=0; i<FONT_HEIGHT_PIXELS; i++) {
|
||||
for (unsigned int j=0; j<pixCharsWidth; j++) {
|
||||
const unsigned int fb_w = hudKeyboard->pixWidth;
|
||||
const unsigned int pixelSize = sizeof(PIXEL_TYPE);
|
||||
const unsigned int glyphScale = hudKeyboard->glyphMultiplier;
|
||||
const unsigned int dstPointStride = pixelSize * glyphScale;
|
||||
const unsigned int dstRowStride = fb_w * dstPointStride;
|
||||
const unsigned int texSubRowStride = dstRowStride + (dstRowStride * (glyphScale-1));
|
||||
const unsigned int indexedIdx = (row * fb_w * FONT_HEIGHT_PIXELS) + (col * FONT80_WIDTH_PIXELS);
|
||||
unsigned int texIdx = ((row * fb_w * FONT_HEIGHT_PIXELS * /*1 row:*/glyphScale) + (col * FONT80_WIDTH_PIXELS)) * dstPointStride;
|
||||
|
||||
// HACK : red <-> green swap
|
||||
PIXEL_TYPE rgba = *((PIXEL_TYPE *)(kbd.model->texPixels + dstIdx));
|
||||
for (unsigned int i=0; i<FONT_HEIGHT_PIXELS; i++, texIdx+=texSubRowStride) {
|
||||
for (unsigned int j=0; j<FONT80_WIDTH_PIXELS; j++, texIdx+=dstPointStride) {
|
||||
// HACK : red <-> green swap of texture data
|
||||
PIXEL_TYPE rgba = *((PIXEL_TYPE *)(kbd.model->texPixels + texIdx));
|
||||
PIXEL_TYPE r = (rgba >> SHIFT_R) & MAX_SATURATION;
|
||||
PIXEL_TYPE g = (rgba >> SHIFT_G) & MAX_SATURATION;
|
||||
#if USE_RGBA4444
|
||||
@ -157,13 +164,16 @@ static void _rerender_character(int col, int row) {
|
||||
#else
|
||||
rgba = ( ((rgba>>SHIFT_B)<<SHIFT_B) | (r << SHIFT_G) | (g << SHIFT_R) );
|
||||
#endif
|
||||
*( (PIXEL_TYPE *)(kbd.model->texPixels + dstIdx) ) = rgba;
|
||||
|
||||
srcIdx += 1;
|
||||
dstIdx += sizeof(PIXEL_TYPE);
|
||||
// scale texture data 1x, 2x, ...
|
||||
unsigned int dstIdx = texIdx;
|
||||
for (unsigned int k=0; k<glyphScale; k++, dstIdx+=dstRowStride) {
|
||||
for (unsigned int l=0; l<glyphScale; l++, dstIdx+=pixelSize) {
|
||||
*( (PIXEL_TYPE *)(kbd.model->texPixels + dstIdx) ) = rgba;
|
||||
}
|
||||
dstIdx -= dstPointStride;
|
||||
}
|
||||
}
|
||||
srcIdx += rowStride;
|
||||
dstIdx = srcIdx * sizeof(PIXEL_TYPE);
|
||||
texIdx -= (FONT80_WIDTH_PIXELS * dstPointStride);
|
||||
}
|
||||
|
||||
kbd.model->texDirty = true;
|
||||
@ -464,6 +474,7 @@ static void *_create_touchkbd_hud(void) {
|
||||
if (hudKeyboard) {
|
||||
hudKeyboard->blackIsTransparent = true;
|
||||
hudKeyboard->opaquePixelHalo = true;
|
||||
hudKeyboard->glyphMultiplier = kbd.glyphMultiplier;
|
||||
}
|
||||
return hudKeyboard;
|
||||
}
|
||||
@ -498,7 +509,9 @@ static void gltouchkbd_setup(void) {
|
||||
|
||||
gltouchkbd_shutdown();
|
||||
|
||||
kbd.model = mdlCreateQuad(-1.0, -1.0, KBD_OBJ_W, KBD_OBJ_H, MODEL_DEPTH, KBD_FB_WIDTH, KBD_FB_HEIGHT, (GLCustom){
|
||||
GLsizei texW = KBD_FB_WIDTH * kbd.glyphMultiplier;
|
||||
GLsizei texH = KBD_FB_HEIGHT * kbd.glyphMultiplier;
|
||||
kbd.model = mdlCreateQuad(-1.0, -1.0, KBD_OBJ_W, KBD_OBJ_H, MODEL_DEPTH, texW, texH, (GLCustom){
|
||||
.create = &_create_touchkbd_hud,
|
||||
.setup = &_setup_touchkbd_hud,
|
||||
.destroy = &_destroy_touchkbd_hud,
|
||||
@ -974,6 +987,8 @@ static void _init_gltouchkbd(void) {
|
||||
kbd.ctrlCol = DEFAULT_CTRL_COL;
|
||||
kbd.ctrlRow = CTRLROW;
|
||||
|
||||
kbd.glyphMultiplier = 1;
|
||||
|
||||
glnode_registerNode(RENDER_LOW, (GLNode){
|
||||
.setup = &gltouchkbd_setup,
|
||||
.shutdown = &gltouchkbd_shutdown,
|
||||
|
@ -71,6 +71,7 @@ static struct {
|
||||
|
||||
static struct {
|
||||
GLModel *model;
|
||||
unsigned int glyphMultiplier;
|
||||
bool topLeftShowing;
|
||||
bool topRightShowing;
|
||||
} menu = { 0 };
|
||||
@ -356,6 +357,7 @@ static void *_create_touchmenu(void) {
|
||||
if (hudMenu) {
|
||||
hudMenu->blackIsTransparent = true;
|
||||
hudMenu->opaquePixelHalo = true;
|
||||
hudMenu->glyphMultiplier = menu.glyphMultiplier;
|
||||
}
|
||||
return hudMenu;
|
||||
}
|
||||
@ -376,7 +378,10 @@ static void gltouchmenu_setup(void) {
|
||||
LOG("gltouchmenu_setup ...");
|
||||
|
||||
mdlDestroyModel(&menu.model);
|
||||
menu.model = mdlCreateQuad(-1.0, 1.0-MENU_OBJ_H, MENU_OBJ_W, MENU_OBJ_H, MODEL_DEPTH, MENU_FB_WIDTH, MENU_FB_HEIGHT, (GLCustom){
|
||||
|
||||
GLsizei texW = MENU_FB_WIDTH * menu.glyphMultiplier;
|
||||
GLsizei texH = MENU_FB_HEIGHT * menu.glyphMultiplier;
|
||||
menu.model = mdlCreateQuad(-1.0, 1.0-MENU_OBJ_H, MENU_OBJ_W, MENU_OBJ_H, MODEL_DEPTH, texW, texH, (GLCustom){
|
||||
.create = &_create_touchmenu,
|
||||
.setup = &_setup_touchmenu,
|
||||
.destroy = &_destroy_touchmenu,
|
||||
@ -552,6 +557,8 @@ static void _init_gltouchmenu(void) {
|
||||
interface_setTouchMenuEnabled = &gltouchmenu_setTouchMenuEnabled;
|
||||
interface_setTouchMenuVisibility = &gltouchmenu_setTouchMenuVisibility;
|
||||
|
||||
menu.glyphMultiplier = 1;
|
||||
|
||||
glnode_registerNode(RENDER_TOP, (GLNode){
|
||||
.setup = &gltouchmenu_setup,
|
||||
.shutdown = &gltouchmenu_shutdown,
|
||||
|
Loading…
Reference in New Issue
Block a user