mirror of
https://github.com/DrBeef/JKXR.git
synced 2024-11-22 20:21:21 +00:00
43ced097e4
Including Pico 4 support!!
499 lines
13 KiB
Java
499 lines
13 KiB
Java
|
|
package com.drbeef.jkquest;
|
|
|
|
|
|
import static android.system.Os.setenv;
|
|
|
|
import android.Manifest;
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.content.Intent;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.res.AssetManager;
|
|
import android.os.Bundle;
|
|
import android.os.RemoteException;
|
|
import android.support.v4.app.ActivityCompat;
|
|
import android.support.v4.content.ContextCompat;
|
|
import android.util.Log;
|
|
import android.util.Pair;
|
|
import android.view.SurfaceHolder;
|
|
import android.view.SurfaceView;
|
|
import android.view.WindowManager;
|
|
|
|
import com.drbeef.externalhapticsservice.HapticServiceClient;
|
|
import com.drbeef.externalhapticsservice.HapticsConstants;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.util.Vector;
|
|
|
|
@SuppressLint("SdCardPath") public class GLES3JNIActivity extends Activity implements SurfaceHolder.Callback
|
|
{
|
|
private static String game = "";
|
|
|
|
private boolean hapticsEnabled = false;
|
|
|
|
// Load the gles3jni library right away to make sure JNI_OnLoad() gets called as the very first thing.
|
|
static
|
|
{
|
|
game = "jo";
|
|
|
|
BufferedReader br;
|
|
try {
|
|
br = new BufferedReader(new FileReader("/sdcard/JKQuest/commandline.txt"));
|
|
String s;
|
|
StringBuilder sb = new StringBuilder(0);
|
|
while ((s = br.readLine()) != null)
|
|
sb.append(s + " ");
|
|
br.close();
|
|
|
|
if (sb.toString().contains("ja"))
|
|
{
|
|
game = "ja";
|
|
}
|
|
} catch (FileNotFoundException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
|
|
System.loadLibrary("openxr_loader");
|
|
System.loadLibrary( "openjk_" + game );
|
|
}
|
|
|
|
private static final String TAG = "JKQuest";
|
|
private static final String APPLICATION = "JKQuest";
|
|
|
|
|
|
private int permissionCount = 0;
|
|
private static final int READ_EXTERNAL_STORAGE_PERMISSION_ID = 1;
|
|
private static final int WRITE_EXTERNAL_STORAGE_PERMISSION_ID = 2;
|
|
|
|
String commandLineParams;
|
|
|
|
private SurfaceView mView;
|
|
private SurfaceHolder mSurfaceHolder;
|
|
private long mNativeHandle;
|
|
|
|
// Main components
|
|
protected static GLES3JNIActivity mSingleton;
|
|
|
|
private Vector<HapticServiceClient> externalHapticsServiceClients = new Vector<>();
|
|
|
|
//Use a vector of pairs, it is possible a given package _could_ in the future support more than one haptic service
|
|
//so a map here of Package -> Action would not work.
|
|
private static Vector<Pair<String, String>> externalHapticsServiceDetails = new Vector<>();
|
|
|
|
|
|
public static void initialize() {
|
|
// The static nature of the singleton and Android quirkyness force us to initialize everything here
|
|
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
|
|
mSingleton = null;
|
|
|
|
//Add possible external haptic service details here
|
|
externalHapticsServiceDetails.add(Pair.create(HapticsConstants.BHAPTICS_PACKAGE, HapticsConstants.BHAPTICS_ACTION_FILTER));
|
|
externalHapticsServiceDetails.add(Pair.create(HapticsConstants.FORCETUBE_PACKAGE, HapticsConstants.FORCETUBE_ACTION_FILTER));
|
|
}
|
|
|
|
public void shutdown() {
|
|
System.exit(0);
|
|
}
|
|
|
|
@Override protected void onCreate( Bundle icicle )
|
|
{
|
|
Log.v( TAG, "----------------------------------------------------------------" );
|
|
Log.v( TAG, "GLES3JNIActivity::onCreate()" );
|
|
super.onCreate( icicle );
|
|
|
|
GLES3JNIActivity.initialize();
|
|
|
|
// So we can call stuff from static callbacks
|
|
mSingleton = this;
|
|
|
|
|
|
mView = new SurfaceView( this );
|
|
setContentView( mView );
|
|
mView.getHolder().addCallback( this );
|
|
|
|
// Force the screen to stay on, rather than letting it dim and shut off
|
|
// while the user is watching a movie.
|
|
getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON );
|
|
|
|
// Force screen brightness to stay at maximum
|
|
WindowManager.LayoutParams params = getWindow().getAttributes();
|
|
params.screenBrightness = 1.0f;
|
|
getWindow().setAttributes( params );
|
|
|
|
checkPermissionsAndInitialize();
|
|
}
|
|
|
|
/** Initializes the Activity only if the permission has been granted. */
|
|
private void checkPermissionsAndInitialize() {
|
|
// Boilerplate for checking runtime permissions in Android.
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
!= PackageManager.PERMISSION_GRANTED){
|
|
ActivityCompat.requestPermissions(
|
|
GLES3JNIActivity.this,
|
|
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
|
WRITE_EXTERNAL_STORAGE_PERMISSION_ID);
|
|
}
|
|
else
|
|
{
|
|
permissionCount++;
|
|
}
|
|
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
!= PackageManager.PERMISSION_GRANTED)
|
|
{
|
|
ActivityCompat.requestPermissions(
|
|
GLES3JNIActivity.this,
|
|
new String[] {Manifest.permission.READ_EXTERNAL_STORAGE},
|
|
READ_EXTERNAL_STORAGE_PERMISSION_ID);
|
|
}
|
|
else
|
|
{
|
|
permissionCount++;
|
|
}
|
|
|
|
if (permissionCount == 2) {
|
|
// Permissions have already been granted.
|
|
create();
|
|
}
|
|
}
|
|
|
|
/** Handles the user accepting the permission. */
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
|
|
if (requestCode == READ_EXTERNAL_STORAGE_PERMISSION_ID) {
|
|
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
|
|
permissionCount++;
|
|
}
|
|
else
|
|
{
|
|
System.exit(0);
|
|
}
|
|
}
|
|
|
|
if (requestCode == WRITE_EXTERNAL_STORAGE_PERMISSION_ID) {
|
|
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
|
|
permissionCount++;
|
|
}
|
|
else
|
|
{
|
|
System.exit(0);
|
|
}
|
|
}
|
|
|
|
checkPermissionsAndInitialize();
|
|
}
|
|
|
|
public void create() {
|
|
//Make the directories
|
|
new File("/sdcard/JKQuest/JK2/base").mkdirs();
|
|
new File("/sdcard/JKQuest/JK3/base").mkdirs();
|
|
|
|
//Copy the command line params file
|
|
copy_asset("/sdcard/JKQuest", "commandline.txt", false);
|
|
|
|
//Copy the weapon adjustment config - should we force overwrite?
|
|
copy_asset("/sdcard/JKQuest/JK2/base", "weapons_vr_jo.cfg", true);
|
|
copy_asset("/sdcard/JKQuest/JK3/base", "weapons_vr_ja.cfg", true);
|
|
|
|
//Our assets
|
|
copy_asset("/sdcard/JKQuest/JK2/base", "z_vr_assets.pk3", true);
|
|
|
|
//Bummser's default configuration
|
|
copy_asset("/sdcard/JKQuest/JK2/base", "openjo_sp.cfg", false);
|
|
|
|
//Read these from a file and pass through
|
|
commandLineParams = new String("jo");
|
|
|
|
//See if user is trying to use command line params
|
|
if (new File("/sdcard/JKQuest/commandline.txt").exists()) // should exist!
|
|
{
|
|
BufferedReader br;
|
|
try {
|
|
br = new BufferedReader(new FileReader("/sdcard/JKQuest/commandline.txt"));
|
|
String s;
|
|
StringBuilder sb = new StringBuilder(0);
|
|
while ((s = br.readLine()) != null)
|
|
sb.append(s + " ");
|
|
br.close();
|
|
|
|
commandLineParams = new String(sb.toString());
|
|
} catch (FileNotFoundException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
try {
|
|
setenv("JK_LIBDIR", getApplicationInfo().nativeLibraryDir, true);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
|
|
}
|
|
|
|
for (Pair<String, String> serviceDetail : externalHapticsServiceDetails) {
|
|
HapticServiceClient client = new HapticServiceClient(this, (state, desc) -> {
|
|
Log.v(APPLICATION, "ExternalHapticsService " + serviceDetail.second + ": " + desc);
|
|
}, new Intent(serviceDetail.second)
|
|
.setPackage(serviceDetail.first));
|
|
|
|
client.bindService();
|
|
externalHapticsServiceClients.add(client);
|
|
}
|
|
|
|
mNativeHandle = GLES3JNILib.onCreate( this, commandLineParams );
|
|
}
|
|
|
|
public void copy_asset(String path, String name, boolean force) {
|
|
File f = new File(path + "/" + name);
|
|
if (!f.exists() || force) {
|
|
|
|
//Ensure we have an appropriate folder
|
|
String fullname = path + "/" + name;
|
|
String directory = fullname.substring(0, fullname.lastIndexOf("/"));
|
|
new File(directory).mkdirs();
|
|
_copy_asset(name, path + "/" + name);
|
|
}
|
|
}
|
|
|
|
public void _copy_asset(String name_in, String name_out) {
|
|
AssetManager assets = this.getAssets();
|
|
|
|
try {
|
|
InputStream in = assets.open(name_in);
|
|
OutputStream out = new FileOutputStream(name_out);
|
|
|
|
copy_stream(in, out);
|
|
|
|
out.close();
|
|
in.close();
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
|
|
public static void copy_stream(InputStream in, OutputStream out)
|
|
throws IOException {
|
|
byte[] buf = new byte[1024];
|
|
while (true) {
|
|
int count = in.read(buf);
|
|
if (count <= 0)
|
|
break;
|
|
out.write(buf, 0, count);
|
|
}
|
|
}
|
|
|
|
@Override protected void onStart()
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::onStart()" );
|
|
super.onStart();
|
|
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onStart(mNativeHandle, this);
|
|
}
|
|
}
|
|
|
|
@Override protected void onResume()
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::onResume()" );
|
|
super.onResume();
|
|
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onResume(mNativeHandle);
|
|
}
|
|
}
|
|
|
|
@Override protected void onPause()
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::onPause()" );
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onPause(mNativeHandle);
|
|
}
|
|
super.onPause();
|
|
}
|
|
|
|
@Override protected void onStop()
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::onStop()" );
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onStop(mNativeHandle);
|
|
}
|
|
super.onStop();
|
|
}
|
|
|
|
@Override protected void onDestroy()
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::onDestroy()" );
|
|
|
|
if ( mSurfaceHolder != null )
|
|
{
|
|
GLES3JNILib.onSurfaceDestroyed( mNativeHandle );
|
|
}
|
|
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onDestroy(mNativeHandle);
|
|
}
|
|
|
|
super.onDestroy();
|
|
// Reset everything in case the user re opens the app
|
|
GLES3JNIActivity.initialize();
|
|
mNativeHandle = 0;
|
|
}
|
|
|
|
@Override public void surfaceCreated( SurfaceHolder holder )
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::surfaceCreated()" );
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onSurfaceCreated( mNativeHandle, holder.getSurface() );
|
|
mSurfaceHolder = holder;
|
|
}
|
|
}
|
|
|
|
@Override public void surfaceChanged( SurfaceHolder holder, int format, int width, int height )
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::surfaceChanged()" );
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onSurfaceChanged( mNativeHandle, holder.getSurface() );
|
|
mSurfaceHolder = holder;
|
|
}
|
|
}
|
|
|
|
@Override public void surfaceDestroyed( SurfaceHolder holder )
|
|
{
|
|
Log.v( TAG, "GLES3JNIActivity::surfaceDestroyed()" );
|
|
if ( mNativeHandle != 0 )
|
|
{
|
|
GLES3JNILib.onSurfaceDestroyed( mNativeHandle );
|
|
mSurfaceHolder = null;
|
|
}
|
|
}
|
|
|
|
public void haptic_event(String event, int position, int flags, int intensity, float angle, float yHeight) {
|
|
|
|
boolean areHapticsEnabled = hapticsEnabled;
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
//Enabled all haptics services if required
|
|
if (!areHapticsEnabled)
|
|
{
|
|
externalHapticsServiceClient.getHapticsService().hapticEnable();
|
|
hapticsEnabled = true;
|
|
continue;
|
|
}
|
|
|
|
//Uses the Doom3Quest and RTCWQuest haptic patterns
|
|
String app = "Doom3Quest";
|
|
String eventID = event;
|
|
if (event.contains(":"))
|
|
{
|
|
String[] items = event.split(":");
|
|
app = items[0];
|
|
eventID = items[1];
|
|
}
|
|
externalHapticsServiceClient.getHapticsService().hapticEvent(app, eventID, position, flags, intensity, angle, yHeight);
|
|
}
|
|
catch (RemoteException r)
|
|
{
|
|
Log.v(TAG, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void haptic_updateevent(String event, int intensity, float angle) {
|
|
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
externalHapticsServiceClient.getHapticsService().hapticUpdateEvent(APPLICATION, event, intensity, angle);
|
|
} catch (RemoteException r) {
|
|
Log.v(APPLICATION, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void haptic_stopevent(String event) {
|
|
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
externalHapticsServiceClient.getHapticsService().hapticStopEvent(APPLICATION, event);
|
|
} catch (RemoteException r) {
|
|
Log.v(APPLICATION, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void haptic_endframe() {
|
|
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
externalHapticsServiceClient.getHapticsService().hapticFrameTick();
|
|
} catch (RemoteException r) {
|
|
Log.v(APPLICATION, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void haptic_enable() {
|
|
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
externalHapticsServiceClient.getHapticsService().hapticEnable();
|
|
} catch (RemoteException r) {
|
|
Log.v(APPLICATION, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void haptic_disable() {
|
|
|
|
for (HapticServiceClient externalHapticsServiceClient : externalHapticsServiceClients) {
|
|
|
|
if (externalHapticsServiceClient.hasService()) {
|
|
try {
|
|
externalHapticsServiceClient.getHapticsService().hapticDisable();
|
|
} catch (RemoteException r) {
|
|
Log.v(APPLICATION, r.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|