Support for looping patterns with rotation

- Steam jets can be directional now
- Added couple of missing haptics files
- Adjusted Pistol/Shotgun and Chainsaw patterns
This commit is contained in:
Simon 2021-03-25 22:25:46 +00:00
parent 7ba05dad6c
commit 2923bdc996
8 changed files with 396 additions and 114 deletions

View File

@ -93,6 +93,7 @@ vrClientInfo vr;
vrClientInfo *pVRClientInfo;
jclass clazz;
static jobject d3questCallbackObj=0;
float radians(float deg) {
return (deg * M_PI) / 180.0;
@ -954,6 +955,49 @@ void Doom3Quest_Vibrate(int channel, float low, float high)
vibration_channel_intensity[channel][1] = high;
}
void jni_haptic_event(const char* event, int position, int flags, int intensity, float angle, float yHeight);
void jni_haptic_updateevent(const char* event, int intensity, float angle);
void jni_haptic_stopevent(const char* event);
void jni_haptic_beginframe();
void jni_haptic_endframe();
void jni_haptic_enable();
void jni_haptic_disable();
void Doom3Quest_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight )
{
jni_haptic_event(event, position, flags, intensity, angle, yHeight);
}
void Doom3Quest_HapticUpdateEvent(const char* event, int intensity, float angle )
{
jni_haptic_updateevent(event, intensity, angle);
}
void Doom3Quest_HapticBeginFrame()
{
jni_haptic_beginframe();
}
void Doom3Quest_HapticEndFrame()
{
jni_haptic_endframe();
}
void Doom3Quest_HapticStopEvent(const char* event)
{
jni_haptic_stopevent(event);
}
void Doom3Quest_HapticEnable()
{
jni_haptic_enable();
}
void Doom3Quest_HapticDisable()
{
jni_haptic_disable();
}
void VR_Doom3Main(int argc, char** argv);
void VR_GetMove( float *joy_forward, float *joy_side, float *hmd_forward, float *hmd_side, float *up, float *yaw, float *pitch, float *roll ) {
@ -1486,7 +1530,6 @@ void shutdownVR() {
ovrRenderer_Destroy( &gAppState.Renderer );
ovrEgl_DestroyContext( &gAppState.Egl );
(*java.Vm)->DetachCurrentThread( java.Vm );
vrapi_Shutdown();
}
void showLoadingIcon();
@ -1580,7 +1623,7 @@ void * AppThreadFunction(void * parm ) {
questType = 2;
if (SS_MULTIPLIER == -1.0f)
{
SS_MULTIPLIER = 1.1f;
SS_MULTIPLIER = 1.2f;
}
if (NUM_MULTI_SAMPLES == -1)
@ -1699,6 +1742,8 @@ void Doom3Quest_processHaptics() {//Handle haptics
else
vrapi_SetHapticVibrationSimple(gAppState.Ovr, controllerIDs[1 - h], 0.0f);
}
Doom3Quest_HapticBeginFrame();
}
void showLoadingIcon()
@ -1881,6 +1926,8 @@ void Doom3Quest_submitFrame()
gAppState.RenderThreadFrameIndex++;
SDL_UnlockMutex(gAppState.RenderThreadFrameIndex_Mutex);
}
Doom3Quest_HapticEndFrame();
}
@ -1917,8 +1964,15 @@ Activity lifecycle
*/
jmethodID android_shutdown;
jmethodID android_haptic_event;
jmethodID android_haptic_updateevent;
jmethodID android_haptic_stopevent;
jmethodID android_haptic_beginframe;
jmethodID android_haptic_endframe;
jmethodID android_haptic_enable;
jmethodID android_haptic_disable;
static JavaVM *jVM;
static jobject shutdownCallbackObj=0;
static jobject jniCallbackObj=0;
void jni_shutdown()
{
@ -1929,7 +1983,100 @@ void jni_shutdown()
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
return (*env)->CallVoidMethod(env, shutdownCallbackObj, android_shutdown);
return (*env)->CallVoidMethod(env, jniCallbackObj, android_shutdown);
}
void jni_haptic_event(const char* event, int position, int flags, int intensity, float angle, float yHeight)
{
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
jstring StringArg1 = (*env)->NewStringUTF(env, event);
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_event, StringArg1, position, flags, intensity, angle, yHeight);
}
void jni_haptic_updateevent(const char* event, int intensity, float angle)
{
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
jstring StringArg1 = (*env)->NewStringUTF(env, event);
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_updateevent, StringArg1, intensity, angle);
}
void jni_haptic_stopevent(const char* event)
{
ALOGV("Calling: jni_haptic_stopevent");
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
jstring StringArg1 = (*env)->NewStringUTF(env, event);
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_stopevent, StringArg1);
}
void jni_haptic_beginframe()
{
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_beginframe);
}
void jni_haptic_endframe()
{
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_endframe);
}
void jni_haptic_enable()
{
ALOGV("Calling: jni_haptic_enable");
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_enable);
}
void jni_haptic_disable()
{
ALOGV("Calling: jni_haptic_disable");
JNIEnv *env;
jobject tmp;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
return (*env)->CallVoidMethod(env, jniCallbackObj, android_haptic_disable);
}
JNIEXPORT jint JNICALL SDL_JNI_OnLoad(JavaVM* vm, void* reserved);
@ -2001,10 +2148,17 @@ JNIEXPORT void JNICALL Java_com_drbeef_doom3quest_GLES3JNILib_onStart( JNIEnv *
{
ALOGV( " GLES3JNILib::onStart()" );
shutdownCallbackObj = (jobject)(*env)->NewGlobalRef(env, obj1);
jclass callbackClass = (*env)->GetObjectClass(env, shutdownCallbackObj);
jniCallbackObj = (jobject)(*env)->NewGlobalRef(env, obj1);
jclass callbackClass = (*env)->GetObjectClass(env, jniCallbackObj);
android_shutdown = (*env)->GetMethodID(env,callbackClass,"shutdown","()V");
android_haptic_event = (*env)->GetMethodID(env, callbackClass, "haptic_event", "(Ljava/lang/String;IIIFF)V");
android_haptic_updateevent = (*env)->GetMethodID(env, callbackClass, "haptic_updateevent", "(Ljava/lang/String;IF)V");
android_haptic_stopevent = (*env)->GetMethodID(env, callbackClass, "haptic_stopevent", "(Ljava/lang/String;)V");
android_haptic_beginframe = (*env)->GetMethodID(env, callbackClass, "haptic_beginframe", "()V");
android_haptic_endframe = (*env)->GetMethodID(env, callbackClass, "haptic_endframe", "()V");
android_haptic_enable = (*env)->GetMethodID(env, callbackClass, "haptic_enable", "()V");
android_haptic_disable = (*env)->GetMethodID(env, callbackClass, "haptic_disable", "()V");
ovrAppThread * appThread = (ovrAppThread *)((size_t)handle);
ovrMessage message;

View File

@ -1631,7 +1631,7 @@ bool idEntity::StartSoundShader( const idSoundShader *shader, const s_channelTyp
float distance = direction.Length();
if (distance <= 150.0F) {
bool repeat = (shader->GetParms()->soundShaderFlags & SSF_LOOPING) != 0;
bool looping = (shader->GetParms()->soundShaderFlags & SSF_LOOPING) != 0;
direction.Normalize();
idVec3 bodyOrigin = vec3_zero;
@ -1639,16 +1639,15 @@ bool idEntity::StartSoundShader( const idSoundShader *shader, const s_channelTyp
player->GetViewPos( bodyOrigin, bodyAxis );
idAngles bodyAng = bodyAxis.ToAngles();
/* float pitch = direction.ToPitch();
if (pitch > 180)
pitch -= 360;
float yHeight = idMath::ClampFloat(-0.5f, 0.45f, -pitch / 90.0f);*/
idAngles directionYaw(0, 180 + (direction.ToYaw() - bodyAng.yaw), 0);
directionYaw.Normalize360();
//Pass sound on in case it can trigger a haptic event (like doors)
float intensity = 40 + Min<float>((int)(150.0f - distance), 80);
common->HapticEvent(shader->GetName(), 4, repeat ? 1 : 0, intensity, directionYaw.yaw, 0);
float intensity = looping ? (100.0f - distance) :
40 + Min<float>((int)(150.0f - distance), 80);
common->HapticEvent(shader->GetName(), 4, looping ? 1 : 0, intensity,
directionYaw.yaw, 0);
}
}

View File

@ -5741,22 +5741,29 @@ void idPlayerHand::NextWeapon( int dir )
vr_weaponHand.SetInteger( 1 - whichHand );
}
if (currentWeapon == WEAPON_CHAINSAW)
{
//Stop all chainsaw haptics immediately
common->HapticStopEvent("chainsaw_idle");
common->HapticStopEvent("chainsaw_fire");
}
idealWeapon = w;
weaponSwitchTime = gameLocal.time + WEAPON_SWITCH_DELAY;
owner->UpdateHudWeapon( whichHand );
if( vr_debugHands.GetBool() )
common->Printf( "Changing weapon\n" );
common->HapticEvent("weapon_switch", 0, 0, 100, 0, 0);
if (idealWeapon == WEAPON_CHAINSAW)
{
//Start chainsaw idling haptic immediately
common->HapticEvent("chainsaw_idle", vr_weaponHand.GetInteger() ? 1 : 2, 1, 100, 0, 0);
}
else
{
common->HapticStopEvent("chainsaw_idle");
}
else
{
common->HapticEvent("weapon_switch", 0, 0, 100, 0, 0);
}
}
if( vr_debugHands.GetBool() )

View File

@ -26,6 +26,7 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <d3es-multithread-master/neo/framework/Game.h>
#include "sys/platform.h"
#include "framework/FileSystem.h"
#include "framework/Session.h"
@ -33,6 +34,9 @@ If you have questions concerning this license or the applicable additional terms
#include "sound/snd_local.h"
//Haptic Stuff
extern "C" void Doom3Quest_HapticUpdateEvent(const char* event, int intensity, float angle );
/*
==================
idSoundWorldLocal::Init
@ -1589,6 +1593,8 @@ void idSoundWorldLocal::CalcEars( int numSpeakers, idVec3 spatializedOrigin, idV
}
}
extern idGame * game;
/*
===============
idSoundWorldLocal::AddChannelContribution
@ -1755,6 +1761,27 @@ void idSoundWorldLocal::AddChannelContribution( idSoundEmitterLocal *sound, idSo
float inputSamples[MIXBUFFER_SAMPLES*2+16];
float *alignedInputSamples = (float *) ( ( ( (intptr_t)inputSamples ) + 15 ) & ~15 );
if (cvarSystem->GetCVarBool("vr_bhaptics") &&
looping &&
game != NULL)
{
idVec3 direction = (listenerPos / DOOM_TO_METERS) - sound->origin;
float distance = direction.Length();
if (distance <= 100.0F) {
direction.Normalize();
idAngles bodyAng = listenerAxis.ToAngles();
idAngles directionYaw(0, 180 + (direction.ToYaw() - bodyAng.yaw), 0);
directionYaw.Normalize360();
int intensity = 100 - distance;
Doom3Quest_HapticUpdateEvent(shader->GetName(), intensity, directionYaw.yaw);
} else{
Doom3Quest_HapticUpdateEvent(shader->GetName(), 0, 0);
}
}
//
// allocate and initialize hardware source
//

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"project":{"createdAt":1614063863216,"description":"","id":"-MUCh-OyqGJ1QiTCDLOU","layout":{"layouts":{"VestBack":[{"index":0,"x":0,"y":0},{"index":1,"x":0.333,"y":0},{"index":2,"x":0.667,"y":0},{"index":3,"x":1,"y":0},{"index":4,"x":0,"y":0.25},{"index":5,"x":0.333,"y":0.25},{"index":6,"x":0.667,"y":0.25},{"index":7,"x":1,"y":0.25},{"index":8,"x":0,"y":0.5},{"index":9,"x":0.333,"y":0.5},{"index":10,"x":0.667,"y":0.5},{"index":11,"x":1,"y":0.5},{"index":12,"x":0,"y":0.75},{"index":13,"x":0.333,"y":0.75},{"index":14,"x":0.667,"y":0.75},{"index":15,"x":1,"y":0.75},{"index":16,"x":0,"y":1},{"index":17,"x":0.333,"y":1},{"index":18,"x":0.667,"y":1},{"index":19,"x":1,"y":1}],"VestFront":[{"index":0,"x":0,"y":0},{"index":1,"x":0.333,"y":0},{"index":2,"x":0.667,"y":0},{"index":3,"x":1,"y":0},{"index":4,"x":0,"y":0.25},{"index":5,"x":0.333,"y":0.25},{"index":6,"x":0.667,"y":0.25},{"index":7,"x":1,"y":0.25},{"index":8,"x":0,"y":0.5},{"index":9,"x":0.333,"y":0.5},{"index":10,"x":0.667,"y":0.5},{"index":11,"x":1,"y":0.5},{"index":12,"x":0,"y":0.75},{"index":13,"x":0.333,"y":0.75},{"index":14,"x":0.667,"y":0.75},{"index":15,"x":1,"y":0.75},{"index":16,"x":0,"y":1},{"index":17,"x":0.333,"y":1},{"index":18,"x":0.667,"y":1},{"index":19,"x":1,"y":1}]},"name":"Tactot","type":"Tactot"},"mediaFileDuration":1,"name":"Body_Reload","tracks":[{"effects":[{"modes":{"VestBack":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":102,"playbackType":"NONE","pointList":[{"index":7,"intensity":0.6}],"startTime":0},{"endTime":204,"playbackType":"FADE_IN","pointList":[{"index":3,"intensity":0.6}],"startTime":102}]},"mode":"DOT_MODE","pathMode":{"feedback":[]}},"VestFront":{"dotMode":{"dotConnected":false,"feedback":[{"endTime":102,"playbackType":"NONE","pointList":[{"index":6,"intensity":0.6},{"index":7,"intensity":0.6}],"startTime":0},{"endTime":204,"playbackType":"FADE_IN","pointList":[{"index":2,"intensity":0.6},{"index":3,"intensity":0.6}],"startTime":102}]},"mode":"DOT_MODE","pathMode":{"feedback":[{"movingPattern":"CONST_SPEED","playbackType":"NONE","visible":true,"pointList":[]}]}}},"name":"Effect 1","offsetTime":204,"startTime":0}],"enable":true},{"enable":true,"effects":[]}],"type":"project","updatedAt":1614063881495},"durationMillis":0,"intervalMillis":20,"size":20}

View File

@ -2,6 +2,22 @@
package com.drbeef.doom3quest;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import com.bhaptics.commons.PermissionUtils;
import com.drbeef.doom3quest.bhaptics.bHaptics;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
@ -11,23 +27,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import static android.system.Os.setenv;
@SuppressLint("SdCardPath") public class GLES3JNIActivity extends Activity implements SurfaceHolder.Callback
@ -41,8 +40,6 @@ import static android.system.Os.setenv;
private static final String TAG = "Doom3Quest";
private int permissionCount = 0;
private static final int READ_EXTERNAL_STORAGE_PERMISSION_ID = 1;
private static final int WRITE_EXTERNAL_STORAGE_PERMISSION_ID = 2;
private String commandLineParams;
@ -50,14 +47,43 @@ import static android.system.Os.setenv;
private SurfaceHolder mSurfaceHolder;
private long mNativeHandle;
// Audio
protected static AudioTrack mAudioTrack;
protected static AudioRecord mAudioRecord;
public void shutdown() {
System.exit(0);
}
public void haptic_event(String event, int position, int flags, int intensity, float angle, float yHeight) {
bHaptics.playHaptic(event, position, flags, intensity, angle, yHeight);
}
public void haptic_updateevent(String event, int intensity, float angle) {
bHaptics.updateRepeatingHaptic(event, intensity, angle);
}
public void haptic_stopevent(String event) {
bHaptics.stopHaptic(event);
}
public void haptic_beginframe() {
bHaptics.beginFrame();
}
public void haptic_endframe() {
bHaptics.endFrame();
}
public void haptic_enable() {
bHaptics.enable(this);
}
public void haptic_disable() {
bHaptics.disable();
}
@Override protected void onCreate( Bundle icicle )
{
Log.v( TAG, "----------------------------------------------------------------" );
@ -80,64 +106,44 @@ import static android.system.Os.setenv;
checkPermissionsAndInitialize();
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
/** 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.
if (PermissionUtils.hasFilePermissions(this)) {
create();
onStart();
}
else
{
requestPermissions();
}
}
/** Handles the user accepting the permission. */
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
if (requestCode == READ_EXTERNAL_STORAGE_PERMISSION_ID) {
if (requestCode == 1) {
//Quit for now
finish();
System.exit(0);
}
//Was this a bHaptics FINE LOCATION perms request?
else if (requestCode == 2) {
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
permissionCount++;
//call enable again
bHaptics.enable(this);
}
else
{
System.exit(0);
//Don't do anything here, we can't enable if permissions were denied
}
}
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() {
@ -194,6 +200,8 @@ import static android.system.Os.setenv;
}
try {
ApplicationInfo ai = getApplicationInfo();
setenv("USER_FILES", "/sdcard/Doom3Quest", true);
setenv("GAMELIBDIR", getApplicationInfo().nativeLibraryDir, true);
setenv("GAMETYPE", "16", true); // hard coded for now
@ -291,7 +299,10 @@ import static android.system.Os.setenv;
Log.v( TAG, "GLES3JNIActivity::onStart()" );
super.onStart();
GLES3JNILib.onStart( mNativeHandle, this );
if ( mNativeHandle != 0 )
{
GLES3JNILib.onStart(mNativeHandle, this);
}
}
@Override protected void onResume()
@ -299,20 +310,29 @@ import static android.system.Os.setenv;
Log.v( TAG, "GLES3JNIActivity::onResume()" );
super.onResume();
GLES3JNILib.onResume( mNativeHandle );
if ( mNativeHandle != 0 )
{
GLES3JNILib.onResume(mNativeHandle);
}
}
@Override protected void onPause()
{
Log.v( TAG, "GLES3JNIActivity::onPause()" );
GLES3JNILib.onPause( mNativeHandle );
if ( mNativeHandle != 0 )
{
GLES3JNILib.onPause(mNativeHandle);
}
super.onPause();
}
@Override protected void onStop()
{
Log.v( TAG, "GLES3JNIActivity::onStop()" );
GLES3JNILib.onStop( mNativeHandle );
if ( mNativeHandle != 0 )
{
GLES3JNILib.onStop(mNativeHandle);
}
super.onStop();
}
@ -320,12 +340,17 @@ import static android.system.Os.setenv;
{
Log.v( TAG, "GLES3JNIActivity::onDestroy()" );
bHaptics.destroy();
if ( mSurfaceHolder != null )
{
GLES3JNILib.onSurfaceDestroyed( mNativeHandle );
}
GLES3JNILib.onDestroy( mNativeHandle );
if ( mNativeHandle != 0 )
{
GLES3JNILib.onDestroy(mNativeHandle);
}
super.onDestroy();
mNativeHandle = 0;
@ -360,5 +385,4 @@ import static android.system.Os.setenv;
mSurfaceHolder = null;
}
}
}

