blob: 58b09339cfda8bfa2bfb643d68a0b8d59af0f31d [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_VR_CONTROLLER_H_
#define CHROME_BROWSER_ANDROID_VR_SHELL_VR_CONTROLLER_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/time/time.h"
#include "chrome/browser/vr/controller_mesh.h"
#include "chrome/browser/vr/platform_controller.h"
#include "device/vr/android/gvr/gvr_gamepad_data_provider.h"
#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/quaternion.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
namespace blink {
class WebGestureEvent;
}
namespace gfx {
class Transform;
}
namespace gvr {
class ControllerState;
}
namespace vr_shell {
// Angle (radians) the beam down from the controller axis, for wrist comfort.
constexpr float kErgoAngleOffset = 0.26f;
using GestureList = std::vector<std::unique_ptr<blink::WebGestureEvent>>;
class VrController : public vr::PlatformController {
public:
// Controller API entry point.
explicit VrController(gvr_context* gvr_context);
~VrController() override;
// Must be called when the Activity gets OnResume().
void OnResume();
// Must be called when the Activity gets OnPause().
void OnPause();
device::GvrGamepadData GetGamepadData();
// Called once per frame to update controller state.
void UpdateState(const gvr::Mat4f& head_direction);
std::unique_ptr<GestureList> DetectGestures();
bool IsTouching();
float TouchPosX();
float TouchPosY();
gfx::Quaternion Orientation() const;
gfx::Point3F Position() const;
void GetTransform(gfx::Transform* out) const;
float GetOpacity() const;
gfx::Point3F GetPointerStart() const;
bool TouchDownHappened();
bool TouchUpHappened();
bool ButtonUpHappened(gvr::ControllerButton button);
bool ButtonDownHappened(gvr::ControllerButton button);
bool ButtonState(gvr::ControllerButton button) const;
bool IsConnected();
// PlatformController
bool IsButtonDown(vr::PlatformController::ButtonType type) const override;
base::TimeTicks GetLastOrientationTimestamp() const override;
base::TimeTicks GetLastTouchTimestamp() const override;
base::TimeTicks GetLastButtonTimestamp() const override;
private:
enum GestureDetectorState {
WAITING, // waiting for user to touch down
TOUCHING, // touching the touch pad but not scrolling
SCROLLING // scrolling on the touch pad
};
struct TouchPoint {
gfx::Vector2dF position;
int64_t timestamp;
};
struct TouchInfo {
TouchPoint touch_point;
bool touch_up;
bool touch_down;
bool is_touching;
};
struct ButtonInfo {
gvr::ControllerButton button;
bool button_up;
bool button_down;
bool button_state;
int64_t timestamp;
};
void UpdateGestureFromTouchInfo(blink::WebGestureEvent* gesture);
bool GetButtonLongPressFromButtonInfo();
// Handle the waiting state.
void HandleWaitingState(blink::WebGestureEvent* gesture);
// Handle the detecting state.
void HandleDetectingState(blink::WebGestureEvent* gesture);
// Handle the scrolling state.
void HandleScrollingState(blink::WebGestureEvent* gesture);
void UpdateTouchInfo();
// Returns true if the touch position is within the slop of the initial touch
// point, false otherwise.
bool InSlop(const gfx::Vector2dF touch_position);
// Returns true if the gesture is in horizontal direction.
bool IsHorizontalGesture();
void Reset();
void UpdateGestureParameters();
// If the user is touching the touch pad and the touch point is different from
// before, update the touch point and return true. Otherwise, return false.
bool UpdateCurrentTouchpoint();
void UpdateOverallVelocity();
void UpdateAlpha();
// State of gesture detector.
GestureDetectorState state_;
std::unique_ptr<gvr::ControllerApi> controller_api_;
// The last controller state (updated once per frame).
std::unique_ptr<gvr::ControllerState> controller_state_;
std::unique_ptr<gvr::GvrApi> gvr_api_;
float last_qx_;
bool pinch_started_;
bool zoom_in_progress_ = false;
bool touch_position_changed_ = false;
// Handedness from user prefs.
gvr::ControllerHandedness handedness_;
// Current touch info after the extrapolation.
std::unique_ptr<TouchInfo> touch_info_;
// A pointer storing the touch point from previous frame.
std::unique_ptr<TouchPoint> prev_touch_point_;
// A pointer storing the touch point from current frame.
std::unique_ptr<TouchPoint> cur_touch_point_;
// Initial touch point.
std::unique_ptr<TouchPoint> init_touch_point_;
// Overall velocity
gfx::Vector2dF overall_velocity_;
// Last velocity that is used for fling and direction detection
gfx::Vector2dF last_velocity_;
// Displacement of the touch point from the previews to the current touch
gfx::Vector2dF displacement_;
int64_t last_touch_timestamp_ = 0;
int64_t last_timestamp_nanos_ = 0;
// Number of consecutively extrapolated touch points
int extrapolated_touch_ = 0;
float alpha_value_ = 1.0f;
DISALLOW_COPY_AND_ASSIGN(VrController);
};
} // namespace vr_shell
#endif // CHROME_BROWSER_ANDROID_VR_SHELL_VR_CONTROLLER_H_