Commit 6e4b5ecb authored by Brandon Jones's avatar Brandon Jones Committed by Commit Bot

Support display of multiple controllers in VRShell

Updates the VR UI model to allow an array of controllers, each of which
will be rendered as part of the UI. This update introduces a concept of
a "primary controller" (largely for porting convenience) that is
currently always the controller at index 0 of the array. We may want to
improve the logic around that in future CLs.

Bug: 873274
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:linux_vr;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I1a91f6550f4d051d35d872118c822f1b6716c614
Reviewed-on: https://chromium-review.googlesource.com/c/1171519
Commit-Queue: Brandon Jones <bajones@chromium.org>
Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612778}
parent 02a45d5f
......@@ -317,7 +317,9 @@ base::TimeDelta BrowserRenderer::ProcessControllerInput(
input_delegate_->GetControllerModel(render_info.head_pose);
ui_->HandleInput(current_time, render_info, controller_model, &reticle_model,
&input_event_list);
ui_->OnControllerUpdated(controller_model, reticle_model);
std::vector<ControllerModel> controller_models;
controller_models.push_back(controller_model);
ui_->OnControllersUpdated(controller_models, reticle_model);
auto controller_time = base::TimeTicks::Now() - timing_start;
ui_controller_update_time_.AddSample(controller_time);
......
......@@ -37,8 +37,8 @@ class MockUi : public UiInterface {
MOCK_METHOD4(SetContentOverlayAlertDialogEnabled,
void(bool, PlatformUiInputDelegate*, float, float));
MOCK_METHOD0(OnPause, void());
void OnControllerUpdated(const ControllerModel&,
const ReticleModel&) override {}
void OnControllersUpdated(const std::vector<ControllerModel>&,
const ReticleModel&) override {}
void OnProjMatrixChanged(const gfx::Transform&) override {}
MOCK_METHOD0(AcceptDoffPromptForTesting, void());
MOCK_METHOD2(GetTargetPointForTesting,
......
......@@ -73,7 +73,7 @@ void Laser::Render(UiElementRenderer* renderer,
const CameraModel& model) const {
// Find the length of the beam (from hand to target).
const float laser_length =
std::sqrt(model_->controller.laser_origin.SquaredDistanceTo(
std::sqrt(model_->primary_controller().laser_origin.SquaredDistanceTo(
model_->reticle.target_point));
// Build a beam, originating from the origin.
......@@ -90,7 +90,7 @@ void Laser::Render(UiElementRenderer* renderer,
mat = rotation_mat * mat;
const gfx::Vector3dF beam_direction =
model_->reticle.target_point - model_->controller.laser_origin;
model_->reticle.target_point - model_->primary_controller().laser_origin;
gfx::Transform beam_direction_mat(
gfx::Quaternion(gfx::Vector3dF(0.0f, 0.0f, -1.0f), beam_direction));
......@@ -106,9 +106,10 @@ void Laser::Render(UiElementRenderer* renderer,
face_transform = beam_direction_mat * gfx::Transform(rot) * mat;
// Move the beam origin to the hand.
face_transform.matrix().postTranslate(model_->controller.laser_origin.x(),
model_->controller.laser_origin.y(),
model_->controller.laser_origin.z());
face_transform.matrix().postTranslate(
model_->primary_controller().laser_origin.x(),
model_->primary_controller().laser_origin.y(),
model_->primary_controller().laser_origin.z());
transform =
model.view_proj_matrix * world_space_transform() * face_transform;
renderer->DrawLaser(computed_opacity(), transform);
......
......@@ -125,4 +125,12 @@ bool Model::reposition_window_permitted() const {
!hosted_platform_ui.hosted_ui_enabled;
}
const ControllerModel& Model::primary_controller() const {
return controllers[0];
}
ControllerModel& Model::mutable_primary_controller() {
return controllers[0];
}
} // namespace vr
......@@ -89,7 +89,9 @@ struct VR_UI_EXPORT Model {
EditedText web_input_text_field_info;
// Controller state.
ControllerModel controller;
const ControllerModel& primary_controller() const;
ControllerModel& mutable_primary_controller(); // For tests
std::vector<ControllerModel> controllers;
ReticleModel reticle;
// State affecting both VR browsing and WebVR.
......
......@@ -80,7 +80,9 @@ void UiPixelTest::DrawUi(const gfx::Vector3dF& laser_direction,
EXPECT_TRUE(ui_->OnBeginFrame(base::TimeTicks(), render_info.head_pose));
ui_->HandleInput(MsToTicks(1), render_info, controller_model, &reticle_model,
&input_event_list);
ui_->OnControllerUpdated(controller_model, reticle_model);
std::vector<ControllerModel> controllers;
controllers.push_back(controller_model);
ui_->OnControllersUpdated(controllers, reticle_model);
ui_->Draw(render_info);
// We produce GL errors while rendering. Clear them all so that we can check
......
......@@ -86,9 +86,12 @@ void UiTest::CreateSceneInternal(
ui_ = ui_instance_.get();
scene_ = ui_instance_->scene();
model_ = ui_instance_->model_for_test();
model_->controller.transform.Translate3d(kStartControllerPosition);
model_->controllers[0].transform.Translate3d(kStartControllerPosition);
OnBeginFrame();
// Need a second BeginFrame here because the first one will add controllers
// to the scene, which need an additional frame to get into a good state.
OnBeginFrame();
}
void UiTest::CreateScene(const UiInitialState& state) {
......
......@@ -453,7 +453,9 @@ ControllerModel VrTestContext::UpdateController(const RenderInfo& render_info,
controller_model.laser_origin = laser_origin + local_offset;
controller_model.handedness = handedness_;
ui_->OnControllerUpdated(controller_model, reticle_model);
std::vector<ControllerModel> controllers;
controllers.push_back(controller_model);
ui_->OnControllersUpdated(controllers, reticle_model);
return controller_model;
}
......
......@@ -440,12 +440,15 @@ void Ui::OnMenuButtonClicked() {
}
}
void Ui::OnControllerUpdated(const ControllerModel& controller_model,
const ReticleModel& reticle_model) {
model_->controller = controller_model;
void Ui::OnControllersUpdated(
const std::vector<ControllerModel>& controller_models,
const ReticleModel& reticle_model) {
model_->controllers = controller_models;
model_->reticle = reticle_model;
model_->controller.resting_in_viewport =
input_manager_->ControllerRestingInViewport();
for (auto& controller : model_->controllers) {
controller.resting_in_viewport =
input_manager_->ControllerRestingInViewport();
}
}
void Ui::OnProjMatrixChanged(const gfx::Transform& proj_matrix) {
......@@ -591,6 +594,7 @@ void Ui::InitializeModel(const UiInitialState& ui_initial_state) {
model_->standalone_vr_device = ui_initial_state.is_standalone_vr_device;
model_->use_new_incognito_strings =
ui_initial_state.use_new_incognito_strings;
model_->controllers.push_back(ControllerModel());
}
void Ui::AcceptDoffPromptForTesting() {
......
......@@ -144,8 +144,9 @@ class VR_UI_EXPORT Ui : public UiInterface,
void CancelPlatformToast() override;
void OnPause() override;
void OnControllerUpdated(const ControllerModel& controller_model,
const ReticleModel& reticle_model) override;
void OnControllersUpdated(
const std::vector<ControllerModel>& controller_models,
const ReticleModel& reticle_model) override;
void OnProjMatrixChanged(const gfx::Transform& proj_matrix) override;
void OnSwapContents(int new_content_id) override;
void OnContentBoundsChanged(int width, int height) override;
......
......@@ -601,9 +601,12 @@ TEST_F(UiInputManagerContentTest, ControllerRestingInViewport) {
// The controller is initially not in the viewport.
EXPECT_FALSE(input_manager_->ControllerRestingInViewport());
std::vector<ControllerModel> controllers;
input_manager_->HandleInput(MsToTicks(1), render_info, controller_model,
&reticle_model, &input_event_list);
ui_->OnControllerUpdated(controller_model, reticle_model);
controllers.push_back(controller_model);
ui_->OnControllersUpdated(controllers, reticle_model);
scene_->OnBeginFrame(base::TimeTicks(), head_pose_);
// Although we are currently looking at the controller, it is not focused yet.
......@@ -612,17 +615,19 @@ TEST_F(UiInputManagerContentTest, ControllerRestingInViewport) {
input_manager_->HandleInput(MsToTicks(50000), render_info, controller_model,
&reticle_model, &input_event_list);
ui_->OnControllerUpdated(controller_model, reticle_model);
controllers[0] = controller_model;
ui_->OnControllersUpdated(controllers, reticle_model);
scene_->OnBeginFrame(base::TimeTicks(), head_pose_);
// Since the controller has been in the viewport for a long time (50s), it
// must report that it is focused.
EXPECT_TRUE(input_manager_->ControllerRestingInViewport());
ui_->OnControllerUpdated(controller_model, reticle_model);
controllers[0] = controller_model;
ui_->OnControllersUpdated(controllers, reticle_model);
scene_->OnBeginFrame(base::TimeTicks(), head_pose_);
EXPECT_TRUE(model_->controller.resting_in_viewport);
EXPECT_TRUE(model_->controllers[0].resting_in_viewport);
EXPECT_TRUE(IsVisible(kControllerTrackpadLabel));
}
......
......@@ -63,8 +63,9 @@ class UiInterface {
float width_percentage,
float height_percentage) = 0;
virtual void OnPause() = 0;
virtual void OnControllerUpdated(const ControllerModel& controller_model,
const ReticleModel& reticle_model) = 0;
virtual void OnControllersUpdated(
const std::vector<ControllerModel>& controller_models,
const ReticleModel& reticle_model) = 0;
virtual void OnProjMatrixChanged(const gfx::Transform& proj_matrix) = 0;
virtual void AcceptDoffPromptForTesting() = 0;
virtual gfx::Point3F GetTargetPointForTesting(
......
This diff is collapsed.
......@@ -54,7 +54,7 @@ class UiSceneCreator {
void CreateWebVrSubtree();
void CreateWebVrOverlayElements();
void CreateWebVrTimeoutScreen();
void CreateController();
void CreateControllers();
void CreateKeyboard();
void Create2dBrowsingHostedUi();
void CreateExternalPromptNotifcationOverlay();
......
......@@ -1068,7 +1068,7 @@ TEST_F(UiTest, ControllerLabels) {
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_FALSE(IsVisible(kControllerBackButtonLabel));
model_->controller.resting_in_viewport = true;
model_->mutable_primary_controller().resting_in_viewport = true;
EXPECT_TRUE(IsVisible(kControllerTrackpadLabel));
EXPECT_FALSE(IsVisible(kControllerTrackpadRepositionLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
......@@ -1111,13 +1111,13 @@ TEST_F(UiTest, ControllerLabels) {
EXPECT_FALSE(IsVisible(kControllerBackButtonLabel));
model_->push_mode(kModeRepositionWindow);
model_->controller.laser_direction = kForwardVector;
model_->mutable_primary_controller().laser_direction = kForwardVector;
EXPECT_FALSE(IsVisible(kControllerTrackpadLabel));
EXPECT_TRUE(IsVisible(kControllerTrackpadRepositionLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_TRUE(IsVisible(kControllerRepositionFinishLabel));
model_->controller.resting_in_viewport = false;
model_->mutable_primary_controller().resting_in_viewport = false;
EXPECT_FALSE(IsVisible(kControllerTrackpadRepositionLabel));
EXPECT_FALSE(IsVisible(kControllerTrackpadLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
......@@ -1140,7 +1140,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
ColorScheme scheme = model_->color_scheme();
model_->controller.battery_level = 5;
model_->mutable_primary_controller().battery_level = 5;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_full);
......@@ -1148,7 +1148,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
EXPECT_EQ(dot_3->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_4->center_color(), scheme.controller_battery_full);
model_->controller.battery_level = 4;
model_->mutable_primary_controller().battery_level = 4;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_full);
......@@ -1156,7 +1156,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
EXPECT_EQ(dot_3->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_4->center_color(), scheme.controller_battery_empty);
model_->controller.battery_level = 3;
model_->mutable_primary_controller().battery_level = 3;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_full);
......@@ -1164,7 +1164,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
EXPECT_EQ(dot_3->center_color(), scheme.controller_battery_empty);
EXPECT_EQ(dot_4->center_color(), scheme.controller_battery_empty);
model_->controller.battery_level = 2;
model_->mutable_primary_controller().battery_level = 2;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_full);
......@@ -1172,7 +1172,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
EXPECT_EQ(dot_3->center_color(), scheme.controller_battery_empty);
EXPECT_EQ(dot_4->center_color(), scheme.controller_battery_empty);
model_->controller.battery_level = 1;
model_->mutable_primary_controller().battery_level = 1;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_full);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_empty);
......@@ -1180,7 +1180,7 @@ TEST_F(UiTest, ControllerBatteryIndicator) {
EXPECT_EQ(dot_3->center_color(), scheme.controller_battery_empty);
EXPECT_EQ(dot_4->center_color(), scheme.controller_battery_empty);
model_->controller.battery_level = 0;
model_->mutable_primary_controller().battery_level = 0;
RunForMs(kAnimationTimeMs);
EXPECT_EQ(dot_0->center_color(), scheme.controller_battery_empty);
EXPECT_EQ(dot_1->center_color(), scheme.controller_battery_empty);
......@@ -1206,7 +1206,7 @@ TEST_F(UiTest, ResetRepositioner) {
EXPECT_NE(original, repositioner->world_space_transform());
repositioner->SetEnabled(false);
model_->controller.recentered = true;
model_->mutable_primary_controller().recentered = true;
OnBeginFrame();
EXPECT_EQ(original, repositioner->world_space_transform());
......
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