Commit ed26c34e authored by Ian Vollick's avatar Ian Vollick Committed by Commit Bot

[vr] Create a button to enable repositioning the content quad

This CL creates a button that enters window repositioning mode. There
is still a great deal of work to be done -- the behavior once we're in
the mode is not what we ultimately want -- but this gets some of the
infrastructure out of the way. Subsequent patches will refine the
repositioning UX.

Bug: 799270
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_vr;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I826a5868d17ee2d1ed5e69b7e1c75eb81142623e
Reviewed-on: https://chromium-review.googlesource.com/888540Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Commit-Queue: Ian Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532142}
parent a237ddcd
...@@ -43,11 +43,12 @@ class Button : public UiElement { ...@@ -43,11 +43,12 @@ class Button : public UiElement {
// method and the associated field can be removed. // method and the associated field can be removed.
void set_hover_offset(float hover_offset) { hover_offset_ = hover_offset; } void set_hover_offset(float hover_offset) { hover_offset_ = hover_offset; }
protected:
bool hovered() const { return hovered_; } bool hovered() const { return hovered_; }
bool down() const { return down_; } bool down() const { return down_; }
bool pressed() const { return pressed_; } bool pressed() const { return pressed_; }
bool enabled() const { return enabled_; } bool enabled() const { return enabled_; }
protected:
const ButtonColors& colors() const { return colors_; } const ButtonColors& colors() const { return colors_; }
float hover_offset() const { return hover_offset_; } float hover_offset() const { return hover_offset_; }
......
...@@ -74,6 +74,7 @@ bool Repositioner::OnBeginFrame(const base::TimeTicks& time, ...@@ -74,6 +74,7 @@ bool Repositioner::OnBeginFrame(const base::TimeTicks& time,
return false; return false;
} }
#ifndef NDEBUG
void Repositioner::DumpGeometry(std::ostringstream* os) const { void Repositioner::DumpGeometry(std::ostringstream* os) const {
gfx::Transform t = world_space_transform(); gfx::Transform t = world_space_transform();
gfx::Vector3dF forward = {0, 0, -1}; gfx::Vector3dF forward = {0, 0, -1};
...@@ -88,5 +89,6 @@ void Repositioner::DumpGeometry(std::ostringstream* os) const { ...@@ -88,5 +89,6 @@ void Repositioner::DumpGeometry(std::ostringstream* os) const {
*os << "rx(" << gfx::RadToDeg(x_rotation) << ") " *os << "rx(" << gfx::RadToDeg(x_rotation) << ") "
<< "ry(" << gfx::RadToDeg(y_rotation) << ") "; << "ry(" << gfx::RadToDeg(y_rotation) << ") ";
} }
#endif
} // namespace vr } // namespace vr
...@@ -37,7 +37,9 @@ class Repositioner : public UiElement { ...@@ -37,7 +37,9 @@ class Repositioner : public UiElement {
void UpdateTransform(const gfx::Transform& head_pose); void UpdateTransform(const gfx::Transform& head_pose);
bool OnBeginFrame(const base::TimeTicks& time, bool OnBeginFrame(const base::TimeTicks& time,
const gfx::Transform& head_pose) override; const gfx::Transform& head_pose) override;
#ifndef NDEBUG
void DumpGeometry(std::ostringstream* os) const override; void DumpGeometry(std::ostringstream* os) const override;
#endif
gfx::Transform transform_; gfx::Transform transform_;
bool enabled_ = false; bool enabled_ = false;
......
...@@ -53,11 +53,13 @@ void ScaledDepthAdjuster::OnSetType() { ...@@ -53,11 +53,13 @@ void ScaledDepthAdjuster::OnSetType() {
DCHECK_EQ(kTypeScaledDepthAdjuster, type()); DCHECK_EQ(kTypeScaledDepthAdjuster, type());
} }
#ifndef NDEBUG
void ScaledDepthAdjuster::DumpGeometry(std::ostringstream* os) const { void ScaledDepthAdjuster::DumpGeometry(std::ostringstream* os) const {
gfx::Transform t = world_space_transform(); gfx::Transform t = world_space_transform();
gfx::Point3F o; gfx::Point3F o;
t.TransformPoint(&o); t.TransformPoint(&o);
*os << "tz(" << delta_z_ << ") "; *os << "tz(" << delta_z_ << ") ";
} }
#endif
} // namespace vr } // namespace vr
...@@ -28,7 +28,10 @@ class ScaledDepthAdjuster : public UiElement { ...@@ -28,7 +28,10 @@ class ScaledDepthAdjuster : public UiElement {
bool OnBeginFrame(const base::TimeTicks& time, bool OnBeginFrame(const base::TimeTicks& time,
const gfx::Transform& head_pose) override; const gfx::Transform& head_pose) override;
void OnSetType() override; void OnSetType() override;
#ifndef NDEBUG
void DumpGeometry(std::ostringstream* os) const override; void DumpGeometry(std::ostringstream* os) const override;
#endif
gfx::Transform transform_; gfx::Transform transform_;
......
...@@ -23,13 +23,7 @@ namespace vr { ...@@ -23,13 +23,7 @@ namespace vr {
namespace { namespace {
static constexpr char kRed[] = "\x1b[31m"; constexpr float kHitTestResolutionInMeter = 0.000001f;
static constexpr char kGreen[] = "\x1b[32m";
static constexpr char kBlue[] = "\x1b[34m";
static constexpr char kCyan[] = "\x1b[36m";
static constexpr char kReset[] = "\x1b[0m";
static constexpr float kHitTestResolutionInMeter = 0.000001f;
int AllocateId() { int AllocateId() {
static int g_next_id = 1; static int g_next_id = 1;
...@@ -50,6 +44,44 @@ bool GetRayPlaneDistance(const gfx::Point3F& ray_origin, ...@@ -50,6 +44,44 @@ bool GetRayPlaneDistance(const gfx::Point3F& ray_origin,
return true; return true;
} }
#ifndef NDEBUG
constexpr char kRed[] = "\x1b[31m";
constexpr char kGreen[] = "\x1b[32m";
constexpr char kBlue[] = "\x1b[34m";
constexpr char kCyan[] = "\x1b[36m";
constexpr char kYellow[] = "\x1b[33m";
constexpr char kReset[] = "\x1b[0m";
void DumpTransformOperations(const cc::TransformOperations& ops,
std::ostringstream* os) {
if (!ops.at(0).IsIdentity()) {
const auto& translate = ops.at(0).translate;
*os << "t(" << translate.x << ", " << translate.y << ", " << translate.z
<< ") ";
}
if (ops.size() < 2u) {
return;
}
if (!ops.at(1).IsIdentity()) {
const auto& rotate = ops.at(1).rotate;
if (rotate.axis.x > 0.0f) {
*os << "rx(" << rotate.angle << ") ";
} else if (rotate.axis.y > 0.0f) {
*os << "ry(" << rotate.angle << ") ";
} else if (rotate.axis.z > 0.0f) {
*os << "rz(" << rotate.angle << ") ";
}
}
if (!ops.at(2).IsIdentity()) {
const auto& scale = ops.at(2).scale;
*os << "s(" << scale.x << ", " << scale.y << ", " << scale.z << ") ";
}
}
#endif
} // namespace } // namespace
EventHandlers::EventHandlers() = default; EventHandlers::EventHandlers() = default;
...@@ -391,6 +423,7 @@ std::string UiElement::DebugName() const { ...@@ -391,6 +423,7 @@ std::string UiElement::DebugName() const {
type() == kTypeNone ? "" : UiElementTypeToString(type()).c_str()); type() == kTypeNone ? "" : UiElementTypeToString(type()).c_str());
} }
#ifndef NDEBUG
void DumpLines(const std::vector<size_t>& counts, void DumpLines(const std::vector<size_t>& counts,
const std::vector<const UiElement*>& ancestors, const std::vector<const UiElement*>& ancestors,
std::ostringstream* os) { std::ostringstream* os) {
...@@ -439,7 +472,7 @@ void UiElement::DumpHierarchy(std::vector<size_t> counts, ...@@ -439,7 +472,7 @@ void UiElement::DumpHierarchy(std::vector<size_t> counts,
*os << DebugName() << kReset << " " << kCyan << DrawPhaseToString(draw_phase_) *os << DebugName() << kReset << " " << kCyan << DrawPhaseToString(draw_phase_)
<< " " << kReset; << " " << kReset;
if (!size().IsEmpty()) { if (size().width() != 0.0f || size().height() != 0.0f) {
*os << kRed << "[" << size().width() << ", " << size().height() << "] " *os << kRed << "[" << size().width() << ", " << size().height() << "] "
<< kReset; << kReset;
} }
...@@ -480,28 +513,11 @@ void UiElement::DumpHierarchy(std::vector<size_t> counts, ...@@ -480,28 +513,11 @@ void UiElement::DumpHierarchy(std::vector<size_t> counts,
} }
void UiElement::DumpGeometry(std::ostringstream* os) const { void UiElement::DumpGeometry(std::ostringstream* os) const {
if (!transform_operations_.at(0).IsIdentity()) { DumpTransformOperations(transform_operations_, os);
const auto& translate = transform_operations_.at(0).translate; *os << kYellow;
*os << "t(" << translate.x << ", " << translate.y << ", " << translate.z DumpTransformOperations(layout_offset_, os);
<< ") ";
}
if (!transform_operations_.at(1).IsIdentity()) {
const auto& rotate = transform_operations_.at(1).rotate;
if (rotate.axis.x > 0.0f) {
*os << "rx(" << rotate.angle << ") ";
} else if (rotate.axis.y > 0.0f) {
*os << "ry(" << rotate.angle << ") ";
} else if (rotate.axis.z > 0.0f) {
*os << "rz(" << rotate.angle << ") ";
}
}
if (!transform_operations_.at(2).IsIdentity()) {
const auto& scale = transform_operations_.at(2).scale;
*os << "s(" << scale.x << ", " << scale.y << ", " << scale.z << ") ";
}
} }
#endif
void UiElement::OnUpdatedWorldSpaceTransform() {} void UiElement::OnUpdatedWorldSpaceTransform() {}
......
...@@ -262,21 +262,25 @@ class UiElement : public cc::AnimationTarget { ...@@ -262,21 +262,25 @@ class UiElement : public cc::AnimationTarget {
LayoutAlignment x_anchoring() const { return x_anchoring_; } LayoutAlignment x_anchoring() const { return x_anchoring_; }
void set_x_anchoring(LayoutAlignment x_anchoring) { void set_x_anchoring(LayoutAlignment x_anchoring) {
DCHECK(x_anchoring == LEFT || x_anchoring == RIGHT || x_anchoring == NONE);
x_anchoring_ = x_anchoring; x_anchoring_ = x_anchoring;
} }
LayoutAlignment y_anchoring() const { return y_anchoring_; } LayoutAlignment y_anchoring() const { return y_anchoring_; }
void set_y_anchoring(LayoutAlignment y_anchoring) { void set_y_anchoring(LayoutAlignment y_anchoring) {
DCHECK(y_anchoring == TOP || y_anchoring == BOTTOM || y_anchoring == NONE);
y_anchoring_ = y_anchoring; y_anchoring_ = y_anchoring;
} }
LayoutAlignment x_centering() const { return x_centering_; } LayoutAlignment x_centering() const { return x_centering_; }
void set_x_centering(LayoutAlignment x_centering) { void set_x_centering(LayoutAlignment x_centering) {
DCHECK(x_centering == LEFT || x_centering == RIGHT || x_centering == NONE);
x_centering_ = x_centering; x_centering_ = x_centering;
} }
LayoutAlignment y_centering() const { return y_centering_; } LayoutAlignment y_centering() const { return y_centering_; }
void set_y_centering(LayoutAlignment y_centering) { void set_y_centering(LayoutAlignment y_centering) {
DCHECK(y_centering == TOP || y_centering == BOTTOM || y_centering == NONE);
y_centering_ = y_centering; y_centering_ = y_centering;
} }
...@@ -418,6 +422,8 @@ class UiElement : public cc::AnimationTarget { ...@@ -418,6 +422,8 @@ class UiElement : public cc::AnimationTarget {
std::string DebugName() const; std::string DebugName() const;
#ifndef NDEBUG
// Writes a pretty-printed version of the UiElement subtree to |os|. The // Writes a pretty-printed version of the UiElement subtree to |os|. The
// vector of counts represents where each ancestor on the ancestor chain is // vector of counts represents where each ancestor on the ancestor chain is
// situated in its parent's list of children. This is used to determine // situated in its parent's list of children. This is used to determine
...@@ -429,6 +435,7 @@ class UiElement : public cc::AnimationTarget { ...@@ -429,6 +435,7 @@ class UiElement : public cc::AnimationTarget {
std::ostringstream* os, std::ostringstream* os,
bool include_bindings) const; bool include_bindings) const;
virtual void DumpGeometry(std::ostringstream* os) const; virtual void DumpGeometry(std::ostringstream* os) const;
#endif
// This is to be used only during the texture / size updated phase (i.e., to // This is to be used only during the texture / size updated phase (i.e., to
// change your size based on your old size). // change your size based on your old size).
......
...@@ -26,6 +26,7 @@ static const char* g_ui_element_name_strings[] = { ...@@ -26,6 +26,7 @@ static const char* g_ui_element_name_strings[] = {
"kWebVrViewportAwareRoot", "kWebVrViewportAwareRoot",
"kContentQuad", "kContentQuad",
"kContentQuadShadow", "kContentQuadShadow",
"kContentQuadRepositionButton",
"kControllerRoot", "kControllerRoot",
"kControllerGroup", "kControllerGroup",
"kLaser", "kLaser",
......
...@@ -25,6 +25,7 @@ enum UiElementName { ...@@ -25,6 +25,7 @@ enum UiElementName {
kWebVrViewportAwareRoot, kWebVrViewportAwareRoot,
kContentQuad, kContentQuad,
kContentQuadShadow, kContentQuadShadow,
kContentQuadRepositionButton,
kControllerRoot, kControllerRoot,
kControllerGroup, kControllerGroup,
kLaser, kLaser,
......
...@@ -209,7 +209,8 @@ void VrTestContext::HandleInput(ui::Event* event) { ...@@ -209,7 +209,8 @@ void VrTestContext::HandleInput(ui::Event* event) {
model_->toggle_mode(kModeRepositionWindow); model_->toggle_mode(kModeRepositionWindow);
break; break;
case ui::DomCode::US_X: case ui::DomCode::US_X:
ui_->OnAppButtonClicked(); model_->experimental_features_enabled =
!model_->experimental_features_enabled;
break; break;
default: default:
break; break;
......
...@@ -262,6 +262,11 @@ void Ui::OnAppButtonClicked() { ...@@ -262,6 +262,11 @@ void Ui::OnAppButtonClicked() {
return; return;
} }
if (model_->reposition_window_enabled()) {
model_->pop_mode(kModeRepositionWindow);
return;
}
// App button click exits the WebVR presentation and fullscreen. // App button click exits the WebVR presentation and fullscreen.
browser_->ExitPresent(); browser_->ExitPresent();
browser_->ExitFullscreen(); browser_->ExitFullscreen();
...@@ -332,12 +337,14 @@ bool Ui::SkipsRedrawWhenNotDirty() const { ...@@ -332,12 +337,14 @@ bool Ui::SkipsRedrawWhenNotDirty() const {
} }
void Ui::Dump(bool include_bindings) { void Ui::Dump(bool include_bindings) {
#ifndef NDEBUG
std::ostringstream os; std::ostringstream os;
os << std::setprecision(3); os << std::setprecision(3);
os << std::endl; os << std::endl;
scene_->root_element().DumpHierarchy(std::vector<size_t>(), &os, scene_->root_element().DumpHierarchy(std::vector<size_t>(), &os,
include_bindings); include_bindings);
LOG(ERROR) << os.str(); LOG(ERROR) << os.str();
#endif
} }
void Ui::OnAssetsLoading() { void Ui::OnAssetsLoading() {
......
...@@ -279,6 +279,15 @@ static constexpr int kControllerLabelTransitionDurationMs = 700; ...@@ -279,6 +279,15 @@ static constexpr int kControllerLabelTransitionDurationMs = 700;
static constexpr float kSkyDistance = 1000.0f; static constexpr float kSkyDistance = 1000.0f;
static constexpr float kGridOpacity = 0.5f; static constexpr float kGridOpacity = 0.5f;
static constexpr float kRepositionButtonDiameter = 0.75f * kCloseButtonDiameter;
// This allows the button to be hittable even when hidden.
static constexpr float kRepositionButtonMinOpacity = 0.001f;
static constexpr float kRepositionButtonMidOpacity = 0.3f;
static constexpr float kRepositionButtonMaxOpacity = 1.0f;
static constexpr float kRepositionButtonXOffset = kIndicatorGap;
static constexpr float kRepositionButtonYOffset = 0.5f * kIndicatorGap;
static constexpr int kRepositionButtonTransitionDurationMs = 750;
} // namespace vr } // namespace vr
#endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_ #endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_
...@@ -505,6 +505,7 @@ void UiSceneCreator::CreateScene() { ...@@ -505,6 +505,7 @@ void UiSceneCreator::CreateScene() {
CreateFullscreenToast(); CreateFullscreenToast();
CreateUnderDevelopmentNotice(); CreateUnderDevelopmentNotice();
CreateVoiceSearchUiGroup(); CreateVoiceSearchUiGroup();
CreateContentRepositioningAffordance();
CreateExitWarning(); CreateExitWarning();
CreateWebVrSubtree(); CreateWebVrSubtree();
CreateKeyboard(); CreateKeyboard();
...@@ -531,8 +532,8 @@ void UiSceneCreator::Create2dBrowsingSubtreeRoots() { ...@@ -531,8 +532,8 @@ void UiSceneCreator::Create2dBrowsingSubtreeRoots() {
element->set_hit_testable(false); element->set_hit_testable(false);
scene_->AddUiElement(k2dBrowsingRoot, std::move(element)); scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
auto repositioner = std::make_unique<Repositioner>(kContentDistance); auto repositioner = Create<Repositioner>(k2dBrowsingRepositioner, kPhaseNone,
repositioner->SetName(k2dBrowsingRepositioner); kContentDistance);
repositioner->AddBinding( repositioner->AddBinding(
VR_BIND_FUNC(bool, Model, model_, model->reposition_window_enabled(), VR_BIND_FUNC(bool, Model, model_, model->reposition_window_enabled(),
Repositioner, repositioner.get(), set_enable)); Repositioner, repositioner.get(), set_enable));
...@@ -716,9 +717,7 @@ void UiSceneCreator::CreateSystemIndicators() { ...@@ -716,9 +717,7 @@ void UiSceneCreator::CreateSystemIndicators() {
void UiSceneCreator::CreateContentQuad() { void UiSceneCreator::CreateContentQuad() {
// Place an invisible but hittable plane behind the content quad, to keep the // Place an invisible but hittable plane behind the content quad, to keep the
// reticle roughly planar with the content if near content. // reticle roughly planar with the content if near content.
auto hit_plane = std::make_unique<InvisibleHitTarget>(); auto hit_plane = Create<InvisibleHitTarget>(kBackplane, kPhaseForeground);
hit_plane->SetName(kBackplane);
hit_plane->SetDrawPhase(kPhaseForeground);
hit_plane->SetSize(kBackplaneSize, kSceneHeight); hit_plane->SetSize(kBackplaneSize, kSceneHeight);
scene_->AddUiElement(k2dBrowsingContentGroup, std::move(hit_plane)); scene_->AddUiElement(k2dBrowsingContentGroup, std::move(hit_plane));
...@@ -1265,6 +1264,53 @@ void UiSceneCreator::CreateVoiceSearchUiGroup() { ...@@ -1265,6 +1264,53 @@ void UiSceneCreator::CreateVoiceSearchUiGroup() {
omnibox_editing_enabled()); omnibox_editing_enabled());
} }
void UiSceneCreator::CreateContentRepositioningAffordance() {
auto reposition_button = Create<DiscButton>(
kContentQuadRepositionButton, kPhaseForeground,
base::BindRepeating(
[](Model* model) { model->push_mode(kModeRepositionWindow); },
base::Unretained(model_)),
kRepositionIcon);
reposition_button->SetSize(kRepositionButtonDiameter,
kRepositionButtonDiameter);
reposition_button->set_y_anchoring(BOTTOM);
reposition_button->set_x_anchoring(RIGHT);
reposition_button->set_x_centering(LEFT);
reposition_button->set_y_centering(BOTTOM);
reposition_button->SetTranslate(kRepositionButtonXOffset,
kRepositionButtonYOffset, 0);
reposition_button->SetTransitionedProperties({OPACITY});
reposition_button->SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kRepositionButtonTransitionDurationMs));
reposition_button->background()->SetTransitionedProperties(
{BACKGROUND_COLOR, TRANSFORM});
reposition_button->SetOpacity(kRepositionButtonMinOpacity);
reposition_button->AddBinding(std::make_unique<Binding<float>>(
VR_BIND_LAMBDA(
[](Model* model, Button* button) {
if (!model->experimental_features_enabled)
return 0.0f;
if (button->hovered())
return kRepositionButtonMaxOpacity;
if (!model->controller.quiescent)
return kRepositionButtonMidOpacity;
return kRepositionButtonMinOpacity;
},
base::Unretained(model_), base::Unretained(reposition_button.get())),
VR_BIND_LAMBDA(
[](UiElement* button, const float& opacity) {
if (opacity == 1.0f)
button->SetVisibleImmediately(true);
else
button->SetOpacity(opacity);
},
base::Unretained(reposition_button.get()))));
VR_BIND_BUTTON_COLORS(model_, reposition_button.get(),
&ColorScheme::button_colors,
&DiscButton::SetButtonColors);
scene_->AddUiElement(kContentQuad, std::move(reposition_button));
}
void UiSceneCreator::CreateController() { void UiSceneCreator::CreateController() {
auto root = std::make_unique<UiElement>(); auto root = std::make_unique<UiElement>();
root->SetName(kControllerRoot); root->SetName(kControllerRoot);
...@@ -1335,7 +1381,8 @@ void UiSceneCreator::CreateController() { ...@@ -1335,7 +1381,8 @@ void UiSceneCreator::CreateController() {
kControllerBackButtonLabel, kControllerBackButtonOffset, kControllerBackButtonLabel, kControllerBackButtonOffset,
l10n_util::GetStringUTF16(IDS_VR_BUTTON_BACK), model_); l10n_util::GetStringUTF16(IDS_VR_BUTTON_BACK), model_);
VR_BIND_VISIBILITY(back_button_label, model->omnibox_editing_enabled() || VR_BIND_VISIBILITY(back_button_label, model->omnibox_editing_enabled() ||
model->voice_search_enabled()); model->voice_search_enabled() ||
model->reposition_window_enabled());
callout_group->AddChild(std::move(back_button_label)); callout_group->AddChild(std::move(back_button_label));
controller->AddChild(std::move(callout_group)); controller->AddChild(std::move(callout_group));
......
...@@ -55,6 +55,7 @@ class UiSceneCreator { ...@@ -55,6 +55,7 @@ class UiSceneCreator {
void CreateAudioPermissionPrompt(); void CreateAudioPermissionPrompt();
void CreateFullscreenToast(); void CreateFullscreenToast();
void CreateVoiceSearchUiGroup(); void CreateVoiceSearchUiGroup();
void CreateContentRepositioningAffordance();
void CreateExitWarning(); void CreateExitWarning();
void CreateWebVrSubtree(); void CreateWebVrSubtree();
void CreateWebVrOverlayElements(); void CreateWebVrOverlayElements();
......
...@@ -1120,10 +1120,51 @@ TEST_F(UiTest, ControllerLabels) { ...@@ -1120,10 +1120,51 @@ TEST_F(UiTest, ControllerLabels) {
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel)); EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_TRUE(IsVisible(kControllerBackButtonLabel)); EXPECT_TRUE(IsVisible(kControllerBackButtonLabel));
model_->pop_mode(kModeVoiceSearch);
EXPECT_TRUE(IsVisible(kControllerTrackpadLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_FALSE(IsVisible(kControllerBackButtonLabel));
model_->push_mode(kModeRepositionWindow);
model_->controller.laser_direction = kForwardVector;
EXPECT_TRUE(IsVisible(kControllerTrackpadLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_TRUE(IsVisible(kControllerBackButtonLabel));
model_->controller.resting_in_viewport = false; model_->controller.resting_in_viewport = false;
EXPECT_FALSE(IsVisible(kControllerTrackpadLabel)); EXPECT_FALSE(IsVisible(kControllerTrackpadLabel));
EXPECT_FALSE(IsVisible(kControllerExitButtonLabel)); EXPECT_FALSE(IsVisible(kControllerExitButtonLabel));
EXPECT_FALSE(IsVisible(kControllerBackButtonLabel)); EXPECT_FALSE(IsVisible(kControllerBackButtonLabel));
} }
TEST_F(UiTest, RepositionButton) {
CreateScene(kNotInCct, kNotInWebVr);
DiscButton* button = static_cast<DiscButton*>(
scene_->GetUiElementByName(kContentQuadRepositionButton));
EXPECT_FALSE(IsVisible(button->name()));
model_->experimental_features_enabled = true;
model_->controller.quiescent = true;
OnBeginFrame();
EXPECT_EQ(kRepositionButtonMinOpacity, button->GetTargetOpacity());
model_->controller.quiescent = false;
OnBeginFrame();
EXPECT_EQ(kRepositionButtonMidOpacity, button->GetTargetOpacity());
button->OnHoverEnter({0, 0});
OnBeginFrame();
EXPECT_EQ(kRepositionButtonMaxOpacity, button->GetTargetOpacity());
// If hovered, the button should remain visible, even the controller is
// quiescent.
model_->controller.quiescent = true;
OnBeginFrame();
EXPECT_EQ(kRepositionButtonMaxOpacity, button->GetTargetOpacity());
button->OnHoverLeave();
OnBeginFrame();
EXPECT_EQ(kRepositionButtonMinOpacity, button->GetTargetOpacity());
}
} // namespace vr } // namespace vr
...@@ -8,8 +8,9 @@ aggregate_vector_icons("vr_vector_icons") { ...@@ -8,8 +8,9 @@ aggregate_vector_icons("vr_vector_icons") {
icon_directory = "." icon_directory = "."
icons = [ icons = [
"sad_tab.icon",
"file_download_done.icon", "file_download_done.icon",
"reposition.icon",
"sad_tab.icon",
] ]
} }
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 24,
MOVE_TO, 10, 9,
R_H_LINE_TO, 4,
V_LINE_TO, 6,
R_H_LINE_TO, 3,
R_LINE_TO, -5, -5,
R_LINE_TO, -5, 5,
R_H_LINE_TO, 3,
R_V_LINE_TO, 3,
CLOSE,
R_MOVE_TO, -1, 1,
H_LINE_TO, 6,
V_LINE_TO, 7,
R_LINE_TO, -5, 5,
R_LINE_TO, 5, 5,
R_V_LINE_TO, -3,
R_H_LINE_TO, 3,
R_V_LINE_TO, -4,
CLOSE,
R_MOVE_TO, 14, 2,
R_LINE_TO, -5, -5,
R_V_LINE_TO, 3,
R_H_LINE_TO, -3,
R_V_LINE_TO, 4,
R_H_LINE_TO, 3,
R_V_LINE_TO, 3,
R_LINE_TO, 5, -5,
CLOSE,
R_MOVE_TO, -9, 3,
R_H_LINE_TO, -4,
R_V_LINE_TO, 3,
H_LINE_TO, 7,
R_LINE_TO, 5, 5,
R_LINE_TO, 5, -5,
R_H_LINE_TO, -3,
R_V_LINE_TO, -3,
CLOSE,
END
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