mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-22 20:30:22 +00:00
First cut at touch menu HUD
- Enables choosing touch keyboard or touch joystick - Enables increasing/decreasing speed - Enables opening main popup menu - Also migrates all gesture responsibility away from Java side of things
This commit is contained in:
parent
1126a319ec
commit
68011fa8f2
@ -44,14 +44,9 @@ public class Apple2Activity extends Activity {
|
|||||||
private Apple2View mView = null;
|
private Apple2View mView = null;
|
||||||
private AlertDialog mQuitDialog = null;
|
private AlertDialog mQuitDialog = null;
|
||||||
private AlertDialog mRebootDialog = null;
|
private AlertDialog mRebootDialog = null;
|
||||||
private GestureDetector mDetector = null;
|
|
||||||
private boolean mSwipeTogglesSpeed = true;
|
|
||||||
private boolean mDoubleTapShowsKeyboard = true;
|
|
||||||
private boolean mSingleTapShowsMainMenu = true;
|
|
||||||
|
|
||||||
private int mWidth = 0;
|
private int mWidth = 0;
|
||||||
private int mHeight = 0;
|
private int mHeight = 0;
|
||||||
private boolean mSoftKeyboardShowing = false;
|
|
||||||
|
|
||||||
private float[] mXCoords = new float[MAX_FINGERS];
|
private float[] mXCoords = new float[MAX_FINGERS];
|
||||||
private float[] mYCoords = new float[MAX_FINGERS];
|
private float[] mYCoords = new float[MAX_FINGERS];
|
||||||
@ -65,8 +60,6 @@ public class Apple2Activity extends Activity {
|
|||||||
private native void nativeGraphicsChanged(int width, int height);
|
private native void nativeGraphicsChanged(int width, int height);
|
||||||
private native void nativeOnKeyDown(int keyCode, int metaState);
|
private native void nativeOnKeyDown(int keyCode, int metaState);
|
||||||
private native void nativeOnKeyUp(int keyCode, int metaState);
|
private native void nativeOnKeyUp(int keyCode, int metaState);
|
||||||
private native void nativeIncreaseCPUSpeed();
|
|
||||||
private native void nativeDecreaseCPUSpeed();
|
|
||||||
|
|
||||||
public native void nativeOnResume(boolean isSystemResume);
|
public native void nativeOnResume(boolean isSystemResume);
|
||||||
public native void nativeOnPause();
|
public native void nativeOnPause();
|
||||||
@ -173,18 +166,10 @@ public class Apple2Activity extends Activity {
|
|||||||
w = h;
|
w = h;
|
||||||
h = w_;
|
h = w_;
|
||||||
}
|
}
|
||||||
if (mView.getHeight() - h > SOFTKEYBOARD_THRESHOLD) {
|
// I actually think this whole observer is now spurious ... but it's triggering SEGFAULT ... should investigate ...
|
||||||
Log.d(TAG, "Soft keyboard appears to be occupying screen real estate ...");
|
|
||||||
Apple2Activity.this.mSoftKeyboardShowing = true;
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Soft keyboard appears to be gone ...");
|
|
||||||
Apple2Activity.this.mSoftKeyboardShowing = false;
|
|
||||||
}
|
|
||||||
nativeGraphicsChanged(w, h);
|
nativeGraphicsChanged(w, h);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mDetector = new GestureDetector(this, new Apple2GestureListener());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -201,10 +186,6 @@ public class Apple2Activity extends Activity {
|
|||||||
Log.d(TAG, "onPause()");
|
Log.d(TAG, "onPause()");
|
||||||
mView.onPause();
|
mView.onPause();
|
||||||
|
|
||||||
if (isSoftKeyboardShowing()) {
|
|
||||||
mView.toggleKeyboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apparently not good to leave popup/dialog windows showing when backgrounding.
|
// Apparently not good to leave popup/dialog windows showing when backgrounding.
|
||||||
// Dismiss these popups to avoid android.view.WindowLeaked issues
|
// Dismiss these popups to avoid android.view.WindowLeaked issues
|
||||||
Apple2MainMenu mainMenu = mView.getMainMenu();
|
Apple2MainMenu mainMenu = mView.getMainMenu();
|
||||||
@ -333,74 +314,12 @@ public class Apple2Activity extends Activity {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mDetector.onTouchEvent(event);
|
mainMenu.show();
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
return super.onTouchEvent(event);
|
return super.onTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Apple2GestureListener extends GestureDetector.SimpleOnGestureListener {
|
|
||||||
private static final String TAG = "Gestures";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDown(MotionEvent event) {
|
|
||||||
Log.d(TAG,"onDown: " + event.toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
|
|
||||||
if ((event1 == null) || (event2 == null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mSwipeTogglesSpeed) {
|
|
||||||
float ev1X = event1.getX();
|
|
||||||
float ev2X = event2.getX();
|
|
||||||
if (ev1X < ev2X) {
|
|
||||||
nativeIncreaseCPUSpeed();
|
|
||||||
} else {
|
|
||||||
nativeDecreaseCPUSpeed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onSingleTapConfirmed(MotionEvent event) {
|
|
||||||
if (event == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Log.d(TAG, "onSingleTapConfirmed: " + event.toString());
|
|
||||||
Apple2MainMenu mainMenu = Apple2Activity.this.mView.getMainMenu();
|
|
||||||
if (mainMenu.isShowing()) {
|
|
||||||
Log.d(TAG, "dismissing main menu");
|
|
||||||
mainMenu.dismiss();
|
|
||||||
} else if (Apple2Activity.this.isSoftKeyboardShowing()) {
|
|
||||||
Log.d(TAG, "hiding keyboard");
|
|
||||||
Apple2Activity.this.mView.toggleKeyboard();
|
|
||||||
} else if (mSingleTapShowsMainMenu) {
|
|
||||||
Log.d(TAG, "showing main menu");
|
|
||||||
Apple2Activity.this.mView.showMainMenu();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDoubleTap(MotionEvent event) {
|
|
||||||
if (event == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mDoubleTapShowsKeyboard) {
|
|
||||||
Log.d(TAG, "onDoubleTap: " + event.toString());
|
|
||||||
if (!Apple2Activity.this.isSoftKeyboardShowing()) {
|
|
||||||
Log.d(TAG, "showing keyboard");
|
|
||||||
Apple2Activity.this.mView.toggleKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void graphicsInitialized(int w, int h) {
|
public void graphicsInitialized(int w, int h) {
|
||||||
if (w < h) {
|
if (w < h) {
|
||||||
// assure landscape dimensions
|
// assure landscape dimensions
|
||||||
@ -431,10 +350,6 @@ public class Apple2Activity extends Activity {
|
|||||||
return mHeight;
|
return mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSoftKeyboardShowing() {
|
|
||||||
return mSoftKeyboardShowing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void maybeQuitApp() {
|
public void maybeQuitApp() {
|
||||||
nativeOnPause();
|
nativeOnPause();
|
||||||
if (mQuitDialog == null) {
|
if (mQuitDialog == null) {
|
||||||
@ -487,14 +402,14 @@ public class Apple2Activity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSwipeTogglesSpeed(boolean swipeTogglesSpeed) {
|
public void setSwipeTogglesSpeed(boolean swipeTogglesSpeed) {
|
||||||
mSwipeTogglesSpeed = swipeTogglesSpeed;
|
//mSwipeTogglesSpeed = swipeTogglesSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSingleTapShowsMainMenu(boolean singleTapShowsMainMenu) {
|
public void setSingleTapShowsMainMenu(boolean singleTapShowsMainMenu) {
|
||||||
mSingleTapShowsMainMenu = singleTapShowsMainMenu;
|
//mSingleTapShowsMainMenu = singleTapShowsMainMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDoubleTapShowsKeyboard(boolean doubleTapShowsKeyboard) {
|
public void setDoubleTapShowsKeyboard(boolean doubleTapShowsKeyboard) {
|
||||||
mDoubleTapShowsKeyboard = doubleTapShowsKeyboard;
|
//mDoubleTapShowsKeyboard = doubleTapShowsKeyboard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,11 +112,6 @@ class Apple2View extends GLSurfaceView {
|
|||||||
return (mMainMenu == null) ? null : mMainMenu.getDisksMenu();
|
return (mMainMenu == null) ? null : mMainMenu.getDisksMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleKeyboard() {
|
|
||||||
InputMethodManager inputMethodManager=(InputMethodManager)mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
inputMethodManager.toggleSoftInputFromWindow(getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
|
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
|
||||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "androidkeys.h"
|
#include "androidkeys.h"
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ANDROID_ACTION_DOWN = 0x0,
|
ANDROID_ACTION_DOWN = 0x0,
|
||||||
@ -25,6 +24,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static bool nativePaused = false;
|
static bool nativePaused = false;
|
||||||
|
static bool nativeRequestsShowMainMenu = false;
|
||||||
|
|
||||||
#if TESTING
|
#if TESTING
|
||||||
static bool _run_tests(void) {
|
static bool _run_tests(void) {
|
||||||
@ -74,6 +74,13 @@ static inline int _androidTouchEvent2JoystickEvent(jint action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _nativeRequestsShowMainMenu(void) {
|
||||||
|
nativeRequestsShowMainMenu = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// JNI functions
|
||||||
|
|
||||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) {
|
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) {
|
||||||
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
|
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
|
||||||
|
|
||||||
@ -118,7 +125,9 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnResume(JNIEnv *env, jobje
|
|||||||
}
|
}
|
||||||
LOG("%s", "native onResume...");
|
LOG("%s", "native onResume...");
|
||||||
if (isSystemResume) {
|
if (isSystemResume) {
|
||||||
// TODO POSSIBLY : message showing paused state
|
if (video_backend->animation_showPaused) {
|
||||||
|
video_backend->animation_showPaused();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nativePaused = false;
|
nativePaused = false;
|
||||||
pthread_mutex_unlock(&interface_mutex);
|
pthread_mutex_unlock(&interface_mutex);
|
||||||
@ -215,73 +224,16 @@ jboolean Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jo
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
bool consumed = interface_onTouchEvent(joyaction, pointerCount, pointerIndex, x_coords, y_coords);
|
bool consumed = interface_onTouchEvent(joyaction, pointerCount, pointerIndex, x_coords, y_coords);
|
||||||
|
if (nativeRequestsShowMainMenu) {
|
||||||
|
nativeRequestsShowMainMenu = false;
|
||||||
|
consumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
(*env)->ReleaseFloatArrayElements(env, xCoords, x_coords, 0);
|
(*env)->ReleaseFloatArrayElements(env, xCoords, x_coords, 0);
|
||||||
(*env)->ReleaseFloatArrayElements(env, yCoords, y_coords, 0);
|
(*env)->ReleaseFloatArrayElements(env, yCoords, y_coords, 0);
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeIncreaseCPUSpeed(JNIEnv *env, jobject obj) {
|
|
||||||
pthread_mutex_lock(&interface_mutex);
|
|
||||||
|
|
||||||
int percent_scale = (int)round(cpu_scale_factor * 100.0);
|
|
||||||
if (percent_scale >= 100) {
|
|
||||||
percent_scale += 25;
|
|
||||||
} else {
|
|
||||||
percent_scale += 5;
|
|
||||||
}
|
|
||||||
cpu_scale_factor = percent_scale/100.0;
|
|
||||||
|
|
||||||
if (cpu_scale_factor > CPU_SCALE_FASTEST) {
|
|
||||||
cpu_scale_factor = CPU_SCALE_FASTEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("native set emulation percentage to %f", cpu_scale_factor);
|
|
||||||
|
|
||||||
if (video_backend->animation_showCPUSpeed) {
|
|
||||||
video_backend->animation_showCPUSpeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning HACK TODO FIXME ... refactor timing stuff
|
|
||||||
timing_toggle_cpu_speed();
|
|
||||||
timing_toggle_cpu_speed();
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&interface_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeDecreaseCPUSpeed(JNIEnv *env, jobject obj) {
|
|
||||||
pthread_mutex_lock(&interface_mutex);
|
|
||||||
|
|
||||||
int percent_scale = (int)round(cpu_scale_factor * 100.0);
|
|
||||||
if (cpu_scale_factor == CPU_SCALE_FASTEST) {
|
|
||||||
cpu_scale_factor = CPU_SCALE_FASTEST0;
|
|
||||||
percent_scale = (int)round(cpu_scale_factor * 100);
|
|
||||||
} else {
|
|
||||||
if (percent_scale > 100) {
|
|
||||||
percent_scale -= 25;
|
|
||||||
} else {
|
|
||||||
percent_scale -= 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu_scale_factor = percent_scale/100.0;
|
|
||||||
|
|
||||||
if (cpu_scale_factor < CPU_SCALE_SLOWEST) {
|
|
||||||
cpu_scale_factor = CPU_SCALE_SLOWEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("native set emulation percentage to %f", cpu_scale_factor);
|
|
||||||
|
|
||||||
if (video_backend->animation_showCPUSpeed) {
|
|
||||||
video_backend->animation_showCPUSpeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning HACK TODO FIXME ... refactor timing stuff
|
|
||||||
timing_toggle_cpu_speed();
|
|
||||||
timing_toggle_cpu_speed();
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&interface_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeSetColor(JNIEnv *env, jobject obj, jint color) {
|
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeSetColor(JNIEnv *env, jobject obj, jint color) {
|
||||||
LOG("native set color : %d", color);
|
LOG("native set color : %d", color);
|
||||||
if (color < COLOR_NONE || color > COLOR_INTERP) {
|
if (color < COLOR_NONE || color > COLOR_INTERP) {
|
||||||
@ -318,3 +270,11 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, job
|
|||||||
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Constructor
|
||||||
|
|
||||||
|
__attribute__((constructor(CTOR_PRIORITY_LATE)))
|
||||||
|
static void _init_jnihooks(void) {
|
||||||
|
video_backend->hostenv_showMainMenu = &_nativeRequestsShowMainMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ APPLE2_VIDEO_SRC = \
|
|||||||
$(APPLE2_SRC_PATH)/video/glalert.c \
|
$(APPLE2_SRC_PATH)/video/glalert.c \
|
||||||
$(APPLE2_SRC_PATH)/video/gltouchjoy.c \
|
$(APPLE2_SRC_PATH)/video/gltouchjoy.c \
|
||||||
$(APPLE2_SRC_PATH)/video/gltouchkbd.c \
|
$(APPLE2_SRC_PATH)/video/gltouchkbd.c \
|
||||||
|
$(APPLE2_SRC_PATH)/video/gltouchmenu.c \
|
||||||
$(APPLE2_SRC_PATH)/video_util/matrixUtil.c \
|
$(APPLE2_SRC_PATH)/video_util/matrixUtil.c \
|
||||||
$(APPLE2_SRC_PATH)/video_util/modelUtil.c \
|
$(APPLE2_SRC_PATH)/video_util/modelUtil.c \
|
||||||
$(APPLE2_SRC_PATH)/video_util/sourceUtil.c \
|
$(APPLE2_SRC_PATH)/video_util/sourceUtil.c \
|
||||||
|
@ -307,10 +307,10 @@ const unsigned char interface_glyphs[256] =
|
|||||||
0x1c, 0x24, 0x04, 0x3e, 0x22, 0x22, 0x2a, 0x3e,
|
0x1c, 0x24, 0x04, 0x3e, 0x22, 0x22, 0x2a, 0x3e,
|
||||||
/* : 0x10 ----------------------- reverse return arrow */
|
/* : 0x10 ----------------------- reverse return arrow */
|
||||||
0x01, 0x01, 0x01, 0x11, 0x31, 0x7f, 0x30, 0x10,
|
0x01, 0x01, 0x01, 0x11, 0x31, 0x7f, 0x30, 0x10,
|
||||||
/* : 0x11 */
|
/* : 0x11 ----------------------- glyph_sprouting_menu */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x7f, 0x41, 0x49, 0x5d, 0x49, 0x41, 0x7f, 0x00,
|
||||||
/* : 0x12 */
|
/* : 0x12 ----------------------- glyph_joystick */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x10, 0x08, 0x1e, 0x22, 0x22, 0x2a, 0x22, 0x3e,
|
||||||
/* : 0x13 */
|
/* : 0x13 */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
/* : 0x14 ----------------------- glyph_lowercase */
|
/* : 0x14 ----------------------- glyph_lowercase */
|
||||||
|
34
src/font.txt
34
src/font.txt
@ -1327,24 +1327,24 @@
|
|||||||
#######
|
#######
|
||||||
....##.
|
....##.
|
||||||
....#..
|
....#..
|
||||||
: 0x11
|
: 0x11 ----------------------- glyph_sprouting_menu
|
||||||
.......
|
#######
|
||||||
.......
|
#.....#
|
||||||
.......
|
#..#..#
|
||||||
.......
|
#.###.#
|
||||||
.......
|
#..#..#
|
||||||
.......
|
#.....#
|
||||||
.......
|
#######
|
||||||
.......
|
|
||||||
: 0x12
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
|
||||||
.......
|
.......
|
||||||
|
: 0x12 ----------------------- glyph_joystick
|
||||||
|
....#..
|
||||||
|
...#...
|
||||||
|
.####..
|
||||||
|
.#...#.
|
||||||
|
.#...#.
|
||||||
|
.#.#.#.
|
||||||
|
.#...#.
|
||||||
|
.#####.
|
||||||
: 0x13
|
: 0x13
|
||||||
.......
|
.......
|
||||||
.......
|
.......
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#if INTERFACE_TOUCH
|
#if INTERFACE_TOUCH
|
||||||
// touch interface managed elsewhere
|
// touch interface managed elsewhere
|
||||||
bool (*interface_onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) = NULL;
|
bool (*interface_onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) = NULL;
|
||||||
|
bool (*interface_isTouchMenuAvailable)(void) = NULL;
|
||||||
|
void (*interface_setTouchMenuEnabled)(bool enabled) = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 2015/04/12 : This was legacy code for rendering the menu interfaces on desktop Linux. Portions here are resurrected
|
// 2015/04/12 : This was legacy code for rendering the menu interfaces on desktop Linux. Portions here are resurrected
|
||||||
|
@ -60,6 +60,12 @@ typedef enum interface_touch_event_t {
|
|||||||
|
|
||||||
// handle touch event
|
// handle touch event
|
||||||
extern bool (*interface_onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords);
|
extern bool (*interface_onTouchEvent)(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords);
|
||||||
|
|
||||||
|
// is the touch menu module itself available?
|
||||||
|
extern bool (*interface_isTouchMenuAvailable)(void);
|
||||||
|
|
||||||
|
// enable/disable touch menu HUD element
|
||||||
|
extern void (*interface_setTouchMenuEnabled)(bool enabled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ uniform sampler2D buttonTexture;
|
|||||||
// Keyboard
|
// Keyboard
|
||||||
uniform sampler2D kbdTexture;
|
uniform sampler2D kbdTexture;
|
||||||
|
|
||||||
|
// HUD Sprouting Menus
|
||||||
|
uniform sampler2D menuLeftTexture;
|
||||||
|
uniform sampler2D menuRightTexture;
|
||||||
|
|
||||||
#if __VERSION__ >= 140
|
#if __VERSION__ >= 140
|
||||||
#define OUTPUT_TEXTURE(TEX) \
|
#define OUTPUT_TEXTURE(TEX) \
|
||||||
vec4 tex = texture(TEX, varTexcoord.st, 0.0); \
|
vec4 tex = texture(TEX, varTexcoord.st, 0.0); \
|
||||||
@ -62,6 +66,10 @@ void main(void)
|
|||||||
OUTPUT_TEXTURE(buttonTexture);
|
OUTPUT_TEXTURE(buttonTexture);
|
||||||
} else if (tex2Use == 4) {
|
} else if (tex2Use == 4) {
|
||||||
OUTPUT_TEXTURE(kbdTexture);
|
OUTPUT_TEXTURE(kbdTexture);
|
||||||
|
} else if (tex2Use == 5) {
|
||||||
|
OUTPUT_TEXTURE(menuLeftTexture);
|
||||||
|
} else if (tex2Use == 6) {
|
||||||
|
OUTPUT_TEXTURE(menuRightTexture);
|
||||||
} else {
|
} else {
|
||||||
//OUTPUT_RED(); -- WTF is this failing?
|
//OUTPUT_RED(); -- WTF is this failing?
|
||||||
}
|
}
|
||||||
|
678
src/video/gltouchmenu.c
Normal file
678
src/video/gltouchmenu.c
Normal file
@ -0,0 +1,678 @@
|
|||||||
|
/*
|
||||||
|
* Apple // emulator for *nix
|
||||||
|
*
|
||||||
|
* This software package is subject to the GNU General Public License
|
||||||
|
* version 2 or later (your choice) as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* THERE ARE NO WARRANTIES WHATSOEVER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "video/glvideo.h"
|
||||||
|
#include "video/glhudmodel.h"
|
||||||
|
#include "video/glnode.h"
|
||||||
|
|
||||||
|
#if !INTERFACE_TOUCH
|
||||||
|
#error this is a touch interface module, possibly you mean to not compile this at all?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MODEL_DEPTH -1/32.f
|
||||||
|
|
||||||
|
#define MENU_TEMPLATE_COLS 2
|
||||||
|
#define MENU_TEMPLATE_ROWS 2
|
||||||
|
|
||||||
|
// HACK NOTE FIXME TODO : interpolated pixel adjustment still necessary ...
|
||||||
|
#define MENU_FB_WIDTH ((MENU_TEMPLATE_COLS * FONT80_WIDTH_PIXELS) + INTERPOLATED_PIXEL_ADJUSTMENT)
|
||||||
|
#define MENU_FB_HEIGHT (MENU_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS)
|
||||||
|
|
||||||
|
#define MENU_OBJ_W 1/2.f
|
||||||
|
#define MENU_OBJ_H 1/2.f
|
||||||
|
|
||||||
|
HUD_CLASS(GLModelHUDMenu,
|
||||||
|
char *pixelsAlt; // alternate color pixels
|
||||||
|
);
|
||||||
|
|
||||||
|
static bool isAvailable = false; // Were there any OpenGL/memory errors on initialization?
|
||||||
|
static bool isEnabled = true; // Does player want this enabled?
|
||||||
|
static float minAlpha = 1/4.f; // Minimum alpha value of components (at zero, will not render)
|
||||||
|
|
||||||
|
static char topLeftTemplateHidden[MENU_TEMPLATE_ROWS][MENU_TEMPLATE_COLS+1] = {
|
||||||
|
"++",
|
||||||
|
"++",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char topLeftTemplateShowing[MENU_TEMPLATE_ROWS][MENU_TEMPLATE_COLS+1] = {
|
||||||
|
"++",
|
||||||
|
"++",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char topRightTemplateHidden[MENU_TEMPLATE_ROWS][MENU_TEMPLATE_COLS+1] = {
|
||||||
|
"++",
|
||||||
|
"++",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char topRightTemplateShowing[MENU_TEMPLATE_ROWS][MENU_TEMPLATE_COLS+1] = {
|
||||||
|
"++",
|
||||||
|
"++",
|
||||||
|
};
|
||||||
|
|
||||||
|
// touch viewport
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
// top left hitbox
|
||||||
|
int topLeftX;
|
||||||
|
int topLeftXHalf;
|
||||||
|
int topLeftXMax;
|
||||||
|
int topLeftY;
|
||||||
|
int topLeftYHalf;
|
||||||
|
int topLeftYMax;
|
||||||
|
|
||||||
|
// top right hitbox
|
||||||
|
int topRightX;
|
||||||
|
int topRightXHalf;
|
||||||
|
int topRightXMax;
|
||||||
|
int topRightY;
|
||||||
|
int topRightYHalf;
|
||||||
|
int topRightYMax;
|
||||||
|
|
||||||
|
} touchport = { 0 };
|
||||||
|
|
||||||
|
// touch menu variables
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
GLModel *model;
|
||||||
|
bool modelDirty; // TODO : movement animation
|
||||||
|
bool isShowing;
|
||||||
|
} hudTopLeft = { 0 };
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
GLModel *model;
|
||||||
|
bool modelDirty; // TODO : movement animation
|
||||||
|
bool isShowing;
|
||||||
|
} hudTopRight = { 0 };
|
||||||
|
|
||||||
|
struct timespec timingBegin = { 0 };
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static inline void _present_menu(GLModel *parent, char *template) {
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)parent->custom;
|
||||||
|
memcpy(hudMenu->tpl, template, sizeof(topLeftTemplateHidden/* assuming all templates the same size */));
|
||||||
|
|
||||||
|
// setup the alternate color (AKA selected) pixels
|
||||||
|
hudMenu->colorScheme = GREEN_ON_BLACK;
|
||||||
|
glhud_setupDefault(parent);
|
||||||
|
memcpy(hudMenu->pixelsAlt, hudMenu->pixels, (hudMenu->pixWidth * hudMenu->pixHeight));
|
||||||
|
|
||||||
|
// setup normal color pixels
|
||||||
|
hudMenu->colorScheme = RED_ON_BLACK;
|
||||||
|
glhud_setupDefault(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _show_top_left(void) {
|
||||||
|
_present_menu(hudTopLeft.model, topLeftTemplateShowing[0]);
|
||||||
|
hudTopLeft.isShowing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _hide_top_left(void) {
|
||||||
|
_present_menu(hudTopLeft.model, topLeftTemplateHidden[0]);
|
||||||
|
hudTopLeft.isShowing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _show_top_right(void) {
|
||||||
|
_present_menu(hudTopRight.model, topRightTemplateShowing[0]);
|
||||||
|
hudTopRight.isShowing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _hide_top_right(void) {
|
||||||
|
_present_menu(hudTopRight.model, topRightTemplateHidden[0]);
|
||||||
|
hudTopRight.isShowing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float _get_menu_visibility(void) {
|
||||||
|
struct timespec now = { 0 };
|
||||||
|
struct timespec deltat = { 0 };
|
||||||
|
float alpha = minAlpha;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
alpha = minAlpha;
|
||||||
|
deltat = timespec_diff(timingBegin, now, NULL);
|
||||||
|
if (deltat.tv_sec == 0) {
|
||||||
|
alpha = 1.0;
|
||||||
|
if (deltat.tv_nsec >= NANOSECONDS_PER_SECOND/2) {
|
||||||
|
alpha -= ((float)deltat.tv_nsec-(NANOSECONDS_PER_SECOND/2)) / (float)(NANOSECONDS_PER_SECOND/2);
|
||||||
|
if (alpha < minAlpha) {
|
||||||
|
alpha = minAlpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _is_point_on_left_menu(float x, float y) {
|
||||||
|
if (hudTopLeft.isShowing) {
|
||||||
|
return (x >= touchport.topLeftX && x <= touchport.topLeftXMax && y >= touchport.topLeftY && y <= touchport.topLeftYMax);
|
||||||
|
} else {
|
||||||
|
return (x >= touchport.topLeftX && x <= touchport.topLeftXHalf && y >= touchport.topLeftY && y <= touchport.topLeftYHalf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _is_point_on_right_menu(float x, float y) {
|
||||||
|
if (hudTopRight.isShowing) {
|
||||||
|
return (x >= touchport.topRightX && x <= touchport.topRightXMax && y >= touchport.topRightY && y <= touchport.topRightYMax);
|
||||||
|
} else {
|
||||||
|
return (x >= touchport.topRightXHalf && x <= touchport.topRightXMax && y >= touchport.topRightY && y <= touchport.topRightYHalf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning FIXME TODO : make this function generic _screen_to_model() ?
|
||||||
|
static inline void _screen_to_menu(float x, float y, OUTPARM int *col, OUTPARM int *row, OUTPARM bool *isTopLeft) {
|
||||||
|
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)(/* assuming both have same width/height */hudTopLeft.model->custom);
|
||||||
|
|
||||||
|
unsigned int keyW = (touchport.topLeftXMax - touchport.topLeftX) / (hudMenu->tplWidth+1/* interpolated adjustment HACK NOTE FIXME TODO */);
|
||||||
|
unsigned int keyH = (touchport.topLeftYMax - touchport.topLeftY) / (hudMenu->tplHeight);
|
||||||
|
const int xOff = (keyW * 0.5); // HACK NOTE FIXME TODO : interpolated pixel adjustment still necessary ...
|
||||||
|
|
||||||
|
hudMenu = NULL;
|
||||||
|
if (x < touchport.width/2) {
|
||||||
|
*isTopLeft = true;
|
||||||
|
hudMenu = (GLModelHUDMenu *)hudTopLeft.model->custom;
|
||||||
|
*col = (x - (touchport.topLeftX+xOff)) / keyW;
|
||||||
|
*row = (y - touchport.topLeftY) / keyH;
|
||||||
|
LOG("SCREEN TO MENU : xOff:%d topLeftX:%d topLeftXMax:%d keyW:%d ... scrn:(%d,%d)->menu:(%d,%d)", xOff, touchport.topLeftX, touchport.topLeftXMax, keyW, (int)x, (int)y, *col, *row);
|
||||||
|
} else {
|
||||||
|
*isTopLeft = false;
|
||||||
|
hudMenu = (GLModelHUDMenu *)hudTopRight.model->custom;
|
||||||
|
*col = (x - (touchport.topRightX+xOff)) / keyW;
|
||||||
|
*row = (y - touchport.topRightY) / keyH;
|
||||||
|
LOG("SCREEN TO MENU : xOff:%d topRightX:%d topRightXMax:%d keyW:%d ... scrn:(%d,%d)->menu:(%d,%d)", xOff, touchport.topRightX, touchport.topRightXMax, keyW, (int)x, (int)y, *col, *row);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*col < 0) {
|
||||||
|
*col = 0;
|
||||||
|
} /* interpolated adjustment HACK NOTE FIXME TODO */ else if (*col >= hudMenu->tplWidth) {
|
||||||
|
*col = hudMenu->tplWidth-1;
|
||||||
|
}
|
||||||
|
if (*row < 0) {
|
||||||
|
*row = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _increase_cpu_speed(void) {
|
||||||
|
pthread_mutex_lock(&interface_mutex);
|
||||||
|
|
||||||
|
int percent_scale = (int)round(cpu_scale_factor * 100.0);
|
||||||
|
if (percent_scale >= 100) {
|
||||||
|
percent_scale += 25;
|
||||||
|
} else {
|
||||||
|
percent_scale += 5;
|
||||||
|
}
|
||||||
|
cpu_scale_factor = percent_scale/100.0;
|
||||||
|
|
||||||
|
if (cpu_scale_factor > CPU_SCALE_FASTEST) {
|
||||||
|
cpu_scale_factor = CPU_SCALE_FASTEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("native set emulation percentage to %f", cpu_scale_factor);
|
||||||
|
|
||||||
|
if (video_backend->animation_showCPUSpeed) {
|
||||||
|
video_backend->animation_showCPUSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning HACK TODO FIXME ... refactor timing stuff
|
||||||
|
timing_toggle_cpu_speed();
|
||||||
|
timing_toggle_cpu_speed();
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&interface_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _decrease_cpu_speed(void) {
|
||||||
|
pthread_mutex_lock(&interface_mutex);
|
||||||
|
|
||||||
|
int percent_scale = (int)round(cpu_scale_factor * 100.0);
|
||||||
|
if (cpu_scale_factor == CPU_SCALE_FASTEST) {
|
||||||
|
cpu_scale_factor = CPU_SCALE_FASTEST0;
|
||||||
|
percent_scale = (int)round(cpu_scale_factor * 100);
|
||||||
|
} else {
|
||||||
|
if (percent_scale > 100) {
|
||||||
|
percent_scale -= 25;
|
||||||
|
} else {
|
||||||
|
percent_scale -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cpu_scale_factor = percent_scale/100.0;
|
||||||
|
|
||||||
|
if (cpu_scale_factor < CPU_SCALE_SLOWEST) {
|
||||||
|
cpu_scale_factor = CPU_SCALE_SLOWEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("native set emulation percentage to %f", cpu_scale_factor);
|
||||||
|
|
||||||
|
if (video_backend->animation_showCPUSpeed) {
|
||||||
|
video_backend->animation_showCPUSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning HACK TODO FIXME ... refactor timing stuff
|
||||||
|
timing_toggle_cpu_speed();
|
||||||
|
timing_toggle_cpu_speed();
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&interface_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _sprout_menu(float x, float y) {
|
||||||
|
|
||||||
|
if (! (_is_point_on_left_menu(x, y) || _is_point_on_right_menu(x, y)) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTopLeft = false;
|
||||||
|
int col = -1;
|
||||||
|
int row = -1;
|
||||||
|
|
||||||
|
_screen_to_menu(x, y, &col, &row, &isTopLeft);
|
||||||
|
|
||||||
|
if (isTopLeft) {
|
||||||
|
|
||||||
|
// hide other
|
||||||
|
_hide_top_right();
|
||||||
|
|
||||||
|
// maybe show this one
|
||||||
|
if (!hudTopLeft.isShowing) {
|
||||||
|
if (col == 0 && row == 0) {
|
||||||
|
_show_top_left();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hudTopLeft.isShowing;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// hide other
|
||||||
|
_hide_top_left();
|
||||||
|
|
||||||
|
// maybe show this one
|
||||||
|
if (!hudTopRight.isShowing) {
|
||||||
|
if (col == 1 && row == 0) {
|
||||||
|
_show_top_right();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hudTopRight.isShowing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _tap_menu_item(float x, float y) {
|
||||||
|
if (! (_is_point_on_left_menu(x, y) || _is_point_on_right_menu(x, y)) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTopLeft = false;
|
||||||
|
int col = -1;
|
||||||
|
int row = -1;
|
||||||
|
|
||||||
|
_screen_to_menu(x, y, &col, &row, &isTopLeft);
|
||||||
|
|
||||||
|
int selectedItem = -1;
|
||||||
|
if (isTopLeft && hudTopLeft.isShowing) {
|
||||||
|
selectedItem = topLeftTemplateShowing[row][col];
|
||||||
|
} else if (!isTopLeft && hudTopRight.isShowing) {
|
||||||
|
selectedItem = topRightTemplateShowing[row][col];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (selectedItem) {
|
||||||
|
|
||||||
|
case MOUSETEXT_LEFT:
|
||||||
|
LOG("decreasing cpu speed...");
|
||||||
|
_decrease_cpu_speed();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOUSETEXT_RIGHT:
|
||||||
|
LOG("increasing cpu speed...");
|
||||||
|
_increase_cpu_speed();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOUSETEXT_CHECKMARK:
|
||||||
|
LOG("showing main menu...");
|
||||||
|
if (video_backend->hostenv_showMainMenu) {
|
||||||
|
video_backend->hostenv_showMainMenu();
|
||||||
|
}
|
||||||
|
_hide_top_right();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICONTEXT_MENU_TOUCHJOY:
|
||||||
|
LOG("showing touch joystick ...");
|
||||||
|
keydriver_setTouchKeyboardOwnsScreen(false);
|
||||||
|
if (video_backend->animation_hideTouchKeyboard) {
|
||||||
|
video_backend->animation_hideTouchKeyboard();
|
||||||
|
}
|
||||||
|
joydriver_setTouchJoystickOwnsScreen(true);
|
||||||
|
if (video_backend->animation_showTouchJoystick) {
|
||||||
|
video_backend->animation_showTouchJoystick();
|
||||||
|
}
|
||||||
|
_hide_top_left();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICONTEXT_UPPERCASE:
|
||||||
|
LOG("showing touch keyboard ...");
|
||||||
|
joydriver_setTouchJoystickOwnsScreen(false);
|
||||||
|
if (video_backend->animation_hideTouchJoystick) {
|
||||||
|
video_backend->animation_hideTouchJoystick();
|
||||||
|
}
|
||||||
|
keydriver_setTouchKeyboardOwnsScreen(true);
|
||||||
|
if (video_backend->animation_showTouchKeyboard) {
|
||||||
|
video_backend->animation_showTouchKeyboard();
|
||||||
|
}
|
||||||
|
_hide_top_left();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICONTEXT_MENU_SPROUT:
|
||||||
|
LOG("sprout ...");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICONTEXT_NONACTIONABLE:
|
||||||
|
default:
|
||||||
|
LOG("nonactionable ...");
|
||||||
|
_hide_top_left();
|
||||||
|
_hide_top_right();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// GLCustom functions
|
||||||
|
|
||||||
|
static void _setup_touchmenu_top_left(GLModel *parent) {
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)parent->custom;
|
||||||
|
|
||||||
|
hudMenu->tplWidth = MENU_TEMPLATE_COLS;
|
||||||
|
hudMenu->tplHeight = MENU_TEMPLATE_ROWS;
|
||||||
|
hudMenu->pixWidth = MENU_FB_WIDTH;
|
||||||
|
hudMenu->pixHeight = MENU_FB_HEIGHT;
|
||||||
|
|
||||||
|
topLeftTemplateHidden[0][0] = ICONTEXT_MENU_SPROUT;
|
||||||
|
topLeftTemplateHidden[0][1] = ICONTEXT_NONACTIONABLE;
|
||||||
|
topLeftTemplateHidden[1][0] = ICONTEXT_NONACTIONABLE;
|
||||||
|
topLeftTemplateHidden[1][1] = ICONTEXT_NONACTIONABLE;
|
||||||
|
|
||||||
|
topLeftTemplateShowing[0][0] = ICONTEXT_MENU_SPROUT;
|
||||||
|
topLeftTemplateShowing[0][1] = MOUSETEXT_RIGHT;
|
||||||
|
topLeftTemplateShowing[1][1] = ICONTEXT_UPPERCASE;
|
||||||
|
topLeftTemplateShowing[1][0] = ICONTEXT_MENU_TOUCHJOY;
|
||||||
|
|
||||||
|
const unsigned int size = sizeof(topLeftTemplateHidden);
|
||||||
|
hudMenu->tpl = calloc(size, 1);
|
||||||
|
hudMenu->pixels = calloc(MENU_FB_WIDTH * MENU_FB_HEIGHT, 1);
|
||||||
|
hudMenu->pixelsAlt = calloc(MENU_FB_WIDTH * MENU_FB_HEIGHT, 1);
|
||||||
|
|
||||||
|
_present_menu(parent, topLeftTemplateHidden[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _setup_touchmenu_top_right(GLModel *parent) {
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)parent->custom;
|
||||||
|
|
||||||
|
hudMenu->tplWidth = MENU_TEMPLATE_COLS;
|
||||||
|
hudMenu->tplHeight = MENU_TEMPLATE_ROWS;
|
||||||
|
hudMenu->pixWidth = MENU_FB_WIDTH;
|
||||||
|
hudMenu->pixHeight = MENU_FB_HEIGHT;
|
||||||
|
|
||||||
|
topRightTemplateHidden[0][0] = ICONTEXT_NONACTIONABLE;
|
||||||
|
topRightTemplateHidden[0][1] = ICONTEXT_MENU_SPROUT;
|
||||||
|
topRightTemplateHidden[1][0] = ICONTEXT_NONACTIONABLE;
|
||||||
|
topRightTemplateHidden[1][1] = ICONTEXT_NONACTIONABLE;
|
||||||
|
|
||||||
|
topRightTemplateShowing[0][0] = MOUSETEXT_LEFT;
|
||||||
|
topRightTemplateShowing[0][1] = ICONTEXT_MENU_SPROUT;
|
||||||
|
topRightTemplateShowing[1][0] = ICONTEXT_NONACTIONABLE;
|
||||||
|
topRightTemplateShowing[1][1] = MOUSETEXT_CHECKMARK;
|
||||||
|
|
||||||
|
const unsigned int size = sizeof(topRightTemplateHidden);
|
||||||
|
hudMenu->tpl = calloc(size, 1);
|
||||||
|
hudMenu->pixels = calloc(MENU_FB_WIDTH * MENU_FB_HEIGHT, 1);
|
||||||
|
hudMenu->pixelsAlt = calloc(MENU_FB_WIDTH * MENU_FB_HEIGHT, 1);
|
||||||
|
|
||||||
|
_present_menu(parent, topRightTemplateHidden[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *_create_touchmenu(void) {
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)calloc(sizeof(GLModelHUDMenu), 1);
|
||||||
|
if (hudMenu) {
|
||||||
|
hudMenu->blackIsTransparent = true;
|
||||||
|
}
|
||||||
|
return hudMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _destroy_touchmenu(GLModel *parent) {
|
||||||
|
GLModelHUDMenu *hudMenu = (GLModelHUDMenu *)parent->custom;
|
||||||
|
if (!hudMenu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FREE(hudMenu->pixelsAlt);
|
||||||
|
glhud_destroyDefault(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// GLNode functions
|
||||||
|
|
||||||
|
static void gltouchmenu_setup(void) {
|
||||||
|
LOG("gltouchmenu_setup ...");
|
||||||
|
|
||||||
|
mdlDestroyModel(&hudTopLeft.model);
|
||||||
|
hudTopLeft.model = mdlCreateQuad(-1.0, 1.0-MENU_OBJ_H, MENU_OBJ_W, MENU_OBJ_H, MODEL_DEPTH, MENU_FB_WIDTH, MENU_FB_HEIGHT, GL_RGBA/*RGBA_8888*/, (GLCustom){
|
||||||
|
.create = &_create_touchmenu,
|
||||||
|
.setup = &_setup_touchmenu_top_left,
|
||||||
|
.destroy = &_destroy_touchmenu,
|
||||||
|
});
|
||||||
|
if (!hudTopLeft.model) {
|
||||||
|
LOG("gltouchmenu initialization problem");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hudTopLeft.model->custom) {
|
||||||
|
LOG("gltouchmenu HUD initialization problem");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdlDestroyModel(&hudTopRight.model);
|
||||||
|
hudTopRight.model = mdlCreateQuad(1.0-MENU_OBJ_W, 1.0-MENU_OBJ_H, MENU_OBJ_W, MENU_OBJ_H, MODEL_DEPTH, MENU_FB_WIDTH, MENU_FB_HEIGHT, GL_RGBA/*RGBA_8888*/, (GLCustom){
|
||||||
|
.create = &_create_touchmenu,
|
||||||
|
.setup = &_setup_touchmenu_top_right,
|
||||||
|
.destroy = &_destroy_touchmenu,
|
||||||
|
});
|
||||||
|
if (!hudTopRight.model) {
|
||||||
|
LOG("gltouchmenu initialization problem");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hudTopRight.model->custom) {
|
||||||
|
LOG("gltouchmenu HUD initialization problem");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &timingBegin);
|
||||||
|
|
||||||
|
isAvailable = true;
|
||||||
|
|
||||||
|
GL_ERRLOG("gltouchmenu_setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gltouchmenu_shutdown(void) {
|
||||||
|
LOG("gltouchmenu_shutdown ...");
|
||||||
|
if (!isAvailable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAvailable = false;
|
||||||
|
|
||||||
|
mdlDestroyModel(&hudTopLeft.model);
|
||||||
|
mdlDestroyModel(&hudTopRight.model);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gltouchmenu_render(void) {
|
||||||
|
if (!isAvailable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float alpha = _get_menu_visibility();
|
||||||
|
if (alpha <= 0.0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(0, 0, touchport.width, touchport.height); // NOTE : show these HUD elements beyond the A2 framebuffer dimensions
|
||||||
|
glUniform1f(alphaValue, alpha);
|
||||||
|
|
||||||
|
// render top left sprouting menu
|
||||||
|
|
||||||
|
glActiveTexture(TEXTURE_ACTIVE_TOUCHMENU_LEFT);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, hudTopLeft.model->textureName);
|
||||||
|
if (hudTopLeft.model->texDirty) {
|
||||||
|
hudTopLeft.model->texDirty = false;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, hudTopLeft.model->texWidth, hudTopLeft.model->texHeight, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, hudTopLeft.model->texPixels);
|
||||||
|
}
|
||||||
|
if (hudTopLeft.modelDirty) {
|
||||||
|
hudTopLeft.modelDirty = false;
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, hudTopLeft.model->posBufferName);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, hudTopLeft.model->positionArraySize, hudTopLeft.model->positions, GL_DYNAMIC_DRAW);
|
||||||
|
}
|
||||||
|
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHMENU_LEFT);
|
||||||
|
glhud_renderDefault(hudTopLeft.model);
|
||||||
|
|
||||||
|
// render top right sprouting menu
|
||||||
|
|
||||||
|
glActiveTexture(TEXTURE_ACTIVE_TOUCHMENU_RIGHT);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, hudTopRight.model->textureName);
|
||||||
|
if (hudTopRight.model->texDirty) {
|
||||||
|
hudTopRight.model->texDirty = false;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, hudTopRight.model->texWidth, hudTopRight.model->texHeight, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, hudTopRight.model->texPixels);
|
||||||
|
}
|
||||||
|
if (hudTopRight.modelDirty) {
|
||||||
|
hudTopRight.modelDirty = false;
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, hudTopRight.model->posBufferName);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, hudTopRight.model->positionArraySize, hudTopRight.model->positions, GL_DYNAMIC_DRAW);
|
||||||
|
}
|
||||||
|
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHMENU_RIGHT);
|
||||||
|
glhud_renderDefault(hudTopRight.model);
|
||||||
|
|
||||||
|
GL_ERRLOG("gltouchmenu_render");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gltouchmenu_reshape(int w, int h) {
|
||||||
|
LOG("gltouchmenu_reshape(%d, %d)", w, h);
|
||||||
|
|
||||||
|
touchport.topLeftX = 0;
|
||||||
|
touchport.topLeftY = 0;
|
||||||
|
touchport.topRightY = 0;
|
||||||
|
|
||||||
|
if (w > touchport.width) {
|
||||||
|
const int menuPixelW = w * (MENU_OBJ_W/2.f);
|
||||||
|
touchport.width = w;
|
||||||
|
touchport.topLeftXHalf = menuPixelW/2;
|
||||||
|
touchport.topLeftXMax = menuPixelW;
|
||||||
|
touchport.topRightX = w - menuPixelW;
|
||||||
|
touchport.topRightXHalf = w - (menuPixelW/2);
|
||||||
|
touchport.topRightXMax = w;
|
||||||
|
}
|
||||||
|
if (h > touchport.height) {
|
||||||
|
const int menuPixelH = h * (MENU_OBJ_H/2.f);
|
||||||
|
touchport.height = h;
|
||||||
|
touchport.topLeftYHalf = menuPixelH/2;
|
||||||
|
touchport.topLeftYMax = menuPixelH;
|
||||||
|
touchport.topRightYHalf = menuPixelH/2;
|
||||||
|
touchport.topRightYMax = menuPixelH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool gltouchmenu_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
|
||||||
|
|
||||||
|
if (!isAvailable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("gltouchmenu_onTouchEvent ...");
|
||||||
|
|
||||||
|
float x = x_coords[pointer_idx];
|
||||||
|
float y = y_coords[pointer_idx];
|
||||||
|
|
||||||
|
bool handled = (_is_point_on_left_menu(x, y) || _is_point_on_right_menu(x, y));
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case TOUCH_DOWN:
|
||||||
|
case TOUCH_POINTER_DOWN:
|
||||||
|
_sprout_menu(x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOUCH_MOVE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOUCH_UP:
|
||||||
|
case TOUCH_POINTER_UP:
|
||||||
|
_tap_menu_item(x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOUCH_CANCEL:
|
||||||
|
LOG("---MENU TOUCH CANCEL");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG("!!!MENU UNKNOWN TOUCH EVENT : %d", action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &timingBegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Animation and settings handling
|
||||||
|
|
||||||
|
static bool gltouchmenu_isTouchMenuAvailable(void) {
|
||||||
|
return isAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gltouchmenu_setTouchMenuEnabled(bool enabled) {
|
||||||
|
isEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _animation_showTouchMenu(void) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &timingBegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _animation_hideTouchMenu(void) {
|
||||||
|
timingBegin = (struct timespec){ 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Constructor
|
||||||
|
|
||||||
|
__attribute__((constructor(CTOR_PRIORITY_LATE)))
|
||||||
|
static void _init_gltouchmenu(void) {
|
||||||
|
LOG("Registering OpenGL software touch menu");
|
||||||
|
|
||||||
|
video_backend->animation_showTouchMenu = &_animation_showTouchMenu;
|
||||||
|
video_backend->animation_hideTouchMenu = &_animation_hideTouchMenu;
|
||||||
|
|
||||||
|
interface_isTouchMenuAvailable = &gltouchmenu_isTouchMenuAvailable;
|
||||||
|
interface_setTouchMenuEnabled = &gltouchmenu_setTouchMenuEnabled;
|
||||||
|
|
||||||
|
glnode_registerNode(RENDER_TOP, (GLNode){
|
||||||
|
.setup = &gltouchmenu_setup,
|
||||||
|
.shutdown = &gltouchmenu_shutdown,
|
||||||
|
.render = &gltouchmenu_render,
|
||||||
|
.reshape = &gltouchmenu_reshape,
|
||||||
|
.onTouchEvent = &gltouchmenu_onTouchEvent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -447,6 +447,16 @@ static GLuint _build_program(demoSource *vertexSource, demoSource *fragmentSourc
|
|||||||
glUniform1i(messageSamplerLoc, TEXTURE_ID_MESSAGE);
|
glUniform1i(messageSamplerLoc, TEXTURE_ID_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLint maxTextureUnits = -1;
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
|
||||||
|
|
||||||
|
if (maxTextureUnits < TEXTURE_ID_MAX) {
|
||||||
|
#warning FIXME TODO ... gracefully handle devices with low max texture units?
|
||||||
|
ERRLOG("OOPS ... MAX TEXTURE UNITS : %d (<%d)", maxTextureUnits, TEXTURE_ID_MAX);
|
||||||
|
} else {
|
||||||
|
LOG("GL_MAX_TEXTURE_IMAGE_UNITS : %d", maxTextureUnits);
|
||||||
|
}
|
||||||
|
|
||||||
#if INTERFACE_TOUCH
|
#if INTERFACE_TOUCH
|
||||||
GLint axisSamplerLoc = glGetUniformLocation(prgName, "axisTexture");
|
GLint axisSamplerLoc = glGetUniformLocation(prgName, "axisTexture");
|
||||||
if (axisSamplerLoc < 0) {
|
if (axisSamplerLoc < 0) {
|
||||||
@ -468,6 +478,20 @@ static GLuint _build_program(demoSource *vertexSource, demoSource *fragmentSourc
|
|||||||
} else {
|
} else {
|
||||||
glUniform1i(kbdSamplerLoc, TEXTURE_ID_TOUCHKBD);
|
glUniform1i(kbdSamplerLoc, TEXTURE_ID_TOUCHKBD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLint menuLeftSamplerLoc = glGetUniformLocation(prgName, "menuLeftTexture");
|
||||||
|
if (menuLeftSamplerLoc < 0) {
|
||||||
|
LOG("OOPS, no menuLeftSamplerLoc shader : %d", menuLeftSamplerLoc);
|
||||||
|
} else {
|
||||||
|
glUniform1i(menuLeftSamplerLoc, TEXTURE_ID_TOUCHMENU_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint menuRightSamplerLoc = glGetUniformLocation(prgName, "menuRightTexture");
|
||||||
|
if (menuRightSamplerLoc < 0) {
|
||||||
|
LOG("OOPS, no menuRightSamplerLoc shader : %d", menuRightSamplerLoc);
|
||||||
|
} else {
|
||||||
|
glUniform1i(menuRightSamplerLoc, TEXTURE_ID_TOUCHMENU_RIGHT);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniformMVPIdx = glGetUniformLocation(prgName, "modelViewProjectionMatrix");
|
uniformMVPIdx = glGetUniformLocation(prgName, "modelViewProjectionMatrix");
|
||||||
|
@ -26,7 +26,10 @@ enum {
|
|||||||
TEXTURE_ID_TOUCHJOY_AXIS,
|
TEXTURE_ID_TOUCHJOY_AXIS,
|
||||||
TEXTURE_ID_TOUCHJOY_BUTTON,
|
TEXTURE_ID_TOUCHJOY_BUTTON,
|
||||||
TEXTURE_ID_TOUCHKBD,
|
TEXTURE_ID_TOUCHKBD,
|
||||||
|
TEXTURE_ID_TOUCHMENU_LEFT,
|
||||||
|
TEXTURE_ID_TOUCHMENU_RIGHT,
|
||||||
#endif
|
#endif
|
||||||
|
TEXTURE_ID_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -36,7 +39,10 @@ enum {
|
|||||||
TEXTURE_ACTIVE_TOUCHJOY_AXIS = GL_TEXTURE2,
|
TEXTURE_ACTIVE_TOUCHJOY_AXIS = GL_TEXTURE2,
|
||||||
TEXTURE_ACTIVE_TOUCHJOY_BUTTON = GL_TEXTURE3,
|
TEXTURE_ACTIVE_TOUCHJOY_BUTTON = GL_TEXTURE3,
|
||||||
TEXTURE_ACTIVE_TOUCHKBD = GL_TEXTURE4,
|
TEXTURE_ACTIVE_TOUCHKBD = GL_TEXTURE4,
|
||||||
|
TEXTURE_ACTIVE_TOUCHMENU_LEFT = GL_TEXTURE5,
|
||||||
|
TEXTURE_ACTIVE_TOUCHMENU_RIGHT = GL_TEXTURE6,
|
||||||
#endif
|
#endif
|
||||||
|
TEXTURE_ACTIVE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GLint uniformTex2Use;
|
extern GLint uniformTex2Use;
|
||||||
|
@ -26,14 +26,22 @@ typedef struct video_backend_s {
|
|||||||
void (*render)(void);
|
void (*render)(void);
|
||||||
void (*shutdown)(void);
|
void (*shutdown)(void);
|
||||||
|
|
||||||
// optional functions
|
// touch HUD functions
|
||||||
|
void (*hostenv_showMainMenu)(void);
|
||||||
void (*animation_showTouchKeyboard)(void);
|
void (*animation_showTouchKeyboard)(void);
|
||||||
void (*animation_hideTouchKeyboard)(void);
|
void (*animation_hideTouchKeyboard)(void);
|
||||||
|
void (*animation_showTouchJoystick)(void);
|
||||||
|
void (*animation_hideTouchJoystick)(void);
|
||||||
|
void (*animation_showTouchMenu)(void);
|
||||||
|
void (*animation_hideTouchMenu)(void);
|
||||||
|
|
||||||
|
// misc animations
|
||||||
void (*animation_showMessage)(char *message, unsigned int cols, unsigned int rows);
|
void (*animation_showMessage)(char *message, unsigned int cols, unsigned int rows);
|
||||||
void (*animation_showPaused)(void);
|
void (*animation_showPaused)(void);
|
||||||
void (*animation_showCPUSpeed)(void);
|
void (*animation_showCPUSpeed)(void);
|
||||||
void (*animation_showDiskChosen)(int drive);
|
void (*animation_showDiskChosen)(int drive);
|
||||||
void (*animation_showTrackSector)(int drive, int track, int sect);
|
void (*animation_showTrackSector)(int drive, int track, int sect);
|
||||||
|
|
||||||
} video_backend_s;
|
} video_backend_s;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -175,6 +183,7 @@ uint8_t floating_bus_hibit(const bool hibit);
|
|||||||
#define MOUSETEXT_OPENAPPLE (MOUSETEXT_BEGIN+0x01)
|
#define MOUSETEXT_OPENAPPLE (MOUSETEXT_BEGIN+0x01)
|
||||||
#define MOUSETEXT_CLOSEDAPPLE (MOUSETEXT_BEGIN+0x00)
|
#define MOUSETEXT_CLOSEDAPPLE (MOUSETEXT_BEGIN+0x00)
|
||||||
#define MOUSETEXT_HOURGLASS (MOUSETEXT_BEGIN+0x03)
|
#define MOUSETEXT_HOURGLASS (MOUSETEXT_BEGIN+0x03)
|
||||||
|
#define MOUSETEXT_CHECKMARK (MOUSETEXT_BEGIN+0x04)
|
||||||
|
|
||||||
#define ICONTEXT_BEGIN 0xA0 // offset + 0x20 length
|
#define ICONTEXT_BEGIN 0xA0 // offset + 0x20 length
|
||||||
#define ICONTEXT_MENU_BEGIN ICONTEXT_BEGIN
|
#define ICONTEXT_MENU_BEGIN ICONTEXT_BEGIN
|
||||||
@ -187,6 +196,9 @@ uint8_t floating_bus_hibit(const bool hibit);
|
|||||||
#define ICONTEXT_UNLOCK (ICONTEXT_BEGIN+0x0F)
|
#define ICONTEXT_UNLOCK (ICONTEXT_BEGIN+0x0F)
|
||||||
#define ICONTEXT_GOTO (ICONTEXT_BEGIN+0x10)
|
#define ICONTEXT_GOTO (ICONTEXT_BEGIN+0x10)
|
||||||
|
|
||||||
|
#define ICONTEXT_MENU_SPROUT (ICONTEXT_BEGIN+0x11)
|
||||||
|
#define ICONTEXT_MENU_TOUCHJOY (ICONTEXT_BEGIN+0x12)
|
||||||
|
|
||||||
#define ICONTEXT_KBD_BEGIN (ICONTEXT_BEGIN+0x14)
|
#define ICONTEXT_KBD_BEGIN (ICONTEXT_BEGIN+0x14)
|
||||||
#define ICONTEXT_LOWERCASE (ICONTEXT_KBD_BEGIN+0x00)
|
#define ICONTEXT_LOWERCASE (ICONTEXT_KBD_BEGIN+0x00)
|
||||||
#define ICONTEXT_UPPERCASE (ICONTEXT_KBD_BEGIN+0x01)
|
#define ICONTEXT_UPPERCASE (ICONTEXT_KBD_BEGIN+0x01)
|
||||||
|
Loading…
Reference in New Issue
Block a user