Commit f0f0ecac authored by Matt Reynolds's avatar Matt Reynolds Committed by Commit Bot

Implement GamepadHapticActuator

GamepadHapticActuator receives haptics commands and forwards them to
GamepadDispatcher, which dispatches them to the device service. It also
manages the state of promises which have been returned to the user as
the result of haptics commands.

Haptics commands include playEffect, which plays a vibration effect on
the target gamepad, and reset, which stops vibration and resets any
vibration-related state on the gamepad. Both commands return a promise
that is resolved with a result code once the command is completed.

BUG=749295

Change-Id: I457c4b0e024c88adcaecdf6695959e06acb20a8e
Reviewed-on: https://chromium-review.googlesource.com/747050
Commit-Queue: Matt Reynolds <mattreynolds@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513032}
parent f634e30b
...@@ -5,14 +5,49 @@ ...@@ -5,14 +5,49 @@
#include "modules/gamepad/GamepadHapticActuator.h" #include "modules/gamepad/GamepadHapticActuator.h"
#include "bindings/core/v8/ScriptPromiseResolver.h" #include "bindings/core/v8/ScriptPromiseResolver.h"
#include "modules/gamepad/GamepadDispatcher.h"
namespace { namespace {
using device::mojom::GamepadHapticsResult;
using device::mojom::GamepadHapticEffectType;
const char kGamepadHapticActuatorTypeVibration[] = "vibration"; const char kGamepadHapticActuatorTypeVibration[] = "vibration";
const char kGamepadHapticActuatorTypeDualRumble[] = "dual-rumble"; const char kGamepadHapticActuatorTypeDualRumble[] = "dual-rumble";
const char kGamepadHapticEffectTypeDualRumble[] = "dual-rumble";
const char kGamepadHapticsResultComplete[] = "complete";
const char kGamepadHapticsResultPreempted[] = "preempted";
const char kGamepadHapticsResultInvalidParameter[] = "invalid-parameter";
const char kGamepadHapticsResultNotSupported[] = "not-supported"; const char kGamepadHapticsResultNotSupported[] = "not-supported";
const double kMaxEffectDurationMillis = 5000.0; // 5 seconds
GamepadHapticEffectType EffectTypeFromString(const String& type) {
if (type == kGamepadHapticEffectTypeDualRumble)
return GamepadHapticEffectType::GamepadHapticEffectTypeDualRumble;
NOTREACHED();
return GamepadHapticEffectType::GamepadHapticEffectTypeDualRumble;
}
String ResultToString(GamepadHapticsResult result) {
switch (result) {
case GamepadHapticsResult::GamepadHapticsResultComplete:
return kGamepadHapticsResultComplete;
case GamepadHapticsResult::GamepadHapticsResultPreempted:
return kGamepadHapticsResultPreempted;
case GamepadHapticsResult::GamepadHapticsResultInvalidParameter:
return kGamepadHapticsResultInvalidParameter;
case GamepadHapticsResult::GamepadHapticsResultNotSupported:
return kGamepadHapticsResultNotSupported;
default:
NOTREACHED();
}
return kGamepadHapticsResultNotSupported;
}
} // namespace } // namespace
namespace blink { namespace blink {
...@@ -25,7 +60,8 @@ GamepadHapticActuator* GamepadHapticActuator::Create(int pad_index) { ...@@ -25,7 +60,8 @@ GamepadHapticActuator* GamepadHapticActuator::Create(int pad_index) {
GamepadHapticActuator::GamepadHapticActuator( GamepadHapticActuator::GamepadHapticActuator(
int pad_index, int pad_index,
device::GamepadHapticActuatorType type) { device::GamepadHapticActuatorType type)
: pad_index_(pad_index) {
SetType(type); SetType(type);
} }
...@@ -49,20 +85,68 @@ ScriptPromise GamepadHapticActuator::playEffect( ...@@ -49,20 +85,68 @@ ScriptPromise GamepadHapticActuator::playEffect(
const String& type, const String& type,
const GamepadEffectParameters& params) { const GamepadEffectParameters& params) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
resolver->Resolve(kGamepadHapticsResultNotSupported);
NOTIMPLEMENTED(); if (params.duration() < 0.0 || params.startDelay() < 0.0 ||
return promise; params.strongMagnitude() < 0.0 || params.strongMagnitude() > 1.0 ||
params.weakMagnitude() < 0.0 || params.weakMagnitude() > 1.0) {
ScriptPromise promise = resolver->Promise();
resolver->Resolve(kGamepadHapticsResultInvalidParameter);
return promise;
}
// Limit the total effect duration.
double effect_duration = params.duration() + params.startDelay();
if (effect_duration > kMaxEffectDurationMillis) {
ScriptPromise promise = resolver->Promise();
resolver->Resolve(kGamepadHapticsResultInvalidParameter);
return promise;
}
auto callback = ConvertToBaseCallback(
WTF::Bind(&GamepadHapticActuator::OnPlayEffectCompleted,
WrapPersistent(this), WrapPersistent(resolver)));
GamepadDispatcher::Instance().PlayVibrationEffectOnce(
pad_index_, EffectTypeFromString(type),
device::mojom::blink::GamepadEffectParameters::New(
params.duration(), params.startDelay(), params.strongMagnitude(),
params.weakMagnitude()),
std::move(callback));
return resolver->Promise();
}
void GamepadHapticActuator::OnPlayEffectCompleted(
ScriptPromiseResolver* resolver,
device::mojom::GamepadHapticsResult result) {
if (result == GamepadHapticsResult::GamepadHapticsResultError) {
resolver->Reject();
return;
}
resolver->Resolve(ResultToString(result));
} }
ScriptPromise GamepadHapticActuator::reset(ScriptState* script_state) { ScriptPromise GamepadHapticActuator::reset(ScriptState* script_state) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
resolver->Resolve(kGamepadHapticsResultNotSupported);
NOTIMPLEMENTED(); auto callback = ConvertToBaseCallback(
return promise; WTF::Bind(&GamepadHapticActuator::OnResetCompleted, WrapPersistent(this),
WrapPersistent(resolver)));
GamepadDispatcher::Instance().ResetVibrationActuator(pad_index_,
std::move(callback));
return resolver->Promise();
}
void GamepadHapticActuator::OnResetCompleted(
ScriptPromiseResolver* resolver,
device::mojom::GamepadHapticsResult result) {
if (result == GamepadHapticsResult::GamepadHapticsResultError) {
resolver->Reject();
return;
}
resolver->Resolve(ResultToString(result));
} }
void GamepadHapticActuator::Trace(blink::Visitor* visitor) { void GamepadHapticActuator::Trace(blink::Visitor* visitor) {
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
#define GamepadHapticActuator_h #define GamepadHapticActuator_h
#include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "device/gamepad/public/cpp/gamepad.h" #include "device/gamepad/public/cpp/gamepad.h"
#include "device/gamepad/public/interfaces/gamepad.mojom-blink.h"
#include "modules/gamepad/GamepadEffectParameters.h" #include "modules/gamepad/GamepadEffectParameters.h"
#include "platform/bindings/ScriptWrappable.h" #include "platform/bindings/ScriptWrappable.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
...@@ -36,6 +38,12 @@ class GamepadHapticActuator final : public ScriptWrappable { ...@@ -36,6 +38,12 @@ class GamepadHapticActuator final : public ScriptWrappable {
private: private:
GamepadHapticActuator(int pad_index, device::GamepadHapticActuatorType); GamepadHapticActuator(int pad_index, device::GamepadHapticActuatorType);
void OnPlayEffectCompleted(ScriptPromiseResolver*,
device::mojom::GamepadHapticsResult);
void OnResetCompleted(ScriptPromiseResolver*,
device::mojom::GamepadHapticsResult);
int pad_index_;
String type_; String type_;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment