OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 HandleWebVrCompatibilityClick(); |
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; |
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::HandleWebVrCompatibilityClick() { |
| 591 if (!ShouldDrawWebVr()) |
| 592 return; |
| 593 |
| 594 // Process screen touch events for Cardboard button compatibility. |
| 595 // Also send tap events for controller "touchpad click" events. |
| 596 if (touch_pending_ || |
| 597 controller_->ButtonUpHappened(gvr::kControllerButtonClick)) { |
| 598 touch_pending_ = false; |
| 599 std::unique_ptr<blink::WebGestureEvent> gesture(new blink::WebGestureEvent( |
| 600 blink::WebInputEvent::kGestureTapDown, |
| 601 blink::WebInputEvent::kNoModifiers, NowSeconds())); |
| 602 gesture->source_device = blink::kWebGestureDeviceTouchpad; |
| 603 gesture->x = 0; |
| 604 gesture->y = 0; |
| 605 SendGestureToContent(std::move(gesture)); |
| 606 DVLOG(1) << __FUNCTION__ << ": sent CLICK gesture"; |
| 607 } |
| 608 } |
| 609 |
| 610 void VrShellGl::SendFlingCancel(GestureList& gesture_list) { |
| 611 if (!fling_target_) |
| 612 return; |
| 613 if (gesture_list.empty() || (gesture_list.front()->GetType() != |
| 614 blink::WebInputEvent::kGestureFlingCancel)) |
| 615 return; |
| 616 // Scrolling currently only supported on content window. |
| 617 DCHECK_EQ(fling_target_->fill(), Fill::CONTENT); |
| 618 SendGestureToContent(std::move(gesture_list.front())); |
| 619 gesture_list.erase(gesture_list.begin()); |
| 620 } |
| 621 |
| 622 void VrShellGl::SendScrollEnd(GestureList& gesture_list) { |
| 623 if (!in_scroll_) |
| 624 return; |
| 625 DCHECK_NE(input_locked_element_, nullptr); |
| 626 if (controller_->ButtonDownHappened(gvr::kControllerButtonClick)) { |
| 627 DCHECK_GT(gesture_list.size(), 0LU); |
| 628 DCHECK_EQ(gesture_list.front()->GetType(), |
| 629 blink::WebInputEvent::kGestureScrollEnd); |
| 630 } |
| 631 // Scrolling currently only supported on content window. |
| 632 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT); |
| 633 if (gesture_list.empty() || (gesture_list.front()->GetType() != |
| 634 blink::WebInputEvent::kGestureScrollEnd)) |
| 635 return; |
| 636 DCHECK_LE(gesture_list.size(), 2LU); |
| 637 SendGestureToContent(std::move(gesture_list.front())); |
| 638 gesture_list.erase(gesture_list.begin()); |
| 639 if (!gesture_list.empty()) { |
| 640 DCHECK_EQ(gesture_list.front()->GetType(), |
| 641 blink::WebInputEvent::kGestureFlingStart); |
| 642 SendGestureToContent(std::move(gesture_list.front())); |
| 643 fling_target_ = input_locked_element_; |
| 644 gesture_list.erase(gesture_list.begin()); |
| 645 } |
| 646 input_locked_element_ = nullptr; |
| 647 in_scroll_ = false; |
| 648 } |
| 649 |
| 650 bool VrShellGl::SendScrollBegin(UiElement* target, GestureList& gesture_list) { |
| 651 if (in_scroll_ || !target) |
| 652 return false; |
| 653 // Scrolling currently only supported on content window. |
| 654 if (target->fill() != Fill::CONTENT) |
| 655 return false; |
| 656 if (gesture_list.empty() || (gesture_list.front()->GetType() != |
| 657 blink::WebInputEvent::kGestureScrollBegin)) |
| 658 return false; |
| 659 input_locked_element_ = target; |
| 660 in_scroll_ = true; |
| 661 |
| 662 SendGestureToContent(std::move(gesture_list.front())); |
| 663 gesture_list.erase(gesture_list.begin()); |
| 664 return true; |
| 665 } |
| 666 |
| 667 void VrShellGl::SendScrollUpdate(GestureList& gesture_list) { |
| 668 if (!in_scroll_) |
| 669 return; |
| 670 DCHECK(input_locked_element_); |
| 671 if (gesture_list.empty() || (gesture_list.front()->GetType() != |
| 672 blink::WebInputEvent::kGestureScrollUpdate)) |
| 673 return; |
| 674 // Scrolling currently only supported on content window. |
| 675 DCHECK_EQ(input_locked_element_->fill(), Fill::CONTENT); |
| 676 SendGestureToContent(std::move(gesture_list.front())); |
| 677 gesture_list.erase(gesture_list.begin()); |
| 678 } |
| 679 |
| 680 void VrShellGl::SendHoverLeave(UiElement* target) { |
| 681 if (!hover_target_ || (target == hover_target_)) |
| 682 return; |
| 683 if (hover_target_->fill() == Fill::CONTENT) { |
| 684 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseLeave, |
| 685 NowSeconds(), gfx::Point())); |
| 686 } else { |
| 687 hover_target_->OnHoverLeave(); |
| 688 } |
| 689 hover_target_ = nullptr; |
| 690 } |
| 691 |
| 692 bool VrShellGl::SendHoverEnter(UiElement* target, |
| 693 const gfx::PointF& target_point, |
| 694 const gfx::Point& local_point_pixels) { |
| 695 if (!target || target == hover_target_) |
| 696 return false; |
| 697 if (target->fill() == Fill::CONTENT) { |
| 698 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseEnter, |
| 699 NowSeconds(), local_point_pixels)); |
| 700 } else { |
| 701 target->OnHoverEnter(target_point); |
| 702 } |
| 703 hover_target_ = target; |
| 704 return true; |
| 705 } |
| 706 |
| 707 void VrShellGl::SendHoverMove(const gfx::PointF& target_point, |
| 708 const gfx::Point& local_point_pixels) { |
| 709 if (!hover_target_) |
| 710 return; |
| 711 if (hover_target_->fill() == Fill::CONTENT) { |
| 712 SendGestureToContent(MakeMouseEvent(blink::WebInputEvent::kMouseMove, |
| 713 NowSeconds(), local_point_pixels)); |
| 714 } else { |
| 715 hover_target_->OnMove(target_point); |
| 716 } |
| 717 } |
| 718 |
| 719 void VrShellGl::SendButtonDown(UiElement* target, |
| 720 const gfx::PointF& target_point) { |
| 721 if (in_click_) |
| 722 return; |
| 723 if (!controller_->ButtonDownHappened(gvr::kControllerButtonClick)) |
| 724 return; |
| 725 input_locked_element_ = target; |
| 726 in_click_ = true; |
| 727 // We don't support down/up for content yet. |
| 728 if (!target || target->fill() == Fill::CONTENT) |
| 729 return; |
| 730 target->OnButtonDown(target_point); |
| 731 } |
| 732 |
| 733 bool VrShellGl::SendButtonUp(UiElement* target, |
| 734 const gfx::PointF& target_point) { |
| 735 if (!in_click_) |
| 736 return false; |
| 737 if (!controller_->ButtonUpHappened(gvr::kControllerButtonClick)) |
| 738 return false; |
| 739 DCHECK(input_locked_element_ == target); |
| 740 input_locked_element_ = nullptr; |
| 741 in_click_ = false; |
| 742 // We don't support down/up for content yet. |
| 743 if (target->fill() == Fill::CONTENT) |
| 744 return false; |
| 745 target->OnButtonUp(target_point); |
| 746 return true; |
| 747 } |
| 748 |
| 749 void VrShellGl::SendTap(UiElement* target, |
| 750 const gfx::PointF& target_point, |
| 751 const gfx::Point& local_point_pixels) { |
| 752 if (!target) |
| 753 return; |
| 754 if (controller_->ButtonUpHappened(gvr::kControllerButtonClick) && |
| 755 target->fill() == Fill::CONTENT) |
| 756 touch_pending_ = true; |
| 757 if (!touch_pending_) |
| 758 return; |
| 759 touch_pending_ = false; |
| 760 if (target->fill() == Fill::CONTENT) { |
| 761 auto gesture = base::MakeUnique<blink::WebGestureEvent>( |
| 762 blink::WebInputEvent::kGestureTapDown, |
| 763 blink::WebInputEvent::kNoModifiers, NowSeconds()); |
| 764 gesture->source_device = blink::kWebGestureDeviceTouchpad; |
| 765 gesture->x = local_point_pixels.x(); |
| 766 gesture->y = local_point_pixels.y(); |
| 767 SendGestureToContent(std::move(gesture)); |
| 768 } else { |
| 769 target->OnButtonDown(target_point); |
| 770 target->OnButtonUp(target_point); |
| 771 } |
| 772 } |
| 773 |
| 774 void VrShellGl::GetVisualTargetElement( |
| 775 const gfx::Vector3dF& controller_direction, |
| 776 gfx::Vector3dF& eye_to_target, |
| 777 gfx::Point3F& target_point, |
| 778 UiElement** target_element, |
| 779 gfx::PointF& target_local_point) const { |
547 // If we place the reticle based on elements intersecting the controller beam, | 780 // 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 | 781 // 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 | 782 // in the field of view. This is physically correct, but hard to use. For |
550 // usability, do the following instead: | 783 // usability, do the following instead: |
551 // | 784 // |
552 // - Project the controller laser onto a distance-limiting sphere. | 785 // - Project the controller laser onto a distance-limiting sphere. |
553 // - Create a vector between the eyes and the outer surface point. | 786 // - Create a vector between the eyes and the outer surface point. |
554 // - If any UI elements intersect this vector, and is within the bounding | 787 // - 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 | 788 // sphere, choose the closest to the eyes, and place the reticle at the |
556 // intersection point. | 789 // intersection point. |
557 | 790 |
558 // Compute the distance from the eyes to the distance limiting sphere. Note | 791 // 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 | 792 // that the sphere is centered at the controller, rather than the eye, for |
560 // simplicity. | 793 // simplicity. |
561 float distance = scene_->GetBackgroundDistance(); | 794 float distance = scene_->GetBackgroundDistance(); |
562 target_point_ = | 795 target_point = |
563 vr::GetRayPoint(pointer_start_, controller_direction, distance); | 796 vr::GetRayPoint(pointer_start_, controller_direction, distance); |
564 gfx::Vector3dF eye_to_target = target_point_ - kOrigin; | 797 eye_to_target = target_point - kOrigin; |
565 vr::NormalizeVector(&eye_to_target); | 798 vr::NormalizeVector(&eye_to_target); |
566 | 799 |
567 // Determine which UI element (if any) intersects the line between the eyes | 800 // Determine which UI element (if any) intersects the line between the eyes |
568 // and the controller target position. | 801 // and the controller target position. |
569 float closest_element_distance = (target_point_ - kOrigin).Length(); | 802 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 | 803 |
575 for (auto& plane : scene_->GetUiElements()) { | 804 for (auto& element : scene_->GetUiElements()) { |
576 if (!plane->IsHitTestable()) | 805 if (!element->IsHitTestable()) |
| 806 continue; |
| 807 gfx::PointF local_point; |
| 808 gfx::Point3F plane_intersection_point; |
| 809 float distance_to_plane; |
| 810 if (!GetTargetLocalPoint(eye_to_target, *element.get(), |
| 811 closest_element_distance, local_point, |
| 812 plane_intersection_point, distance_to_plane)) |
577 continue; | 813 continue; |
578 | 814 |
579 float distance_to_plane; | 815 if (local_point.x() < 0.0f || local_point.x() >= 1.0f || |
580 if (!plane->GetRayDistance(kOrigin, eye_to_target, &distance_to_plane)) | 816 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; | 817 continue; |
595 | 818 |
596 closest_element_distance = distance_to_plane; | 819 closest_element_distance = distance_to_plane; |
597 target_point_ = plane_intersection_point; | 820 target_point = plane_intersection_point; |
598 target_element_ = plane.get(); | 821 *target_element = element.get(); |
599 target_x = x; | 822 target_local_point = local_point; |
600 target_y = y; | |
601 } | 823 } |
| 824 } |
602 | 825 |
603 // Handle input targeting on the content quad, ignoring any other elements. | 826 bool VrShellGl::GetTargetLocalPoint(const gfx::Vector3dF& eye_to_target, |
604 // Content is treated specially to accomodate scrolling, flings, etc. | 827 const UiElement& element, |
605 InputTarget input_target = InputTarget::NONE; | 828 float max_distance_to_plane, |
606 int pixel_x = 0; | 829 gfx::PointF& target_local_point, |
607 int pixel_y = 0; | 830 gfx::Point3F& target_point, |
608 if (target_element_ != nullptr && target_element_->fill() == Fill::CONTENT) { | 831 float& distance_to_plane) const { |
609 input_target = InputTarget::CONTENT; | 832 if (!element.GetRayDistance(kOrigin, eye_to_target, &distance_to_plane)) |
610 gfx::RectF pixel_rect(0, 0, content_tex_css_width_, | 833 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 | 834 |
617 // Handle input targeting on all non-content elements. | 835 if (distance_to_plane < 0 || distance_to_plane >= max_distance_to_plane) |
618 SendInputToUiElements(target_element_); | 836 return false; |
| 837 |
| 838 target_point = vr::GetRayPoint(kOrigin, eye_to_target, distance_to_plane); |
| 839 gfx::PointF unit_xy_point = element.GetUnitRectangleCoordinates(target_point); |
| 840 |
| 841 target_local_point.set_x(0.5f + unit_xy_point.x()); |
| 842 target_local_point.set_y(0.5f - unit_xy_point.y()); |
| 843 return true; |
619 } | 844 } |
620 | 845 |
621 void VrShellGl::HandleControllerAppButtonActivity( | 846 void VrShellGl::HandleControllerAppButtonActivity( |
622 const gfx::Vector3dF& controller_direction) { | 847 const gfx::Vector3dF& controller_direction) { |
623 // Note that button up/down state is transient, so ButtonDownHappened only | 848 // 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). | 849 // returns true for a single frame (and we're guaranteed not to miss it). |
625 if (controller_->ButtonDownHappened( | 850 if (controller_->ButtonDownHappened( |
626 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { | 851 gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { |
627 controller_start_direction_ = controller_direction; | 852 controller_start_direction_ = controller_direction; |
628 } | 853 } |
(...skipping 12 matching lines...) Expand all Loading... |
641 direction = | 866 direction = |
642 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT; | 867 gesture_xz_angle < 0 ? UiInterface::LEFT : UiInterface::RIGHT; |
643 browser_->AppButtonGesturePerformed(direction); | 868 browser_->AppButtonGesturePerformed(direction); |
644 } | 869 } |
645 } | 870 } |
646 if (direction == UiInterface::NONE) | 871 if (direction == UiInterface::NONE) |
647 browser_->AppButtonClicked(); | 872 browser_->AppButtonClicked(); |
648 } | 873 } |
649 } | 874 } |
650 | 875 |
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( | 876 void VrShellGl::SendGestureToContent( |
771 std::unique_ptr<blink::WebInputEvent> event) { | 877 std::unique_ptr<blink::WebInputEvent> event) { |
772 browser_->ProcessContentGesture(std::move(event)); | 878 browser_->ProcessContentGesture(std::move(event)); |
773 } | 879 } |
774 | 880 |
775 void VrShellGl::DrawFrame(int16_t frame_index) { | 881 void VrShellGl::DrawFrame(int16_t frame_index) { |
776 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); | 882 TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); |
777 | 883 |
778 base::TimeTicks current_time = base::TimeTicks::Now(); | 884 base::TimeTicks current_time = base::TimeTicks::Now(); |
779 | 885 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 | 1176 |
1071 // Scale the pointer to have a fixed FOV size at any distance. | 1177 // Scale the pointer to have a fixed FOV size at any distance. |
1072 const float eye_to_target = | 1178 const float eye_to_target = |
1073 std::sqrt(target_point_.SquaredDistanceTo(kOrigin)); | 1179 std::sqrt(target_point_.SquaredDistanceTo(kOrigin)); |
1074 vr::ScaleM( | 1180 vr::ScaleM( |
1075 mat, | 1181 mat, |
1076 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f}, | 1182 {kReticleWidth * eye_to_target, kReticleHeight * eye_to_target, 1.0f}, |
1077 &mat); | 1183 &mat); |
1078 | 1184 |
1079 vr::Quatf rotation; | 1185 vr::Quatf rotation; |
1080 if (target_element_ != nullptr) { | 1186 if (cursor_render_target_ != nullptr) { |
1081 // Make the reticle planar to the element it's hitting. | 1187 // Make the reticle planar to the element it's hitting. |
1082 rotation = GetRotationFromZAxis(target_element_->GetNormal()); | 1188 rotation = GetRotationFromZAxis(cursor_render_target_->GetNormal()); |
1083 } else { | 1189 } else { |
1084 // Rotate the cursor to directly face the eyes. | 1190 // Rotate the cursor to directly face the eyes. |
1085 rotation = GetRotationFromZAxis(target_point_ - kOrigin); | 1191 rotation = GetRotationFromZAxis(target_point_ - kOrigin); |
1086 } | 1192 } |
1087 vr::Mat4f rotation_mat; | 1193 vr::Mat4f rotation_mat; |
1088 vr::QuatToMatrix(rotation, &rotation_mat); | 1194 vr::QuatToMatrix(rotation, &rotation_mat); |
1089 vr::MatrixMul(rotation_mat, mat, &mat); | 1195 vr::MatrixMul(rotation_mat, mat, &mat); |
1090 | 1196 |
1091 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset); | 1197 gfx::Point3F target_point = ScalePoint(target_point_, kReticleOffset); |
1092 // Place the pointer slightly in front of the plane intersection point. | 1198 // Place the pointer slightly in front of the plane intersection point. |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 // This assumes that the initial webvr_surface_size_ was set to the | 1430 // This assumes that the initial webvr_surface_size_ was set to the |
1325 // appropriate recommended render resolution as the default size during | 1431 // appropriate recommended render resolution as the default size during |
1326 // InitializeGl. Revisit if the initialization order changes. | 1432 // InitializeGl. Revisit if the initialization order changes. |
1327 device::mojom::VRDisplayInfoPtr info = | 1433 device::mojom::VRDisplayInfoPtr info = |
1328 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), | 1434 device::GvrDelegate::CreateVRDisplayInfo(gvr_api_.get(), |
1329 webvr_surface_size_, device_id); | 1435 webvr_surface_size_, device_id); |
1330 browser_->RunVRDisplayInfoCallback(callback, &info); | 1436 browser_->RunVRDisplayInfoCallback(callback, &info); |
1331 } | 1437 } |
1332 | 1438 |
1333 } // namespace vr_shell | 1439 } // namespace vr_shell |
OLD | NEW |