mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-01-03 06:30:33 +00:00
First cut at GL Touch Joystick
This commit is contained in:
parent
d63bd7b412
commit
30236cb400
@ -37,6 +37,7 @@ public class Apple2Activity extends Activity {
|
||||
private final static int BUF_SZ = 4096;
|
||||
private final static String PREFS_CONFIGURED = "prefs_configured";
|
||||
private final static int SOFTKEYBOARD_THRESHOLD = 50;
|
||||
private final static int MAX_FINGERS = 32;// HACK ...
|
||||
|
||||
private Apple2View mView = null;
|
||||
private AlertDialog mQuitDialog = null;
|
||||
@ -48,6 +49,9 @@ public class Apple2Activity extends Activity {
|
||||
private int mHeight = 0;
|
||||
private boolean mSoftKeyboardShowing = false;
|
||||
|
||||
private float[] mXCoords = new float[MAX_FINGERS];
|
||||
private float[] mYCoords = new float[MAX_FINGERS];
|
||||
|
||||
static {
|
||||
System.loadLibrary("apple2ix");
|
||||
}
|
||||
@ -63,7 +67,8 @@ public class Apple2Activity extends Activity {
|
||||
public native void nativeOnResume();
|
||||
public native void nativeOnPause();
|
||||
public native void nativeOnQuit();
|
||||
public native boolean nativeOnTouch(int action, float x, float y);
|
||||
public native boolean nativeOnTouch(int action, int pointerCount, int pointerIndex, float[] xCoords, float[] yCoords);
|
||||
|
||||
public native void nativeReboot();
|
||||
public native void nativeRender();
|
||||
|
||||
@ -238,6 +243,45 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
private String actionToString(int action) {
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
return "CANCEL:"+action;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
return "DOWN:"+action;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
return "MOVE:"+action;
|
||||
case MotionEvent.ACTION_UP:
|
||||
return "UP:"+action;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
return "PDOWN:"+action;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
return "PUP:"+action;
|
||||
default:
|
||||
return "UNK:"+action;
|
||||
}
|
||||
}
|
||||
|
||||
private void printSamples(MotionEvent ev) {
|
||||
final int historySize = ev.getHistorySize();
|
||||
final int pointerCount = ev.getPointerCount();
|
||||
|
||||
/*
|
||||
for (int h = 0; h < historySize; h++) {
|
||||
Log.d(TAG, "Event "+ev.getAction().toString()+" at historical time "+ev.getHistoricalEventTime(h)+" :");
|
||||
for (int p = 0; p < pointerCount; p++) {
|
||||
Log.d(TAG, " pointer "+ev.getPointerId(p)+": ("+ev.getHistoricalX(p, h)+","+ev.getHistoricalY(p, h)+")");
|
||||
}
|
||||
}
|
||||
*/
|
||||
int pointerIndex = ev.getActionIndex();
|
||||
|
||||
Log.d(TAG, "Event "+actionToString(ev.getActionMasked())+" for "+pointerIndex+" at time "+ev.getEventTime()+" :");
|
||||
for (int p=0; p<pointerCount; p++) {
|
||||
Log.d(TAG, " pointer "+ev.getPointerId(p)+": ("+ev.getX(p)+","+ev.getY(p)+")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
do {
|
||||
@ -251,16 +295,21 @@ public class Apple2Activity extends Activity {
|
||||
break;
|
||||
}
|
||||
|
||||
printSamples(event);
|
||||
int action = event.getActionMasked();
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int pointerCount = event.getPointerCount();
|
||||
for (int i=0; i<pointerCount/* && i < MAX_FINGERS */; i++) {
|
||||
mXCoords[i] = event.getX(i);
|
||||
mYCoords[i] = event.getY(i);
|
||||
}
|
||||
|
||||
boolean nativeHandled = nativeOnTouch(action, x, y);
|
||||
boolean nativeHandled = nativeOnTouch(action, pointerCount, pointerIndex, mXCoords, mYCoords);
|
||||
if (nativeHandled) {
|
||||
break;
|
||||
}
|
||||
|
||||
this.mDetector.onTouchEvent(event);
|
||||
//this.mDetector.onTouchEvent(event);
|
||||
} while (false);
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
|
@ -15,6 +15,15 @@
|
||||
#include <jni.h>
|
||||
#include <math.h>
|
||||
|
||||
enum {
|
||||
ANDROID_ACTION_DOWN = 0x0,
|
||||
ANDROID_ACTION_UP = 0x1,
|
||||
ANDROID_ACTION_MOVE = 0x2,
|
||||
ANDROID_ACTION_CANCEL = 0x3,
|
||||
ANDROID_ACTION_POINTER_DOWN = 0x5,
|
||||
ANDROID_ACTION_POINTER_UP = 0x6,
|
||||
};
|
||||
|
||||
static bool nativePaused = false;
|
||||
|
||||
#if TESTING
|
||||
@ -45,6 +54,26 @@ static bool _run_tests(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int _androidTouchEvent2JoystickEvent(jint action) {
|
||||
switch (action) {
|
||||
case ANDROID_ACTION_DOWN:
|
||||
return TOUCH_DOWN;
|
||||
case ANDROID_ACTION_MOVE:
|
||||
return TOUCH_MOVE;
|
||||
case ANDROID_ACTION_UP:
|
||||
return TOUCH_UP;
|
||||
case ANDROID_ACTION_POINTER_DOWN:
|
||||
return TOUCH_POINTER_DOWN;
|
||||
case ANDROID_ACTION_POINTER_UP:
|
||||
return TOUCH_POINTER_UP;
|
||||
case ANDROID_ACTION_CANCEL:
|
||||
return TOUCH_CANCEL;
|
||||
default:
|
||||
LOG("Unknown Android event : %d", action);
|
||||
return TOUCH_CANCEL;
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) {
|
||||
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
|
||||
data_dir = strdup(dataDir);
|
||||
@ -154,8 +183,23 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnKeyUp(JNIEnv *env, jobjec
|
||||
#endif
|
||||
}
|
||||
|
||||
jboolean Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jobject obj, jint action, jfloat keyCode, jfloat metaState) {
|
||||
return false;
|
||||
jboolean Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jobject obj, jint action, jint pointerCount, jint pointerIndex, jfloatArray xCoords, jfloatArray yCoords) {
|
||||
//LOG("nativeOnTouch : %d/%d/%d :", action, pointerCount, pointerIndex);
|
||||
|
||||
jfloat *x_coords = (*env)->GetFloatArrayElements(env, xCoords, 0);
|
||||
jfloat *y_coords = (*env)->GetFloatArrayElements(env, yCoords, 0);
|
||||
|
||||
int joyaction = _androidTouchEvent2JoystickEvent(action);
|
||||
|
||||
//for (unsigned int i=0; i<pointerCount; i++) {
|
||||
// LOG("\t[%f,%f]", x_coords[i], y_coords[i]);
|
||||
//}
|
||||
|
||||
bool consumed = joydriver_onTouchEvent(joyaction, pointerCount, pointerIndex, x_coords, y_coords);
|
||||
|
||||
(*env)->ReleaseFloatArrayElements(env, xCoords, x_coords, 0);
|
||||
(*env)->ReleaseFloatArrayElements(env, yCoords, y_coords, 0);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeIncreaseCPUSpeed(JNIEnv *env, jobject obj) {
|
||||
|
@ -33,5 +33,5 @@ APPLE2_MAIN_SRC = \
|
||||
$(APPLE2_SRC_PATH)/timing.c $(APPLE2_SRC_PATH)/zlib-helpers.c $(APPLE2_SRC_PATH)/joystick.c $(APPLE2_SRC_PATH)/keys.c \
|
||||
$(APPLE2_SRC_PATH)/disk.c $(APPLE2_SRC_PATH)/cpu-supp.c
|
||||
|
||||
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -DDEBUGGER=1 -std=gnu11 -I$(APPLE2_SRC_PATH)
|
||||
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DTOUCH_JOYSTICK=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -DDEBUGGER=1 -std=gnu11 -I$(APPLE2_SRC_PATH)
|
||||
|
||||
|
@ -219,15 +219,7 @@ static void c_calibrate_keypad_joystick()
|
||||
}
|
||||
}
|
||||
#endif // KEYPAD_JOYSTICK
|
||||
#endif // INTERFACE_CLASSIC
|
||||
|
||||
#ifdef TOUCH_JOYSTICK
|
||||
// TBD ...
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifdef INTERFACE_CLASSIC
|
||||
void c_calibrate_joystick()
|
||||
{
|
||||
if (joy_mode == JOY_PCJOY)
|
||||
@ -245,7 +237,7 @@ void c_calibrate_joystick()
|
||||
#endif // INTERFACE_CLASSIC
|
||||
|
||||
extern void gldriver_joystick_reset(void);
|
||||
void c_joystick_reset()
|
||||
void c_joystick_reset(void)
|
||||
{
|
||||
#if VIDEO_OPENGL && !TESTING
|
||||
if (!is_headless) {
|
||||
@ -264,3 +256,23 @@ void c_joystick_reset()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOUCH_JOYSTICK
|
||||
bool (*joydriver_onTouchEvent)(joystick_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) = NULL;
|
||||
|
||||
// is the touch joystick available
|
||||
bool (*joydriver_isTouchJoystickAvailable)(void) = NULL;
|
||||
|
||||
// enable/disable touch joystick
|
||||
void (*joydriver_setTouchJoyEnabled)(bool enabled) = NULL;
|
||||
|
||||
// set the joystick button parameters (7bit ASCII characters or MOUSETEXT values)
|
||||
void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val) = NULL;
|
||||
|
||||
// set the axis type
|
||||
void (*joydriver_setTouchAxisType)(touchjoy_axis_type_t axisType) = NULL;
|
||||
|
||||
// set the axis button parameters (7bit ASCII characters or MOUSETEXT values)
|
||||
void (*joydriver_setTouchAxisValues)(char up, char left, char right, char down) = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,13 +9,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 65c02 CPU Timing Support.
|
||||
*
|
||||
* Copyleft 2013 Aaron Culliney
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _JOYSTICK_H_
|
||||
#define _JOYSTICK_H_
|
||||
|
||||
@ -39,4 +32,40 @@ void c_joystick_reset(void);
|
||||
void c_calibrate_joystick(void);
|
||||
#endif
|
||||
|
||||
#if TOUCH_JOYSTICK
|
||||
|
||||
typedef enum joystick_touch_event_t {
|
||||
TOUCH_CANCEL = 0,
|
||||
TOUCH_DOWN,
|
||||
TOUCH_MOVE,
|
||||
TOUCH_UP,
|
||||
TOUCH_POINTER_DOWN,
|
||||
TOUCH_POINTER_UP,
|
||||
} joystick_touch_event_t;
|
||||
|
||||
typedef enum touchjoy_axis_type_t {
|
||||
AXIS_EMULATED_DEVICE = 0, // touch joystick axes emulate a physical joystick device
|
||||
AXIS_EMULATED_KEYBOARD, // touch joystick axes send single key events
|
||||
} touchjoy_axis_type_t;
|
||||
|
||||
// handle touch event
|
||||
extern bool (*joydriver_onTouchEvent)(joystick_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords);
|
||||
|
||||
// is the touch joystick available
|
||||
extern bool (*joydriver_isTouchJoystickAvailable)(void);
|
||||
|
||||
// enable/disable touch joystick
|
||||
extern void (*joydriver_setTouchJoyEnabled)(bool enabled);
|
||||
|
||||
// set the joystick button parameters (7bit ASCII characters or MOUSETEXT values)
|
||||
extern void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val);
|
||||
|
||||
// set the axis type
|
||||
extern void (*joydriver_setTouchAxisType)(touchjoy_axis_type_t axisType);
|
||||
|
||||
// set the axis button parameters (7bit ASCII characters or MOUSETEXT values)
|
||||
extern void (*joydriver_setTouchAxisValues)(char up, char left, char right, char down);
|
||||
|
||||
#endif // TOUCH_JOYSTICK
|
||||
|
||||
#endif // whole file
|
||||
|
@ -30,21 +30,37 @@ uniform sampler2D framebufferTexture;
|
||||
// Floating message
|
||||
uniform sampler2D messageTexture;
|
||||
|
||||
// Joystick axis
|
||||
uniform sampler2D axisTexture;
|
||||
|
||||
// Joystick buttons
|
||||
uniform sampler2D buttonTexture;
|
||||
|
||||
#if __VERSION__ >= 140
|
||||
#define OUTPUT_TEXTURE(TEX) \
|
||||
vec4 tex = texture(TEX, varTexcoord.st, 0.0); \
|
||||
fragColor = vec4(tex.r, tex.g, tex.b, 1.0*aValue)
|
||||
fragColor = vec4(tex.r, tex.g, tex.b, tex.a*aValue)
|
||||
#define OUTPUT_RED() \
|
||||
fragColor = vec4(1.0, 0.0, 0.0, 1.0)
|
||||
#else
|
||||
#define OUTPUT_TEXTURE(TEX) \
|
||||
vec4 tex = texture2D(TEX, varTexcoord.st, 0.0); \
|
||||
gl_FragColor = vec4(tex.r, tex.g, tex.b, 1.0*aValue)
|
||||
gl_FragColor = vec4(tex.r, tex.g, tex.b, tex.a*aValue)
|
||||
#define OUTPUT_RED() \
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0)
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if (tex2Use == 1) {
|
||||
OUTPUT_TEXTURE(messageTexture);
|
||||
} else {
|
||||
if (tex2Use == 0) {
|
||||
OUTPUT_TEXTURE(framebufferTexture);
|
||||
} else if (tex2Use == 1) {
|
||||
OUTPUT_TEXTURE(messageTexture);
|
||||
} else if (tex2Use == 2) {
|
||||
OUTPUT_TEXTURE(axisTexture);
|
||||
} else if (tex2Use == 3) {
|
||||
OUTPUT_TEXTURE(buttonTexture);
|
||||
} else {
|
||||
//OUTPUT_RED(); -- WTF is this failing?
|
||||
}
|
||||
}
|
||||
|
@ -74,3 +74,11 @@ void gldriver_animation_render(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void gldriver_animation_reshape(int w, int h) {
|
||||
glanim_array_node_t *p = animations;
|
||||
while (p) {
|
||||
p->anim->reshape(w, h);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,14 +14,11 @@
|
||||
#ifndef _GLANIMATION_H_
|
||||
#define _GLANIMATION_H_
|
||||
|
||||
typedef void (*glanim_ctor_fn)(void);
|
||||
typedef void (*glanim_dtor_fn)(void);
|
||||
typedef void (*glanim_render_fn)(void);
|
||||
|
||||
typedef struct glanim_t {
|
||||
glanim_ctor_fn ctor;
|
||||
glanim_dtor_fn dtor;
|
||||
glanim_render_fn render;
|
||||
void (*ctor)(void);
|
||||
void (*dtor)(void);
|
||||
void (*render)(void);
|
||||
void (*reshape)(int w, int h);
|
||||
} glanim_t;
|
||||
|
||||
// register an animation
|
||||
@ -36,5 +33,8 @@ void gldriver_animation_destroy(void);
|
||||
// renders the animation
|
||||
void gldriver_animation_render(void);
|
||||
|
||||
// renders the animation
|
||||
void gldriver_animation_reshape(int w, int h);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -48,10 +48,10 @@ static glanim_t cpuMessageAnimation = { 0 };
|
||||
static void _create_message_model(void) {
|
||||
|
||||
const GLfloat messageObj_positions[] = {
|
||||
-0.3, -0.3, -0.1, 1.0,
|
||||
0.3, -0.3, -0.1, 1.0,
|
||||
-0.3, 0.3, -0.1, 1.0,
|
||||
0.3, 0.3, -0.1, 1.0,
|
||||
-0.3, -0.3, -0.0625, 1.0,
|
||||
0.3, -0.3, -0.0625, 1.0,
|
||||
-0.3, 0.3, -0.0625, 1.0,
|
||||
0.3, 0.3, -0.0625, 1.0,
|
||||
};
|
||||
const GLfloat messageObj_texcoords[] = {
|
||||
0.0, 1.0,
|
||||
@ -349,6 +349,10 @@ static void cpuanim_render(void) {
|
||||
_render_message_object(alpha, cpuMessageObjVAOName, cpuMessageObjPosBufferName, cpuMessageObjTexcoordBufferName, cpuMessageObjElementBufferName);
|
||||
}
|
||||
|
||||
static void cpuanim_reshape(int w, int h) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
static void cpuanim_show(void) {
|
||||
if (!animation_subsystem_functional) {
|
||||
return;
|
||||
@ -403,6 +407,7 @@ static void _init_glcpuanim(void) {
|
||||
cpuMessageAnimation.ctor = &cpuanim_init;
|
||||
cpuMessageAnimation.dtor = &cpuanim_destroy;
|
||||
cpuMessageAnimation.render = &cpuanim_render;
|
||||
cpuMessageAnimation.reshape = &cpuanim_reshape;
|
||||
gldriver_register_animation(&cpuMessageAnimation);
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,802 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// GL touch joystick -- Created by Aaron Culliney
|
||||
|
||||
#include "common.h"
|
||||
#include "video/glvideo.h"
|
||||
|
||||
void gldriver_joystick_reset(void) {
|
||||
#define MAX_FINGERS 32
|
||||
#define TOUCHJOY_TEMPLATE_COLS 5
|
||||
#define TOUCHJOY_TEMPLATE_ROWS 5
|
||||
|
||||
// HACK NOTE FIXME TODO : interpolated pixel adjustment still necessary ...
|
||||
#define TOUCHJOY_FB_WIDTH ((TOUCHJOY_TEMPLATE_COLS * FONT80_WIDTH_PIXELS) + INTERPOLATED_PIXEL_ADJUSTMENT)
|
||||
#define TOUCHJOY_FB_HEIGHT (TOUCHJOY_TEMPLATE_ROWS * FONT_HEIGHT_PIXELS)
|
||||
|
||||
enum {
|
||||
TOUCHED_NONE = -1,
|
||||
TOUCHED_BUTTON0 = 0,
|
||||
TOUCHED_BUTTON1,
|
||||
TOUCHED_BOTH,
|
||||
};
|
||||
|
||||
static bool isAvailable = false;
|
||||
static bool isEnabled = true;
|
||||
static bool isVisible = true;
|
||||
|
||||
static char axisTemplate[TOUCHJOY_TEMPLATE_ROWS][TOUCHJOY_TEMPLATE_COLS+1] = {
|
||||
"|||||",
|
||||
"| @ |",
|
||||
"|@+@|",
|
||||
"| @ |",
|
||||
"|||||",
|
||||
};
|
||||
|
||||
static char buttonTemplate[TOUCHJOY_TEMPLATE_ROWS][TOUCHJOY_TEMPLATE_COLS+1] = {
|
||||
" |||",
|
||||
" |@|",
|
||||
"|||||",
|
||||
"|@|+ ",
|
||||
"||| ",
|
||||
};
|
||||
|
||||
static const GLfloat model_width = 0.5;
|
||||
static const GLfloat model_height = 0.5;
|
||||
static glanim_t touchjoyAnimation = { 0 };
|
||||
|
||||
static int viewportWidth = 0;
|
||||
static int viewportHeight = 0;
|
||||
|
||||
// touch axis variables
|
||||
|
||||
static demoModel *touchAxisObjModel = NULL;
|
||||
static GLuint touchAxisObjVAOName = UNINITIALIZED_GL;
|
||||
static GLuint touchAxisObjTextureName = UNINITIALIZED_GL;
|
||||
static GLuint touchAxisObjPosBufferName = UNINITIALIZED_GL;
|
||||
static GLuint touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
static GLuint touchAxisObjElementBufferName = UNINITIALIZED_GL;
|
||||
|
||||
static int touchAxisObjModelScreenX = 0;
|
||||
static int touchAxisObjModelScreenY = 0;
|
||||
static int touchAxisObjModelScreenXMax = 0;
|
||||
static int touchAxisObjModelScreenYMax = 0;
|
||||
|
||||
static uint8_t touchAxisObjFB[TOUCHJOY_FB_WIDTH * TOUCHJOY_FB_HEIGHT] = { 0 };
|
||||
static uint8_t touchAxisObjPixels[TOUCHJOY_FB_WIDTH * TOUCHJOY_FB_HEIGHT * 4] = { 0 };// RGBA8888
|
||||
static bool axisTextureDirty = true;
|
||||
|
||||
static int trackingAxisIndex = TOUCHED_NONE;
|
||||
|
||||
// button object variables
|
||||
|
||||
static demoModel *buttonObjModel = NULL;
|
||||
static GLuint buttonObjVAOName = UNINITIALIZED_GL;
|
||||
static GLuint buttonObjTextureName = UNINITIALIZED_GL;
|
||||
static GLuint buttonObjPosBufferName = UNINITIALIZED_GL;
|
||||
static GLuint buttonObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
static GLuint buttonObjElementBufferName = UNINITIALIZED_GL;
|
||||
|
||||
static int buttonObj0ScreenX = 0;
|
||||
static int buttonObj0ScreenY = 0;
|
||||
static int buttonObj0ScreenXMax = 0;
|
||||
static int buttonObj0ScreenYMax = 0;
|
||||
|
||||
static int buttonObj1ScreenX = 0;
|
||||
static int buttonObj1ScreenY = 0;
|
||||
static int buttonObj1ScreenXMax = 0;
|
||||
static int buttonObj1ScreenYMax = 0;
|
||||
|
||||
static uint8_t buttonObjFB[TOUCHJOY_FB_WIDTH * TOUCHJOY_FB_HEIGHT] = { 0 };
|
||||
static uint8_t buttonObjPixels[TOUCHJOY_FB_WIDTH * TOUCHJOY_FB_HEIGHT * 4] = { 0 };// RGBA8888
|
||||
static bool buttonTextureDirty = true;
|
||||
|
||||
static int trackingButton0Index = TOUCHED_NONE;
|
||||
static int trackingButton1Index = TOUCHED_NONE;
|
||||
static int trackingButtonBothIndex = TOUCHED_NONE;
|
||||
|
||||
// configurables for current touchjoy
|
||||
|
||||
static uint8_t button0Char = MOUSETEXT_OPENAPPLE;
|
||||
static uint8_t button1Char = MOUSETEXT_CLOSEDAPPLE;
|
||||
static touchjoy_axis_type_t touchjoy_axisType = AXIS_EMULATED_DEVICE;
|
||||
static uint8_t upChar = MOUSETEXT_UP;
|
||||
static uint8_t leftChar = MOUSETEXT_LEFT;
|
||||
static uint8_t rightChar = MOUSETEXT_RIGHT;
|
||||
static uint8_t downChar = MOUSETEXT_DOWN;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static demoModel *_create_model(GLfloat skew_x, GLfloat skew_y) {
|
||||
|
||||
/* 2...3
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* 0...1
|
||||
*/
|
||||
|
||||
const GLfloat obj_positions[] = {
|
||||
skew_x, skew_y, -0.03125, 1.0,
|
||||
skew_x+model_width, skew_y, -0.03125, 1.0,
|
||||
skew_x, skew_y+model_height, -0.03125, 1.0,
|
||||
skew_x+model_width, skew_y+model_height, -0.03125, 1.0,
|
||||
};
|
||||
const GLfloat obj_texcoords[] = {
|
||||
0.0, 1.0,
|
||||
1.0, 1.0,
|
||||
0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
};
|
||||
const GLushort indices[] = {
|
||||
0, 1, 2, 2, 1, 3
|
||||
};
|
||||
|
||||
demoModel *obj = calloc(1, sizeof(demoModel));
|
||||
obj->numVertices = 4;
|
||||
obj->numElements = 6;
|
||||
|
||||
obj->positions = malloc(sizeof(obj_positions));
|
||||
memcpy(obj->positions, &obj_positions[0], sizeof(obj_positions));
|
||||
obj->positionType = GL_FLOAT;
|
||||
obj->positionSize = 4; // x,y,z coordinates
|
||||
obj->positionArraySize = sizeof(obj_positions);
|
||||
|
||||
obj->texcoords = malloc(sizeof(obj_texcoords));
|
||||
memcpy(obj->texcoords, &obj_texcoords[0], sizeof(obj_texcoords));
|
||||
obj->texcoordType = GL_FLOAT;
|
||||
obj->texcoordSize = 2; // s,t coordinates
|
||||
obj->texcoordArraySize = sizeof(obj_texcoords);
|
||||
|
||||
obj->normals = NULL;
|
||||
obj->normalType = GL_NONE;
|
||||
obj->normalSize = GL_NONE;
|
||||
obj->normalArraySize = 0;
|
||||
|
||||
obj->elements = malloc(sizeof(indices));
|
||||
memcpy(obj->elements, &indices[0], sizeof(indices));
|
||||
obj->elementType = GL_UNSIGNED_SHORT;
|
||||
obj->elementArraySize = sizeof(indices);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void _create_VAO_VBOs(const demoModel *model, GLuint *vaoName, GLuint *posBufferName, GLuint *texcoordBufferName, GLuint *elementBufferName) {
|
||||
|
||||
// Create a vertex array object (VAO) to cache model parameters
|
||||
#if USE_VAO
|
||||
glGenVertexArrays(1, vaoName);
|
||||
glBindVertexArray(*vaoName);
|
||||
#endif
|
||||
|
||||
// Create a vertex buffer object (VBO) to store positions and load data
|
||||
glGenBuffers(1, posBufferName);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, *posBufferName);
|
||||
glBufferData(GL_ARRAY_BUFFER, model->positionArraySize, model->positions, GL_STATIC_DRAW);
|
||||
|
||||
#if USE_VAO
|
||||
// Enable the position attribute for this VAO
|
||||
glEnableVertexAttribArray(POS_ATTRIB_IDX);
|
||||
|
||||
// Get the size of the position type so we can set the stride properly
|
||||
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
|
||||
|
||||
// Set up parmeters for position attribute in the VAO including,
|
||||
// size, type, stride, and offset in the currenly bound VAO
|
||||
// This also attaches the position VBO to the VAO
|
||||
glVertexAttribPointer(POS_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
|
||||
model->positionSize, // How many elements are there per position?
|
||||
model->positionType, // What is the type of this data?
|
||||
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
|
||||
model->positionSize*posTypeSize, // What is the stride (i.e. bytes between positions)?
|
||||
0); // What is the offset in the VBO to the position data?
|
||||
#endif
|
||||
|
||||
if (model->texcoords) {
|
||||
// Create a VBO to store texcoords
|
||||
glGenBuffers(1, texcoordBufferName);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, *texcoordBufferName);
|
||||
|
||||
// Allocate and load texcoord data into the VBO
|
||||
glBufferData(GL_ARRAY_BUFFER, model->texcoordArraySize, model->texcoords, GL_STATIC_DRAW);
|
||||
|
||||
#if USE_VAO
|
||||
// Enable the texcoord attribute for this VAO
|
||||
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
|
||||
|
||||
// Get the size of the texcoord type so we can set the stride properly
|
||||
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
|
||||
|
||||
// Set up parmeters for texcoord attribute in the VAO including,
|
||||
// size, type, stride, and offset in the currenly bound VAO
|
||||
// This also attaches the texcoord VBO to VAO
|
||||
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
|
||||
model->texcoordSize, // How many elements are there per texture coord?
|
||||
model->texcoordType, // What is the type of this data in the array?
|
||||
GL_TRUE, // Do we want to normalize this data (0-1 range for fixed-point types)
|
||||
model->texcoordSize*texcoordTypeSize, // What is the stride (i.e. bytes between texcoords)?
|
||||
0); // What is the offset in the VBO to the texcoord data?
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a VBO to vertex array elements
|
||||
// This also attaches the element array buffer to the VAO
|
||||
glGenBuffers(1, elementBufferName);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementBufferName);
|
||||
|
||||
// Allocate and load vertex array element data into VBO
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model->elementArraySize, model->elements, GL_STATIC_DRAW);
|
||||
|
||||
GL_ERRLOG("gltouchjoy finished creating VAO/VBOs");
|
||||
}
|
||||
|
||||
static void _destroy_VAO_VBOs(GLuint vaoName, GLuint posBufferName, GLuint texcoordBufferName, GLuint elementBufferName) {
|
||||
|
||||
// Bind the VAO so we can get data from it
|
||||
#if USE_VAO
|
||||
glBindVertexArray(vaoName);
|
||||
|
||||
// For every possible attribute set in the VAO
|
||||
for (GLuint index = 0; index < 16; index++) {
|
||||
// Get the VBO set for that attibute
|
||||
GLuint bufName = 0;
|
||||
glGetVertexAttribiv(index , GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
|
||||
|
||||
// If there was a VBO set...
|
||||
if (bufName) {
|
||||
//...delete the VBO
|
||||
glDeleteBuffers(1, &bufName);
|
||||
}
|
||||
}
|
||||
|
||||
// Get any element array VBO set in the VAO
|
||||
{
|
||||
GLuint bufName = 0;
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&bufName);
|
||||
|
||||
// If there was a element array VBO set in the VAO
|
||||
if (bufName) {
|
||||
//...delete the VBO
|
||||
glDeleteBuffers(1, &bufName);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, delete the VAO
|
||||
glDeleteVertexArrays(1, &vaoName);
|
||||
#else
|
||||
glDeleteBuffers(1, &posBufferName);
|
||||
glDeleteBuffers(1, &texcoordBufferName);
|
||||
glDeleteBuffers(1, &elementBufferName);
|
||||
#endif
|
||||
|
||||
GL_ERRLOG("gltouchjoy destroying VAO/VBOs");
|
||||
}
|
||||
|
||||
static GLuint _create_texture(GLvoid *pixels) {
|
||||
GLuint texName = UNINITIALIZED_GL;
|
||||
|
||||
// Create a texture object to apply to model
|
||||
glGenTextures(1, &texName);
|
||||
glBindTexture(GL_TEXTURE_2D, texName);
|
||||
|
||||
// Set up filter and wrap modes for this texture object
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// Indicate that pixel rows are tightly packed
|
||||
// (defaults to stride of 4 which is kind of only good for
|
||||
// RGBA or FLOAT data types)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
// register texture with OpenGL
|
||||
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, TOUCHJOY_FB_WIDTH, TOUCHJOY_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
GL_ERRLOG("gltouchjoy texture");
|
||||
|
||||
return texName;
|
||||
}
|
||||
|
||||
static void _setup_object(char *submenu, uint8_t *fb, uint8_t *pixels) {
|
||||
|
||||
// render template into indexed fb
|
||||
unsigned int submenu_width = TOUCHJOY_TEMPLATE_COLS;
|
||||
unsigned int submenu_height = TOUCHJOY_TEMPLATE_ROWS;
|
||||
video_interface_print_submenu_centered_fb(fb, submenu_width, submenu_height, submenu, submenu_width, submenu_height);
|
||||
|
||||
// generate RGBA_8888 from indexed color
|
||||
unsigned int count = TOUCHJOY_FB_WIDTH * TOUCHJOY_FB_HEIGHT;
|
||||
for (unsigned int i=0, j=0; i<count; i++, j+=4) {
|
||||
uint8_t index = *(fb + i);
|
||||
uint32_t rgb = (((uint32_t)(colormap[index].red) << 0 ) |
|
||||
((uint32_t)(colormap[index].green) << 8 ) |
|
||||
((uint32_t)(colormap[index].blue) << 16));
|
||||
if (rgb == 0) {
|
||||
// make black transparent for joystick
|
||||
} else {
|
||||
rgb |= ((uint32_t)0xff << 24);
|
||||
}
|
||||
*( (uint32_t*)(pixels + j) ) = rgb;
|
||||
}
|
||||
}
|
||||
|
||||
static void _setup_axis_object(void) {
|
||||
axisTemplate[1][2] = upChar;
|
||||
axisTemplate[2][1] = leftChar;
|
||||
axisTemplate[2][3] = rightChar;
|
||||
axisTemplate[3][2] = downChar;
|
||||
_setup_object(axisTemplate[0], touchAxisObjFB, touchAxisObjPixels);
|
||||
axisTextureDirty = true;
|
||||
}
|
||||
|
||||
static void _setup_button_object(void) {
|
||||
buttonTemplate[1][3] = button1Char;
|
||||
buttonTemplate[3][1] = button0Char;
|
||||
_setup_object(buttonTemplate[0], buttonObjFB, buttonObjPixels);
|
||||
buttonTextureDirty = true;
|
||||
}
|
||||
|
||||
static void _model_to_screen(float screenCoords[4], demoModel *model) {
|
||||
|
||||
float x0 = 1.0;
|
||||
float y0 = 1.0;
|
||||
float x1 = -1.0;
|
||||
float y1 = -1.0;
|
||||
|
||||
#if PERSPECTIVE
|
||||
#error TODO FIXME we really should do it this way regardless of whether we are using PERSPECTIVE ...
|
||||
// project models to screen space for touch handling
|
||||
GLfloat mvp[16];
|
||||
#else
|
||||
#warning TODO FIXME ... should really use matrix calculations (assuming identity/orthographic for now)
|
||||
GLfloat *positions = (GLfloat *)(model->positions);
|
||||
unsigned int stride = model->positionSize;
|
||||
unsigned int len = model->positionArraySize/_get_gl_type_size(model->positionType);
|
||||
for (unsigned int i=0; i < len; i += stride) {
|
||||
float x = (positions[i] + 1.f) / 2.f;
|
||||
if (x < x0) {
|
||||
x0 = x;
|
||||
}
|
||||
if (x > x1) {
|
||||
x1 = x;
|
||||
}
|
||||
float y = (positions[i+1] + 1.f) / 2.f;
|
||||
LOG("\tmodel x:%f, y:%f", x, y);
|
||||
if (y < y0) {
|
||||
y0 = y;
|
||||
}
|
||||
if (y > y1) {
|
||||
y1 = y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// OpenGL screen origin is bottom-left (Android is top-left)
|
||||
float yFlip0 = viewportHeight - (y1 * viewportHeight);
|
||||
float yFlip1 = viewportHeight - (y0 * viewportHeight);
|
||||
|
||||
screenCoords[0] = x0 * viewportWidth;
|
||||
screenCoords[1] = yFlip0;
|
||||
screenCoords[2] = x1 * viewportWidth;
|
||||
screenCoords[3] = yFlip1;
|
||||
}
|
||||
|
||||
static void gltouchjoy_init(void) {
|
||||
LOG("gltouchjoy_init ...");
|
||||
|
||||
mdlDestroyModel(touchAxisObjModel);
|
||||
mdlDestroyModel(buttonObjModel);
|
||||
|
||||
touchAxisObjModel = _create_model(-1.05, -1.0);
|
||||
touchAxisObjVAOName = UNINITIALIZED_GL;
|
||||
touchAxisObjPosBufferName = UNINITIALIZED_GL;
|
||||
touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
touchAxisObjElementBufferName = UNINITIALIZED_GL;
|
||||
_create_VAO_VBOs(touchAxisObjModel, &touchAxisObjVAOName, &touchAxisObjPosBufferName, &touchAxisObjTexcoordBufferName, &touchAxisObjElementBufferName);
|
||||
if (touchAxisObjPosBufferName == UNINITIALIZED_GL || touchAxisObjTexcoordBufferName == UNINITIALIZED_GL || touchAxisObjElementBufferName == UNINITIALIZED_GL)
|
||||
{
|
||||
LOG("gltouchjoy not initializing axis");
|
||||
return;
|
||||
}
|
||||
|
||||
touchAxisObjTextureName = _create_texture(touchAxisObjPixels);
|
||||
if (touchAxisObjTextureName == UNINITIALIZED_GL) {
|
||||
LOG("gltouchjoy not initializing axis: texture error");
|
||||
return;
|
||||
}
|
||||
_setup_axis_object();
|
||||
|
||||
float screenCoords[4] = { 0 };
|
||||
|
||||
_model_to_screen(screenCoords, touchAxisObjModel);
|
||||
touchAxisObjModelScreenX = (int)screenCoords[0];
|
||||
touchAxisObjModelScreenY = (int)screenCoords[1];
|
||||
touchAxisObjModelScreenXMax = (int)screenCoords[2];
|
||||
touchAxisObjModelScreenYMax = (int)screenCoords[3];
|
||||
LOG("axis screen coords: [%d,%d] -> [%d,%d]", touchAxisObjModelScreenX, touchAxisObjModelScreenY, touchAxisObjModelScreenXMax, touchAxisObjModelScreenYMax);
|
||||
|
||||
// button object
|
||||
|
||||
buttonObjModel = _create_model(1.05-model_width, -1.0);
|
||||
buttonObjVAOName = UNINITIALIZED_GL;
|
||||
buttonObjPosBufferName = UNINITIALIZED_GL;
|
||||
buttonObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
buttonObjElementBufferName = UNINITIALIZED_GL;
|
||||
_create_VAO_VBOs(buttonObjModel, &buttonObjVAOName, &buttonObjPosBufferName, &buttonObjTexcoordBufferName, &buttonObjElementBufferName);
|
||||
if (buttonObjPosBufferName == UNINITIALIZED_GL || buttonObjTexcoordBufferName == UNINITIALIZED_GL || buttonObjElementBufferName == UNINITIALIZED_GL)
|
||||
{
|
||||
LOG("gltouchjoy not initializing buttons");
|
||||
return;
|
||||
}
|
||||
|
||||
buttonObjTextureName = _create_texture(buttonObjPixels);
|
||||
if (buttonObjTextureName == UNINITIALIZED_GL) {
|
||||
LOG("not initializing buttons: texture error");
|
||||
return;
|
||||
}
|
||||
_setup_button_object();
|
||||
|
||||
// NOTE : button model is a composite of both button 0 and button 1 (with ability to press both with one touch)
|
||||
|
||||
_model_to_screen(screenCoords, buttonObjModel);
|
||||
|
||||
int button0W = ((int)screenCoords[2] - (int)screenCoords[0]) >>1;
|
||||
buttonObj0ScreenX = (int)screenCoords[0]+button0W;
|
||||
buttonObj0ScreenY = (int)screenCoords[1];
|
||||
buttonObj0ScreenXMax = (int)screenCoords[2];
|
||||
buttonObj0ScreenYMax = (int)screenCoords[3];
|
||||
LOG("button 0 screen coords: [%d,%d] -> [%d,%d]", buttonObj0ScreenX, buttonObj0ScreenY, buttonObj0ScreenXMax, buttonObj0ScreenYMax);
|
||||
|
||||
int button1H = ((int)screenCoords[3] - (int)screenCoords[1]) >>1;
|
||||
buttonObj1ScreenX = (int)screenCoords[0];
|
||||
buttonObj1ScreenY = (int)screenCoords[1]+button1H;
|
||||
buttonObj1ScreenXMax = (int)screenCoords[2];
|
||||
buttonObj1ScreenYMax = (int)screenCoords[3];
|
||||
LOG("button 1 screen coords: [%d,%d] -> [%d,%d]", buttonObj1ScreenX, buttonObj1ScreenY, buttonObj1ScreenXMax, buttonObj1ScreenYMax);
|
||||
|
||||
isAvailable = true;
|
||||
}
|
||||
|
||||
static void gltouchjoy_destroy(void) {
|
||||
LOG("gltouchjoy_destroy ...");
|
||||
if (!isAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
isAvailable = false;
|
||||
|
||||
glDeleteTextures(1, &touchAxisObjTextureName);
|
||||
touchAxisObjTextureName = UNINITIALIZED_GL;
|
||||
_destroy_VAO_VBOs(touchAxisObjVAOName, touchAxisObjPosBufferName, touchAxisObjTexcoordBufferName, touchAxisObjElementBufferName);
|
||||
touchAxisObjVAOName = UNINITIALIZED_GL;
|
||||
touchAxisObjPosBufferName = UNINITIALIZED_GL;
|
||||
touchAxisObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
touchAxisObjElementBufferName = UNINITIALIZED_GL;
|
||||
mdlDestroyModel(touchAxisObjModel);
|
||||
touchAxisObjModel = NULL;
|
||||
|
||||
glDeleteTextures(1, &buttonObjTextureName);
|
||||
buttonObjTextureName = UNINITIALIZED_GL;
|
||||
_destroy_VAO_VBOs(buttonObjVAOName, buttonObjPosBufferName, buttonObjTexcoordBufferName, buttonObjElementBufferName);
|
||||
buttonObjVAOName = UNINITIALIZED_GL;
|
||||
buttonObjPosBufferName = UNINITIALIZED_GL;
|
||||
buttonObjTexcoordBufferName = UNINITIALIZED_GL;
|
||||
buttonObjElementBufferName = UNINITIALIZED_GL;
|
||||
mdlDestroyModel(buttonObjModel);
|
||||
buttonObjModel = NULL;
|
||||
}
|
||||
|
||||
static void _render_object(demoModel *model, GLuint vaoName, GLuint posBufferName, GLuint texcoordBufferName, GLuint elementBufferName) {
|
||||
|
||||
// Bind our vertex array object
|
||||
#if USE_VAO
|
||||
glBindVertexArray(vaoName);
|
||||
#else
|
||||
glBindBuffer(GL_ARRAY_BUFFER, posBufferName);
|
||||
|
||||
GLsizei posTypeSize = _get_gl_type_size(model->positionType);
|
||||
GLsizei texcoordTypeSize = _get_gl_type_size(model->texcoordType);
|
||||
|
||||
// Set up parmeters for position attribute in the VAO including, size, type, stride, and offset in the currenly
|
||||
// bound VAO This also attaches the position VBO to the VAO
|
||||
glVertexAttribPointer(POS_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
|
||||
model->positionSize, // How many elements are there per position?
|
||||
model->positionType, // What is the type of this data?
|
||||
GL_FALSE, // Do we want to normalize this data (0-1 range for fixed-pont types)
|
||||
model->positionSize*posTypeSize, // What is the stride (i.e. bytes between positions)?
|
||||
0); // What is the offset in the VBO to the position data?
|
||||
glEnableVertexAttribArray(POS_ATTRIB_IDX);
|
||||
|
||||
// Set up parmeters for texcoord attribute in the VAO including, size, type, stride, and offset in the currenly
|
||||
// bound VAO This also attaches the texcoord VBO to VAO
|
||||
glBindBuffer(GL_ARRAY_BUFFER, texcoordBufferName);
|
||||
glVertexAttribPointer(TEXCOORD_ATTRIB_IDX, // What attibute index will this array feed in the vertex shader (see buildProgram)
|
||||
model->texcoordSize, // How many elements are there per texture coord?
|
||||
model->texcoordType, // What is the type of this data in the array?
|
||||
GL_TRUE, // Do we want to normalize this data (0-1 range for fixed-point types)
|
||||
model->texcoordSize*texcoordTypeSize,// What is the stride (i.e. bytes between texcoords)?
|
||||
0); // What is the offset in the VBO to the texcoord data?
|
||||
glEnableVertexAttribArray(TEXCOORD_ATTRIB_IDX);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferName);
|
||||
#endif
|
||||
|
||||
glUniform1f(alphaValue, 1.0);
|
||||
|
||||
// Draw the object
|
||||
glDrawElements(GL_TRIANGLES, model->numElements, model->elementType, 0);
|
||||
GL_ERRLOG("gltouchjoy render");
|
||||
}
|
||||
|
||||
static void gltouchjoy_render(void) {
|
||||
if (!isAvailable) {
|
||||
return;
|
||||
}
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
glViewport(0, 0, viewportWidth, viewportHeight);
|
||||
|
||||
glActiveTexture(TEXTURE_ACTIVE_TOUCHJOY_AXIS);
|
||||
glBindTexture(GL_TEXTURE_2D, touchAxisObjTextureName);
|
||||
if (axisTextureDirty) {
|
||||
axisTextureDirty = false;
|
||||
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, TOUCHJOY_FB_WIDTH, TOUCHJOY_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)touchAxisObjPixels);
|
||||
}
|
||||
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHJOY_AXIS);
|
||||
_render_object(touchAxisObjModel, touchAxisObjVAOName, touchAxisObjPosBufferName, touchAxisObjTexcoordBufferName, touchAxisObjElementBufferName);
|
||||
|
||||
glActiveTexture(TEXTURE_ACTIVE_TOUCHJOY_BUTTON);
|
||||
glBindTexture(GL_TEXTURE_2D, buttonObjTextureName);
|
||||
if (buttonTextureDirty) {
|
||||
buttonTextureDirty = false;
|
||||
glTexImage2D(GL_TEXTURE_2D, /*level*/0, /*internal format*/GL_RGBA, TOUCHJOY_FB_WIDTH, TOUCHJOY_FB_HEIGHT, /*border*/0, /*format*/GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)buttonObjPixels);
|
||||
}
|
||||
glUniform1i(uniformTex2Use, TEXTURE_ID_TOUCHJOY_BUTTON);
|
||||
_render_object(buttonObjModel, buttonObjVAOName, buttonObjPosBufferName, buttonObjTexcoordBufferName, buttonObjElementBufferName);
|
||||
}
|
||||
|
||||
static void gltouchjoy_reshape(int w, int h) {
|
||||
LOG("gltouchjoy_reshape(%d, %d)", w, h);
|
||||
|
||||
if (w > viewportWidth) {
|
||||
viewportWidth = w;
|
||||
}
|
||||
if (h > viewportHeight) {
|
||||
viewportHeight = h;
|
||||
}
|
||||
}
|
||||
|
||||
static void gltouchjoy_resetJoystick(void) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
static inline bool _is_point_on_axis(float x, float y) {
|
||||
return (x >= touchAxisObjModelScreenX && x <= touchAxisObjModelScreenXMax && y >= touchAxisObjModelScreenY && y <= touchAxisObjModelScreenYMax);
|
||||
}
|
||||
|
||||
static inline bool _is_point_on_button0(float x, float y) {
|
||||
return (x >= buttonObj0ScreenX && x <= buttonObj0ScreenXMax && y >= buttonObj0ScreenY && y <= buttonObj0ScreenYMax);
|
||||
}
|
||||
|
||||
static inline bool _is_point_on_button1(float x, float y) {
|
||||
return (x >= buttonObj1ScreenX && x <= buttonObj1ScreenXMax && y >= buttonObj1ScreenY && y <= buttonObj1ScreenYMax);
|
||||
}
|
||||
|
||||
static inline void _move_joystick_axis(float x, float y) {
|
||||
|
||||
int buttonW = touchAxisObjModelScreenXMax - touchAxisObjModelScreenX;
|
||||
float halfJoyX = buttonW/2.f;
|
||||
int buttonH = touchAxisObjModelScreenYMax - touchAxisObjModelScreenY;
|
||||
float halfJoyY = buttonH/2.f;
|
||||
|
||||
float x_mod = 256.f/buttonW;
|
||||
float y_mod = 256.f/buttonH;
|
||||
|
||||
float x0 = (x - touchAxisObjModelScreenX) * x_mod;
|
||||
float y0 = (y - touchAxisObjModelScreenY) * y_mod;
|
||||
|
||||
joy_x = (uint16_t)x0;
|
||||
if (joy_x > 0xff) {
|
||||
joy_x = 0xff;
|
||||
}
|
||||
joy_y = (uint16_t)y0;
|
||||
if (joy_y > 0xff) {
|
||||
joy_y = 0xff;
|
||||
}
|
||||
|
||||
LOG("\tjoystick : (%d,%d)", joy_x, joy_y);
|
||||
}
|
||||
|
||||
static bool gltouchjoy_onTouchEvent(joystick_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
|
||||
|
||||
if (!isAvailable) {
|
||||
return false;
|
||||
}
|
||||
if (!isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool axisConsumed = false;
|
||||
bool buttonConsumed = false;
|
||||
|
||||
float x = x_coords[pointer_idx];
|
||||
float y = y_coords[pointer_idx];
|
||||
|
||||
switch (action) {
|
||||
case TOUCH_DOWN:
|
||||
LOG("---TOUCH DOWN");
|
||||
case TOUCH_POINTER_DOWN:
|
||||
if (action == TOUCH_POINTER_DOWN) {
|
||||
LOG("---TOUCH POINTER DOWN");
|
||||
}
|
||||
if (_is_point_on_axis(x, y)) {
|
||||
if (trackingAxisIndex >= 0) {
|
||||
// already tracking a different pointer for the axis ...
|
||||
axisConsumed = true;
|
||||
trackingAxisIndex = pointer_idx;
|
||||
LOG("\taxis event : saw %d but already tracking %d", pointer_idx, trackingAxisIndex);
|
||||
_move_joystick_axis(x, y);
|
||||
} else {
|
||||
axisConsumed = true;
|
||||
trackingAxisIndex = pointer_idx;
|
||||
LOG("\taxis event : begin tracking %d", trackingAxisIndex);
|
||||
_move_joystick_axis(x, y);
|
||||
}
|
||||
} else {
|
||||
bool isOn0 = _is_point_on_button0(x, y);
|
||||
bool isOn1 = _is_point_on_button1(x, y);
|
||||
if (isOn0 && isOn1) {
|
||||
trackingButton0Index = TOUCHED_NONE;
|
||||
trackingButton1Index = TOUCHED_NONE;
|
||||
trackingButtonBothIndex = pointer_idx;
|
||||
buttonConsumed = true;
|
||||
joy_button0 = 0x80;
|
||||
joy_button1 = 0x80;
|
||||
LOG("\tbutton0&1 event : index:%d joy_button0:%02X joy_button1:%02X", pointer_idx, joy_button0, joy_button1);
|
||||
} else if (isOn0) {
|
||||
trackingButton0Index = pointer_idx;
|
||||
trackingButton1Index = TOUCHED_NONE;
|
||||
trackingButtonBothIndex = TOUCHED_NONE;
|
||||
buttonConsumed = true;
|
||||
joy_button0 = 0x80;
|
||||
joy_button1 = 0x0;
|
||||
LOG("\tbutton0 event : index:%d joy_button0:%02X", pointer_idx, joy_button0);
|
||||
} else if (isOn1) {
|
||||
trackingButton0Index = TOUCHED_NONE;
|
||||
trackingButton1Index = pointer_idx;
|
||||
trackingButtonBothIndex = TOUCHED_NONE;
|
||||
buttonConsumed = true;
|
||||
joy_button0 = 0x0;
|
||||
joy_button1 = 0x80;
|
||||
LOG("\tbutton1 event : index:%d joy_button1:%02X", pointer_idx, joy_button1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TOUCH_MOVE:
|
||||
LOG("---TOUCH MOVE");
|
||||
if (trackingAxisIndex >= 0) {
|
||||
axisConsumed = true;
|
||||
x = x_coords[trackingAxisIndex];
|
||||
y = y_coords[trackingAxisIndex];
|
||||
LOG("\t...tracking axis:%d (count:%d)", trackingAxisIndex, pointer_count);
|
||||
_move_joystick_axis(x, y);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOUCH_UP:
|
||||
LOG("---TOUCH UP");
|
||||
case TOUCH_POINTER_UP:
|
||||
if (action == TOUCH_POINTER_UP) {
|
||||
LOG("---TOUCH POINTER UP");
|
||||
}
|
||||
if (pointer_idx == trackingAxisIndex) {
|
||||
axisConsumed = true;
|
||||
trackingAxisIndex = TOUCHED_NONE;
|
||||
joy_x = HALF_JOY_RANGE;
|
||||
joy_y = HALF_JOY_RANGE;
|
||||
LOG("\taxis went up");
|
||||
} else if (pointer_idx == trackingButtonBothIndex) {
|
||||
buttonConsumed = true;
|
||||
trackingButtonBothIndex = TOUCHED_NONE;
|
||||
joy_button0 = 0x0;
|
||||
joy_button1 = 0x0;
|
||||
LOG("\tbuttons up joy_button0:%02X joy_button1:%02X", joy_button0, joy_button1);
|
||||
} else if (pointer_idx == trackingButton0Index) {
|
||||
buttonConsumed = true;
|
||||
trackingButton0Index = TOUCHED_NONE;
|
||||
joy_button0 = 0x0;
|
||||
LOG("\tbutton0 up joy_button0:%02X", joy_button0);
|
||||
} else if (pointer_idx == trackingButton1Index) {
|
||||
buttonConsumed = true;
|
||||
trackingButton1Index = TOUCHED_NONE;
|
||||
joy_button1 = 0x0;
|
||||
LOG("\tbutton1 up joy_button1:%02X", joy_button1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOUCH_CANCEL:
|
||||
LOG("---TOUCH CANCEL");
|
||||
trackingAxisIndex = TOUCHED_NONE;
|
||||
trackingButton0Index = TOUCHED_NONE;
|
||||
trackingButton1Index = TOUCHED_NONE;
|
||||
trackingButtonBothIndex = TOUCHED_NONE;
|
||||
joy_button0 = 0x0;
|
||||
joy_button1 = 0x0;
|
||||
joy_x = HALF_JOY_RANGE;
|
||||
joy_y = HALF_JOY_RANGE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("gltouchjoy saw unknown touch event : %d", action);
|
||||
break;
|
||||
}
|
||||
|
||||
if (axisConsumed || buttonConsumed) {
|
||||
LOG("\tconsumed event");
|
||||
return true;
|
||||
} else {
|
||||
LOG("\tDID NOT consume...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool gltouchjoy_isTouchJoystickAvailable(void) {
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
static void gltouchjoy_setTouchJoyEnabled(bool enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
void gltouchjoy_setTouchButtonValues(char button0Val, char button1Val) {
|
||||
button0Char = button0Val;
|
||||
button1Char = button1Val;
|
||||
_setup_button_object();
|
||||
}
|
||||
|
||||
void gltouchjoy_setTouchAxisType(touchjoy_axis_type_t axisType) {
|
||||
touchjoy_axisType = axisType;
|
||||
_setup_axis_object();
|
||||
}
|
||||
|
||||
void gltouchjoy_setTouchAxisValues(char up, char left, char right, char down) {
|
||||
upChar = up;
|
||||
leftChar = left;
|
||||
rightChar = right;
|
||||
downChar = down;
|
||||
if (touchjoy_axisType == AXIS_EMULATED_KEYBOARD) {
|
||||
_setup_axis_object();
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void _init_gltouchjoy(void) {
|
||||
LOG("Registering OpenGL software touch joystick");
|
||||
|
||||
joydriver_onTouchEvent = &gltouchjoy_onTouchEvent;
|
||||
joydriver_isTouchJoystickAvailable = &gltouchjoy_isTouchJoystickAvailable;
|
||||
joydriver_setTouchJoyEnabled = &gltouchjoy_setTouchJoyEnabled;
|
||||
joydriver_setTouchButtonValues = &gltouchjoy_setTouchButtonValues;
|
||||
joydriver_setTouchAxisType = &gltouchjoy_setTouchAxisType;
|
||||
joydriver_setTouchAxisValues = &gltouchjoy_setTouchAxisValues;
|
||||
|
||||
touchjoyAnimation.ctor = &gltouchjoy_init;
|
||||
touchjoyAnimation.dtor = &gltouchjoy_destroy;
|
||||
touchjoyAnimation.render = &gltouchjoy_render;
|
||||
touchjoyAnimation.reshape = &gltouchjoy_reshape;
|
||||
gldriver_register_animation(&touchjoyAnimation);
|
||||
}
|
||||
|
||||
void gldriver_joystick_reset(void) {
|
||||
#warning FIXME
|
||||
#warning TODO
|
||||
#warning expunge
|
||||
#warning this
|
||||
#warning API
|
||||
#warning ...
|
||||
}
|
||||
|
@ -476,6 +476,22 @@ static GLuint _build_program(demoSource *vertexSource, demoSource *fragmentSourc
|
||||
glUniform1i(messageSamplerLoc, TEXTURE_ID_MESSAGE);
|
||||
}
|
||||
|
||||
#if TOUCH_JOYSTICK
|
||||
GLint axisSamplerLoc = glGetUniformLocation(prgName, "axisTexture");
|
||||
if (axisSamplerLoc < 0) {
|
||||
LOG("OOPS, no axisSamplerLoc shader : %d", axisSamplerLoc);
|
||||
} else {
|
||||
glUniform1i(axisSamplerLoc, TEXTURE_ID_TOUCHJOY_AXIS);
|
||||
}
|
||||
|
||||
GLint buttonSamplerLoc = glGetUniformLocation(prgName, "buttonTexture");
|
||||
if (buttonSamplerLoc < 0) {
|
||||
LOG("OOPS, no buttonSamplerLoc shader : %d", buttonSamplerLoc);
|
||||
} else {
|
||||
glUniform1i(buttonSamplerLoc, TEXTURE_ID_TOUCHJOY_BUTTON);
|
||||
}
|
||||
#endif
|
||||
|
||||
uniformMVPIdx = glGetUniformLocation(prgName, "modelViewProjectionMatrix");
|
||||
if (uniformMVPIdx < 0) {
|
||||
LOG("OOPS, no modelViewProjectionMatrix in shader : %d", uniformMVPIdx);
|
||||
@ -799,6 +815,9 @@ static void gldriver_reshape(int w, int h) {
|
||||
#endif
|
||||
|
||||
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
|
||||
|
||||
// Prep any other objects/animations
|
||||
gldriver_animation_reshape(w, h);
|
||||
}
|
||||
|
||||
#if USE_GLUT
|
||||
|
@ -44,11 +44,19 @@ enum {
|
||||
enum {
|
||||
TEXTURE_ID_FRAMEBUFFER=0,
|
||||
TEXTURE_ID_MESSAGE,
|
||||
#if TOUCH_JOYSTICK
|
||||
TEXTURE_ID_TOUCHJOY_AXIS,
|
||||
TEXTURE_ID_TOUCHJOY_BUTTON,
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
TEXTURE_ACTIVE_FRAMEBUFFER = GL_TEXTURE0,
|
||||
TEXTURE_ACTIVE_MESSAGE = GL_TEXTURE1,
|
||||
#if TOUCH_JOYSTICK
|
||||
TEXTURE_ACTIVE_TOUCHJOY_AXIS = GL_TEXTURE2,
|
||||
TEXTURE_ACTIVE_TOUCHJOY_BUTTON = GL_TEXTURE3,
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline GLsizei _get_gl_type_size(GLenum type) {
|
||||
|
Loading…
Reference in New Issue
Block a user