|
@@ -946,6 +946,103 @@ err_effectdone:
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+BOOL DIGetDirectionUpdateFlag(DIEFFECT *before, DIEFFECT *after)
|
|
|
|
|
+{
|
|
|
|
|
+ if (before->cAxes != after->cAxes) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ // rglDirection must be non-null for DIEP_DIRECTION to be a valid flag
|
|
|
|
|
+ if (after->rglDirection == NULL) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (before->rglDirection == NULL) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return SDL_memcmp(before->rglDirection, after->rglDirection, sizeof(LONG) * before->cAxes) != 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+BOOL DIGetEnvelopeUpdateFlag(DIEFFECT* before, DIEFFECT* after)
|
|
|
|
|
+{
|
|
|
|
|
+ if (before->lpEnvelope == NULL && after->lpEnvelope == NULL) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // A null lpEnvelope is valid for DIEP_ENVELOPE (clears the envelope from the effect)
|
|
|
|
|
+ if (before->lpEnvelope == NULL || after->lpEnvelope == NULL) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return SDL_memcmp(before->lpEnvelope, after->lpEnvelope, sizeof(DIENVELOPE)) != 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+BOOL DIGetTypeSpecificParamsUpdateFlag(DIEFFECT *before, DIEFFECT *after)
|
|
|
|
|
+{
|
|
|
|
|
+ // Shouldn't happen since this implies an effect's type somehow changed, but need to check to avoid an out-of-bounds memcmp
|
|
|
|
|
+ if (before->cbTypeSpecificParams != after->cbTypeSpecificParams) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ // lpvTypeSpecificParams must be non-null for the DIEP_TYPESPECIFICPARAMS flag.
|
|
|
|
|
+ if (after->lpvTypeSpecificParams == NULL) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (before->lpvTypeSpecificParams == NULL) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return SDL_memcmp(before->lpvTypeSpecificParams, after->lpvTypeSpecificParams, before->cbTypeSpecificParams) != 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ Calculate the exact flags needed when updating an existing DirectInput haptic effect.
|
|
|
|
|
+*/
|
|
|
|
|
+DWORD DICalculateUpdateFlags(DIEFFECT *before, DIEFFECT *after)
|
|
|
|
|
+{
|
|
|
|
|
+ DWORD flags = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (DIGetDirectionUpdateFlag(before, after)) {
|
|
|
|
|
+ flags |= DIEP_DIRECTION;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (before->dwDuration != after->dwDuration) {
|
|
|
|
|
+ flags |= DIEP_DURATION;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (DIGetEnvelopeUpdateFlag(before, after)) {
|
|
|
|
|
+ flags |= DIEP_ENVELOPE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (before->dwStartDelay != after->dwStartDelay) {
|
|
|
|
|
+ flags |= DIEP_STARTDELAY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (before->dwTriggerButton != after->dwTriggerButton) {
|
|
|
|
|
+ flags |= DIEP_TRIGGERBUTTON;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (before->dwTriggerRepeatInterval != after->dwTriggerRepeatInterval) {
|
|
|
|
|
+ flags |= DIEP_TRIGGERREPEATINTERVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (DIGetTypeSpecificParamsUpdateFlag(before, after)) {
|
|
|
|
|
+ flags |= DIEP_TYPESPECIFICPARAMS;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (flags == 0) {
|
|
|
|
|
+ /* Awkward: SDL_UpdateHapticEffect was called, but nothing was changed.
|
|
|
|
|
+ * Calling IDirectInputEffect_SetParameters with no flags is nonsense,
|
|
|
|
|
+ * so our options are to either send all the flags, or exit early.
|
|
|
|
|
+ * Sending all the flags seems like the safer option: The programmer may be trying
|
|
|
|
|
+ * to force an update for some reason (e.g. driver bug workaround?). Conversely,
|
|
|
|
|
+ * if the programmer doesn't want IDirectInputEffect_SetParameters to be called, they
|
|
|
|
|
+ * can just avoid calling SDL_UpdateHapticEffect when there's no changes. */
|
|
|
|
|
+ flags = DIEP_DIRECTION |
|
|
|
|
|
+ DIEP_DURATION |
|
|
|
|
|
+ DIEP_ENVELOPE |
|
|
|
|
|
+ DIEP_STARTDELAY |
|
|
|
|
|
+ DIEP_TRIGGERBUTTON |
|
|
|
|
|
+ DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return flags;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
bool SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data)
|
|
bool SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data)
|
|
|
{
|
|
{
|
|
|
HRESULT ret;
|
|
HRESULT ret;
|
|
@@ -958,14 +1055,7 @@ bool SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *eff
|
|
|
goto err_update;
|
|
goto err_update;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* Set the flags. Might be worthwhile to diff temp with loaded effect and
|
|
|
|
|
- * only change those parameters. */
|
|
|
|
|
- flags = DIEP_DIRECTION |
|
|
|
|
|
- DIEP_DURATION |
|
|
|
|
|
- DIEP_ENVELOPE |
|
|
|
|
|
- DIEP_STARTDELAY |
|
|
|
|
|
- DIEP_TRIGGERBUTTON |
|
|
|
|
|
- DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
|
|
|
|
|
|
|
+ flags = DICalculateUpdateFlags(&effect->hweffect->effect, &temp);
|
|
|
|
|
|
|
|
// Create the actual effect.
|
|
// Create the actual effect.
|
|
|
ret =
|
|
ret =
|