mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-06-01 13:41:28 +00:00
First cut at allowing portrait mode (on mobile devices)
This commit is contained in:
parent
70afe71c82
commit
5354b0cfd5
|
@ -66,6 +66,7 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "json_parse.h"
|
||||
#include "vm.h"
|
||||
#include "timing.h"
|
||||
#include "cpu.h"
|
||||
|
|
|
@ -1180,8 +1180,8 @@ void video_shutdown(bool emulatorShuttingDown) {
|
|||
render_thread_id = 0;
|
||||
}
|
||||
|
||||
void video_reshape(int w, int h) {
|
||||
video_backend->reshape(w, h);
|
||||
void video_reshape(int w, int h, bool landscape) {
|
||||
video_backend->reshape(w, h, landscape);
|
||||
}
|
||||
|
||||
void video_render(void) {
|
||||
|
|
|
@ -71,7 +71,7 @@ void _video_setRenderThread(pthread_t id);
|
|||
/*
|
||||
* Reshape the display to particular dimensions.
|
||||
*/
|
||||
void video_reshape(int w, int h);
|
||||
void video_reshape(int w, int h, bool landscape);
|
||||
|
||||
/*
|
||||
* Setup the display. This may be called multiple times in a run, and is
|
||||
|
|
|
@ -22,6 +22,7 @@ bool (*interface_isTouchMenuAvailable)(void) = NULL;
|
|||
void (*interface_setTouchMenuEnabled)(bool enabled) = NULL;
|
||||
void (*interface_setTouchMenuVisibility)(float inactiveAlpha, float activeAlpha) = NULL;
|
||||
void (*interface_setGlyphScale)(int glyphScale) = NULL;
|
||||
void (*(*interface_getModelDataSetter)(interface_device_t device))(const char *jsonData) = NULL;
|
||||
#endif
|
||||
|
||||
// 2015/04/12 : This was legacy code for rendering the menu interfaces on desktop Linux. Portions here are resurrected
|
||||
|
|
|
@ -46,9 +46,13 @@ void interface_plotMessage(uint8_t *fb, interface_colorscheme_t cs, char *messag
|
|||
#if INTERFACE_TOUCH
|
||||
typedef enum interface_device_t {
|
||||
TOUCH_DEVICE_NONE = 0,
|
||||
TOUCH_DEVICE_FRAMEBUFFER = 0,
|
||||
TOUCH_DEVICE_JOYSTICK,
|
||||
TOUCH_DEVICE_JOYSTICK_KEYPAD,
|
||||
TOUCH_DEVICE_KEYBOARD,
|
||||
TOUCH_DEVICE_TOPMENU,
|
||||
TOUCH_DEVICE_ALERT,
|
||||
// ...
|
||||
TOUCH_DEVICE_DEVICE_MAX,
|
||||
} interface_device_t;
|
||||
|
||||
|
@ -90,6 +94,9 @@ extern void (*interface_setTouchMenuVisibility)(float inactiveAlpha, float activ
|
|||
|
||||
// set a finer-grained font size (if glyphScale > 1)
|
||||
extern void (*interface_setGlyphScale)(int glyphScale);
|
||||
|
||||
// get model-specific functions
|
||||
extern void (*(*interface_getModelDataSetter)(interface_device_t device))(const char *jsonData);
|
||||
#endif
|
||||
|
||||
#define EXT_GZ ".gz"
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#define MODEL_DEPTH -0.0625
|
||||
|
||||
#define ALERT_MODEL_W 0.7
|
||||
#define ALERT_MODEL_H 0.7
|
||||
|
||||
static bool isEnabled = true;
|
||||
static pthread_mutex_t messageMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static char *nextMessage = NULL;
|
||||
|
@ -21,6 +24,7 @@ static unsigned int nextMessageCols = 0;
|
|||
static unsigned int nextMessageRows = 0;
|
||||
static struct timespec messageTimingBegin = { 0 };
|
||||
static GLModel *messageModel = NULL;
|
||||
static GLfloat landscapeScale = 1.f;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -58,12 +62,13 @@ static void _alertToModel(char *message, unsigned int messageCols, unsigned int
|
|||
const unsigned int fbWidth = (messageCols * FONT80_WIDTH_PIXELS);
|
||||
const unsigned int fbHeight = (messageRows * FONT_HEIGHT_PIXELS);
|
||||
|
||||
GLfloat modelHeight = (ALERT_MODEL_H * landscapeScale);
|
||||
messageModel = mdlCreateQuad((GLModelParams_s){
|
||||
.skew_x = -0.3,
|
||||
.skew_y = -0.3,
|
||||
.skew_x = -1.0 + ALERT_MODEL_W,
|
||||
.skew_y = 1.0 - modelHeight,
|
||||
.z = MODEL_DEPTH,
|
||||
.obj_w = 0.7,
|
||||
.obj_h = 0.7,
|
||||
.obj_w = ALERT_MODEL_W,
|
||||
.obj_h = (ALERT_MODEL_H * landscapeScale),
|
||||
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
|
||||
.tex_w = fbWidth,
|
||||
.tex_h = fbHeight,
|
||||
|
@ -196,8 +201,9 @@ static void alert_render(void) {
|
|||
glhud_renderDefault(messageModel);
|
||||
}
|
||||
|
||||
static void alert_reshape(int w, int h) {
|
||||
// no-op
|
||||
static void alert_reshape(int w, int h, bool landscape) {
|
||||
swizzleDimensions(&w, &h, landscape);
|
||||
landscapeScale = landscape ? 1.f : ((GLfloat)w/h);
|
||||
}
|
||||
|
||||
#if INTERFACE_TOUCH
|
||||
|
@ -380,7 +386,9 @@ static void _init_glalert(void) {
|
|||
.render = &alert_render,
|
||||
.reshape = &alert_reshape,
|
||||
#if INTERFACE_TOUCH
|
||||
.type = TOUCH_DEVICE_ALERT,
|
||||
.onTouchEvent = &alert_onTouchEvent,
|
||||
.setData = NULL,
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ static void _glnode_initGLUTPre(void) {
|
|||
}
|
||||
|
||||
static void _glnode_reshapeGLUT(int w, int h) {
|
||||
video_reshape(w, h);
|
||||
video_reshape(w, h, /*landscape:*/true);
|
||||
}
|
||||
|
||||
static void _glnode_initGLUTPost(void) {
|
||||
|
@ -202,10 +202,10 @@ static void glnode_renderNodes(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void glnode_reshapeNodes(int w, int h) {
|
||||
static void glnode_reshapeNodes(int w, int h, bool landscape) {
|
||||
glnode_array_node_s *p = head;
|
||||
while (p) {
|
||||
p->node.reshape(w, h);
|
||||
p->node.reshape(w, h, landscape);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +224,17 @@ static int64_t glnode_onTouchEvent(interface_touch_event_t action, int pointer_c
|
|||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void (*glnode_getModelDataSetter(interface_device_t type))(const char *jsonData) {
|
||||
glnode_array_node_s *p = head;
|
||||
while (p) {
|
||||
if (p->node.type == type) {
|
||||
return p->node.setData;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void glnode_mainLoop(void) {
|
||||
|
@ -256,5 +267,6 @@ static void _init_glnode_manager(void) {
|
|||
|
||||
#if INTERFACE_TOUCH
|
||||
interface_onTouchEvent = &glnode_onTouchEvent;
|
||||
interface_getModelDataSetter = &glnode_getModelDataSetter;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
// TODO: implement 3D CRT object, possibly with perspective drawing?
|
||||
#define PERSPECTIVE 0
|
||||
|
||||
#define PREF_PORTRAIT_HEIGHT_SCALE "portraitHeightScale"
|
||||
#define PREF_PORTRAIT_POSITION_SCALE "portraitPositionScale"
|
||||
|
||||
enum {
|
||||
TEXTURE_ID_FRAMEBUFFER=0,
|
||||
TEXTURE_ID_MESSAGE,
|
||||
|
@ -97,14 +100,25 @@ typedef struct GLNode {
|
|||
void (*setup)(void);
|
||||
void (*shutdown)(void);
|
||||
void (*render)(void);
|
||||
void (*reshape)(int w, int h, bool landscape);
|
||||
#if INTERFACE_TOUCH
|
||||
interface_device_t type;
|
||||
int64_t (*onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords);
|
||||
void (*setData)(const char *jsonData);
|
||||
#endif
|
||||
void (*reshape)(int w, int h);
|
||||
} GLNode;
|
||||
|
||||
// registers a node with manager
|
||||
void glnode_registerNode(glnode_render_order_t order, GLNode node);
|
||||
|
||||
// swizzle width/height if they don't match landscape/portrait
|
||||
static void inline swizzleDimensions(int *w, int *h, bool landscape) {
|
||||
if ( (landscape && (*w < *h)) || (!landscape && (*w > *h)) ) {
|
||||
int x = *w;
|
||||
*w = *h;
|
||||
*h = x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // whole file
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ static struct {
|
|||
int buttonY;
|
||||
int buttonYMax;
|
||||
|
||||
// Are we in landscape mode
|
||||
bool landscape;
|
||||
|
||||
// TODO FIXME : support 2-players!
|
||||
} touchport = { 0 };
|
||||
|
||||
|
@ -543,41 +546,29 @@ static void gltouchjoy_render(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void gltouchjoy_reshape(int w, int h) {
|
||||
LOG("gltouchjoy_reshape(%d, %d)", w, h);
|
||||
static void gltouchjoy_reshape(int w, int h, bool landscape) {
|
||||
LOG("w:%d h:%d landscape:%d", w, h, landscape);
|
||||
|
||||
touchport.landscape = landscape;
|
||||
swizzleDimensions(&w, &h, landscape);
|
||||
touchport.width = w;
|
||||
touchport.height = h;
|
||||
|
||||
touchport.axisY = 0;
|
||||
touchport.axisYMax = h;
|
||||
touchport.buttonY = 0;
|
||||
touchport.buttonYMax = h;
|
||||
|
||||
if (joyglobals.axisIsOnLeft) {
|
||||
touchport.axisX = 0;
|
||||
touchport.axisY = 0;
|
||||
touchport.buttonY = 0;
|
||||
|
||||
if (w >= touchport.width) {
|
||||
touchport.width = w;
|
||||
touchport.axisXMax = (w * joyglobals.screenDivider);
|
||||
touchport.buttonX = (w * joyglobals.screenDivider);
|
||||
touchport.buttonXMax = w;
|
||||
}
|
||||
if (h >= touchport.height) {
|
||||
touchport.height = h;
|
||||
touchport.axisYMax = h;
|
||||
touchport.buttonYMax = h;
|
||||
}
|
||||
touchport.axisXMax = (w * joyglobals.screenDivider);
|
||||
touchport.buttonX = (w * joyglobals.screenDivider);
|
||||
touchport.buttonXMax = w;
|
||||
} else {
|
||||
touchport.buttonX = 0;
|
||||
touchport.buttonY = 0;
|
||||
touchport.axisY = 0;
|
||||
|
||||
if (w >= touchport.width) {
|
||||
touchport.width = w;
|
||||
touchport.buttonXMax = (w * joyglobals.screenDivider);
|
||||
touchport.axisX = (w * joyglobals.screenDivider);
|
||||
touchport.axisXMax = w;
|
||||
}
|
||||
if (h >= touchport.height) {
|
||||
touchport.height = h;
|
||||
touchport.buttonYMax = h;
|
||||
touchport.axisYMax = h;
|
||||
}
|
||||
touchport.buttonXMax = (w * joyglobals.screenDivider);
|
||||
touchport.axisX = (w * joyglobals.screenDivider);
|
||||
touchport.axisXMax = w;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -941,22 +932,20 @@ static void gltouchjoy_setTouchAxisTypes(uint8_t rosetteChars[(ROSETTE_ROWS * RO
|
|||
static void gltouchjoy_setScreenDivision(float screenDivider) {
|
||||
joyglobals.screenDivider = screenDivider;
|
||||
// force reshape here to apply changes ...
|
||||
gltouchjoy_reshape(touchport.width, touchport.height);
|
||||
gltouchjoy_reshape(touchport.width, touchport.height, touchport.landscape);
|
||||
}
|
||||
|
||||
static void gltouchjoy_setAxisOnLeft(bool axisIsOnLeft) {
|
||||
joyglobals.axisIsOnLeft = axisIsOnLeft;
|
||||
// force reshape here to apply changes ...
|
||||
gltouchjoy_reshape(touchport.width, touchport.height);
|
||||
gltouchjoy_reshape(touchport.width, touchport.height, touchport.landscape);
|
||||
}
|
||||
|
||||
static void gltouchjoy_beginCalibration(void) {
|
||||
video_clear();
|
||||
joyglobals.isCalibrating = true;
|
||||
}
|
||||
|
||||
static void gltouchjoy_endCalibration(void) {
|
||||
video_redraw();
|
||||
joyglobals.isCalibrating = false;
|
||||
}
|
||||
|
||||
|
@ -1039,11 +1028,13 @@ static void _init_gltouchjoy(void) {
|
|||
joydriver_isCalibrating = &gltouchjoy_isCalibrating;
|
||||
|
||||
glnode_registerNode(RENDER_LOW, (GLNode){
|
||||
.type = TOUCH_DEVICE_JOYSTICK,
|
||||
.setup = &gltouchjoy_setup,
|
||||
.shutdown = &gltouchjoy_shutdown,
|
||||
.render = &gltouchjoy_render,
|
||||
.reshape = &gltouchjoy_reshape,
|
||||
.onTouchEvent = &gltouchjoy_onTouchEvent,
|
||||
.setData = NULL,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include "video/glhudmodel.h"
|
||||
#include "video/glnode.h"
|
||||
#include "json_parse.h"
|
||||
|
||||
#if !INTERFACE_TOUCH
|
||||
#error this is a touch interface module, possibly you mean to not compile this at all?
|
||||
|
@ -26,7 +25,7 @@
|
|||
|
||||
#define MODEL_DEPTH -1/32.f
|
||||
|
||||
#define KBD_TEMPLATE_COLS 10
|
||||
#define KBD_TEMPLATE_COLS 10 // 10 cols for a mobile keyboard in portrait seems to be a defacto standard across iOS/Android ...
|
||||
#define KBD_TEMPLATE_ROWS 8
|
||||
|
||||
#define DEFAULT_CTRL_COL 2
|
||||
|
@ -38,8 +37,8 @@
|
|||
#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
|
||||
#define KBD_OBJ_W GL_MODEL_MAX // model width fits screen
|
||||
#define KBD_OBJ_H_LANDSCAPE GL_MODEL_MAX
|
||||
|
||||
static bool isAvailable = false; // Were there any OpenGL/memory errors on gltouchkbd initialization?
|
||||
static bool isEnabled = true; // Does player want touchkbd enabled?
|
||||
|
@ -108,6 +107,11 @@ static struct {
|
|||
|
||||
int kbdW;
|
||||
int kbdH;
|
||||
|
||||
// raw device dimensions
|
||||
int rawWidth;
|
||||
int rawHeight;
|
||||
int isLandscape;
|
||||
} touchport = { 0 };
|
||||
|
||||
// keyboard variables
|
||||
|
@ -115,6 +119,10 @@ static struct {
|
|||
static struct {
|
||||
GLModel *model;
|
||||
|
||||
GLfloat modelHeight;
|
||||
GLfloat modelSkewY;
|
||||
bool modelDirty;
|
||||
|
||||
int selectedCol;
|
||||
int selectedRow;
|
||||
|
||||
|
@ -124,6 +132,8 @@ static struct {
|
|||
bool ctrlPressed;
|
||||
|
||||
unsigned int glyphMultiplier;
|
||||
float portraitHeightScale;
|
||||
float portraitPositionScale;
|
||||
|
||||
struct timespec timingBegin;
|
||||
|
||||
|
@ -176,6 +186,29 @@ static void _rerender_character(int col, int row) {
|
|||
kbd.model->texDirty = true;
|
||||
}
|
||||
|
||||
// non-destructively adjust model height/position
|
||||
static void _reset_model(void) {
|
||||
|
||||
/* 2...3
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* 0...1
|
||||
*/
|
||||
const GLfloat skew_x = -GL_MODEL_HALF;
|
||||
const GLfloat skew_y = kbd.modelSkewY;
|
||||
const GLfloat obj_w = KBD_OBJ_W;
|
||||
const GLfloat obj_h = kbd.modelHeight;
|
||||
|
||||
GLfloat *quad = (GLfloat *)(kbd.model->positions);
|
||||
quad[0 +0] = skew_x; quad[0 +1] = skew_y;
|
||||
quad[4 +0] = skew_x+obj_w; quad[4 +1] = skew_y;
|
||||
quad[8 +0] = skew_x; quad[8 +1] = skew_y+obj_h;
|
||||
quad[12+0] = skew_x+obj_w; quad[12+1] = skew_y+obj_h;
|
||||
|
||||
kbd.modelDirty = true;
|
||||
}
|
||||
|
||||
static inline void _rerender_selected(int col, int row) {
|
||||
if ((col >= 0) && (row >= 0)) {
|
||||
_rerender_character(col, row);
|
||||
|
@ -481,12 +514,12 @@ static void gltouchkbd_setup(void) {
|
|||
gltouchkbd_shutdown();
|
||||
|
||||
kbd.model = mdlCreateQuad((GLModelParams_s){
|
||||
.skew_x = -1.0,
|
||||
.skew_y = -1.0,
|
||||
.skew_x = -GL_MODEL_HALF,
|
||||
.skew_y = kbd.modelSkewY,
|
||||
.z = MODEL_DEPTH,
|
||||
.obj_w = KBD_OBJ_W,
|
||||
.obj_h = KBD_OBJ_H,
|
||||
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
|
||||
.obj_h = kbd.modelHeight,
|
||||
.positionUsageHint = GL_DYNAMIC_DRAW, // positions might change
|
||||
.tex_w = KBD_FB_WIDTH * kbd.glyphMultiplier,
|
||||
.tex_h = KBD_FB_HEIGHT * kbd.glyphMultiplier,
|
||||
.texcoordUsageHint = GL_DYNAMIC_DRAW, // but key texture does
|
||||
|
@ -546,28 +579,64 @@ static void gltouchkbd_render(void) {
|
|||
_HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHKBD, kbd.model->textureName);
|
||||
glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, kbd.model->texWidth, kbd.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, kbd.model->texPixels);
|
||||
}
|
||||
if (kbd.modelDirty) {
|
||||
kbd.modelDirty = false;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, kbd.model->posBufferName);
|
||||
glBufferData(GL_ARRAY_BUFFER, kbd.model->positionArraySize, kbd.model->positions, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
glUniform1i(texSamplerLoc, TEXTURE_ID_TOUCHKBD);
|
||||
glhud_renderDefault(kbd.model);
|
||||
}
|
||||
}
|
||||
|
||||
static void gltouchkbd_reshape(int w, int h) {
|
||||
LOG("gltouchkbd_reshape(%d, %d)", w, h);
|
||||
static void gltouchkbd_reshape(int w, int h, bool landscape) {
|
||||
LOG("w:%d h:%d landscape:%d", w, h, landscape);
|
||||
|
||||
touchport.rawWidth = w;
|
||||
touchport.rawHeight = h;
|
||||
touchport.isLandscape = landscape;
|
||||
|
||||
touchport.kbdX = 0;
|
||||
|
||||
if (w > touchport.width) {
|
||||
touchport.width = w;
|
||||
touchport.kbdXMax = w * (KBD_OBJ_W/2.f);
|
||||
}
|
||||
if (h > touchport.height) {
|
||||
touchport.height = h;
|
||||
touchport.kbdY = h * (1.f - (KBD_OBJ_H/2.f));
|
||||
touchport.kbdYMax = h;
|
||||
}
|
||||
swizzleDimensions(&w, &h, landscape);
|
||||
touchport.width = w;
|
||||
touchport.height = h;
|
||||
|
||||
kbd.modelHeight = landscape ? KBD_OBJ_H_LANDSCAPE : (GL_MODEL_MAX * kbd.portraitHeightScale);
|
||||
kbd.modelSkewY = -GL_MODEL_HALF + ((GL_MODEL_MAX - kbd.modelHeight) * kbd.portraitPositionScale);
|
||||
|
||||
touchport.kbdXMax = w * (KBD_OBJ_W/GL_MODEL_MAX);
|
||||
|
||||
touchport.kbdY = h * (GL_MODEL_HALF - (kbd.modelHeight/GL_MODEL_MAX));
|
||||
touchport.kbdY = h * ((GL_MODEL_MAX - (kbd.modelSkewY + GL_MODEL_HALF + kbd.modelHeight)) / GL_MODEL_MAX);
|
||||
touchport.kbdYMax = h * ((GL_MODEL_MAX - (kbd.modelSkewY + GL_MODEL_HALF)) / GL_MODEL_MAX);
|
||||
|
||||
LOG("modelHeight:%f modelSkewY:%f kbdY:%d kbdYMax:%d", kbd.modelHeight, kbd.modelSkewY, touchport.kbdY, touchport.kbdYMax);
|
||||
|
||||
touchport.kbdW = touchport.kbdXMax - touchport.kbdX;
|
||||
touchport.kbdH = touchport.kbdYMax - touchport.kbdY;
|
||||
|
||||
if (kbd.model) {
|
||||
_reset_model();
|
||||
}
|
||||
}
|
||||
|
||||
static void gltouchkbd_setData(const char *jsonData) {
|
||||
JSON_s parsedData = { 0 };
|
||||
int tokCount = json_createFromString(jsonData, &parsedData);
|
||||
|
||||
do {
|
||||
if (tokCount < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_HEIGHT_SCALE, &kbd.portraitHeightScale);
|
||||
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_POSITION_SCALE, &kbd.portraitPositionScale);
|
||||
|
||||
gltouchkbd_reshape(touchport.rawWidth, touchport.rawHeight, touchport.isLandscape);
|
||||
} while (0);
|
||||
|
||||
json_destroy(&parsedData);
|
||||
}
|
||||
|
||||
static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
|
||||
|
@ -698,12 +767,10 @@ static void gltouchkbd_setLowercaseEnabled(bool enabled) {
|
|||
}
|
||||
|
||||
static void gltouchkbd_beginCalibration(void) {
|
||||
video_clear();
|
||||
isCalibrating = true;
|
||||
}
|
||||
|
||||
static void gltouchkbd_endCalibration(void) {
|
||||
video_redraw();
|
||||
isCalibrating = false;
|
||||
}
|
||||
|
||||
|
@ -991,6 +1058,9 @@ static void _init_gltouchkbd(void) {
|
|||
keydriver_loadAltKbd = &gltouchkbd_loadAltKbd;
|
||||
keydriver_setGlyphScale = &gltouchkbd_setGlyphScale;
|
||||
|
||||
kbd.portraitHeightScale = 0.5f;
|
||||
kbd.portraitPositionScale = 0.f;
|
||||
|
||||
kbd.selectedCol = -1;
|
||||
kbd.selectedRow = -1;
|
||||
|
||||
|
@ -1000,11 +1070,13 @@ static void _init_gltouchkbd(void) {
|
|||
kbd.glyphMultiplier = 1;
|
||||
|
||||
glnode_registerNode(RENDER_LOW, (GLNode){
|
||||
.type = TOUCH_DEVICE_KEYBOARD,
|
||||
.setup = &gltouchkbd_setup,
|
||||
.shutdown = &gltouchkbd_shutdown,
|
||||
.render = &gltouchkbd_render,
|
||||
.reshape = &gltouchkbd_reshape,
|
||||
.onTouchEvent = &gltouchkbd_onTouchEvent,
|
||||
.setData = &gltouchkbd_setData,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#define MENU_FB_HEIGHT (MENU_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS)
|
||||
|
||||
#define MENU_OBJ_W 2.0
|
||||
#define MENU_OBJ_H 0.5 // NOTE : intent is to complement touch keyboard height
|
||||
#define MENU_OBJ_H_LANDSCAPE (2.0/4.0) // NOTE : intent is to match touch keyboard height in landscape mode
|
||||
#define MENU_OBJ_H_PORTRAIT (1.0/4.0)
|
||||
|
||||
static bool isAvailable = false; // Were there any OpenGL/memory errors on initialization?
|
||||
static bool isEnabled = true; // Does player want this enabled?
|
||||
|
@ -58,6 +59,7 @@ static struct {
|
|||
int topRightYHalf;
|
||||
int topRightYMax;
|
||||
|
||||
GLfloat modelHeight;
|
||||
} touchport = { 0 };
|
||||
|
||||
// touch menu variables
|
||||
|
@ -360,10 +362,10 @@ static void gltouchmenu_setup(void) {
|
|||
|
||||
menu.model = mdlCreateQuad((GLModelParams_s){
|
||||
.skew_x = -1.0,
|
||||
.skew_y = 1.0-MENU_OBJ_H,
|
||||
.skew_y = 1.0-touchport.modelHeight,
|
||||
.z = MODEL_DEPTH,
|
||||
.obj_w = MENU_OBJ_W,
|
||||
.obj_h = MENU_OBJ_H,
|
||||
.obj_h = touchport.modelHeight,
|
||||
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
|
||||
.tex_w = MENU_FB_WIDTH * menu.glyphMultiplier,
|
||||
.tex_h = MENU_FB_HEIGHT * menu.glyphMultiplier,
|
||||
|
@ -428,30 +430,31 @@ static void gltouchmenu_render(void) {
|
|||
GL_ERRLOG("gltouchmenu_render");
|
||||
}
|
||||
|
||||
static void gltouchmenu_reshape(int w, int h) {
|
||||
LOG("gltouchmenu_reshape(%d, %d)", w, h);
|
||||
static void gltouchmenu_reshape(int w, int h, bool landscape) {
|
||||
LOG("w:%d h:%d landscape:%d", w, h, landscape);
|
||||
|
||||
touchport.topLeftX = 0;
|
||||
touchport.topLeftY = 0;
|
||||
touchport.topRightY = 0;
|
||||
|
||||
if (w > touchport.width) {
|
||||
touchport.width = w;
|
||||
const unsigned int keyW = touchport.width / MENU_TEMPLATE_COLS;
|
||||
touchport.topLeftXHalf = keyW;
|
||||
touchport.topLeftXMax = keyW*2;
|
||||
touchport.topRightX = w - (keyW*2);
|
||||
touchport.topRightXHalf = w - keyW;
|
||||
touchport.topRightXMax = w;
|
||||
}
|
||||
if (h > touchport.height) {
|
||||
touchport.height = h;
|
||||
const unsigned int menuH = h * (MENU_OBJ_H/2.0);
|
||||
touchport.topLeftYHalf = menuH/2;
|
||||
touchport.topLeftYMax = menuH;
|
||||
touchport.topRightYHalf = menuH/2;
|
||||
touchport.topRightYMax = menuH;
|
||||
}
|
||||
swizzleDimensions(&w, &h, landscape);
|
||||
touchport.width = w;
|
||||
touchport.height = h;
|
||||
|
||||
touchport.modelHeight = landscape ? MENU_OBJ_H_LANDSCAPE : MENU_OBJ_H_PORTRAIT;;
|
||||
|
||||
const unsigned int keyW = touchport.width / MENU_TEMPLATE_COLS;
|
||||
touchport.topLeftXHalf = keyW;
|
||||
touchport.topLeftXMax = keyW*2;
|
||||
touchport.topRightX = w - (keyW*2);
|
||||
touchport.topRightXHalf = w - keyW;
|
||||
touchport.topRightXMax = w;
|
||||
|
||||
const unsigned int menuH = h * (touchport.modelHeight/2.0);
|
||||
touchport.topLeftYHalf = menuH/2;
|
||||
touchport.topLeftYMax = menuH;
|
||||
touchport.topRightYHalf = menuH/2;
|
||||
touchport.topRightYMax = menuH;
|
||||
}
|
||||
|
||||
static int64_t gltouchmenu_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
|
||||
|
@ -565,11 +568,13 @@ static void _init_gltouchmenu(void) {
|
|||
menu.maxAlpha = 1.f;
|
||||
|
||||
glnode_registerNode(RENDER_TOP, (GLNode){
|
||||
.type = TOUCH_DEVICE_TOPMENU,
|
||||
.setup = &gltouchmenu_setup,
|
||||
.shutdown = &gltouchmenu_shutdown,
|
||||
.render = &gltouchmenu_render,
|
||||
.reshape = &gltouchmenu_reshape,
|
||||
.onTouchEvent = &gltouchmenu_onTouchEvent,
|
||||
.setData = NULL,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@ static int viewportY = 0;
|
|||
static int viewportWidth = SCANWIDTH*1.5;
|
||||
static int viewportHeight = SCANHEIGHT*1.5;
|
||||
|
||||
static int rawWidth = SCANWIDTH*1.5;
|
||||
static int rawHeight = SCANHEIGHT*1.5;
|
||||
static bool isLandscape = true;
|
||||
static float portraitPositionScale = 3/4.f;
|
||||
|
||||
GLint texSamplerLoc = UNINITIALIZED_GL;
|
||||
GLint alphaValue = UNINITIALIZED_GL;
|
||||
GLuint mainShaderProgram = UNINITIALIZED_GL;
|
||||
|
@ -155,8 +160,8 @@ static void glvideo_init(void) {
|
|||
.skew_x = -1.0, // model space coords
|
||||
.skew_y = -1.0,
|
||||
.z = 0.0,
|
||||
.obj_w = 2.0, // entire model space (-1.0 to 1.0)
|
||||
.obj_h = 2.0,
|
||||
.obj_w = GL_MODEL_MAX, // entire model space (-1.0 to 1.0)
|
||||
.obj_h = GL_MODEL_MAX,
|
||||
.positionUsageHint = GL_STATIC_DRAW, // positions don't change
|
||||
.tex_w = SCANWIDTH,
|
||||
.tex_h = SCANHEIGHT,
|
||||
|
@ -277,9 +282,7 @@ static void glvideo_render(void) {
|
|||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
#if MOBILE_DEVICE
|
||||
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
|
||||
#endif
|
||||
|
||||
#if PERSPECTIVE
|
||||
// Calculate modelview and projection matrices
|
||||
|
@ -379,8 +382,14 @@ static void glvideo_render(void) {
|
|||
GL_ERRLOG("glvideo_render");
|
||||
}
|
||||
|
||||
static void glvideo_reshape(int w, int h) {
|
||||
//LOG("reshape to w:%d h:%d", w, h);
|
||||
static void glvideo_reshape(int w, int h, bool landscape) {
|
||||
LOG("w:%d h:%d landscape:%d", w, h, landscape);
|
||||
|
||||
rawWidth = w;
|
||||
rawHeight = h;
|
||||
isLandscape = landscape;
|
||||
|
||||
swizzleDimensions(&w, &h, landscape);
|
||||
|
||||
int w2 = ((float)h * (SCANWIDTH/(float)SCANHEIGHT));
|
||||
int h2 = ((float)w / (SCANWIDTH/(float)SCANHEIGHT));
|
||||
|
@ -397,6 +406,9 @@ static void glvideo_reshape(int w, int h) {
|
|||
viewportY = (h-h2)/2;
|
||||
viewportWidth = w;
|
||||
viewportHeight = h2;
|
||||
if (!isLandscape) {
|
||||
viewportY = (h-h2) * portraitPositionScale;
|
||||
}
|
||||
//LOG("OK2 : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
|
||||
} else {
|
||||
viewportX = 0;
|
||||
|
@ -405,11 +417,26 @@ static void glvideo_reshape(int w, int h) {
|
|||
viewportHeight = h;
|
||||
//LOG("small viewport : x:%d,y:%d w:%d,h:%d", viewportX, viewportY, viewportWidth, viewportHeight);
|
||||
}
|
||||
|
||||
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
|
||||
}
|
||||
|
||||
#if INTERFACE_TOUCH
|
||||
static void glvideo_setData(const char *jsonData) {
|
||||
JSON_s parsedData = { 0 };
|
||||
int tokCount = json_createFromString(jsonData, &parsedData);
|
||||
|
||||
do {
|
||||
if (tokCount < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
json_mapParseFloatValue(&parsedData, PREF_PORTRAIT_POSITION_SCALE, &portraitPositionScale);
|
||||
|
||||
glvideo_reshape(rawWidth, rawHeight, isLandscape);
|
||||
} while (0);
|
||||
|
||||
json_destroy(&parsedData);
|
||||
}
|
||||
|
||||
static int64_t glvideo_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
|
||||
// no-op
|
||||
return 0x0;
|
||||
|
@ -428,7 +455,9 @@ static void _init_glvideo(void) {
|
|||
.render = &glvideo_render,
|
||||
.reshape = &glvideo_reshape,
|
||||
#if INTERFACE_TOUCH
|
||||
.type = TOUCH_DEVICE_FRAMEBUFFER,
|
||||
.onTouchEvent = &glvideo_onTouchEvent,
|
||||
.setData = &glvideo_setData,
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
typedef struct video_backend_s {
|
||||
void (*init)(void *context);
|
||||
void (*main_loop)(void);
|
||||
void (*reshape)(int width, int height);
|
||||
void (*reshape)(int width, int height, bool landscape);
|
||||
void (*render)(void);
|
||||
void (*shutdown)(bool emulatorShuttingDown);
|
||||
} video_backend_s;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#define GL_MODEL_MAX 2.0 // entire model space (-1.0 to 1.0)
|
||||
#define GL_MODEL_HALF 1.0
|
||||
|
||||
enum {
|
||||
POS_ATTRIB_IDX,
|
||||
TEXCOORD_ATTRIB_IDX,
|
||||
|
|
Loading…
Reference in New Issue
Block a user