View File

@ -42,16 +42,37 @@ public class bHaptics {
this.key = key;
this.altKey = altKey;
this.group = group;
this.directional = false;
this.intensity = intensity;
this.duration = duration;
this.rotation = 0;
this.level = 100;
}
public Haptic(Haptic haptic) {
this.type = haptic.type;
this.key = haptic.key;
this.altKey = haptic.altKey;
this.group = haptic.group;
this.directional = haptic.directional;
this.intensity = haptic.intensity;
this.duration = haptic.duration;
this.rotation = 0;
this.level = 100;
}
public final String key;
public final String altKey;
public final String group;
public final float intensity;
public boolean directional; // can be changed for specific repeating patterns
public final float duration;
public final PositionType type;
public final float intensity;
//These two values can be changed over time when playing a looping effect
public float rotation;
public float level;
};
private static final String TAG = "Doom3Quest.bHaptics";
@ -132,14 +153,20 @@ public class bHaptics {
registerFromAsset(context, "bHaptics/Interaction/Arms/Healthstation_L.tact", PositionType.ForearmL, "healstation", "pickup");
registerFromAsset(context, "bHaptics/Interaction/Arms/Healthstation_R.tact", PositionType.ForearmR, "healstation", "pickup");
registerFromAsset(context, "bHaptics/Interaction/Vest/DoorSlide.tact", "doorslide", "door");
registerFromAsset(context, "bHaptics/Interaction/Vest/DoorSlide.tact", PositionType.Vest, "doorslide", "door", 1.0f, 0.5f);
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Scan.tact", PositionType.Vest, "scan", "environment", 1.0f, 1.15f);
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Scan.tact", PositionType.Vest, "decontaminate", "environment", 0.5f, 0.75f);
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Chamber_Up.tact", "liftup", "environment");
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Chamber_Down.tact", "liftdown", "environment");
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Machine.tact", "machine", "environment");
registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", "spark", "environment");
registerFromAsset(context, "bHaptics/Interaction/Head/Spark.tact", PositionType.Head, "spark", "environment");
registerFromAsset(context, "bHaptics/Interaction/Head/Spark.tact", PositionType.Head, "spark", "environment", 0.5f, 0.5f);
//Directional based place holder for looping steam pattern
registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", PositionType.Vest, "steam_loop", "environment", 0.5f, 0.25f);
eventToEffectKeyMap.get("steam_loop").elementAt(0).directional = true;
registerFromAsset(context, "bHaptics/Interaction/Vest/Spark.tact", "steam_blast", "environment");
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_PDA_Open.tact", "pda_open", "pda");
registerFromAsset(context, "bHaptics/Interaction/Vest/Body_PDA_Open.tact", "pda_close", "pda");
@ -174,16 +201,16 @@ public class bHaptics {
registerFromAsset(context, "bHaptics/Weapon/Arms/ReloadFinish_Mirror.tact", PositionType.ForearmL, "weapon_reload_finish", "weapon");
//Chainsaw Idle
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1.tact", PositionType.Right, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1.tact", PositionType.ForearmR, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1_Mirror.tact", PositionType.Left, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1_Mirror.tact", PositionType.ForearmL, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2.tact", PositionType.Right, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2.tact", PositionType.ForearmR, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2_Mirror.tact", PositionType.Left, "chainsaw_idle", "weapon");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2_Mirror.tact", PositionType.ForearmL, "chainsaw_idle", "weapon");
//Chainsaw Fire
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2.tact", PositionType.Right, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2.tact", PositionType.ForearmR, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV2_Mirror.tact", PositionType.Left, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV2_Mirror.tact", PositionType.ForearmL, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1.tact", PositionType.Right, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1.tact", PositionType.ForearmR, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Chainsaw_LV1_Mirror.tact", PositionType.Left, "chainsaw_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Chainsaw_LV1_Mirror.tact", PositionType.ForearmL, "chainsaw_fire", "weapon_fire");
//Fist
registerFromAsset(context, "bHaptics/Weapon/Vest/Fist_Mirror.tact", PositionType.Left, "punch", "weapon_fire");
@ -192,16 +219,16 @@ public class bHaptics {
registerFromAsset(context, "bHaptics/Weapon/Arms/Fist.tact", PositionType.ForearmR, "punch", "weapon_fire");
//Pistol
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV2_Mirror.tact", PositionType.Left, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV2_Mirror.tact", PositionType.ForearmL, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV2.tact", PositionType.Right, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV2.tact", PositionType.ForearmR, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV3_Mirror.tact", PositionType.Left, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV3_Mirror.tact", PositionType.ForearmL, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV3.tact", PositionType.Right, "pistol_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV3.tact", PositionType.ForearmR, "pistol_fire", "weapon_fire");
//Shotgun
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV3_Mirror.tact", PositionType.Left, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV3_Mirror.tact", PositionType.ForearmL, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV3.tact", PositionType.Right, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV3.tact", PositionType.ForearmR, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV2_Mirror.tact", PositionType.Left, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV2_Mirror.tact", PositionType.ForearmL, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV2.tact", PositionType.Right, "shotgun_fire", "weapon_fire");
registerFromAsset(context, "bHaptics/Weapon/Arms/Recoil_LV2.tact", PositionType.ForearmR, "shotgun_fire", "weapon_fire");
//Plasma Gun
registerFromAsset(context, "bHaptics/Weapon/Vest/Recoil_LV1_Mirror.tact", PositionType.Left, "plasmagun_fire", "weapon_fire");
@ -381,11 +408,19 @@ public class bHaptics {
public static void beginFrame()
{
Vector<String> toRemove = new Vector<>();
if (enabled && hasPairedDevice) {
repeatingHaptics.forEach((key, haptic) -> {
//If a repeating haptic isn't playing, start it again
if (!player.isPlaying(haptic.altKey)) {
player.submitRegistered(haptic.key, haptic.altKey, 100, 1.0f, 0, 0);
if (haptic.level == 0) {
if (player.isPlaying(haptic.altKey))
{
player.turnOff(haptic.altKey);
}
}
else if (!player.isPlaying(haptic.altKey)) {
//If a repeating haptic isn't playing, start it again with last known values
float flIntensity = ((haptic.level / 100.0F) * haptic.intensity);
player.submitRegistered(haptic.key, haptic.altKey, flIntensity, haptic.duration, haptic.rotation, 0);
}
});
}
@ -516,7 +551,14 @@ public class bHaptics {
//If this is a repeating event, then add to the set to play in begin frame
if (flags == 1)
{
repeatingHaptics.put(key, haptic);
Haptic repeatingHaptic = new Haptic(haptic);
if (haptic.directional) {
repeatingHaptic.rotation = flAngle;
}
repeatingHaptic.level = intensity;
repeatingHaptics.put(key, repeatingHaptic);
}
else {
player.submitRegistered(haptic.key, haptic.altKey, flIntensity, flDuration, flAngle, yHeight);
@ -554,7 +596,7 @@ public class bHaptics {
key.contains("explode")) {
key = "fireball"; // Just re-use this one
}
else if (key.contains("noair")) {
else if (key.contains("noair") || key.contains("gasp")) {
key = "noair";
}
else if (key.contains("shotgun")) {
@ -595,6 +637,16 @@ public class bHaptics {
{
key = "spark";
}
else if (key.contains("steam"))
{
if (key.contains("blast") || key.contains("shot") || key.contains("chuff")) {
key = "steam_blast";
}
else
{
key = "steam_loop";
}
}
else if (key.contains("player") && key.contains("jump"))
{
key = "jump_start";
@ -623,6 +675,23 @@ public class bHaptics {
}
}
public static void updateRepeatingHaptic(String event, float intensity, float angle) {
if (enabled && hasPairedDevice) {
String key = getHapticEventKey(event);
if (repeatingHaptics.containsKey(key))
{
Haptic haptic = repeatingHaptics.get(key);
if (haptic.directional) {
haptic.rotation = angle;
}
haptic.level = intensity;
}
}
}
public static String read(Context context, String fileName) {
try {