android: initial port
This commit is contained in:
parent
1a700fd06b
commit
3fef353291
18 changed files with 1360 additions and 13 deletions
|
@ -147,8 +147,12 @@ Default build-depended cvar and constant values
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEFAULT_RENDERER
|
#ifndef DEFAULT_RENDERER
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#define DEFAULT_RENDERER "gles1"
|
||||||
|
#else
|
||||||
#define DEFAULT_RENDERER "gl"
|
#define DEFAULT_RENDERER "gl"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#define DEFAULT_CON_MAXFRAC "0.5"
|
#define DEFAULT_CON_MAXFRAC "0.5"
|
||||||
|
|
|
@ -137,7 +137,7 @@ typedef struct dll_info_s
|
||||||
void *link; // hinstance of loading library
|
void *link; // hinstance of loading library
|
||||||
} dll_info_t;
|
} dll_info_t;
|
||||||
|
|
||||||
typedef void (*setpair_t)( const char *key, const char *value, void *buffer, void *numpairs );
|
typedef void (*setpair_t)( const char *key, const void *value, void *buffer, void *numpairs );
|
||||||
|
|
||||||
// config strings are a general means of communication from
|
// config strings are a general means of communication from
|
||||||
// the server to all connected clients.
|
// the server to all connected clients.
|
||||||
|
|
|
@ -16,6 +16,7 @@ GNU General Public License for more details.
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
sentence_t g_Sentences[MAX_SENTENCES];
|
sentence_t g_Sentences[MAX_SENTENCES];
|
||||||
static uint g_numSentences;
|
static uint g_numSentences;
|
||||||
|
|
|
@ -302,7 +302,6 @@ void DSP_ClearState( void );
|
||||||
|
|
||||||
qboolean S_Init( void );
|
qboolean S_Init( void );
|
||||||
void S_Shutdown( void );
|
void S_Shutdown( void );
|
||||||
void S_Activate( qboolean active );
|
|
||||||
void S_SoundList_f( void );
|
void S_SoundList_f( void );
|
||||||
void S_SoundInfo_f( void );
|
void S_SoundInfo_f( void );
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,5 @@ void R_SaveVideoMode( int w, int h );
|
||||||
void VID_CheckChanges( void );
|
void VID_CheckChanges( void );
|
||||||
const char *VID_GetModeString( int vid_mode );
|
const char *VID_GetModeString( int vid_mode );
|
||||||
void VID_StartupGamma( void );
|
void VID_StartupGamma( void );
|
||||||
void GL_SwapBuffers();
|
|
||||||
|
|
||||||
#endif // VID_COMMON
|
#endif // VID_COMMON
|
||||||
|
|
|
@ -492,7 +492,7 @@ int Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function );
|
||||||
int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description );
|
int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description );
|
||||||
void Cmd_RemoveCommand( const char *cmd_name );
|
void Cmd_RemoveCommand( const char *cmd_name );
|
||||||
qboolean Cmd_Exists( const char *cmd_name );
|
qboolean Cmd_Exists( const char *cmd_name );
|
||||||
void Cmd_LookupCmds( char *buffer, void *ptr, setpair_t callback );
|
void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback );
|
||||||
qboolean Cmd_GetMapList( const char *s, char *completedname, int length );
|
qboolean Cmd_GetMapList( const char *s, char *completedname, int length );
|
||||||
qboolean Cmd_GetDemoList( const char *s, char *completedname, int length );
|
qboolean Cmd_GetDemoList( const char *s, char *completedname, int length );
|
||||||
qboolean Cmd_GetMovieList( const char *s, char *completedname, int length );
|
qboolean Cmd_GetMovieList( const char *s, char *completedname, int length );
|
||||||
|
|
|
@ -93,7 +93,7 @@ write screenshot into clipboard
|
||||||
*/
|
*/
|
||||||
void Sys_SetClipboardData( const byte *buffer, size_t size )
|
void Sys_SetClipboardData( const byte *buffer, size_t size )
|
||||||
{
|
{
|
||||||
Platform_SetClipboardText( (char *)buffer, size );
|
Platform_SetClipboardText( buffer, size );
|
||||||
}
|
}
|
||||||
#endif // XASH_DEDICATED
|
#endif // XASH_DEDICATED
|
||||||
|
|
||||||
|
|
956
engine/platform/android/android.c
Normal file
956
engine/platform/android/android.c
Normal file
|
@ -0,0 +1,956 @@
|
||||||
|
/*
|
||||||
|
android_nosdl.c - android backend
|
||||||
|
Copyright (C) 2016-2019 mittorn
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#if defined __ANDROID__ || 1
|
||||||
|
#include "input.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "platform/android/android_priv.h"
|
||||||
|
#include "errno.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#ifndef JNICALL
|
||||||
|
#define JNICALL // a1ba: workaround for my IDE, where Java files are not included
|
||||||
|
#define JNIEXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
convar_t *android_sleep;
|
||||||
|
|
||||||
|
static const int s_android_scantokey[] =
|
||||||
|
{
|
||||||
|
0, K_LEFTARROW, K_RIGHTARROW, K_AUX26, K_ESCAPE, // 0
|
||||||
|
K_AUX26, K_AUX25, '0', '1', '2', // 5
|
||||||
|
'3', '4', '5', '6', '7', // 10
|
||||||
|
'8', '9', '*', '#', K_UPARROW, // 15
|
||||||
|
K_DOWNARROW, K_LEFTARROW, K_RIGHTARROW, K_ENTER, K_AUX32, // 20
|
||||||
|
K_AUX31, K_AUX29, K_AUX28, K_AUX27, 'a', // 25
|
||||||
|
'b', 'c', 'd', 'e', 'f', // 30
|
||||||
|
'g', 'h', 'i', 'j', 'k', // 35
|
||||||
|
'l', 'm', 'n', 'o', 'p', // 40
|
||||||
|
'q', 'r', 's', 't', 'u', // 45
|
||||||
|
'v', 'w', 'x', 'y', 'z', // 50
|
||||||
|
',', '.', K_ALT, K_ALT, K_SHIFT, // 55
|
||||||
|
K_SHIFT, K_TAB, K_SPACE, 0, 0, // 60
|
||||||
|
0, K_ENTER, K_BACKSPACE, '`', '-', // 65
|
||||||
|
'=', '[', ']', '\\', ';', // 70
|
||||||
|
'\'', '/', '@', K_KP_NUMLOCK, 0, // 75
|
||||||
|
0, '+', '`', 0, 0, // 80
|
||||||
|
0, 0, 0, 0, 0, // 85
|
||||||
|
0, 0, K_PGUP, K_PGDN, 0, // 90
|
||||||
|
0, K_AUX1, K_AUX2, K_AUX14, K_AUX3, // 95
|
||||||
|
K_AUX4, K_AUX15, K_AUX6, K_AUX7, K_JOY1, // 100
|
||||||
|
K_JOY2, K_AUX10, K_AUX11, K_ESCAPE, K_ESCAPE, // 105
|
||||||
|
0, K_ESCAPE, K_DEL, K_CTRL, K_CTRL, // 110
|
||||||
|
K_CAPSLOCK, 0, 0, 0, 0, // 115
|
||||||
|
0, K_PAUSE, K_HOME, K_END, K_INS, // 120
|
||||||
|
0, 0, 0, 0, 0, // 125
|
||||||
|
0, K_F1, K_F2, K_F3, K_F4, // 130
|
||||||
|
K_F5, K_F6, K_F7, K_F8, K_F9, // 135
|
||||||
|
K_F10, K_F11, K_F12, K_KP_NUMLOCK, K_KP_INS, // 140
|
||||||
|
K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5, // 145
|
||||||
|
K_KP_RIGHTARROW,K_KP_HOME, K_KP_UPARROW, K_KP_PGUP, K_KP_SLASH, // 150
|
||||||
|
0, K_KP_MINUS, K_KP_PLUS, K_KP_DEL, ',', // 155
|
||||||
|
K_KP_ENTER, '=', '(', ')'
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ANDROID_MAX_EVENTS 64
|
||||||
|
#define MAX_FINGERS 10
|
||||||
|
|
||||||
|
typedef enum event_type
|
||||||
|
{
|
||||||
|
event_touch_down,
|
||||||
|
event_touch_up,
|
||||||
|
event_touch_move,
|
||||||
|
event_key_down,
|
||||||
|
event_key_up,
|
||||||
|
event_set_pause,
|
||||||
|
event_resize,
|
||||||
|
event_joyhat,
|
||||||
|
event_joyball,
|
||||||
|
event_joybutton,
|
||||||
|
event_joyaxis,
|
||||||
|
event_joyadd,
|
||||||
|
event_joyremove,
|
||||||
|
event_onpause,
|
||||||
|
event_ondestroy,
|
||||||
|
event_onresume,
|
||||||
|
event_onfocuschange
|
||||||
|
} eventtype_t;
|
||||||
|
|
||||||
|
typedef struct touchevent_s
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
} touchevent_t;
|
||||||
|
|
||||||
|
typedef struct joyball_s
|
||||||
|
{
|
||||||
|
short xrel;
|
||||||
|
short yrel;
|
||||||
|
byte ball;
|
||||||
|
} joyball_t;
|
||||||
|
|
||||||
|
typedef struct joyhat_s
|
||||||
|
{
|
||||||
|
byte hat;
|
||||||
|
byte key;
|
||||||
|
} joyhat_t;
|
||||||
|
|
||||||
|
typedef struct joyaxis_s
|
||||||
|
{
|
||||||
|
short val;
|
||||||
|
byte axis;
|
||||||
|
} joyaxis_t;
|
||||||
|
|
||||||
|
typedef struct joybutton_s
|
||||||
|
{
|
||||||
|
int down;
|
||||||
|
byte button;
|
||||||
|
} joybutton_t;
|
||||||
|
|
||||||
|
typedef struct keyevent_s
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
} keyevent_t;
|
||||||
|
|
||||||
|
typedef struct event_s
|
||||||
|
{
|
||||||
|
eventtype_t type;
|
||||||
|
int arg;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
touchevent_t touch;
|
||||||
|
joyhat_t hat;
|
||||||
|
joyball_t ball;
|
||||||
|
joyaxis_t axis;
|
||||||
|
joybutton_t button;
|
||||||
|
keyevent_t key;
|
||||||
|
};
|
||||||
|
} event_t;
|
||||||
|
|
||||||
|
typedef struct finger_s
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
qboolean down;
|
||||||
|
} finger_t;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
pthread_mutex_t mutex; // this mutex is locked while not running frame, used for events synchronization
|
||||||
|
pthread_mutex_t framemutex; // this mutex is locked while engine is running and unlocked while it reading events, used for pause in background.
|
||||||
|
event_t queue[ANDROID_MAX_EVENTS];
|
||||||
|
volatile int count;
|
||||||
|
finger_t fingers[MAX_FINGERS];
|
||||||
|
char inputtext[256];
|
||||||
|
float mousex, mousey;
|
||||||
|
} events = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
|
||||||
|
|
||||||
|
struct jnimethods_s jni;
|
||||||
|
struct nativeegl_s negl;
|
||||||
|
struct jnimouse_s jnimouse;
|
||||||
|
|
||||||
|
#define Android_Lock() pthread_mutex_lock(&events.mutex);
|
||||||
|
#define Android_Unlock() pthread_mutex_unlock(&events.mutex);
|
||||||
|
#define Android_PushEvent() Android_Unlock()
|
||||||
|
|
||||||
|
typedef void (*pfnChangeGame)( const char *progname );
|
||||||
|
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func );
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_AllocEvent
|
||||||
|
|
||||||
|
Lock event queue and return pointer to next event.
|
||||||
|
Caller must do Android_PushEvent() to unlock queue after setting parameters.
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
event_t *Android_AllocEvent()
|
||||||
|
{
|
||||||
|
Android_Lock();
|
||||||
|
if( events.count == ANDROID_MAX_EVENTS )
|
||||||
|
{
|
||||||
|
events.count--; //override last event
|
||||||
|
__android_log_print( ANDROID_LOG_ERROR, "Xash", "Too many events!!!" );
|
||||||
|
}
|
||||||
|
return &events.queue[ events.count++ ];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================================================
|
||||||
|
JNI callbacks
|
||||||
|
|
||||||
|
On application start, setenv and onNativeResize called from
|
||||||
|
ui thread to set up engine configuration
|
||||||
|
nativeInit called directly from engine thread and will not return until exit.
|
||||||
|
These functions may be called from other threads at any time:
|
||||||
|
nativeKey
|
||||||
|
nativeTouch
|
||||||
|
onNativeResize
|
||||||
|
nativeString
|
||||||
|
nativeSetPause
|
||||||
|
=====================================================
|
||||||
|
*/
|
||||||
|
#define VA_ARGS(...) , ##__VA_ARGS__ // GCC extension
|
||||||
|
#define DECLARE_JNI_INTERFACE( ret, name, ... ) \
|
||||||
|
JNIEXPORT ret JNICALL Java_in_celest_xash3d_XashActivity_##name( JNIEnv *env, jclass clazz VA_ARGS(__VA_ARGS__) )
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( int, nativeInit, jobject array )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int argc;
|
||||||
|
int status;
|
||||||
|
/* Prepare the arguments. */
|
||||||
|
|
||||||
|
int len = (*env)->GetArrayLength(env, array);
|
||||||
|
char* argv[1 + len + 1];
|
||||||
|
argc = 0;
|
||||||
|
argv[argc++] = strdup("app_process");
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
const char* utf;
|
||||||
|
char* arg = NULL;
|
||||||
|
jstring string = (*env)->GetObjectArrayElement(env, array, i);
|
||||||
|
if (string) {
|
||||||
|
utf = (*env)->GetStringUTFChars(env, string, 0);
|
||||||
|
if (utf) {
|
||||||
|
arg = strdup(utf);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, string, utf);
|
||||||
|
}
|
||||||
|
(*env)->DeleteLocalRef(env, string);
|
||||||
|
}
|
||||||
|
if (!arg) {
|
||||||
|
arg = strdup("");
|
||||||
|
}
|
||||||
|
argv[argc++] = arg;
|
||||||
|
}
|
||||||
|
argv[argc] = NULL;
|
||||||
|
prctl(PR_SET_DUMPABLE, 1);
|
||||||
|
|
||||||
|
/* Init callbacks. */
|
||||||
|
|
||||||
|
jni.env = env;
|
||||||
|
jni.actcls = (*env)->FindClass(env, "in/celest/xash3d/XashActivity");
|
||||||
|
jni.swapBuffers = (*env)->GetStaticMethodID(env, jni.actcls, "swapBuffers", "()V");
|
||||||
|
jni.toggleEGL = (*env)->GetStaticMethodID(env, jni.actcls, "toggleEGL", "(I)V");
|
||||||
|
jni.enableTextInput = (*env)->GetStaticMethodID(env, jni.actcls, "showKeyboard", "(I)V");
|
||||||
|
jni.vibrate = (*env)->GetStaticMethodID(env, jni.actcls, "vibrate", "(I)V" );
|
||||||
|
jni.messageBox = (*env)->GetStaticMethodID(env, jni.actcls, "messageBox", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||||
|
jni.createGLContext = (*env)->GetStaticMethodID(env, jni.actcls, "createGLContext", "(I)Z");
|
||||||
|
jni.getGLAttribute = (*env)->GetStaticMethodID(env, jni.actcls, "getGLAttribute", "(I)I");
|
||||||
|
jni.deleteGLContext = (*env)->GetStaticMethodID(env, jni.actcls, "deleteGLContext", "()Z");
|
||||||
|
jni.notify = (*env)->GetStaticMethodID(env, jni.actcls, "engineThreadNotify", "()V");
|
||||||
|
jni.setTitle = (*env)->GetStaticMethodID(env, jni.actcls, "setTitle", "(Ljava/lang/String;)V");
|
||||||
|
jni.setIcon = (*env)->GetStaticMethodID(env, jni.actcls, "setIcon", "(Ljava/lang/String;)V");
|
||||||
|
jni.getAndroidId = (*env)->GetStaticMethodID(env, jni.actcls, "getAndroidID", "()Ljava/lang/String;");
|
||||||
|
jni.saveID = (*env)->GetStaticMethodID(env, jni.actcls, "saveID", "(Ljava/lang/String;)V");
|
||||||
|
jni.loadID = (*env)->GetStaticMethodID(env, jni.actcls, "loadID", "()Ljava/lang/String;");
|
||||||
|
jni.showMouse = (*env)->GetStaticMethodID(env, jni.actcls, "showMouse", "(I)V");
|
||||||
|
jni.shellExecute = (*env)->GetStaticMethodID(env, jni.actcls, "shellExecute", "(Ljava/lang/String;)V");
|
||||||
|
|
||||||
|
/* Run the application. */
|
||||||
|
|
||||||
|
status = Host_Main( argc, argv, getenv("XASH3D_GAMEDIR"), false, NULL );
|
||||||
|
|
||||||
|
/* Release the arguments. */
|
||||||
|
|
||||||
|
for (i = 0; i < argc; ++i)
|
||||||
|
free(argv[i]);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, onNativeResize, jint width, jint height )
|
||||||
|
{
|
||||||
|
event_t *event;
|
||||||
|
|
||||||
|
if( !width || !height )
|
||||||
|
return;
|
||||||
|
|
||||||
|
jni.width=width, jni.height=height;
|
||||||
|
|
||||||
|
// alloc update event to change screen size
|
||||||
|
event = Android_AllocEvent();
|
||||||
|
event->type = event_resize;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeQuit )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeSetPause, jint pause )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_set_pause;
|
||||||
|
event->arg = pause;
|
||||||
|
Android_PushEvent();
|
||||||
|
|
||||||
|
// if pause enabled, hold engine by locking frame mutex.
|
||||||
|
// Engine will stop after event reading and will not continue untill unlock
|
||||||
|
if( android_sleep && android_sleep->value )
|
||||||
|
{
|
||||||
|
if( pause )
|
||||||
|
pthread_mutex_lock( &events.framemutex );
|
||||||
|
else
|
||||||
|
pthread_mutex_unlock( &events.framemutex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeUnPause )
|
||||||
|
{
|
||||||
|
// UnPause engine before sending critical events
|
||||||
|
if( android_sleep && android_sleep->value )
|
||||||
|
pthread_mutex_unlock( &events.framemutex );
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeKey, jint down, jint code )
|
||||||
|
{
|
||||||
|
event_t *event;
|
||||||
|
|
||||||
|
if( code < 0 )
|
||||||
|
{
|
||||||
|
event = Android_AllocEvent();
|
||||||
|
event->arg = (-code) & 255;
|
||||||
|
event->type = down?event_key_down:event_key_up;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( code >= ( sizeof( s_android_scantokey ) / sizeof( s_android_scantokey[0] ) ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
event = Android_AllocEvent();
|
||||||
|
event->type = down?event_key_down:event_key_up;
|
||||||
|
event->arg = s_android_scantokey[code];
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeString, jobject string )
|
||||||
|
{
|
||||||
|
char* str = (char *) (*env)->GetStringUTFChars(env, string, NULL);
|
||||||
|
|
||||||
|
Android_Lock();
|
||||||
|
strncat( events.inputtext, str, 256 );
|
||||||
|
Android_Unlock();
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars(env, string, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SOFTFP_LINK
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeTouch, jint finger, jint action, jfloat x, jfloat y ) __attribute__((pcs("aapcs")));
|
||||||
|
#endif
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeTouch, jint finger, jint action, jfloat x, jfloat y )
|
||||||
|
{
|
||||||
|
float dx, dy;
|
||||||
|
event_t *event;
|
||||||
|
|
||||||
|
// if something wrong with android event
|
||||||
|
if( finger > MAX_FINGERS )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// not touch action?
|
||||||
|
if( !( action >=0 && action <= 2 ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 0.0f .. 1.0f
|
||||||
|
x /= jni.width;
|
||||||
|
y /= jni.height;
|
||||||
|
|
||||||
|
if( action )
|
||||||
|
dx = x - events.fingers[finger].x, dy = y - events.fingers[finger].y;
|
||||||
|
else
|
||||||
|
dx = dy = 0.0f;
|
||||||
|
events.fingers[finger].x = x, events.fingers[finger].y = y;
|
||||||
|
|
||||||
|
// check if we should skip some events
|
||||||
|
if( ( action == 2 ) && ( !dx && !dy ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( ( action == 0 ) && events.fingers[finger].down )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( ( action == 1 ) && !events.fingers[finger].down )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( action == 2 && !events.fingers[finger].down )
|
||||||
|
action = 0;
|
||||||
|
|
||||||
|
if( action == 0 )
|
||||||
|
events.fingers[finger].down = true;
|
||||||
|
else if( action == 1 )
|
||||||
|
events.fingers[finger].down = false;
|
||||||
|
|
||||||
|
event = Android_AllocEvent();
|
||||||
|
event->arg = finger;
|
||||||
|
event->type = action;
|
||||||
|
event->touch.x = x;
|
||||||
|
event->touch.y = y;
|
||||||
|
event->touch.dx = dx;
|
||||||
|
event->touch.dy = dy;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeBall, jint id, jbyte ball, jshort xrel, jshort yrel )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
|
||||||
|
event->type = event_joyball;
|
||||||
|
event->arg = id;
|
||||||
|
event->ball.ball = ball;
|
||||||
|
event->ball.xrel = xrel;
|
||||||
|
event->ball.yrel = yrel;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeHat, jint id, jbyte hat, jbyte key, jboolean down )
|
||||||
|
{
|
||||||
|
static byte engineKeys;
|
||||||
|
|
||||||
|
if( !key )
|
||||||
|
engineKeys = 0; // centered;
|
||||||
|
|
||||||
|
if( down )
|
||||||
|
engineKeys |= key;
|
||||||
|
else
|
||||||
|
engineKeys &= ~key;
|
||||||
|
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_joyhat;
|
||||||
|
event->arg = id;
|
||||||
|
event->hat.hat = hat;
|
||||||
|
event->hat.key = engineKeys;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeAxis, jint id, jbyte axis, jshort val )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_joyaxis;
|
||||||
|
event->arg = id;
|
||||||
|
event->axis.axis = axis;
|
||||||
|
event->axis.val = val;
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "Xash", "axis %i %i", axis, val );
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeJoyButton, jint id, jbyte button, jboolean down )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_joybutton;
|
||||||
|
event->arg = id;
|
||||||
|
event->button.button = button;
|
||||||
|
event->button.down = down;
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "Xash", "button %i", button );
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeJoyAdd, jint id )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_joyadd;
|
||||||
|
event->arg = id;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeJoyDel, jint id )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_joyremove;
|
||||||
|
event->arg = id;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeOnResume )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_onresume;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeOnFocusChange )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_onfocuschange;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeOnPause )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_onpause;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeOnDestroy )
|
||||||
|
{
|
||||||
|
event_t *event = Android_AllocEvent();
|
||||||
|
event->type = event_ondestroy;
|
||||||
|
Android_PushEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( int, setenv, jstring key, jstring value, jboolean overwrite )
|
||||||
|
{
|
||||||
|
char* k = (char *) (*env)->GetStringUTFChars(env, key, NULL);
|
||||||
|
char* v = (char *) (*env)->GetStringUTFChars(env, value, NULL);
|
||||||
|
int err = setenv(k, v, overwrite);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, key, k);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, value, v);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( void, nativeMouseMove, jfloat x, jfloat y )
|
||||||
|
{
|
||||||
|
Android_Lock();
|
||||||
|
events.mousex += x;
|
||||||
|
events.mousey += y;
|
||||||
|
Android_Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JNI_INTERFACE( int, nativeTestWritePermission, jstring jPath )
|
||||||
|
{
|
||||||
|
char *path = (char *)(*env)->GetStringUTFChars(env, jPath, NULL);
|
||||||
|
FILE *fd;
|
||||||
|
char testFile[PATH_MAX];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// maybe generate new file everytime?
|
||||||
|
Q_snprintf( testFile, PATH_MAX, "%s/.testfile", path );
|
||||||
|
|
||||||
|
__android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: file=%s", testFile );
|
||||||
|
|
||||||
|
fd = fopen( testFile, "w+" );
|
||||||
|
|
||||||
|
if( fd )
|
||||||
|
{
|
||||||
|
__android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: passed" );
|
||||||
|
ret = 1;
|
||||||
|
fclose( fd );
|
||||||
|
|
||||||
|
remove( testFile );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: error=%s", strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars( env, jPath, path );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *reserved )
|
||||||
|
{
|
||||||
|
return JNI_VERSION_1_6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_Init
|
||||||
|
|
||||||
|
Initialize android-related cvars
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_Init()
|
||||||
|
{
|
||||||
|
android_sleep = Cvar_Get( "android_sleep", "1", FCVAR_ARCHIVE, "Enable sleep in background" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_EnableTextInput
|
||||||
|
|
||||||
|
Show virtual keyboard
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Platform_EnableTextInput( qboolean enable )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.enableTextInput, enable );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_Vibrate
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Platform_Vibrate( float life, char flags )
|
||||||
|
{
|
||||||
|
if( life )
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.vibrate, (int)life );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_GetNativeObject
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void *Platform_GetNativeObject( const char *objName )
|
||||||
|
{
|
||||||
|
static const char *availObjects[] = { "JNIEnv", "ActivityClass", NULL };
|
||||||
|
void *object = NULL;
|
||||||
|
|
||||||
|
if( !objName )
|
||||||
|
{
|
||||||
|
object = (void*)availObjects;
|
||||||
|
}
|
||||||
|
else if( !strcasecmp( objName, "JNIEnv" ) )
|
||||||
|
{
|
||||||
|
object = (void*)jni.env;
|
||||||
|
}
|
||||||
|
else if( !strcasecmp( objName, "ActivityClass" ) )
|
||||||
|
{
|
||||||
|
object = (void*)jni.actcls;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_MessageBox
|
||||||
|
|
||||||
|
Show messagebox and wait for OK button press
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Platform_MessageBox( const char *title, const char *text, qboolean parentMainWindow )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.messageBox, (*jni.env)->NewStringUTF( jni.env, title ), (*jni.env)->NewStringUTF( jni.env ,text ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_GetAndroidID
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
const char *Android_GetAndroidID( void )
|
||||||
|
{
|
||||||
|
static char id[65];
|
||||||
|
|
||||||
|
if( id[0] )
|
||||||
|
return id;
|
||||||
|
|
||||||
|
jstring resultJNIStr = (jstring)(*jni.env)->CallStaticObjectMethod( jni.env, jni.actcls, jni.getAndroidId );
|
||||||
|
const char *resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL );
|
||||||
|
Q_strncpy( id, resultCStr, 64 );
|
||||||
|
(*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr );
|
||||||
|
|
||||||
|
if( !id[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_LoadID
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
const char *Android_LoadID( void )
|
||||||
|
{
|
||||||
|
static char id[65];
|
||||||
|
jstring resultJNIStr = (jstring)(*jni.env)->CallStaticObjectMethod( jni.env, jni.actcls, jni.loadID );
|
||||||
|
const char *resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL );
|
||||||
|
Q_strncpy( id, resultCStr, 64 );
|
||||||
|
(*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr );
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_SaveID
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_SaveID( const char *id )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.saveID, (*jni.env)->NewStringUTF( jni.env, id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_MouseMove
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_MouseMove( float *x, float *y )
|
||||||
|
{
|
||||||
|
*x = jnimouse.x;
|
||||||
|
*y = jnimouse.y;
|
||||||
|
jnimouse.x = 0;
|
||||||
|
jnimouse.y = 0;
|
||||||
|
// Con_Reportf( "Android_MouseMove: %f %f\n", *x, *y );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_AddMove
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_AddMove( float x, float y )
|
||||||
|
{
|
||||||
|
jnimouse.x += x;
|
||||||
|
jnimouse.y += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_GetMousePos( int *x, int *y )
|
||||||
|
{
|
||||||
|
// stub
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_SetMousePos( int x, int y )
|
||||||
|
{
|
||||||
|
// stub
|
||||||
|
}
|
||||||
|
|
||||||
|
int Platform_JoyInit( int numjoy )
|
||||||
|
{
|
||||||
|
// stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_ShowMouse
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_ShowMouse( qboolean show )
|
||||||
|
{
|
||||||
|
if( m_ignore->value )
|
||||||
|
show = true;
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.showMouse, show );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_ShellExecute
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Platform_ShellExecute( const char *path, const char *parms )
|
||||||
|
{
|
||||||
|
jstring jstr;
|
||||||
|
|
||||||
|
if( !path )
|
||||||
|
return; // useless
|
||||||
|
|
||||||
|
// get java.lang.String
|
||||||
|
jstr = (*jni.env)->NewStringUTF( jni.env, path );
|
||||||
|
|
||||||
|
// open browser
|
||||||
|
(*jni.env)->CallStaticVoidMethod(jni.env, jni.actcls, jni.shellExecute, jstr);
|
||||||
|
|
||||||
|
// no need to free jstr
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_GetClipboardText( char *buffer, size_t size )
|
||||||
|
{
|
||||||
|
// stub
|
||||||
|
if( size ) buffer[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_SetClipboardText( const char *buffer, size_t size )
|
||||||
|
{
|
||||||
|
// stub
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_RunEvents
|
||||||
|
|
||||||
|
Execute all events from queue
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Platform_RunEvents()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// enter events read
|
||||||
|
Android_Lock();
|
||||||
|
pthread_mutex_unlock( &events.framemutex );
|
||||||
|
|
||||||
|
for( i = 0; i < events.count; i++ )
|
||||||
|
{
|
||||||
|
switch( events.queue[i].type )
|
||||||
|
{
|
||||||
|
case event_touch_down:
|
||||||
|
case event_touch_up:
|
||||||
|
case event_touch_move:
|
||||||
|
#if 0 // TOUCHTODO
|
||||||
|
IN_TouchEvent( events.queue[i].type, events.queue[i].arg,
|
||||||
|
events.queue[i].touch.x, events.queue[i].touch.y,
|
||||||
|
events.queue[i].touch.dx, events.queue[i].touch.dy );
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case event_key_down:
|
||||||
|
Key_Event( events.queue[i].arg, true );
|
||||||
|
|
||||||
|
if( events.queue[i].arg == K_AUX31 || events.queue[i].arg == K_AUX29 )
|
||||||
|
{
|
||||||
|
host.force_draw_version = true;
|
||||||
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case event_key_up:
|
||||||
|
Key_Event( events.queue[i].arg, false );
|
||||||
|
|
||||||
|
if( events.queue[i].arg == K_AUX31 || events.queue[i].arg == K_AUX29 )
|
||||||
|
{
|
||||||
|
host.force_draw_version = true;
|
||||||
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case event_set_pause:
|
||||||
|
// destroy EGL surface when hiding application
|
||||||
|
if( !events.queue[i].arg )
|
||||||
|
{
|
||||||
|
host.status = HOST_FRAME;
|
||||||
|
SNDDMA_Activate( true );
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 );
|
||||||
|
Android_UpdateSurface();
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED ); // set swap interval
|
||||||
|
host.force_draw_version = true;
|
||||||
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( events.queue[i].arg )
|
||||||
|
{
|
||||||
|
host.status = HOST_NOFOCUS;
|
||||||
|
SNDDMA_Activate( false );
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 );
|
||||||
|
negl.valid = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case event_resize:
|
||||||
|
// reinitialize EGL and change engine screen size
|
||||||
|
if( host.status == HOST_NORMAL && ( refState.width != jni.width || refState.height != jni.height ) )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 );
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 );
|
||||||
|
Android_UpdateSurface();
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED ); // set swap interval
|
||||||
|
VID_SetMode();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case event_joyadd:
|
||||||
|
Joy_AddEvent( events.queue[i].arg );
|
||||||
|
break;
|
||||||
|
case event_joyremove:
|
||||||
|
Joy_RemoveEvent( events.queue[i].arg );
|
||||||
|
break;
|
||||||
|
case event_joyball:
|
||||||
|
if( !Joy_IsActive() )
|
||||||
|
Joy_AddEvent( 0 );
|
||||||
|
Joy_BallMotionEvent( events.queue[i].arg, events.queue[i].ball.ball,
|
||||||
|
events.queue[i].ball.xrel, events.queue[i].ball.yrel );
|
||||||
|
break;
|
||||||
|
case event_joyhat:
|
||||||
|
if( !Joy_IsActive() )
|
||||||
|
Joy_AddEvent( 0 );
|
||||||
|
Joy_HatMotionEvent( events.queue[i].arg, events.queue[i].hat.hat, events.queue[i].hat.key );
|
||||||
|
break;
|
||||||
|
case event_joyaxis:
|
||||||
|
if( !Joy_IsActive() )
|
||||||
|
Joy_AddEvent( 0 );
|
||||||
|
Joy_AxisMotionEvent( events.queue[i].arg, events.queue[i].axis.axis, events.queue[i].axis.val );
|
||||||
|
break;
|
||||||
|
case event_joybutton:
|
||||||
|
if( !Joy_IsActive() )
|
||||||
|
Joy_AddEvent( 0 );
|
||||||
|
Joy_ButtonEvent( events.queue[i].arg, events.queue[i].button.button, (byte)events.queue[i].button.down );
|
||||||
|
break;
|
||||||
|
case event_ondestroy:
|
||||||
|
//host.skip_configs = true; // skip config save, because engine may be killed during config save
|
||||||
|
Sys_Quit();
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.notify );
|
||||||
|
break;
|
||||||
|
case event_onpause:
|
||||||
|
#ifdef PARANOID_CONFIG_SAVE
|
||||||
|
switch( host.status )
|
||||||
|
{
|
||||||
|
case HOST_INIT:
|
||||||
|
case HOST_CRASHED:
|
||||||
|
case HOST_ERR_FATAL:
|
||||||
|
Con_Reportf( S_WARN "Abnormal host state during onPause (%d), skipping config save!\n", host.status );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// restore all latched cheat cvars
|
||||||
|
Cvar_SetCheatState( true );
|
||||||
|
Host_WriteConfig();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// disable sound during call/screen-off
|
||||||
|
SNDDMA_Activate( false );
|
||||||
|
host.status = HOST_NOFOCUS;
|
||||||
|
// stop blocking UI thread
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.notify );
|
||||||
|
|
||||||
|
break;
|
||||||
|
case event_onresume:
|
||||||
|
// re-enable sound after onPause
|
||||||
|
host.status = HOST_FRAME;
|
||||||
|
SNDDMA_Activate( true );
|
||||||
|
host.force_draw_version = true;
|
||||||
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
|
break;
|
||||||
|
case event_onfocuschange:
|
||||||
|
host.force_draw_version = true;
|
||||||
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events.count = 0; // no more events
|
||||||
|
|
||||||
|
// text input handled separately to allow unicode symbols
|
||||||
|
for( i = 0; events.inputtext[i]; i++ )
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
// if engine does not use utf-8, we need to convert it to preferred encoding
|
||||||
|
if( !Q_stricmp( cl_charset->string, "utf-8" ) )
|
||||||
|
ch = (unsigned char)events.inputtext[i];
|
||||||
|
else
|
||||||
|
ch = Con_UtfProcessCharForce( (unsigned char)events.inputtext[i] );
|
||||||
|
|
||||||
|
if( !ch ) // utf-8
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// some keyboards may send enter as text
|
||||||
|
if( ch == '\n' )
|
||||||
|
{
|
||||||
|
Key_Event( K_ENTER, true );
|
||||||
|
Key_Event( K_ENTER, false );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise just push it by char, text render will decode unicode strings
|
||||||
|
CL_CharEvent( ch );
|
||||||
|
}
|
||||||
|
events.inputtext[0] = 0; // no more text
|
||||||
|
|
||||||
|
jnimouse.x += events.mousex;
|
||||||
|
events.mousex = 0;
|
||||||
|
jnimouse.y += events.mousey;
|
||||||
|
events.mousey = 0;
|
||||||
|
|
||||||
|
//end events read
|
||||||
|
Android_Unlock();
|
||||||
|
pthread_mutex_lock( &events.framemutex );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __ANDROID__
|
51
engine/platform/android/android_priv.h
Normal file
51
engine/platform/android/android_priv.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef ANDROID_PRIV_H
|
||||||
|
#define ANDROID_PRIV_H
|
||||||
|
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
extern struct jnimethods_s
|
||||||
|
{
|
||||||
|
jclass actcls;
|
||||||
|
JavaVM *vm;
|
||||||
|
JNIEnv *env;
|
||||||
|
jmethodID swapBuffers;
|
||||||
|
jmethodID toggleEGL;
|
||||||
|
jmethodID enableTextInput;
|
||||||
|
jmethodID vibrate;
|
||||||
|
jmethodID messageBox;
|
||||||
|
jmethodID createGLContext;
|
||||||
|
jmethodID getGLAttribute;
|
||||||
|
jmethodID deleteGLContext;
|
||||||
|
jmethodID notify;
|
||||||
|
jmethodID setTitle;
|
||||||
|
jmethodID setIcon;
|
||||||
|
jmethodID getAndroidId;
|
||||||
|
jmethodID saveID;
|
||||||
|
jmethodID loadID;
|
||||||
|
jmethodID showMouse;
|
||||||
|
jmethodID shellExecute;
|
||||||
|
int width, height;
|
||||||
|
} jni;
|
||||||
|
|
||||||
|
extern struct nativeegl_s
|
||||||
|
{
|
||||||
|
qboolean valid;
|
||||||
|
EGLDisplay dpy;
|
||||||
|
EGLSurface surface;
|
||||||
|
} negl;
|
||||||
|
|
||||||
|
extern struct jnimouse_s
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
} jnimouse;
|
||||||
|
|
||||||
|
//
|
||||||
|
// vid_android.c
|
||||||
|
//
|
||||||
|
void Android_UpdateSurface( void );
|
||||||
|
|
||||||
|
#endif // ANDROID_PRIV_H
|
|
@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "platform.h"
|
#include "platform/platform.h"
|
||||||
#if XASH_SOUND == SOUND_OPENSLES
|
#if XASH_SOUND == SOUND_OPENSLES
|
||||||
#include <SLES/OpenSLES.h>
|
#include <SLES/OpenSLES.h>
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
|
@ -194,7 +194,7 @@ static const char *SNDDMA_Android_Init( void )
|
||||||
snddma_android_pos = 0;
|
snddma_android_pos = 0;
|
||||||
dma.initialized = true;
|
dma.initialized = true;
|
||||||
|
|
||||||
S_Activate( true );
|
SNDDMA_Activate( true );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
308
engine/platform/android/vid_android.c
Normal file
308
engine/platform/android/vid_android.c
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#if defined XASH_VIDEO == VIDEO_ANDROID || 1
|
||||||
|
#include "input.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "platform/android/android_priv.h"
|
||||||
|
#include "vid_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_SwapInterval
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
static void Android_SwapInterval( int interval )
|
||||||
|
{
|
||||||
|
// there is no eglSwapInterval in EGL10/EGL11 classes,
|
||||||
|
// so only native backend supported
|
||||||
|
if( negl.valid )
|
||||||
|
eglSwapInterval( negl.dpy, interval );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_SetTitle
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
static void Android_SetTitle( const char *title )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.setTitle, (*jni.env)->NewStringUTF( jni.env, title ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_SetIcon
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
static void Android_SetIcon( const char *path )
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.setIcon, (*jni.env)->NewStringUTF( jni.env, path ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_GetScreenRes
|
||||||
|
|
||||||
|
Resolution got from last resize event
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
static void Android_GetScreenRes( int *width, int *height )
|
||||||
|
{
|
||||||
|
*width=jni.width, *height=jni.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_UpdateSurface
|
||||||
|
|
||||||
|
Check if we may use native EGL without jni calls
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_UpdateSurface( void )
|
||||||
|
{
|
||||||
|
negl.valid = false;
|
||||||
|
|
||||||
|
if( Sys_CheckParm("-nonativeegl") )
|
||||||
|
return; //disabled by user
|
||||||
|
|
||||||
|
negl.dpy = eglGetCurrentDisplay();
|
||||||
|
|
||||||
|
if( negl.dpy == EGL_NO_DISPLAY )
|
||||||
|
return;
|
||||||
|
|
||||||
|
negl.surface = eglGetCurrentSurface(EGL_DRAW);
|
||||||
|
|
||||||
|
if( negl.surface == EGL_NO_SURFACE )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// now check if swapBuffers does not give error
|
||||||
|
if( eglSwapBuffers( negl.dpy, negl.surface ) == EGL_FALSE )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// double check
|
||||||
|
if( eglGetError() != EGL_SUCCESS )
|
||||||
|
return;
|
||||||
|
|
||||||
|
__android_log_print( ANDROID_LOG_VERBOSE, "Xash", "native EGL enabled" );
|
||||||
|
|
||||||
|
negl.valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_GetGLAttribute
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
static int Android_GetGLAttribute( int eglAttr )
|
||||||
|
{
|
||||||
|
int ret = (*jni.env)->CallStaticIntMethod( jni.env, jni.actcls, jni.getGLAttribute, eglAttr );
|
||||||
|
// Con_Reportf( "Android_GetGLAttribute( %i ) => %i\n", eglAttr, ret );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_InitGL
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
qboolean Android_InitGL()
|
||||||
|
{
|
||||||
|
int colorBits[3];
|
||||||
|
qboolean result;
|
||||||
|
|
||||||
|
// result = (*jni.env)->CallStaticBooleanMethod( jni.env, jni.actcls, jni.createGLContext, (int)gl_stencilbits->value );
|
||||||
|
|
||||||
|
/*colorBits[0] = Android_GetGLAttribute( EGL_RED_SIZE );
|
||||||
|
colorBits[1] = Android_GetGLAttribute( EGL_GREEN_SIZE );
|
||||||
|
colorBits[2] = Android_GetGLAttribute( EGL_BLUE_SIZE );
|
||||||
|
glConfig.color_bits = colorBits[0] + colorBits[1] + colorBits[2];
|
||||||
|
glConfig.alpha_bits = Android_GetGLAttribute( EGL_ALPHA_SIZE );
|
||||||
|
glConfig.depth_bits = Android_GetGLAttribute( EGL_DEPTH_SIZE );
|
||||||
|
glConfig.stencil_bits = Android_GetGLAttribute( EGL_STENCIL_SIZE );
|
||||||
|
glState.stencilEnabled = glConfig.stencil_bits ? true : false;*/
|
||||||
|
|
||||||
|
Android_UpdateSurface();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_ShutdownGL
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void Android_ShutdownGL()
|
||||||
|
{
|
||||||
|
(*jni.env)->CallStaticBooleanMethod( jni.env, jni.actcls, jni.deleteGLContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
Android_SwapBuffers
|
||||||
|
|
||||||
|
Update screen. Use native EGL if possible
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void GL_SwapBuffers()
|
||||||
|
{
|
||||||
|
if( negl.valid )
|
||||||
|
{
|
||||||
|
eglSwapBuffers( negl.dpy, negl.surface );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// nanoGL_Flush();
|
||||||
|
(*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.swapBuffers );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean R_Init_Video( const int type )
|
||||||
|
{
|
||||||
|
string safe;
|
||||||
|
qboolean retval;
|
||||||
|
|
||||||
|
if( FS_FileExists( GI->iconpath, true ) )
|
||||||
|
{
|
||||||
|
if( host.rodir[0] )
|
||||||
|
{
|
||||||
|
Android_SetIcon( va( "%s/%s/%s", host.rodir, GI->gamefolder, GI->iconpath ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Android_SetIcon( va( "%s/%s/%s", host.rootdir, GI->gamefolder, GI->iconpath ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Android_SetTitle( GI->title );
|
||||||
|
|
||||||
|
VID_StartupGamma();
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case REF_SOFTWARE:
|
||||||
|
glw_state.software = true;
|
||||||
|
Host_Error( "software mode isn't supported on Android yet! :(\n", type );
|
||||||
|
break;
|
||||||
|
case REF_GL:
|
||||||
|
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||||
|
glw_state.safe = bound( SAFE_NO, Q_atoi( safe ), SAFE_DONTCARE );
|
||||||
|
|
||||||
|
// refdll can request some attributes
|
||||||
|
ref.dllFuncs.GL_SetupAttributes( glw_state.safe );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !(retval = VID_SetMode()) )
|
||||||
|
{
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case REF_GL:
|
||||||
|
// refdll also can check extensions
|
||||||
|
ref.dllFuncs.GL_InitExtensions();
|
||||||
|
break;
|
||||||
|
case REF_SOFTWARE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
host.renderinfo_changed = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_Free_Video( void )
|
||||||
|
{
|
||||||
|
// GL_DeleteContext ();
|
||||||
|
|
||||||
|
// VID_DestroyWindow ();
|
||||||
|
|
||||||
|
// R_FreeVideoModes();
|
||||||
|
|
||||||
|
ref.dllFuncs.GL_ClearExtensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qboolean VID_SetMode( void )
|
||||||
|
{
|
||||||
|
R_ChangeDisplaySettings( 0, 0, false ); // width and height are ignored anyway
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen )
|
||||||
|
{
|
||||||
|
Android_GetScreenRes(&width, &height);
|
||||||
|
|
||||||
|
Con_Reportf( "R_ChangeDisplaySettings: forced resolution to %dx%d)\n", width, height);
|
||||||
|
|
||||||
|
R_SaveVideoMode( width, height );
|
||||||
|
|
||||||
|
host.window_center_x = width / 2;
|
||||||
|
host.window_center_y = height / 2;
|
||||||
|
|
||||||
|
refState.wideScreen = true; // V_AdjustFov will check for widescreen
|
||||||
|
|
||||||
|
return rserr_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_SetAttribute( int attr, int val )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_GetAttribute( int attr, int *val )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int R_MaxVideoModes()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vidmode_t* R_GetVideoMode( int num )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GL_GetProcAddress( const char *name ) // RenderAPI requirement
|
||||||
|
{
|
||||||
|
return NULL; // not implemented, only static for now
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_UpdateSwapInterval( void )
|
||||||
|
{
|
||||||
|
// disable VSync while level is loading
|
||||||
|
if( cls.state < ca_active )
|
||||||
|
{
|
||||||
|
Android_SwapInterval( 0 );
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
}
|
||||||
|
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
|
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
Android_SwapInterval( gl_vsync->value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *SW_LockBuffer()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SW_UnlockBuffer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -36,6 +36,12 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
|
||||||
// see system.c
|
// see system.c
|
||||||
// qboolean Sys_DebuggerPresent( void );
|
// qboolean Sys_DebuggerPresent( void );
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
const char *Android_GetAndroidID( void );
|
||||||
|
const char *Android_LoadID( void );
|
||||||
|
void Android_SaveID( const char *id );
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
|
@ -64,7 +70,12 @@ void Platform_GetMousePos( int *x, int *y );
|
||||||
void Platform_SetMousePos( int x, int y );
|
void Platform_SetMousePos( int x, int y );
|
||||||
// Clipboard
|
// Clipboard
|
||||||
void Platform_GetClipboardText( char *buffer, size_t size );
|
void Platform_GetClipboardText( char *buffer, size_t size );
|
||||||
void Platform_SetClipboardText( char *buffer, size_t size );
|
void Platform_SetClipboardText( const char *buffer, size_t size );
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
void Android_ShowMouse( qboolean show );
|
||||||
|
void Android_MouseMove( float *x, float *y );
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
@ -94,6 +105,7 @@ void* GL_GetProcAddress( const char *name ); // RenderAPI requirement
|
||||||
void GL_UpdateSwapInterval( void );
|
void GL_UpdateSwapInterval( void );
|
||||||
int GL_SetAttribute( int attr, int val );
|
int GL_SetAttribute( int attr, int val );
|
||||||
int GL_GetAttribute( int attr, int *val );
|
int GL_GetAttribute( int attr, int *val );
|
||||||
|
void GL_SwapBuffers();
|
||||||
void *SW_LockBuffer();
|
void *SW_LockBuffer();
|
||||||
void SW_UnlockBuffer();
|
void SW_UnlockBuffer();
|
||||||
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b );
|
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b );
|
||||||
|
|
|
@ -18,6 +18,7 @@ GNU General Public License for more details.
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
#include "menu_int.h"
|
||||||
|
|
||||||
static qboolean Sys_FindExecutable( const char *baseName, char *buf, size_t size )
|
static qboolean Sys_FindExecutable( const char *baseName, char *buf, size_t size )
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,7 @@ static qboolean Sys_FindExecutable( const char *baseName, char *buf, size_t size
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
void Platform_ShellExecute( const char *path, const char *parms )
|
void Platform_ShellExecute( const char *path, const char *parms )
|
||||||
{
|
{
|
||||||
char xdgOpen[128];
|
char xdgOpen[128];
|
||||||
|
@ -88,6 +90,7 @@ void Platform_ShellExecute( const char *path, const char *parms )
|
||||||
Con_Reportf( S_WARN "Could not find "OPEN_COMMAND" utility\n" );
|
Con_Reportf( S_WARN "Could not find "OPEN_COMMAND" utility\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // __ANDROID__
|
||||||
|
|
||||||
#ifdef XASH_DEDICATED
|
#ifdef XASH_DEDICATED
|
||||||
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
|
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
|
||||||
|
|
|
@ -72,7 +72,7 @@ Platform_SetClipobardText
|
||||||
|
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
void Platform_SetClipboardText( char *buffer, size_t size )
|
void Platform_SetClipboardText( const char *buffer, size_t size )
|
||||||
{
|
{
|
||||||
SDL_SetClipboardText( buffer );
|
SDL_SetClipboardText( buffer );
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ GNU General Public License for more details.
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
#include "menu_int.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BOOL WINAPI IsDebuggerPresent(VOID);
|
BOOL WINAPI IsDebuggerPresent(VOID);
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
|
@ -27,6 +27,7 @@ def configure(conf):
|
||||||
conf.env.append_unique('DEFINES', 'XASH_DEDICATED')
|
conf.env.append_unique('DEFINES', 'XASH_DEDICATED')
|
||||||
elif conf.env.DEST_OS2 == 'android': # Android doesn't need SDL2
|
elif conf.env.DEST_OS2 == 'android': # Android doesn't need SDL2
|
||||||
conf.check_cc(lib='log')
|
conf.check_cc(lib='log')
|
||||||
|
conf.check_cc(lib='EGL')
|
||||||
else:
|
else:
|
||||||
conf.load('sdl2')
|
conf.load('sdl2')
|
||||||
if not conf.env.HAVE_SDL2:
|
if not conf.env.HAVE_SDL2:
|
||||||
|
@ -73,7 +74,7 @@ def build(bld):
|
||||||
source += bld.path.ant_glob(['platform/sdl/*.c'])
|
source += bld.path.ant_glob(['platform/sdl/*.c'])
|
||||||
|
|
||||||
if bld.env.DEST_OS2 == 'android':
|
if bld.env.DEST_OS2 == 'android':
|
||||||
libs.append('LOG')
|
libs += ['LOG', 'EGL']
|
||||||
source += bld.path.ant_glob(['platform/android/*.c*'])
|
source += bld.path.ant_glob(['platform/android/*.c*'])
|
||||||
|
|
||||||
# add client files
|
# add client files
|
||||||
|
|
|
@ -47,6 +47,8 @@ def configure(conf):
|
||||||
conf.check( lib='GL' )
|
conf.check( lib='GL' )
|
||||||
|
|
||||||
conf.env.append_unique('DEFINES', 'REF_DLL')
|
conf.env.append_unique('DEFINES', 'REF_DLL')
|
||||||
|
if conf.env.DEST_OS2 == 'android':
|
||||||
|
conf.check_cc(lib='log')
|
||||||
|
|
||||||
def build(bld):
|
def build(bld):
|
||||||
libs = [ 'public', 'M' ]
|
libs = [ 'public', 'M' ]
|
||||||
|
|
|
@ -106,6 +106,10 @@ class Android:
|
||||||
def cxx(self):
|
def cxx(self):
|
||||||
return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + 'g++'))
|
return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + 'g++'))
|
||||||
|
|
||||||
|
def system_stl(self):
|
||||||
|
# TODO: proper STL support
|
||||||
|
return os.path.abspath(os.path.join(self.ndk_home, 'sources', 'cxx-stl', 'system', 'include'))
|
||||||
|
|
||||||
def sysroot(self):
|
def sysroot(self):
|
||||||
arch = self.arch
|
arch = self.arch
|
||||||
if self.is_arm():
|
if self.is_arm():
|
||||||
|
@ -118,6 +122,7 @@ class Android:
|
||||||
|
|
||||||
def cflags(self):
|
def cflags(self):
|
||||||
cflags = ['--sysroot={0}'.format(self.sysroot()), '-DANDROID', '-D__ANDROID__']
|
cflags = ['--sysroot={0}'.format(self.sysroot()), '-DANDROID', '-D__ANDROID__']
|
||||||
|
cflags += ['-I{0}'.format(self.system_stl())]
|
||||||
if self.is_arm():
|
if self.is_arm():
|
||||||
if self.arch.startswith('armeabi-v7a'):
|
if self.arch.startswith('armeabi-v7a'):
|
||||||
# ARMv7 support
|
# ARMv7 support
|
||||||
|
@ -178,15 +183,19 @@ def configure(conf):
|
||||||
android = Android(android_ndk_path, values[0], values[1], values[2])
|
android = Android(android_ndk_path, values[0], values[1], values[2])
|
||||||
conf.options.ALLOW64 = True # skip pointer length check
|
conf.options.ALLOW64 = True # skip pointer length check
|
||||||
conf.options.NO_VGUI = True # skip vgui
|
conf.options.NO_VGUI = True # skip vgui
|
||||||
|
conf.options.NANOGL = True
|
||||||
|
conf.options.GLWES = True
|
||||||
|
conf.options.GL = False
|
||||||
conf.environ['CC'] = android.cc()
|
conf.environ['CC'] = android.cc()
|
||||||
conf.environ['CXX'] = android.cxx()
|
conf.environ['CXX'] = android.cxx()
|
||||||
conf.env.CFLAGS += android.cflags()
|
conf.env.CFLAGS += android.cflags()
|
||||||
conf.env.CXXFLAGS += android.cflags()
|
conf.env.CXXFLAGS += android.cflags()
|
||||||
conf.env.LINKFLAGS += android.ldflags()
|
conf.env.LINKFLAGS += android.ldflags()
|
||||||
|
|
||||||
if android.is_hardfp():
|
|
||||||
conf.env.HAVE_M = True
|
conf.env.HAVE_M = True
|
||||||
|
if android.is_hardfp():
|
||||||
conf.env.LIB_M = ['m_hard']
|
conf.env.LIB_M = ['m_hard']
|
||||||
|
else: conf.env.LIB_M = ['m']
|
||||||
|
|
||||||
conf.msg('Selected Android NDK', android_ndk_path)
|
conf.msg('Selected Android NDK', android_ndk_path)
|
||||||
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
|
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
|
||||||
|
|
Loading…
Add table
Reference in a new issue