Initial rumbler support

This commit is contained in:
endolf 2003-12-01 23:42:30 +00:00
parent f4c4499bf3
commit a4176e75f8
3 changed files with 198 additions and 12 deletions

View file

@ -86,6 +86,9 @@ class DirectInputDevice extends AbstractController {
* @see DirectInputAxis for a breakdown of this structure
*/
int[] data = new int[32];
/** Array list of rumblers */
private ArrayList rumblerList = new ArrayList();
/**
* Private constructor
@ -150,6 +153,16 @@ class DirectInputDevice extends AbstractController {
list.add(DirectInputAxis.createAxis(this, id, didft, name));
}
/**
* Callback called by enumDevice to add a rumbler
*
* @param effect the natie effect id
* @param axisID The axis ID
*/
private void addRumbler(long effect, Axis.Identifier axisID) {
rumblerList.add(new DirectInputRumbler(this, effect, axisID));
}
/** Polls axes for data. Returns false if the controller is no longer valid.
* Polling reflects the current state of the device when polled, and is
* unbuffered.
@ -174,6 +187,13 @@ class DirectInputDevice extends AbstractController {
return 0;
}
/**
* Returns the rumbler array
*/
public Rumbler[] getRumblers() {
return (Rumbler[]) rumblerList.toArray(new Rumbler[0]);
}
/**
* Polls the device; native method. The data from the poll is stored in
* the data array.

View file

@ -0,0 +1,31 @@
/*
* DirectInputRumbler.java
*
* Created on 01 December 2003, 21:39
*/
package net.java.games.input;
/**
*
* @author Jeremy
*/
public class DirectInputRumbler implements net.java.games.input.Rumbler {
private DirectInputDevice device;
private long effect;
private Axis.Identifier axisID;
/** Creates a new instance of DirectInputRumbler */
public DirectInputRumbler(DirectInputDevice device, long effect, Axis.Identifier axisID) {
this.device = device;
this.effect = effect;
this.axisID = axisID;
}
public void rumble(float intensity) {
setRumble(effect, intensity);
}
private native void setRumble(long effect, float intensity);
}

View file

@ -29,6 +29,7 @@ jclass CLASS_DirectInputKeyboard = NULL;
jclass CLASS_DirectInputMouse = NULL;
jmethodID MID_AddDevice = NULL;
jmethodID MID_AddAxis = NULL;
jmethodID MID_AddRumbler = NULL;
jmethodID MID_RenameKey = NULL;
jmethodID MID_RenameAxis = NULL;
jfieldID FID_X = NULL;
@ -261,6 +262,11 @@ BOOL InitIDs(JNIEnv* env) {
if (MID_AddAxis == NULL) {
return FALSE;
}
MID_AddRumbler = env->GetMethodID(CLASS_DirectInputDevice, "addRumbler",
"(JLnet/java/games/input/Axis$Identifier;)V");
if (MID_AddRumbler == NULL) {
return FALSE;
}
CLASS_DirectInputKeyboard =
env->FindClass("net/java/games/input/DirectInputKeyboard");
if (CLASS_DirectInputKeyboard == NULL) {
@ -359,6 +365,19 @@ Java_net_java_games_input_DirectInputEnvironmentPlugin_directInputCreate
return (jlong)(long)lpDirectInput;
}
BOOL CALLBACK CountFFAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
DWORD* pdwNumForceFeedbackAxis = (DWORD*) pContext;
if( (pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0 ) {
//printf("%s is ff enabled\n", pdidoi->tszName);
(*pdwNumForceFeedbackAxis)++;
}
return DIENUM_CONTINUE;
}
/*
* Enumeration callback for devices
*
@ -396,6 +415,14 @@ BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
}
*/
//find out if this device is ff enabled
DWORD numForceFeedbackAxis = 0;
res = lpDevice->EnumObjects( CountFFAxesCallback,
(VOID*)&numForceFeedbackAxis, DIDFT_AXIS );
if(FAILED(res)) {
PrintDIError("getting ff devices", res);
}
// Set the data format
LPCDIDATAFORMAT lpDataFormat;
DWORD category = GET_DIDEVICE_TYPE(lpddi->dwDevType)&0xFF;
@ -417,10 +444,10 @@ BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
if (FAILED(
res = lpDevice->SetProperty(DIPROP_BUFFERSIZE,
&dipropdw.diph))) {
PrintDIError("SetProperty", res);
lpDevice->Release();
return DIENUM_STOP;
}
PrintDIError("SetProperty", res);
lpDevice->Release();
return DIENUM_STOP;
}
break;
case DI8DEVTYPE_JOYSTICK:
default:
@ -435,13 +462,23 @@ BOOL CALLBACK EnumDeviceCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
return DIENUM_STOP;
}
// Set the cooperative level
if(FAILED(res = lpDevice->SetCooperativeLevel(hwndDummy,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))){
PrintDIError("SetCooperativeLevel", res);
lpDevice->Release();
return DIENUM_STOP;
}
if(numForceFeedbackAxis>0) {
// Set the cooperative level
if(FAILED(res = lpDevice->SetCooperativeLevel(hwndDummy,
DISCL_EXCLUSIVE | DISCL_BACKGROUND))){
PrintDIError("SetCooperativeLevel", res);
lpDevice->Release();
return DIENUM_STOP;
}
} else {
// Set the cooperative level
if(FAILED(res = lpDevice->SetCooperativeLevel(hwndDummy,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))){
PrintDIError("SetCooperativeLevel", res);
lpDevice->Release();
return DIENUM_STOP;
}
}
// get polling
DIDEVCAPS didc;
@ -567,6 +604,8 @@ BOOL CALLBACK EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi,
jobject obj = pData->obj;
jobject list = pData->list;
jobject identifier = NULL;
char ffEnabled = 0;
HRESULT res;
if (lpddoi->guidType == GUID_XAxis) {
identifier = env->GetStaticObjectField(CLASS_AxisIdentifier, FID_X);
@ -606,15 +645,111 @@ BOOL CALLBACK EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi,
res=lpDevice->SetProperty(DIPROP_RANGE,&joy_axis_range.diph))){
PrintDIError("SetProperty", res);
}
//check if this axis is ff enabled
if( (lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 ) {
//printf("%s is ff enabled\n", lpddoi->tszName);
ffEnabled = 1;
}
}
jint didft = (jint)lpddoi->dwType;
jint didft = (jint)lpddoi->dwType;
jstring name = env->NewStringUTF(lpddoi->tszName);
// Add the axis into our list
env->CallVoidMethod(obj, MID_AddAxis, list, identifier, didft,
name);
if(ffEnabled) {
// This application needs only one effect: Applying raw forces.
DWORD rgdwAxes;
LONG rglDirection = 0;
if(lpddoi->guidType == GUID_XAxis) {
//printf("effect is in the x axis\n");
rgdwAxes = DIJOFS_X;
} else if(lpddoi->guidType == GUID_YAxis) {
//printf("effect is in the y axis\n");
rgdwAxes = DIJOFS_Y;
}
DICONSTANTFORCE cf = { DI_FFNOMINALMAX };
DIEFFECT eff;
ZeroMemory( &eff, sizeof(eff) );
eff.dwSize = sizeof(DIEFFECT);
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
eff.dwDuration = INFINITE;
eff.dwSamplePeriod = 0;
eff.dwGain = DI_FFNOMINALMAX;
eff.dwTriggerButton = DIEB_NOTRIGGER;
eff.dwTriggerRepeatInterval = 0;
eff.cAxes = 1;
eff.rgdwAxes = &rgdwAxes;
eff.rglDirection = &rglDirection;
eff.lpEnvelope = 0;
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
eff.lpvTypeSpecificParams = &cf;
eff.dwStartDelay = 0;
cf.lMagnitude = (long) (0);
LPDIRECTINPUTEFFECT g_pEffect;
// Create the prepared effect
if( FAILED( res = lpDevice->CreateEffect( GUID_ConstantForce,
&eff, &g_pEffect, NULL ) ) )
{
PrintDIError("Create effect", res);
return res;
}
env->CallVoidMethod(obj, MID_AddRumbler, (jlong)(long)g_pEffect, identifier);
}
return DIENUM_CONTINUE;
}
/*
* Class: org_java_games_input_DirectInputRumbler
* Method setRumble
* Signature (JF)Z
*/
extern "C" JNIEXPORT jboolean JNICALL
Java_net_java_games_input_DirectInputRumbler_setRumble
(JNIEnv *env, jobject obj, jlong effect, jfloat value)
{
LPDIRECTINPUTEFFECT g_pEffect = (LPDIRECTINPUTEFFECT)(long)effect;
float force = (float)value;
HRESULT hr;
DICONSTANTFORCE cf = { DI_FFNOMINALMAX };
DIEFFECT eff;
ZeroMemory( &eff, sizeof(eff) );
eff.dwSize = sizeof(DIEFFECT);
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
eff.lpvTypeSpecificParams = &cf;
cf.lMagnitude = (long) (((float)DI_FFNOMINALMAX)*force);
//printf("force: %f, mag: %d\n", force, cf.lMagnitude);
hr = g_pEffect->SetParameters( &eff, DIEP_TYPESPECIFICPARAMS );
if (FAILED(hr)) {
PrintDIError("set parameters", hr);
return hr;
}
if(force!=0) {
hr = g_pEffect->Start(1,0);
if (FAILED(hr)) {
PrintDIError("start", hr);
return hr;
}
} else {
hr = g_pEffect->Stop();
if (FAILED(hr)) {
PrintDIError("stop", hr);
return hr;
}
}
}
/*
* Class: org_java_games_input_DirectInputDevice
* Method: enumObjects