Commit 820c5377 authored by Ian Vollick's avatar Ian Vollick Committed by Commit Bot

[vr] Implement controller quiescence

When the controller is inactive, we should fade it out.

Also includes some minor changes in VrShellGl to reuse
the current time rather than recomputing it.

Bug: 776521
Change-Id: I5ce7708b3eddc04b9ad65d176eb544be7446cbca
Reviewed-on: https://chromium-review.googlesource.com/752344Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Commit-Queue: Ian Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513937}
parent c04ba387
...@@ -422,7 +422,7 @@ void VrShellGl::OnWebVRFrameAvailable() { ...@@ -422,7 +422,7 @@ void VrShellGl::OnWebVRFrameAvailable() {
ui_->OnWebVrFrameAvailable(); ui_->OnWebVrFrameAvailable();
DrawFrame(frame_index); DrawFrame(frame_index, base::TimeTicks::Now());
if (web_vr_mode_) if (web_vr_mode_)
++webvr_frames_received_; ++webvr_frames_received_;
ScheduleOrCancelWebVrFrameTimeout(); ScheduleOrCancelWebVrFrameTimeout();
...@@ -546,7 +546,8 @@ void VrShellGl::InitializeRenderer() { ...@@ -546,7 +546,8 @@ void VrShellGl::InitializeRenderer() {
browser_->GvrDelegateReady(gvr_api_->GetViewerType()); browser_->GvrDelegateReady(gvr_api_->GetViewerType());
} }
void VrShellGl::UpdateController(const gfx::Transform& head_pose) { void VrShellGl::UpdateController(const gfx::Transform& head_pose,
base::TimeTicks current_time) {
TRACE_EVENT0("gpu", "VrShellGl::UpdateController"); TRACE_EVENT0("gpu", "VrShellGl::UpdateController");
gvr::Mat4f gvr_head_pose; gvr::Mat4f gvr_head_pose;
TransformToGvrMat(head_pose, &gvr_head_pose); TransformToGvrMat(head_pose, &gvr_head_pose);
...@@ -558,11 +559,13 @@ void VrShellGl::UpdateController(const gfx::Transform& head_pose) { ...@@ -558,11 +559,13 @@ void VrShellGl::UpdateController(const gfx::Transform& head_pose) {
controller_data.connected = false; controller_data.connected = false;
browser_->UpdateGamepadData(controller_data); browser_->UpdateGamepadData(controller_data);
HandleControllerInput(laser_origin, GetForwardVector(head_pose)); HandleControllerInput(laser_origin, GetForwardVector(head_pose),
current_time);
} }
void VrShellGl::HandleControllerInput(const gfx::Point3F& laser_origin, void VrShellGl::HandleControllerInput(const gfx::Point3F& laser_origin,
const gfx::Vector3dF& head_direction) { const gfx::Vector3dF& head_direction,
base::TimeTicks current_time) {
if (is_exiting_) { if (is_exiting_) {
// When we're exiting, we don't show the reticle and the only input // When we're exiting, we don't show the reticle and the only input
// processing we do is to handle immediate exits. // processing we do is to handle immediate exits.
...@@ -616,8 +619,8 @@ void VrShellGl::HandleControllerInput(const gfx::Point3F& laser_origin, ...@@ -616,8 +619,8 @@ void VrShellGl::HandleControllerInput(const gfx::Point3F& laser_origin,
controller_model.laser_origin = laser_origin; controller_model.laser_origin = laser_origin;
vr::ReticleModel reticle_model; vr::ReticleModel reticle_model;
ui_->input_manager()->HandleInput(controller_model, &reticle_model, ui_->input_manager()->HandleInput(current_time, controller_model,
&gesture_list); &reticle_model, &gesture_list);
ui_->OnControllerUpdated(controller_model, reticle_model); ui_->OnControllerUpdated(controller_model, reticle_model);
} }
...@@ -891,16 +894,14 @@ void VrShellGl::UpdateEyeInfos(const gfx::Transform& head_pose, ...@@ -891,16 +894,14 @@ void VrShellGl::UpdateEyeInfos(const gfx::Transform& head_pose,
} }
} }
void VrShellGl::DrawFrame(int16_t frame_index) { void VrShellGl::DrawFrame(int16_t frame_index, base::TimeTicks current_time) {
TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index);
if (!webvr_delayed_frame_submit_.IsCancelled()) { if (!webvr_delayed_frame_submit_.IsCancelled()) {
webvr_delayed_frame_submit_.Cancel(); webvr_delayed_frame_submit_.Cancel();
DrawIntoAcquiredFrame(frame_index); DrawIntoAcquiredFrame(frame_index, current_time);
return; return;
} }
base::TimeTicks current_time = base::TimeTicks::Now();
CHECK(!acquired_frame_); CHECK(!acquired_frame_);
// Reset the viewport list to just the pair of viewports for the // Reset the viewport list to just the pair of viewports for the
...@@ -957,18 +958,17 @@ void VrShellGl::DrawFrame(int16_t frame_index) { ...@@ -957,18 +958,17 @@ void VrShellGl::DrawFrame(int16_t frame_index) {
// WebVR handles controller input in OnVsync. // WebVR handles controller input in OnVsync.
if (!ShouldDrawWebVr()) if (!ShouldDrawWebVr())
UpdateController(render_info_primary_.head_pose); UpdateController(render_info_primary_.head_pose, current_time);
bool textures_changed = ui_->scene()->UpdateTextures(); bool textures_changed = ui_->scene()->UpdateTextures();
// TODO(mthiesse): For now, just pretend the controller isn't dirty, even // TODO(mthiesse): Determine if a visible controller is actually drawn in the
// though it is, so that we can measure/test this rendering path that avoids // viewport.
// redaws. This is fine because this is still behind a flag. bool controller_dirty = ui_->IsControllerVisible();
static bool controller_dirty_ = false;
// TODO(mthiesse): Refine this notion of when we need to redraw. If only a // TODO(mthiesse): Refine this notion of when we need to redraw. If only a
// portion of the screen is dirtied, we can update just redraw that portion. // portion of the screen is dirtied, we can update just redraw that portion.
bool redraw_needed = controller_dirty_ || scene_changed || textures_changed || bool redraw_needed = controller_dirty || scene_changed || textures_changed ||
content_frame_available_; content_frame_available_;
gfx::Vector3dF old_forward_vector = GetForwardVector(last_used_head_pose_); gfx::Vector3dF old_forward_vector = GetForwardVector(last_used_head_pose_);
...@@ -987,10 +987,11 @@ void VrShellGl::DrawFrame(int16_t frame_index) { ...@@ -987,10 +987,11 @@ void VrShellGl::DrawFrame(int16_t frame_index) {
if (!acquired_frame_) if (!acquired_frame_)
return; return;
DrawIntoAcquiredFrame(frame_index); DrawIntoAcquiredFrame(frame_index, current_time);
} }
void VrShellGl::DrawIntoAcquiredFrame(int16_t frame_index) { void VrShellGl::DrawIntoAcquiredFrame(int16_t frame_index,
base::TimeTicks current_time) {
TRACE_EVENT1("gpu", "VrShellGl::DrawIntoAcquiredFrame", "frame", frame_index); TRACE_EVENT1("gpu", "VrShellGl::DrawIntoAcquiredFrame", "frame", frame_index);
last_used_head_pose_ = render_info_primary_.head_pose; last_used_head_pose_ = render_info_primary_.head_pose;
...@@ -1284,9 +1285,9 @@ void VrShellGl::OnVSync(base::TimeTicks frame_time) { ...@@ -1284,9 +1285,9 @@ void VrShellGl::OnVSync(base::TimeTicks frame_time) {
// DrawFrame. // DrawFrame.
gfx::Transform head_pose; gfx::Transform head_pose;
device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose);
UpdateController(head_pose); UpdateController(head_pose, frame_time);
} else { } else {
DrawFrame(-1); DrawFrame(-1, frame_time);
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "chrome/browser/android/vr_shell/vr_controller.h" #include "chrome/browser/android/vr_shell/vr_controller.h"
#include "chrome/browser/vr/content_input_delegate.h" #include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/controller_mesh.h" #include "chrome/browser/vr/controller_mesh.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/ui_input_manager.h" #include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_renderer.h" #include "chrome/browser/vr/ui_renderer.h"
#include "device/vr/vr_service.mojom.h" #include "device/vr/vr_service.mojom.h"
...@@ -130,8 +131,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider, ...@@ -130,8 +131,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider,
int viewport_offset, int viewport_offset,
const gfx::Size& render_size, const gfx::Size& render_size,
vr::RenderInfo* out_render_info); vr::RenderInfo* out_render_info);
void DrawFrame(int16_t frame_index); void DrawFrame(int16_t frame_index, base::TimeTicks current_time);
void DrawIntoAcquiredFrame(int16_t frame_index); void DrawIntoAcquiredFrame(int16_t frame_index, base::TimeTicks current_time);
void DrawFrameSubmitWhenReady(int16_t frame_index, void DrawFrameSubmitWhenReady(int16_t frame_index,
const gfx::Transform& head_pose, const gfx::Transform& head_pose,
std::unique_ptr<gl::GLFenceEGL> fence); std::unique_ptr<gl::GLFenceEGL> fence);
...@@ -140,7 +141,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider, ...@@ -140,7 +141,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider,
void DrawWebVr(); void DrawWebVr();
bool WebVrPoseByteIsValid(int pose_index_byte); bool WebVrPoseByteIsValid(int pose_index_byte);
void UpdateController(const gfx::Transform& head_pose); void UpdateController(const gfx::Transform& head_pose,
base::TimeTicks current_time);
std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent( std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent(
blink::WebInputEvent::Type type, blink::WebInputEvent::Type type,
const gfx::PointF& normalized_web_content_location); const gfx::PointF& normalized_web_content_location);
...@@ -166,7 +168,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider, ...@@ -166,7 +168,8 @@ class VrShellGl : public device::mojom::VRPresentationProvider,
void SendImmediateExitRequestIfNecessary(); void SendImmediateExitRequestIfNecessary();
void HandleControllerInput(const gfx::Point3F& laser_origin, void HandleControllerInput(const gfx::Point3F& laser_origin,
const gfx::Vector3dF& head_direction); const gfx::Vector3dF& head_direction,
base::TimeTicks current_time);
void HandleControllerAppButtonActivity( void HandleControllerAppButtonActivity(
const gfx::Vector3dF& controller_direction); const gfx::Vector3dF& controller_direction);
void SendGestureToContent(std::unique_ptr<blink::WebInputEvent> event); void SendGestureToContent(std::unique_ptr<blink::WebInputEvent> event);
......
...@@ -21,6 +21,7 @@ static const char* g_ui_element_name_strings[] = { ...@@ -21,6 +21,7 @@ static const char* g_ui_element_name_strings[] = {
"kWebVrRoot", "kWebVrRoot",
"kWebVrViewportAwareRoot", "kWebVrViewportAwareRoot",
"kContentQuad", "kContentQuad",
"kControllerRoot",
"kControllerGroup", "kControllerGroup",
"kLaser", "kLaser",
"kController", "kController",
......
...@@ -21,6 +21,7 @@ enum UiElementName { ...@@ -21,6 +21,7 @@ enum UiElementName {
kWebVrRoot, kWebVrRoot,
kWebVrViewportAwareRoot, kWebVrViewportAwareRoot,
kContentQuad, kContentQuad,
kControllerRoot,
kControllerGroup, kControllerGroup,
kLaser, kLaser,
kController, kController,
......
...@@ -23,6 +23,7 @@ struct ControllerModel { ...@@ -23,6 +23,7 @@ struct ControllerModel {
UiInputManager::ButtonState app_button_state = UiInputManager::UP; UiInputManager::ButtonState app_button_state = UiInputManager::UP;
UiInputManager::ButtonState home_button_state = UiInputManager::UP; UiInputManager::ButtonState home_button_state = UiInputManager::UP;
float opacity = 1.0f; float opacity = 1.0f;
bool quiescent = false;
}; };
} // namespace vr } // namespace vr
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/vr/browser_ui_interface.h" #include "chrome/browser/vr/browser_ui_interface.h"
#include "chrome/browser/vr/model/model.h" #include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/test/animation_utils.h"
#include "chrome/browser/vr/test/constants.h" #include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/ui_browser_interface.h" #include "chrome/browser/vr/ui_browser_interface.h"
#include "chrome/browser/vr/ui_input_manager.h" #include "chrome/browser/vr/ui_input_manager.h"
...@@ -96,8 +97,8 @@ void UiPixelTest::DrawUi(const gfx::Vector3dF& laser_direction, ...@@ -96,8 +97,8 @@ void UiPixelTest::DrawUi(const gfx::Vector3dF& laser_direction,
gfx::Vector3dF(-render_info.head_pose.matrix().get(2, 0), gfx::Vector3dF(-render_info.head_pose.matrix().get(2, 0),
-render_info.head_pose.matrix().get(2, 1), -render_info.head_pose.matrix().get(2, 1),
-render_info.head_pose.matrix().get(2, 2)))); -render_info.head_pose.matrix().get(2, 2))));
ui_->input_manager()->HandleInput(controller_model, &reticle_model, ui_->input_manager()->HandleInput(MsToTicks(1), controller_model,
&gesture_list); &reticle_model, &gesture_list);
ui_->OnControllerUpdated(controller_model, reticle_model); ui_->OnControllerUpdated(controller_model, reticle_model);
ui_->ui_renderer()->Draw(render_info); ui_->ui_renderer()->Draw(render_info);
......
...@@ -92,6 +92,13 @@ void VrTestContext::DrawFrame() { ...@@ -92,6 +92,13 @@ void VrTestContext::DrawFrame() {
render_info.left_eye_info.proj_matrix = proj_matrix; render_info.left_eye_info.proj_matrix = proj_matrix;
render_info.left_eye_info.view_proj_matrix = proj_matrix * head_pose_; render_info.left_eye_info.view_proj_matrix = proj_matrix * head_pose_;
GestureList gesture_list;
ReticleModel reticle_model;
ui_->input_manager()->HandleInput(base::TimeTicks::Now(),
last_controller_model_, &reticle_model,
&gesture_list);
ui_->OnControllerUpdated(last_controller_model_, reticle_model);
// Update the render position of all UI elements (including desktop). // Update the render position of all UI elements (including desktop).
ui_->scene()->OnBeginFrame(current_time, kForwardVector); ui_->scene()->OnBeginFrame(current_time, kForwardVector);
ui_->OnProjMatrixChanged(render_info.left_eye_info.proj_matrix); ui_->OnProjMatrixChanged(render_info.left_eye_info.proj_matrix);
...@@ -210,8 +217,9 @@ void VrTestContext::HandleInput(ui::Event* event) { ...@@ -210,8 +217,9 @@ void VrTestContext::HandleInput(ui::Event* event) {
GestureList gesture_list; GestureList gesture_list;
ReticleModel reticle_model; ReticleModel reticle_model;
ui_->input_manager()->HandleInput(controller_model, &reticle_model, ui_->input_manager()->HandleInput(base::TimeTicks::Now(), controller_model,
&gesture_list); &reticle_model, &gesture_list);
last_controller_model_ = controller_model;
ui_->OnControllerUpdated(controller_model, reticle_model); ui_->OnControllerUpdated(controller_model, reticle_model);
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <cstdint> #include <cstdint>
#include "chrome/browser/vr/content_input_delegate.h" #include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/ui_browser_interface.h" #include "chrome/browser/vr/ui_browser_interface.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
...@@ -80,6 +81,8 @@ class VrTestContext : public vr::ContentInputDelegate, ...@@ -80,6 +81,8 @@ class VrTestContext : public vr::ContentInputDelegate,
bool fullscreen_ = false; bool fullscreen_ = false;
bool incognito_ = false; bool incognito_ = false;
ControllerModel last_controller_model_;
DISALLOW_COPY_AND_ASSIGN(VrTestContext); DISALLOW_COPY_AND_ASSIGN(VrTestContext);
}; };
......
...@@ -140,6 +140,7 @@ void Ui::OnControllerUpdated(const ControllerModel& controller_model, ...@@ -140,6 +140,7 @@ void Ui::OnControllerUpdated(const ControllerModel& controller_model,
const ReticleModel& reticle_model) { const ReticleModel& reticle_model) {
model_->controller = controller_model; model_->controller = controller_model;
model_->reticle = reticle_model; model_->reticle = reticle_model;
model_->controller.quiescent = input_manager_->controller_quiescent();
} }
void Ui::OnProjMatrixChanged(const gfx::Transform& proj_matrix) { void Ui::OnProjMatrixChanged(const gfx::Transform& proj_matrix) {
...@@ -159,4 +160,9 @@ void Ui::OnWebVrTimedOut() { ...@@ -159,4 +160,9 @@ void Ui::OnWebVrTimedOut() {
model_->web_vr_timeout_state = kWebVrTimedOut; model_->web_vr_timeout_state = kWebVrTimedOut;
} }
bool Ui::IsControllerVisible() const {
UiElement* controller_group = scene_->GetUiElementByName(kControllerGroup);
return controller_group && controller_group->GetTargetOpacity() > 0.0f;
}
} // namespace vr } // namespace vr
...@@ -83,6 +83,7 @@ class Ui : public BrowserUiInterface, public UiInterface { ...@@ -83,6 +83,7 @@ class Ui : public BrowserUiInterface, public UiInterface {
void OnWebVrFrameAvailable() override; void OnWebVrFrameAvailable() override;
void OnWebVrTimedOut() override; void OnWebVrTimedOut() override;
void OnWebVrTimeoutImminent() override; void OnWebVrTimeoutImminent() override;
bool IsControllerVisible() const override;
void SetOmniboxSuggestions(std::unique_ptr<OmniboxSuggestions> suggestions); void SetOmniboxSuggestions(std::unique_ptr<OmniboxSuggestions> suggestions);
......
...@@ -24,6 +24,9 @@ static constexpr gfx::PointF kInvalidTargetPoint = ...@@ -24,6 +24,9 @@ static constexpr gfx::PointF kInvalidTargetPoint =
std::numeric_limits<float>::max()); std::numeric_limits<float>::max());
static constexpr gfx::Point3F kOrigin = {0.0f, 0.0f, 0.0f}; static constexpr gfx::Point3F kOrigin = {0.0f, 0.0f, 0.0f};
static constexpr float kControllerQuiescenceAngularThresholdDegrees = 3.5f;
static constexpr float kControllerQuiescenceTemporalThresholdSeconds = 1.2f;
gfx::Point3F GetRayPoint(const gfx::Point3F& rayOrigin, gfx::Point3F GetRayPoint(const gfx::Point3F& rayOrigin,
const gfx::Vector3dF& rayVector, const gfx::Vector3dF& rayVector,
float scale) { float scale) {
...@@ -108,9 +111,11 @@ UiInputManager::UiInputManager(UiScene* scene) : scene_(scene) {} ...@@ -108,9 +111,11 @@ UiInputManager::UiInputManager(UiScene* scene) : scene_(scene) {}
UiInputManager::~UiInputManager() {} UiInputManager::~UiInputManager() {}
void UiInputManager::HandleInput(const ControllerModel& controller_model, void UiInputManager::HandleInput(base::TimeTicks current_time,
const ControllerModel& controller_model,
ReticleModel* reticle_model, ReticleModel* reticle_model,
GestureList* gesture_list) { GestureList* gesture_list) {
UpdateQuiescenceState(current_time, controller_model);
gfx::Vector3dF eye_to_target; gfx::Vector3dF eye_to_target;
reticle_model->target_element_id = 0; reticle_model->target_element_id = 0;
reticle_model->target_local_point = kInvalidTargetPoint; reticle_model->target_local_point = kInvalidTargetPoint;
...@@ -407,4 +412,34 @@ void UiInputManager::GetVisualTargetElement( ...@@ -407,4 +412,34 @@ void UiInputManager::GetVisualTargetElement(
&closest_element_distance); &closest_element_distance);
} }
void UiInputManager::UpdateQuiescenceState(
base::TimeTicks current_time,
const ControllerModel& controller_model) {
// Update quiescence state.
gfx::Point3F old_position;
gfx::Point3F old_forward_position(0, 0, -1);
last_significant_controller_transform_.TransformPoint(&old_position);
last_significant_controller_transform_.TransformPoint(&old_forward_position);
gfx::Vector3dF old_forward = old_forward_position - old_position;
old_forward.GetNormalized(&old_forward);
gfx::Point3F new_position;
gfx::Point3F new_forward_position(0, 0, -1);
controller_model.transform.TransformPoint(&new_position);
controller_model.transform.TransformPoint(&new_forward_position);
gfx::Vector3dF new_forward = new_forward_position - new_position;
new_forward.GetNormalized(&new_forward);
float angle = AngleBetweenVectorsInDegrees(old_forward, new_forward);
if (angle > kControllerQuiescenceAngularThresholdDegrees || in_click_ ||
in_scroll_) {
controller_quiescent_ = false;
last_significant_controller_transform_ = controller_model.transform;
last_significant_controller_update_time_ = current_time;
} else if ((current_time - last_significant_controller_update_time_)
.InSecondsF() >
kControllerQuiescenceTemporalThresholdSeconds) {
controller_quiescent_ = true;
}
}
} // namespace vr } // namespace vr
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "base/time/time.h"
#include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector3d_f.h" #include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/transform.h"
namespace blink { namespace blink {
class WebGestureEvent; class WebGestureEvent;
...@@ -38,10 +40,13 @@ class UiInputManager { ...@@ -38,10 +40,13 @@ class UiInputManager {
explicit UiInputManager(UiScene* scene); explicit UiInputManager(UiScene* scene);
~UiInputManager(); ~UiInputManager();
// TODO(tiborg): Use generic gesture type instead of blink::WebGestureEvent. // TODO(tiborg): Use generic gesture type instead of blink::WebGestureEvent.
void HandleInput(const ControllerModel& controller_model, void HandleInput(base::TimeTicks current_time,
const ControllerModel& controller_model,
ReticleModel* reticle_model, ReticleModel* reticle_model,
GestureList* gesture_list); GestureList* gesture_list);
bool controller_quiescent() const { return controller_quiescent_; }
private: private:
void SendFlingCancel(GestureList* gesture_list, void SendFlingCancel(GestureList* gesture_list,
const gfx::PointF& target_point); const gfx::PointF& target_point);
...@@ -65,6 +70,8 @@ class UiInputManager { ...@@ -65,6 +70,8 @@ class UiInputManager {
void GetVisualTargetElement(const ControllerModel& controller_model, void GetVisualTargetElement(const ControllerModel& controller_model,
ReticleModel* reticle_model, ReticleModel* reticle_model,
gfx::Vector3dF* out_eye_to_target) const; gfx::Vector3dF* out_eye_to_target) const;
void UpdateQuiescenceState(base::TimeTicks current_time,
const ControllerModel& controller_model);
UiScene* scene_; UiScene* scene_;
int hover_target_id_ = 0; int hover_target_id_ = 0;
...@@ -77,6 +84,10 @@ class UiInputManager { ...@@ -77,6 +84,10 @@ class UiInputManager {
bool in_scroll_ = false; bool in_scroll_ = false;
ButtonState previous_button_state_ = ButtonState::UP; ButtonState previous_button_state_ = ButtonState::UP;
base::TimeTicks last_significant_controller_update_time_;
gfx::Transform last_significant_controller_transform_;
bool controller_quiescent_ = false;
}; };
} // namespace vr } // namespace vr
......
...@@ -72,7 +72,7 @@ class UiInputManagerTest : public testing::Test { ...@@ -72,7 +72,7 @@ class UiInputManagerTest : public testing::Test {
controller_model.touchpad_button_state = button_state; controller_model.touchpad_button_state = button_state;
ReticleModel reticle_model; ReticleModel reticle_model;
GestureList gesture_list; GestureList gesture_list;
input_manager_->HandleInput(controller_model, &reticle_model, input_manager_->HandleInput(MsToTicks(1), controller_model, &reticle_model,
&gesture_list); &gesture_list);
} }
...@@ -110,11 +110,13 @@ TEST_F(UiInputManagerTest, ReticleRenderTarget) { ...@@ -110,11 +110,13 @@ TEST_F(UiInputManagerTest, ReticleRenderTarget) {
ReticleModel reticle_model; ReticleModel reticle_model;
GestureList gesture_list; GestureList gesture_list;
input_manager_->HandleInput(controller_model, &reticle_model, &gesture_list); input_manager_->HandleInput(MsToTicks(1), controller_model, &reticle_model,
&gesture_list);
EXPECT_EQ(0, reticle_model.target_element_id); EXPECT_EQ(0, reticle_model.target_element_id);
controller_model.laser_direction = kForwardVector; controller_model.laser_direction = kForwardVector;
input_manager_->HandleInput(controller_model, &reticle_model, &gesture_list); input_manager_->HandleInput(MsToTicks(1), controller_model, &reticle_model,
&gesture_list);
EXPECT_EQ(p_element->id(), reticle_model.target_element_id); EXPECT_EQ(p_element->id(), reticle_model.target_element_id);
EXPECT_NEAR(-1.0, reticle_model.target_point.z(), kEpsilon); EXPECT_NEAR(-1.0, reticle_model.target_point.z(), kEpsilon);
} }
...@@ -243,7 +245,8 @@ TEST_F(UiInputManagerContentTest, NoMouseMovesDuringClick) { ...@@ -243,7 +245,8 @@ TEST_F(UiInputManagerContentTest, NoMouseMovesDuringClick) {
controller_model.touchpad_button_state = UiInputManager::ButtonState::DOWN; controller_model.touchpad_button_state = UiInputManager::ButtonState::DOWN;
ReticleModel reticle_model; ReticleModel reticle_model;
GestureList gesture_list; GestureList gesture_list;
input_manager_->HandleInput(controller_model, &reticle_model, &gesture_list); input_manager_->HandleInput(MsToTicks(1), controller_model, &reticle_model,
&gesture_list);
// We should have hit the content quad if our math was correct. // We should have hit the content quad if our math was correct.
ASSERT_NE(0, reticle_model.target_element_id); ASSERT_NE(0, reticle_model.target_element_id);
...@@ -254,7 +257,8 @@ TEST_F(UiInputManagerContentTest, NoMouseMovesDuringClick) { ...@@ -254,7 +257,8 @@ TEST_F(UiInputManagerContentTest, NoMouseMovesDuringClick) {
// set the expected number of calls to zero. // set the expected number of calls to zero.
EXPECT_CALL(*content_input_delegate_, OnContentMove(testing::_)).Times(0); EXPECT_CALL(*content_input_delegate_, OnContentMove(testing::_)).Times(0);
input_manager_->HandleInput(controller_model, &reticle_model, &gesture_list); input_manager_->HandleInput(MsToTicks(1), controller_model, &reticle_model,
&gesture_list);
} }
} // namespace vr } // namespace vr
...@@ -43,6 +43,8 @@ class UiInterface { ...@@ -43,6 +43,8 @@ class UiInterface {
virtual void OnWebVrFrameAvailable() = 0; virtual void OnWebVrFrameAvailable() = 0;
virtual void OnWebVrTimedOut() = 0; virtual void OnWebVrTimedOut() = 0;
virtual void OnWebVrTimeoutImminent() = 0; virtual void OnWebVrTimeoutImminent() = 0;
virtual bool IsControllerVisible() const = 0;
}; };
} // namespace vr } // namespace vr
......
...@@ -192,6 +192,9 @@ static constexpr float kSuggestionTextFieldWidth = 0.3f; ...@@ -192,6 +192,9 @@ static constexpr float kSuggestionTextFieldWidth = 0.3f;
static constexpr float kSuggestionContentTextHeight = 0.02f; static constexpr float kSuggestionContentTextHeight = 0.02f;
static constexpr float kSuggestionDescriptionTextHeight = 0.015f; static constexpr float kSuggestionDescriptionTextHeight = 0.015f;
static constexpr int kControllerFadeInMs = 200;
static constexpr int kControllerFadeOutMs = 550;
} // namespace vr } // namespace vr
#endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_ #endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_
...@@ -630,11 +630,11 @@ void UiSceneManager::CreateVoiceSearchUiGroup(Model* model) { ...@@ -630,11 +630,11 @@ void UiSceneManager::CreateVoiceSearchUiGroup(Model* model) {
} }
void UiSceneManager::CreateController(Model* model) { void UiSceneManager::CreateController(Model* model) {
auto group = base::MakeUnique<UiElement>(); auto root = base::MakeUnique<UiElement>();
group->set_name(kControllerGroup); root->set_name(kControllerRoot);
group->SetVisible(true); root->SetVisible(true);
group->set_hit_testable(false); root->set_hit_testable(false);
group->AddBinding(base::MakeUnique<Binding<bool>>( root->AddBinding(base::MakeUnique<Binding<bool>>(
base::Bind( base::Bind(
[](Model* m, UiSceneManager* mgr) { [](Model* m, UiSceneManager* mgr) {
bool browsing_mode = bool browsing_mode =
...@@ -643,8 +643,25 @@ void UiSceneManager::CreateController(Model* model) { ...@@ -643,8 +643,25 @@ void UiSceneManager::CreateController(Model* model) {
}, },
base::Unretained(model), base::Unretained(this)), base::Unretained(model), base::Unretained(this)),
base::Bind([](UiElement* v, const bool& b) { v->SetVisible(b); }, base::Bind([](UiElement* v, const bool& b) { v->SetVisible(b); },
base::Unretained(group.get())))); base::Unretained(root.get()))));
scene_->AddUiElement(kRoot, std::move(group)); scene_->AddUiElement(kRoot, std::move(root));
auto group = base::MakeUnique<UiElement>();
group->set_name(kControllerGroup);
group->SetVisible(true);
group->set_hit_testable(false);
group->SetTransitionedProperties({OPACITY});
group->AddBinding(base::MakeUnique<Binding<bool>>(
base::Bind([](Model* m) { return !m->controller.quiescent; },
base::Unretained(model)),
base::Bind(
[](UiElement* e, const bool& visible) {
e->SetTransitionDuration(base::TimeDelta::FromMilliseconds(
visible ? kControllerFadeInMs : kControllerFadeOutMs));
e->SetVisible(visible);
},
base::Unretained(group.get()))));
scene_->AddUiElement(kControllerRoot, std::move(group));
auto controller = base::MakeUnique<Controller>(); auto controller = base::MakeUnique<Controller>();
controller->set_draw_phase(kPhaseForeground); controller->set_draw_phase(kPhaseForeground);
......
...@@ -731,4 +731,22 @@ TEST_F(UiSceneManagerTest, OmniboxSuggestionBindings) { ...@@ -731,4 +731,22 @@ TEST_F(UiSceneManagerTest, OmniboxSuggestionBindings) {
EXPECT_EQ(NumVisibleChildren(kSuggestionLayout), initially_visible); EXPECT_EQ(NumVisibleChildren(kSuggestionLayout), initially_visible);
} }
TEST_F(UiSceneManagerTest, ControllerQuiescence) {
MakeManager(kNotInCct, kNotInWebVr);
OnBeginFrame();
EXPECT_TRUE(IsVisible(kControllerGroup));
model_->controller.quiescent = true;
EXPECT_TRUE(AnimateBy(MsToDelta(500)));
EXPECT_TRUE(IsVisible(kControllerGroup));
EXPECT_TRUE(AnimateBy(MsToDelta(100)));
EXPECT_FALSE(IsVisible(kControllerGroup));
UiElement* controller_group = scene_->GetUiElementByName(kControllerGroup);
model_->controller.quiescent = false;
EXPECT_TRUE(AnimateBy(MsToDelta(100)));
EXPECT_GT(1.0f, controller_group->computed_opacity());
EXPECT_TRUE(AnimateBy(MsToDelta(150)));
EXPECT_EQ(1.0f, controller_group->computed_opacity());
}
} // namespace vr } // namespace vr
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