Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell_gl.cc

Issue 2878543002: Refactor VR Shell Input. Locks input to click/scroll targets. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h" 5 #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
6 6
7 #include <chrono> 7 #include <chrono>
8 #include <limits> 8 #include <limits>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "chrome/browser/android/vr_shell/ui_scene_manager.h" 21 #include "chrome/browser/android/vr_shell/ui_scene_manager.h"
22 #include "chrome/browser/android/vr_shell/vr_controller.h" 22 #include "chrome/browser/android/vr_shell/vr_controller.h"
23 #include "chrome/browser/android/vr_shell/vr_gl_thread.h" 23 #include "chrome/browser/android/vr_shell/vr_gl_thread.h"
24 #include "chrome/browser/android/vr_shell/vr_gl_util.h" 24 #include "chrome/browser/android/vr_shell/vr_gl_util.h"
25 #include "chrome/browser/android/vr_shell/vr_shell.h" 25 #include "chrome/browser/android/vr_shell/vr_shell.h"
26 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" 26 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
27 #include "device/vr/android/gvr/gvr_delegate.h" 27 #include "device/vr/android/gvr/gvr_delegate.h"
28 #include "device/vr/android/gvr/gvr_device.h" 28 #include "device/vr/android/gvr/gvr_device.h"
29 #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" 29 #include "device/vr/android/gvr/gvr_gamepad_data_provider.h"
30 #include "device/vr/vr_math.h" 30 #include "device/vr/vr_math.h"
31 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
31 #include "third_party/WebKit/public/platform/WebInputEvent.h" 32 #include "third_party/WebKit/public/platform/WebInputEvent.h"
32 #include "third_party/WebKit/public/platform/WebMouseEvent.h" 33 #include "third_party/WebKit/public/platform/WebMouseEvent.h"
33 #include "ui/gl/android/scoped_java_surface.h" 34 #include "ui/gl/android/scoped_java_surface.h"
34 #include "ui/gl/android/surface_texture.h" 35 #include "ui/gl/android/surface_texture.h"
35 #include "ui/gl/gl_bindings.h" 36 #include "ui/gl/gl_bindings.h"
36 #include "ui/gl/gl_context.h" 37 #include "ui/gl/gl_context.h"
37 #include "ui/gl/gl_surface.h" 38 #include "ui/gl/gl_surface.h"
38 #include "ui/gl/init/gl_factory.h" 39 #include "ui/gl/init/gl_factory.h"
39 40
40 namespace vr_shell { 41 namespace vr_shell {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 result.m[0][2] = A; 131 result.m[0][2] = A;
131 result.m[1][1] = Y; 132 result.m[1][1] = Y;
132 result.m[1][2] = B; 133 result.m[1][2] = B;
133 result.m[2][2] = C; 134 result.m[2][2] = C;
134 result.m[2][3] = D; 135 result.m[2][3] = D;
135 result.m[3][2] = -1; 136 result.m[3][2] = -1;
136 137
137 return result; 138 return result;
138 } 139 }
139 140
140 std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent(WebInputEvent::Type type, 141 std::unique_ptr<blink::WebMouseEvent> MakeMouseEvent(
141 double timestamp, 142 blink::WebInputEvent::Type type,
142 float x, 143 double timestamp,
143 float y) { 144 const gfx::Point& loc) {
144 std::unique_ptr<blink::WebMouseEvent> mouse_event(new blink::WebMouseEvent( 145 std::unique_ptr<blink::WebMouseEvent> mouse_event(new blink::WebMouseEvent(
145 type, blink::WebInputEvent::kNoModifiers, timestamp)); 146 type, blink::WebInputEvent::kNoModifiers, timestamp));
146 mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse; 147 mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse;
147 mouse_event->SetPositionInWidget(x, y); 148 mouse_event->SetPositionInWidget(loc.x(), loc.y());
148 mouse_event->click_count = 1; 149 mouse_event->click_count = 1;
149 150
150 return mouse_event; 151 return mouse_event;
151 } 152 }
152 153
153 enum class ViewerType { 154 enum class ViewerType {
154 UNKNOWN_TYPE = 0, 155 UNKNOWN_TYPE = 0,
155 CARDBOARD = 1, 156 CARDBOARD = 1,
156 DAYDREAM = 2, 157 DAYDREAM = 2,
157 VIEWER_TYPE_MAX, 158 VIEWER_TYPE_MAX,
(...skipping 18 matching lines...) Expand all
176 gvr::Rectf UVFromGfxRect(gfx::RectF rect) { 177 gvr::Rectf UVFromGfxRect(gfx::RectF rect) {
177 return {rect.x(), rect.x() + rect.width(), 1.0f - rect.bottom(), 178 return {rect.x(), rect.x() + rect.width(), 1.0f - rect.bottom(),
178 1.0f - rect.y()}; 179 1.0f - rect.y()};
179 } 180 }
180 181
181 gfx::RectF GfxRectFromUV(gvr::Rectf rect) { 182 gfx::RectF GfxRectFromUV(gvr::Rectf rect) {
182 return gfx::RectF(rect.left, 1.0 - rect.top, rect.right - rect.left, 183 return gfx::RectF(rect.left, 1.0 - rect.top, rect.right - rect.left,
183 rect.top - rect.bottom); 184 rect.top - rect.bottom);
184 } 185 }
185 186
187 double NowSeconds() {
188 return (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
189 }
190
186 } // namespace 191 } // namespace
187 192
188 VrShellGl::VrShellGl(VrBrowserInterface* browser, 193 VrShellGl::VrShellGl(VrBrowserInterface* browser,
189 gvr_context* gvr_api, 194 gvr_context* gvr_api,
190 bool initially_web_vr, 195 bool initially_web_vr,
191 bool reprojected_rendering, 196 bool reprojected_rendering,
192 UiScene* scene) 197 UiScene* scene)
193 : web_vr_mode_(initially_web_vr), 198 : web_vr_mode_(initially_web_vr),
194 surfaceless_rendering_(reprojected_rendering), 199 surfaceless_rendering_(reprojected_rendering),
195 task_runner_(base::ThreadTaskRunnerHandle::Get()), 200 task_runner_(base::ThreadTaskRunnerHandle::Get()),
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 } 502 }
498 503
499 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) { 504 void VrShellGl::UpdateController(const gfx::Vector3dF& head_direction) {
500 controller_->UpdateState(head_direction); 505 controller_->UpdateState(head_direction);
501 pointer_start_ = controller_->GetPointerStart(); 506 pointer_start_ = controller_->GetPointerStart();
502 507
503 browser_->UpdateGamepadData(controller_->GetGamepadData()); 508 browser_->UpdateGamepadData(controller_->GetGamepadData());
504 } 509 }
505 510
506 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) { 511 void VrShellGl::HandleControllerInput(const gfx::Vector3dF& head_direction) {
507 if (ShouldDrawWebVr()) { 512 HandleWebVrCompatClick();
cjgrant 2017/05/10 20:16:25 s/Compat/Compatibility/
mthiesse 2017/05/10 21:09:08 Done.
508 // Process screen touch events for Cardboard button compatibility.
509 // Also send tap events for controller "touchpad click" events.
510 if (touch_pending_ ||
511 controller_->ButtonUpHappened(
512 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) {
513 touch_pending_ = false;
514 std::unique_ptr<WebGestureEvent> gesture(new WebGestureEvent(
515 WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers,
516 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF()));
517 gesture->source_device = blink::kWebGestureDeviceTouchpad;
518 gesture->x = 0;
519 gesture->y = 0;
520 SendGestureToContent(std::move(gesture));
521 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture";
522 }
523 }
524 513
525 gfx::Vector3dF ergo_neutral_pose; 514 gfx::Vector3dF ergo_neutral_pose;
526 if (!controller_->IsConnected()) { 515 if (!controller_->IsConnected()) {
527 // No controller detected, set up a gaze cursor that tracks the 516 // No controller detected, set up a gaze cursor that tracks the
528 // forward direction. 517 // forward direction.
529 ergo_neutral_pose = {0.0f, 0.0f, -1.0f}; 518 ergo_neutral_pose = {0.0f, 0.0f, -1.0f};
530 controller_quat_ = GetRotationFromZAxis(head_direction); 519 controller_quat_ = GetRotationFromZAxis(head_direction);
531 } else { 520 } else {
532 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)}; 521 ergo_neutral_pose = {0.0f, -sin(kErgoAngleOffset), -cos(kErgoAngleOffset)};
533 controller_quat_ = controller_->Orientation(); 522 controller_quat_ = controller_->Orientation();
534 } 523 }
535 524
536 vr::Mat4f mat; 525 vr::Mat4f mat;
537 QuatToMatrix(controller_quat_, &mat); 526 QuatToMatrix(controller_quat_, &mat);
538 gfx::Vector3dF controller_direction = 527 gfx::Vector3dF controller_direction =
539 vr::MatrixVectorMul(mat, ergo_neutral_pose); 528 vr::MatrixVectorMul(mat, ergo_neutral_pose);
540 529
541 HandleControllerAppButtonActivity(controller_direction); 530 HandleControllerAppButtonActivity(controller_direction);
542 531
543 if (ShouldDrawWebVr()) { 532 if (ShouldDrawWebVr())
544 return; 533 return;
cjgrant 2017/05/10 20:16:26 Blank line after return?
mthiesse 2017/05/10 21:09:08 Done.
545 } 534 gfx::PointF target_local_point;
546 535 gfx::Vector3dF eye_to_target;
536 cursor_render_target_ = nullptr;
537 GetVisualTargetElement(controller_direction, eye_to_target, target_point_,
538 &cursor_render_target_, target_local_point);
539
540 UiElement* target_element = nullptr;
541 if (input_locked_element_) {
542 gfx::Point3F plane_intersection_point;
543 float distance_to_plane;
544 GetTargetLocalPoint(eye_to_target, *input_locked_element_,
545 2 * scene_->GetBackgroundDistance(), target_local_point,
546 plane_intersection_point, distance_to_plane);
547 target_element = input_locked_element_;
548 } else if (!in_scroll_ && !in_click_) {
549 target_element = cursor_render_target_;
550 }
551
552 // Handle input targeting on the content quad, ignoring any other elements.
553 // Content is treated specially to accomodate scrolling, flings, etc.
554 gfx::Point local_point_pixels;
555 if (target_element && (target_element->fill() == Fill::CONTENT)) {
556 gfx::RectF pixel_rect(0, 0, content_tex_css_width_,
557 content_tex_css_height_);
558 local_point_pixels.set_x(pixel_rect.x() +
559 pixel_rect.width() * target_local_point.x());
560 local_point_pixels.set_y(pixel_rect.y() +
561 pixel_rect.height() * target_local_point.y());
562 }
563 std::unique_ptr<GestureList> gesture_list_ptr = controller_->DetectGestures();
564 GestureList& gesture_list = *gesture_list_ptr;
565 for (const std::unique_ptr<blink::WebGestureEvent>& gesture : gesture_list) {
566 gesture->x = local_point_pixels.x();
567 gesture->y = local_point_pixels.y();
568 }
569 SendFlingCancel(gesture_list);
570 // For simplicity, don't allow scrolling while clicking until we need to.
571 if (!in_click_) {
572 SendScrollEnd(gesture_list);
573 if (!SendScrollBegin(target_element, gesture_list)) {
574 SendScrollUpdate(gesture_list);
575 }
576 }
577 // If we're still scrolling, don't hover (and we can't be clicking, because
578 // click ends scroll).
579 if (in_scroll_)
580 return;
581 SendHoverLeave(target_element);
582 if (!SendHoverEnter(target_element, target_local_point, local_point_pixels)) {
583 SendHoverMove(target_local_point, local_point_pixels);
584 }
585 SendButtonDown(target_element, target_local_point);
586 if (!SendButtonUp(target_element, target_local_point))
587 SendTap(target_element, target_local_point, local_point_pixels);
588 }
589
590 void VrShellGl::HandleWebVrCompatClick() {
591 if (!ShouldDrawWebVr())
592 return;
593 // Process screen touch events for Cardboard button compatibility.
594 // Also send tap events for controller "touchpad click" events.
595 if (touch_pending_ ||
596 controller_->ButtonUpHappened(gvr::kControllerButtonClick)) {
597 touch_pending_ = false;
598 std::unique_ptr<blink::WebGestureEvent> gesture(new blink::WebGestureEvent(
599 blink::WebInputEvent::kGestureTapDown,
600 blink::WebInputEvent::kNoModifiers, NowSeconds()));
601 gesture->source_device = blink::kWebGestureDeviceTouchpad;
602 gesture->x = 0;
603 gesture->y = 0;
604 SendGestureToContent(std::move(gesture));
605 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture";
606 }
607 }
608
609 void VrShellGl::SendFlingCancel(GestureList& gesture_list) {
610 if (!fling_target_)
611 return;
612 if (gesture_list.empty() || (gesture_list.front()->GetType() !=
613 blink::WebInputEvent::kGestureFlingCancel))
614 return;
615 // Scrolling currently only supported on content window.
616 DCHECK_EQ(fling_target_->fill(), Fill::CONTENT);
617 SendGestureToContent(std::move(gesture_list.front()));
618 gesture_list.erase(gesture_list.begin());
619 }
620
621 void VrShellGl::SendScrollEnd(GestureList& gesture_list) {
622 if (!in_scroll_)
623 return;
624 DCHECK_NE(input_locked_element_, nullptr);
625 if (controller_->ButtonDownHappened(gvr::kControllerButtonClick)) {
626 DCHECK_GT(gesture_list.size(), 0LU);
627 DCHECK_EQ(gesture_list.front()->GetType(),
628 blink::WebInputEvent::kGestureScrollEnd);
629 }
630 // Scrolling currently only supported on content window.
631 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT);
632 if (gesture_list.empty() || (gesture_list.front()->GetType() !=
633 blink::WebInputEvent::kGestureScrollEnd))
634 return;
635 DCHECK_LE(gesture_list.size(), 2LU);
636 SendGestureToContent(std::move(gesture_list.front()));
637 gesture_list.erase(gesture_list.begin());
638 if (!gesture_list.empty()) {
639 DCHECK_EQ(gesture_list.front()->GetType(),
640 blink::WebInputEvent::kGestureFlingStart);
641 SendGestureToContent(std::move(gesture_list.front()));
642 fling_target_ = input_locked_element_;
643 gesture_list.erase(gesture_list.begin());
644 }
645 input_locked_element_ = nullptr;
646 in_scroll_ = false;
647 }
648
649 bool VrShellGl::SendScrollBegin(UiElement* target, GestureList& gesture_list) {
650 if (in_scroll_ || !target)
651 return false;
652 // Scrolling currently only supported on content window.
653 if (target->fill() != Fill::CONTENT)
654 return false;
655 if (gesture_list.empty() || (gesture_list.front()->GetType() !=
656 blink::WebInputEvent::kGestureScrollBegin))
657 return false;
658 input_locked_element_ = target;
659 in_scroll_ = true;
660
661 SendGestureToContent(std::move(gesture_list.front()));
662 gesture_list.erase(gesture_list.begin());
663 return true;
664 }
665
666 void VrShellGl::SendScrollUpdate(GestureList& gesture_list) {
667 if (!in_scroll_)
668 return;
669 DCHECK(input_locked_element_);
670 if (gesture_list.empty() || (gesture_list.front()->GetType() !=
671 blink::WebInputEvent::kGestureScrollUpdate))
672 return;
673 // Scrolling currently only supported on content window.
674 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT);
675 SendGestureToContent(std::move(gesture_list.front()));
676 gesture_list.erase(gesture_list.begin());
677 }
678
679 void VrShellGl::SendHoverLeave(UiElement* target) {
680 if (!hover_target_ || (target == hover_target_))
681 return;
682 if (hover_target_->fill() == Fill::CONTENT) {
683 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseLeave,
684 NowSeconds(), gfx::Point()));
685 } else {
686 hover_target_->OnHoverLeave();
687 }
688 hover_target_ = nullptr;
689 }
690
691 bool VrShellGl::SendHoverEnter(UiElement* target,
692 const gfx::PointF& target_point,
693 const gfx::Point& local_point_pixels) {
694 if (!target || target == hover_target_)
695 return false;
696 if (target->fill() == Fill::CONTENT) {
697 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseEnter,
698 NowSeconds(), local_point_pixels));
699 } else {
700 target->OnHoverEnter(target_point);
701 }
702 hover_target_ = target;
703 return true;
704 }
705
706 void VrShellGl::SendHoverMove(const gfx::PointF& target_point,
707 const gfx::Point& local_point_pixels) {
708 if (!hover_target_)
709 return;
710 if (hover_target_->fill() == Fill::CONTENT) {
711 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseMove,
712 NowSeconds(), local_point_pixels));
713 } else {
714 hover_target_->OnMove(target_point);
715 }
716 }
717
718 void VrShellGl::SendButtonDown(UiElement* target,
719 const gfx::PointF& target_point) {
720 if (in_click_)
721 return;
722 if (!controller_->ButtonDownHappened(gvr::kControllerButtonClick))
cjgrant 2017/05/10 20:16:26 Isn't it more intuitive to not call SendButtonDown
mthiesse 2017/05/10 21:09:08 So this is a stylistic choice. I decided to avoid
723 return;
724 input_locked_element_ = target;
725 in_click_ = true;
726 // We don't support down/up for content yet.
727 if (!target || target->fill() == Fill::CONTENT)
728 return;
729 target->OnButtonDown(target_point);
730 }
731
732 bool VrShellGl::SendButtonUp(UiElement* target,
733 const gfx::PointF& target_point) {
734 if (!in_click_)
735 return false;
736 if (!controller_->ButtonUpHappened(gvr::kControllerButtonClick))
737 return false;
738 DCHECK(input_locked_element_ == target);
739 input_locked_element_ = nullptr;
740 in_click_ = false;
741 // We don't support down/up for content yet.
742 if (target->fill() == Fill::CONTENT)
743 return false;
744 target->OnButtonUp(target_point);
745 return true;
746 }
747
748 void VrShellGl::SendTap(UiElement* target,
749 const gfx::PointF& target_point,
750 const gfx::Point& local_point_pixels) {
751 if (!target)
752 return;
753 if (controller_->ButtonUpHappened(gvr::kControllerButtonClick) &&
754 target->fill() == Fill::CONTENT)
755 touch_pending_ = true;
756 if (!touch_pending_)
757 return;
758 touch_pending_ = false;
759 if (target->fill() == Fill::CONTENT) {
760 auto gesture = base::MakeUnique<blink::WebGestureEvent>(
761 blink::WebInputEvent::kGestureTapDown,
762 blink::WebInputEvent::kNoModifiers, NowSeconds());
763 gesture->source_device = blink::kWebGestureDeviceTouchpad;
764 gesture->x = local_point_pixels.x();
765 gesture->y = local_point_pixels.y();
766 SendGestureToContent(std::move(gesture));
767 } else {
768 target->OnButtonDown(target_point);
769 target->OnButtonUp(target_point);
770 }
771 }
772
773 void VrShellGl::GetVisualTargetElement(
774 const gfx::Vector3dF& controller_direction,
775 gfx::Vector3dF& eye_to_target,
776 gfx::Point3F& target_point,
777 UiElement** target_element,
778 gfx::PointF& target_local_point) const {
547 // If we place the reticle based on elements intersecting the controller beam, 779 // If we place the reticle based on elements intersecting the controller beam,
548 // we can end up with the reticle hiding behind elements, or jumping laterally 780 // we can end up with the reticle hiding behind elements, or jumping laterally
549 // in the field of view. This is physically correct, but hard to use. For 781 // in the field of view. This is physically correct, but hard to use. For
550 // usability, do the following instead: 782 // usability, do the following instead:
551 // 783 //
552 // - Project the controller laser onto a distance-limiting sphere. 784 // - Project the controller laser onto a distance-limiting sphere.
553 // - Create a vector between the eyes and the outer surface point. 785 // - Create a vector between the eyes and the outer surface point.
554 // - If any UI elements intersect this vector, and is within the bounding 786 // - If any UI elements intersect this vector, and is within the bounding
555 // sphere, choose the closest to the eyes, and place the reticle at the 787 // sphere, choose the closest to the eyes, and place the reticle at the
556 // intersection point. 788 // intersection point.
557 789
558 // Compute the distance from the eyes to the distance limiting sphere. Note 790 // Compute the distance from the eyes to the distance limiting sphere. Note
559 // that the sphere is centered at the controller, rather than the eye, for 791 // that the sphere is centered at the controller, rather than the eye, for
560 // simplicity. 792 // simplicity.
561 float distance = scene_->GetBackgroundDistance(); 793 float distance = scene_->GetBackgroundDistance();
562 target_point_ = 794 target_point =
563 vr::GetRayPoint(pointer_start_, controller_direction, distance); 795 vr::GetRayPoint(pointer_start_, controller_direction, distance);
564 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; 796 eye_to_target = target_point - kOrigin;
565 vr::NormalizeVector(&eye_to_target); 797 vr::NormalizeVector(&eye_to_target);
566 798
567 // Determine which UI element (if any) intersects the line between the eyes 799 // Determine which UI element (if any) intersects the line between the eyes
568 // and the controller target position. 800 // and the controller target position.
569 float closest_element_distance = (target_point_ - kOrigin).Length(); 801 float closest_element_distance = (target_point - kOrigin).Length();
570 previous_target_element_ = target_element_;
571 target_element_ = nullptr;
572 float target_x;
573 float target_y;
574 802
575 for (auto& plane : scene_->GetUiElements()) { 803 for (auto& element : scene_->GetUiElements()) {
576 if (!plane->IsHitTestable()) 804 if (!element->IsHitTestable())
805 continue;
806 gfx::PointF local_point;
807 gfx::Point3F plane_intersection_point;
808 float distance_to_plane;
809 if (!GetTargetLocalPoint(eye_to_target, *element.get(),
cjgrant 2017/05/10 20:16:26 So to be totally clear, the idea of having an elem
mthiesse 2017/05/10 21:09:08 yes.
810 closest_element_distance, local_point,
811 plane_intersection_point, distance_to_plane))
577 continue; 812 continue;
578 813
579 float distance_to_plane; 814 if (local_point.x() < 0.0f || local_point.x() >= 1.0f ||
580 if (!plane->GetRayDistance(kOrigin, eye_to_target, &distance_to_plane)) 815 local_point.y() < 0.0f || local_point.y() >= 1.0f)
581 continue;
582
583 if (distance_to_plane < 0 || distance_to_plane >= closest_element_distance)
584 continue;
585
586 gfx::Point3F plane_intersection_point =
587 vr::GetRayPoint(kOrigin, eye_to_target, distance_to_plane);
588 gfx::PointF unit_xy_point =
589 plane->GetUnitRectangleCoordinates(plane_intersection_point);
590
591 float x = 0.5f + unit_xy_point.x();
592 float y = 0.5f - unit_xy_point.y();
593 if (x < 0.0f || x >= 1.0f || y < 0.0f || y >= 1.0f)
594 continue; 816 continue;
595 817
596 closest_element_distance = distance_to_plane; 818 closest_element_distance = distance_to_plane;
597 target_point_ = plane_intersection_point; 819 target_point = plane_intersection_point;
598 target_element_ = plane.get(); 820 *target_element = element.get();
599 target_x = x; 821 target_local_point = local_point;
600 target_y = y;
601 } 822 }
823 }
602 824
603 // Handle input targeting on the content quad, ignoring any other elements. 825 bool VrShellGl::GetTargetLocalPoint(const gfx::Vector3dF& eye_to_target,
604 // Content is treated specially to accomodate scrolling, flings, etc. 826 const UiElement& element,
605 InputTarget input_target = InputTarget::NONE; 827 float max_distance_to_plane,
606 int pixel_x = 0; 828 gfx::PointF& target_local_point,
607 int pixel_y = 0; 829 gfx::Point3F& target_point,
608 if (target_element_ != nullptr && target_element_->fill() == Fill::CONTENT) { 830 float& distance_to_plane) const {
609 input_target = InputTarget::CONTENT; 831 if (!element.GetRayDistance(kOrigin, eye_to_target, &distance_to_plane))
610 gfx::RectF pixel_rect(0, 0, content_tex_css_width_, 832 return false;
611 content_tex_css_height_);
612 pixel_x = pixel_rect.x() + pixel_rect.width() * target_x;
613 pixel_y = pixel_rect.y() + pixel_rect.height() * target_y;
614 }
615 SendInputToContent(input_target, pixel_x, pixel_y);
616 833
617 // Handle input targeting on all non-content elements. 834 if (distance_to_plane < 0 || distance_to_plane >= max_distance_to_plane)
618 SendInputToUiElements(target_element_); 835 return false;
836
837 target_point = vr::GetRayPoint(kOrigin, eye_to_target, distance_to_plane);
838 gfx::PointF unit_xy_point = element.GetUnitRectangleCoordinates(target_point);
839
840 target_local_point.set_x(0.5f + unit_xy_point.x());
841 target_local_point.set_y(0.5f - unit_xy_point.y());
842 return true;
619 } 843 }
620 844
621 void VrShellGl::HandleControllerAppButtonActivity( 845 void VrShellGl::HandleControllerAppButtonActivity(
622 const gfx::Vector3dF& controller_direction) { 846 const gfx::Vector3dF& controller_direction) {
623 // Note that button up/down state is transient, so ButtonDownHappened only 847 // Note that button up/down state is transient, so ButtonDownHappened only
624 // returns true for a single frame (and we're guaranteed not to miss it). 848 // returns true for a single frame (and we're guaranteed not to miss it).
625 if (controller_->ButtonDownHappened( 849 if (controller_->ButtonDownHappened(
626 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { 850 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) {
627 controller_start_direction_ = controller_direction; 851 controller_start_direction_ = controller_direction;
628 } 852 }
(...skipping 12 matching lines...) Expand all
641 direction = 865 direction =
642 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT; 866 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT;
643 browser_->AppButtonGesturePerformed(direction); 867 browser_->AppButtonGesturePerformed(direction);
644 } 868 }
645 } 869 }
646 if (direction == UiInterface::NONE) 870 if (direction == UiInterface::NONE)
647 browser_->AppButtonClicked(); 871 browser_->AppButtonClicked();
648 } 872 }
649 } 873 }
650 874
651 void VrShellGl::SendInputToContent(InputTarget input_target,
652 int pixel_x,
653 int pixel_y) {
654 std::vector<std::unique_ptr<WebGestureEvent>> gesture_list =
655 controller_->DetectGestures();
656 double timestamp = gesture_list.front()->TimeStampSeconds();
657
658 if (touch_pending_) {
659 touch_pending_ = false;
660 std::unique_ptr<WebGestureEvent> event(
661 new WebGestureEvent(WebInputEvent::kGestureTapDown,
662 WebInputEvent::kNoModifiers, timestamp));
663 event->source_device = blink::kWebGestureDeviceTouchpad;
664 event->x = pixel_x;
665 event->y = pixel_y;
666 gesture_list.push_back(std::move(event));
667 }
668
669 for (auto& gesture : gesture_list) {
670 gesture->x = pixel_x;
671 gesture->y = pixel_y;
672 auto movableGesture = base::MakeUnique<WebGestureEvent>(*gesture);
673
674 switch (gesture->GetType()) {
675 // Once the user starts scrolling send all the scroll events to this
676 // element until the scrolling stops.
677 case WebInputEvent::kGestureScrollBegin:
678 current_scroll_target_ = input_target;
679 if (current_scroll_target_ != InputTarget::NONE) {
680 SendGestureToContent(std::move(movableGesture));
681 }
682 break;
683 case WebInputEvent::kGestureScrollEnd:
684 if (current_scroll_target_ != InputTarget::NONE) {
685 SendGestureToContent(std::move(movableGesture));
686 }
687 current_fling_target_ = current_scroll_target_;
688 current_scroll_target_ = InputTarget::NONE;
689 break;
690 case WebInputEvent::kGestureScrollUpdate:
691 if (current_scroll_target_ != InputTarget::NONE) {
692 SendGestureToContent(std::move(movableGesture));
693 }
694 break;
695 case WebInputEvent::kGestureFlingStart:
696 if (current_fling_target_ != InputTarget::NONE) {
697 SendGestureToContent(std::move(movableGesture));
698 }
699 current_fling_target_ = InputTarget::NONE;
700 break;
701 case WebInputEvent::kGestureFlingCancel:
702 current_fling_target_ = InputTarget::NONE;
703 if (input_target != InputTarget::NONE) {
704 SendGestureToContent(std::move(movableGesture));
705 }
706 break;
707 case WebInputEvent::kGestureTapDown:
708 current_fling_target_ = InputTarget::NONE;
709 if (input_target != InputTarget::NONE) {
710 SendGestureToContent(std::move(movableGesture));
711 }
712 break;
713 case WebInputEvent::kUndefined:
714 break;
715 default:
716 NOTREACHED();
717 }
718 }
719
720 // Hover support
721 bool new_target = input_target != current_input_target_;
722 if (new_target && current_input_target_ != InputTarget::NONE) {
723 // Send a move event indicating that the pointer moved off of an element.
724 SendGestureToContent(
725 MakeMouseEvent(WebInputEvent::kMouseLeave, timestamp, 0, 0));
726 }
727 current_input_target_ = input_target;
728 if (current_input_target_ != InputTarget::NONE) {
729 WebInputEvent::Type type =
730 new_target ? WebInputEvent::kMouseEnter : WebInputEvent::kMouseMove;
731 SendGestureToContent(MakeMouseEvent(type, timestamp, pixel_x, pixel_y));
732 }
733 }
734
735 void VrShellGl::SendInputToUiElements(UiElement* target_element) {
736 if (target_element != previous_target_element_) {
737 if (previous_target_element_ &&
738 previous_target_element_->fill() != Fill::CONTENT) {
739 task_runner_->PostTask(
740 FROM_HERE, base::Bind(&UiElement::OnHoverLeave,
741 base::Unretained(previous_target_element_)));
742 }
743 if (target_element && target_element->fill() != Fill::CONTENT) {
744 task_runner_->PostTask(FROM_HERE,
745 base::Bind(&UiElement::OnHoverEnter,
746 base::Unretained(target_element)));
747 }
748 click_target_element_ = nullptr;
749 }
750 if (target_element && target_element->fill() != Fill::CONTENT) {
751 if (controller_->ButtonDownHappened(
752 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) {
753 task_runner_->PostTask(FROM_HERE,
754 base::Bind(&UiElement::OnButtonDown,
755 base::Unretained(target_element)));
756 click_target_element_ = target_element;
757 }
758 if (controller_->ButtonUpHappened(
759 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK)) {
760 if (click_target_element_ == target_element) {
761 task_runner_->PostTask(FROM_HERE,
762 base::Bind(&UiElement::OnButtonUp,
763 base::Unretained(target_element)));
764 }
765 click_target_element_ = nullptr;
766 }
767 }
768 }
769
770 void VrShellGl::SendGestureToContent( 875 void VrShellGl::SendGestureToContent(
771 std::unique_ptr<blink::WebInputEvent> event) { 876 std::unique_ptr<blink::WebInputEvent> event) {
772 browser_->ProcessContentGesture(std::move(event)); 877 browser_->ProcessContentGesture(std::move(event));
773 } 878 }
774 879
775 void VrShellGl::DrawFrame(int16_t frame_index) { 880 void VrShellGl::DrawFrame(int16_t frame_index) {
776 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); 881 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index);
777 882
778 base::TimeTicks current_time = base::TimeTicks::Now(); 883 base::TimeTicks current_time = base::TimeTicks::Now();
779 884
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 default: 1139 default:
1035 break; 1140 break;
1036 } 1141 }
1037 } 1142 }
1038 vr_shell_renderer_->Flush(); 1143 vr_shell_renderer_->Flush();
1039 } 1144 }
1040 1145
1041 std::vector<const UiElement*> VrShellGl::GetElementsInDrawOrder( 1146 std::vector<const UiElement*> VrShellGl::GetElementsInDrawOrder(
1042 const vr::Mat4f& view_matrix, 1147 const vr::Mat4f& view_matrix,
1043 const std::vector<const UiElement*>& elements) { 1148 const std::vector<const UiElement*>& elements) {
1044 typedef std::pair<float, const UiElement*> DistanceElementPair; 1149 std::vector<const UiElement*> sorted_elements = elements;
1045 std::vector<DistanceElementPair> zOrderedElementPairs;
1046 zOrderedElementPairs.reserve(elements.size());
1047
1048 for (const auto* element : elements) {
1049 // Distance is the abs(z) value in view space.
1050 gfx::Vector3dF element_position =
1051 vr::GetTranslation(element->TransformMatrix());
1052
1053 float distance =
1054 std::fabs(vr::MatrixVectorMul(view_matrix, element_position).z());
1055 zOrderedElementPairs.push_back(std::make_pair(distance, element));
1056 }
1057 1150
1058 // Sort elements primarily based on their draw phase (lower draw phase first) 1151 // Sort elements primarily based on their draw phase (lower draw phase first)
1059 // and secondarily based on their distance (larger distance first). 1152 // and secondarily based on their distance (larger z-axis first).
cjgrant 2017/05/10 20:16:26 "...based on their Z-axis distance..." maybe?
mthiesse 2017/05/10 21:09:08 Done.
mthiesse 2017/05/10 21:09:08 Didn't mean to include these changes in this CL. W
1060 std::sort( 1153 // TODO(mthiesse): This will not work well for elements not directly in front
1061 zOrderedElementPairs.begin(), zOrderedElementPairs.end(), 1154 // of the user, but works well enough for our initial release, and provides a
1062 [](const DistanceElementPair& first, const DistanceElementPair& second) { 1155 // consistent ordering that we can easily design around.
1063 if (first.second->draw_phase() != second.second->draw_phase()) { 1156 std::sort(sorted_elements.begin(), sorted_elements.end(),
1064 return first.second->draw_phase() < second.second->draw_phase(); 1157 [](const UiElement* first, const UiElement* second) {
1065 } else { 1158 if (first->draw_phase() != second->draw_phase()) {
1066 return first.first > second.first; 1159 return first->draw_phase() < second->draw_phase();
1067 } 1160 } else {
1068 }); 1161 return first->translation().z() < second->translation().z();
1162 }
1163 });
1069 1164
1070 std::vector<const UiElement*> zOrderedElements; 1165 return sorted_elements;
1071 zOrderedElements.reserve(elements.size());
1072 for (auto distanceElementPair : zOrderedElementPairs) {
1073 zOrderedElements.push_back(distanceElementPair.second);
1074 }
1075 return zOrderedElements;
1076 } 1166 }
1077 1167
1078 void VrShellGl::DrawCursor(const vr::Mat4f& render_matrix) { 1168 void VrShellGl::DrawCursor(const vr::Mat4f& render_matrix) {
1079 vr::Mat4f mat; 1169 vr::Mat4f mat;
1080 vr::SetIdentityM(&mat); 1170 vr::SetIdentityM(&mat);
1081 1171
1082 // Draw the reticle. 1172 // Draw the reticle.
1083 1173
1084 // Scale the pointer to have a fixed FOV size at any distance. 1174 // Scale the pointer to have a fixed FOV size at any distance.
1085 const float eye_to_target = 1175 const float eye_to_target =
1086 std::sqrt(target_point_.SquaredDistanceTo(kOrigin)); 1176 std::sqrt(target_point_.SquaredDistanceTo(kOrigin));
1087 vr::ScaleM( 1177 vr::ScaleM(
1088 mat, 1178 mat,
1089 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f}, 1179 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f},
1090 &mat); 1180 &mat);
1091 1181
1092 vr::Quatf rotation; 1182 vr::Quatf rotation;
1093 if (target_element_ != nullptr) { 1183 if (cursor_render_target_ != nullptr) {
1094 // Make the reticle planar to the element it's hitting. 1184 // Make the reticle planar to the element it's hitting.
1095 rotation = GetRotationFromZAxis(target_element_->GetNormal()); 1185 rotation = GetRotationFromZAxis(cursor_render_target_->GetNormal());
1096 } else { 1186 } else {
1097 // Rotate the cursor to directly face the eyes. 1187 // Rotate the cursor to directly face the eyes.
1098 rotation = GetRotationFromZAxis(target_point_ - kOrigin); 1188 rotation = GetRotationFromZAxis(target_point_ - kOrigin);
1099 } 1189 }
1100 vr::Mat4f rotation_mat; 1190 vr::Mat4f rotation_mat;
1101 vr::QuatToMatrix(rotation, &rotation_mat); 1191 vr::QuatToMatrix(rotation, &rotation_mat);
1102 vr::MatrixMul(rotation_mat, mat, &mat); 1192 vr::MatrixMul(rotation_mat, mat, &mat);
1103 1193
1104 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset); 1194 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset);
1105 // Place the pointer slightly in front of the plane intersection point. 1195 // Place the pointer slightly in front of the plane intersection point.
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 // This assumes that the initial webvr_surface_size_ was set to the 1427 // This assumes that the initial webvr_surface_size_ was set to the
1338 // appropriate recommended render resolution as the default size during 1428 // appropriate recommended render resolution as the default size during
1339 // InitializeGl. Revisit if the initialization order changes. 1429 // InitializeGl. Revisit if the initialization order changes.
1340 device::mojom::VRDisplayInfoPtr info = 1430 device::mojom::VRDisplayInfoPtr info =
1341 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), 1431 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(),
1342 webvr_surface_size_, device_id); 1432 webvr_surface_size_, device_id);
1343 browser_->RunVRDisplayInfoCallback(callback, &info); 1433 browser_->RunVRDisplayInfoCallback(callback, &info);
1344 } 1434 }
1345 1435
1346 } // namespace vr_shell 1436 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698