| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/ui_scene.h" | 5 #include "chrome/browser/android/vr_shell/ui_scene.h" |
| 6 | 6 |
| 7 #define _USE_MATH_DEFINES // For M_PI in MSVC. | 7 #define _USE_MATH_DEFINES // For M_PI in MSVC. |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/android/vr_shell/animation.h" | |
| 15 #include "chrome/browser/android/vr_shell/easing.h" | |
| 16 #include "chrome/browser/android/vr_shell/ui_elements/ui_element.h" | 14 #include "chrome/browser/android/vr_shell/ui_elements/ui_element.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "ui/gfx/transform_util.h" |
| 18 | 17 |
| 19 #define TOLERANCE 0.0001 | 18 #define TOLERANCE 0.0001 |
| 20 | 19 |
| 21 #define EXPECT_VEC3F_NEAR(a, b) \ | 20 #define EXPECT_VEC3F_NEAR(a, b) \ |
| 22 EXPECT_NEAR(a.x(), b.x(), TOLERANCE); \ | 21 EXPECT_NEAR(a.x(), b.x(), TOLERANCE); \ |
| 23 EXPECT_NEAR(a.y(), b.y(), TOLERANCE); \ | 22 EXPECT_NEAR(a.y(), b.y(), TOLERANCE); \ |
| 24 EXPECT_NEAR(a.z(), b.z(), TOLERANCE); | 23 EXPECT_NEAR(a.z(), b.z(), TOLERANCE); |
| 25 | 24 |
| 26 namespace vr_shell { | 25 namespace vr_shell { |
| 27 | 26 |
| 28 namespace { | 27 namespace { |
| 29 | 28 |
| 30 base::TimeTicks usToTicks(uint64_t us) { | 29 base::TimeTicks usToTicks(uint64_t us) { |
| 31 return base::TimeTicks::FromInternalValue(us); | 30 return base::TimeTicks::FromInternalValue(us); |
| 32 } | 31 } |
| 33 | 32 |
| 34 base::TimeDelta usToDelta(uint64_t us) { | |
| 35 return base::TimeDelta::FromInternalValue(us); | |
| 36 } | |
| 37 | |
| 38 void addElement(UiScene* scene, int id) { | 33 void addElement(UiScene* scene, int id) { |
| 39 auto element = base::MakeUnique<UiElement>(); | 34 auto element = base::MakeUnique<UiElement>(id); |
| 40 element->set_id(id); | |
| 41 scene->AddUiElement(std::move(element)); | 35 scene->AddUiElement(std::move(element)); |
| 42 } | 36 } |
| 43 | 37 |
| 44 void addAnimation(UiScene* scene, | |
| 45 int element_id, | |
| 46 int animation_id, | |
| 47 Animation::Property property) { | |
| 48 std::unique_ptr<easing::Easing> easing = base::MakeUnique<easing::Linear>(); | |
| 49 std::vector<float> from; | |
| 50 std::vector<float> to = {1, 1, 1, 1}; | |
| 51 auto animation = | |
| 52 base::MakeUnique<Animation>(animation_id, property, std::move(easing), | |
| 53 from, to, usToTicks(0), usToDelta(1)); | |
| 54 scene->AddAnimation(element_id, std::move(animation)); | |
| 55 } | |
| 56 | |
| 57 } // namespace | 38 } // namespace |
| 58 | 39 |
| 59 TEST(UiScene, AddRemoveElements) { | 40 TEST(UiScene, AddRemoveElements) { |
| 60 UiScene scene; | 41 UiScene scene; |
| 61 | 42 |
| 62 EXPECT_EQ(scene.GetUiElements().size(), 0u); | 43 EXPECT_EQ(scene.GetUiElements().size(), 0u); |
| 63 addElement(&scene, 0); | 44 addElement(&scene, 1); |
| 64 EXPECT_EQ(scene.GetUiElements().size(), 1u); | 45 EXPECT_EQ(scene.GetUiElements().size(), 1u); |
| 65 addElement(&scene, 99); | 46 addElement(&scene, 99); |
| 66 EXPECT_EQ(scene.GetUiElements().size(), 2u); | 47 EXPECT_EQ(scene.GetUiElements().size(), 2u); |
| 67 | 48 |
| 68 EXPECT_NE(scene.GetUiElementById(0), nullptr); | 49 EXPECT_NE(scene.GetUiElementById(1), nullptr); |
| 69 EXPECT_NE(scene.GetUiElementById(99), nullptr); | 50 EXPECT_NE(scene.GetUiElementById(99), nullptr); |
| 51 EXPECT_EQ(scene.GetUiElementById(2), nullptr); |
| 52 |
| 53 scene.RemoveUiElement(1); |
| 54 EXPECT_EQ(scene.GetUiElements().size(), 1u); |
| 70 EXPECT_EQ(scene.GetUiElementById(1), nullptr); | 55 EXPECT_EQ(scene.GetUiElementById(1), nullptr); |
| 71 | |
| 72 scene.RemoveUiElement(0); | |
| 73 EXPECT_EQ(scene.GetUiElements().size(), 1u); | |
| 74 EXPECT_EQ(scene.GetUiElementById(0), nullptr); | |
| 75 scene.RemoveUiElement(99); | 56 scene.RemoveUiElement(99); |
| 76 EXPECT_EQ(scene.GetUiElements().size(), 0u); | 57 EXPECT_EQ(scene.GetUiElements().size(), 0u); |
| 77 EXPECT_EQ(scene.GetUiElementById(99), nullptr); | 58 EXPECT_EQ(scene.GetUiElementById(99), nullptr); |
| 78 | 59 |
| 79 scene.RemoveUiElement(0); | 60 scene.RemoveUiElement(1); |
| 80 scene.RemoveUiElement(99); | 61 scene.RemoveUiElement(99); |
| 81 EXPECT_EQ(scene.GetUiElements().size(), 0u); | 62 EXPECT_EQ(scene.GetUiElements().size(), 0u); |
| 82 } | 63 } |
| 83 | 64 |
| 84 TEST(UiScene, AddRemoveAnimations) { | |
| 85 UiScene scene; | |
| 86 addElement(&scene, 0); | |
| 87 auto* element = scene.GetUiElementById(0); | |
| 88 | |
| 89 EXPECT_EQ(element->animations().size(), 0u); | |
| 90 addAnimation(&scene, 0, 0, Animation::Property::SIZE); | |
| 91 EXPECT_EQ(element->animations().size(), 1u); | |
| 92 EXPECT_EQ(element->animations()[0]->property, Animation::Property::SIZE); | |
| 93 addAnimation(&scene, 0, 1, Animation::Property::SCALE); | |
| 94 EXPECT_EQ(element->animations().size(), 2u); | |
| 95 EXPECT_EQ(element->animations()[1]->property, Animation::Property::SCALE); | |
| 96 | |
| 97 scene.RemoveAnimation(0, 0); | |
| 98 EXPECT_EQ(element->animations().size(), 1u); | |
| 99 EXPECT_EQ(element->animations()[0]->property, Animation::Property::SCALE); | |
| 100 scene.RemoveAnimation(0, 1); | |
| 101 EXPECT_EQ(element->animations().size(), 0u); | |
| 102 | |
| 103 scene.RemoveAnimation(0, 0); | |
| 104 EXPECT_EQ(element->animations().size(), 0u); | |
| 105 } | |
| 106 | |
| 107 // This test creates a parent and child UI element, each with their own | 65 // This test creates a parent and child UI element, each with their own |
| 108 // transformations, and ensures that the child's computed total transform | 66 // transformations, and ensures that the child's computed total transform |
| 109 // incorporates the parent's transform as well as its own. | 67 // incorporates the parent's transform as well as its own. |
| 110 TEST(UiScene, ParentTransformAppliesToChild) { | 68 TEST(UiScene, ParentTransformAppliesToChild) { |
| 111 UiScene scene; | 69 UiScene scene; |
| 112 | 70 |
| 113 // Add a parent element, with distinct transformations. | 71 // Add a parent element, with distinct transformations. |
| 114 // Size of the parent should be ignored by the child. | 72 // Size of the parent should be ignored by the child. |
| 115 auto element = base::MakeUnique<UiElement>(); | 73 auto element = base::MakeUnique<UiElement>(1); |
| 116 element->set_id(0); | |
| 117 element->set_size({1000, 1000, 1}); | 74 element->set_size({1000, 1000, 1}); |
| 118 element->set_scale({3, 3, 1}); | 75 |
| 119 element->set_rotation(gfx::Quaternion(gfx::Vector3dF(0, 0, 1), M_PI / 2)); | 76 cc::TransformOperations operations; |
| 120 element->set_translation({6, 1, 0}); | 77 operations.AppendTranslate(6, 1, 0); |
| 78 operations.AppendRotate(0, 0, 1, 180 / 2); |
| 79 operations.AppendScale(3, 3, 1); |
| 80 element->set_transform_operations(operations); |
| 121 scene.AddUiElement(std::move(element)); | 81 scene.AddUiElement(std::move(element)); |
| 122 | 82 |
| 123 // Add a child to the parent, with different transformations. | 83 // Add a child to the parent, with different transformations. |
| 124 element = base::MakeUnique<UiElement>(); | 84 element = base::MakeUnique<UiElement>(2); |
| 125 element->set_id(1); | 85 element->set_parent_id(1); |
| 126 element->set_parent_id(0); | |
| 127 element->set_size({1, 1, 1}); | 86 element->set_size({1, 1, 1}); |
| 128 element->set_scale({2, 2, 1}); | 87 |
| 129 element->set_rotation(gfx::Quaternion(gfx::Vector3dF(0, 0, 1), M_PI / 2)); | 88 cc::TransformOperations child_operations; |
| 130 element->set_translation({3, 0, 0}); | 89 child_operations.AppendTranslate(3, 0, 0); |
| 90 child_operations.AppendRotate(0, 0, 1, 180 / 2); |
| 91 child_operations.AppendScale(2, 2, 1); |
| 92 element->set_transform_operations(child_operations); |
| 131 scene.AddUiElement(std::move(element)); | 93 scene.AddUiElement(std::move(element)); |
| 132 const UiElement* child = scene.GetUiElementById(1); | 94 const UiElement* child = scene.GetUiElementById(2); |
| 133 | 95 |
| 134 gfx::Point3F origin(0, 0, 0); | 96 gfx::Point3F origin(0, 0, 0); |
| 135 gfx::Point3F point(1, 0, 0); | 97 gfx::Point3F point(1, 0, 0); |
| 136 | 98 |
| 137 scene.OnBeginFrame(usToTicks(0)); | 99 scene.OnBeginFrame(usToTicks(1)); |
| 138 child->transform().TransformPoint(&origin); | 100 child->screen_space_transform().TransformPoint(&origin); |
| 139 child->transform().TransformPoint(&point); | 101 child->screen_space_transform().TransformPoint(&point); |
| 140 EXPECT_VEC3F_NEAR(gfx::Point3F(6, 10, 0), origin); | 102 EXPECT_VEC3F_NEAR(gfx::Point3F(6, 10, 0), origin); |
| 141 EXPECT_VEC3F_NEAR(gfx::Point3F(0, 10, 0), point); | 103 EXPECT_VEC3F_NEAR(gfx::Point3F(0, 10, 0), point); |
| 142 } | 104 } |
| 143 | 105 |
| 144 TEST(UiScene, Opacity) { | 106 TEST(UiScene, Opacity) { |
| 145 UiScene scene; | 107 UiScene scene; |
| 146 | 108 |
| 147 auto element = base::MakeUnique<UiElement>(); | 109 auto element = base::MakeUnique<UiElement>(1); |
| 148 element->set_id(0); | |
| 149 element->set_opacity(0.5); | 110 element->set_opacity(0.5); |
| 150 scene.AddUiElement(std::move(element)); | 111 scene.AddUiElement(std::move(element)); |
| 151 | 112 |
| 152 element = base::MakeUnique<UiElement>(); | 113 element = base::MakeUnique<UiElement>(2); |
| 153 element->set_id(1); | 114 element->set_parent_id(1); |
| 154 element->set_parent_id(0); | |
| 155 element->set_opacity(0.5); | 115 element->set_opacity(0.5); |
| 156 scene.AddUiElement(std::move(element)); | 116 scene.AddUiElement(std::move(element)); |
| 157 | 117 |
| 158 scene.OnBeginFrame(usToTicks(0)); | 118 scene.OnBeginFrame(usToTicks(1)); |
| 159 EXPECT_EQ(0.5f, scene.GetUiElementById(0)->computed_opacity()); | 119 EXPECT_EQ(0.5f, scene.GetUiElementById(1)->computed_opacity()); |
| 160 EXPECT_EQ(0.25f, scene.GetUiElementById(1)->computed_opacity()); | 120 EXPECT_EQ(0.25f, scene.GetUiElementById(2)->computed_opacity()); |
| 161 } | 121 } |
| 162 | 122 |
| 163 TEST(UiScene, LockToFov) { | 123 TEST(UiScene, LockToFov) { |
| 164 UiScene scene; | 124 UiScene scene; |
| 165 | 125 |
| 166 auto element = base::MakeUnique<UiElement>(); | 126 auto element = base::MakeUnique<UiElement>(1); |
| 167 element->set_id(0); | |
| 168 element->set_lock_to_fov(true); | 127 element->set_lock_to_fov(true); |
| 169 scene.AddUiElement(std::move(element)); | 128 scene.AddUiElement(std::move(element)); |
| 170 | 129 |
| 171 element = base::MakeUnique<UiElement>(); | 130 element = base::MakeUnique<UiElement>(2); |
| 172 element->set_id(1); | 131 element->set_parent_id(1); |
| 173 element->set_parent_id(0); | |
| 174 element->set_lock_to_fov(false); | 132 element->set_lock_to_fov(false); |
| 175 scene.AddUiElement(std::move(element)); | 133 scene.AddUiElement(std::move(element)); |
| 176 | 134 |
| 177 scene.OnBeginFrame(usToTicks(0)); | 135 scene.OnBeginFrame(usToTicks(1)); |
| 178 EXPECT_TRUE(scene.GetUiElementById(0)->computed_lock_to_fov()); | |
| 179 EXPECT_TRUE(scene.GetUiElementById(1)->computed_lock_to_fov()); | 136 EXPECT_TRUE(scene.GetUiElementById(1)->computed_lock_to_fov()); |
| 137 EXPECT_TRUE(scene.GetUiElementById(2)->computed_lock_to_fov()); |
| 180 } | 138 } |
| 181 | 139 |
| 182 typedef struct { | 140 typedef struct { |
| 183 XAnchoring x_anchoring; | 141 XAnchoring x_anchoring; |
| 184 YAnchoring y_anchoring; | 142 YAnchoring y_anchoring; |
| 185 float expected_x; | 143 float expected_x; |
| 186 float expected_y; | 144 float expected_y; |
| 187 } AnchoringTestCase; | 145 } AnchoringTestCase; |
| 188 | 146 |
| 189 class AnchoringTest : public ::testing::TestWithParam<AnchoringTestCase> {}; | 147 class AnchoringTest : public ::testing::TestWithParam<AnchoringTestCase> {}; |
| 190 | 148 |
| 191 TEST_P(AnchoringTest, VerifyCorrectPosition) { | 149 TEST_P(AnchoringTest, VerifyCorrectPosition) { |
| 192 UiScene scene; | 150 UiScene scene; |
| 193 | 151 |
| 194 // Create a parent element with non-unity size and scale. | 152 // Create a parent element with non-unity size and scale. |
| 195 auto element = base::MakeUnique<UiElement>(); | 153 auto element = base::MakeUnique<UiElement>(1); |
| 196 element->set_id(0); | |
| 197 element->set_size({2, 2, 1}); | 154 element->set_size({2, 2, 1}); |
| 198 element->set_scale({2, 2, 1}); | 155 cc::TransformOperations operations; |
| 156 operations.AppendScale(2, 2, 1); |
| 157 element->set_transform_operations(operations); |
| 199 scene.AddUiElement(std::move(element)); | 158 scene.AddUiElement(std::move(element)); |
| 200 | 159 |
| 201 // Add a child to the parent, with anchoring. | 160 // Add a child to the parent, with anchoring. |
| 202 element = base::MakeUnique<UiElement>(); | 161 element = base::MakeUnique<UiElement>(2); |
| 203 element->set_id(1); | 162 element->set_parent_id(1); |
| 204 element->set_parent_id(0); | |
| 205 element->set_x_anchoring(GetParam().x_anchoring); | 163 element->set_x_anchoring(GetParam().x_anchoring); |
| 206 element->set_y_anchoring(GetParam().y_anchoring); | 164 element->set_y_anchoring(GetParam().y_anchoring); |
| 207 scene.AddUiElement(std::move(element)); | 165 scene.AddUiElement(std::move(element)); |
| 208 | 166 |
| 209 scene.OnBeginFrame(usToTicks(0)); | 167 scene.OnBeginFrame(usToTicks(1)); |
| 210 const UiElement* child = scene.GetUiElementById(1); | 168 const UiElement* child = scene.GetUiElementById(2); |
| 211 EXPECT_NEAR(GetParam().expected_x, child->GetCenter().x(), TOLERANCE); | 169 EXPECT_NEAR(GetParam().expected_x, child->GetCenter().x(), TOLERANCE); |
| 212 EXPECT_NEAR(GetParam().expected_y, child->GetCenter().y(), TOLERANCE); | 170 EXPECT_NEAR(GetParam().expected_y, child->GetCenter().y(), TOLERANCE); |
| 213 scene.RemoveUiElement(1); | 171 scene.RemoveUiElement(2); |
| 214 } | 172 } |
| 215 | 173 |
| 216 const std::vector<AnchoringTestCase> anchoring_test_cases = { | 174 const std::vector<AnchoringTestCase> anchoring_test_cases = { |
| 217 {XAnchoring::XNONE, YAnchoring::YNONE, 0, 0}, | 175 {XAnchoring::XNONE, YAnchoring::YNONE, 0, 0}, |
| 218 {XAnchoring::XLEFT, YAnchoring::YNONE, -2, 0}, | 176 {XAnchoring::XLEFT, YAnchoring::YNONE, -2, 0}, |
| 219 {XAnchoring::XRIGHT, YAnchoring::YNONE, 2, 0}, | 177 {XAnchoring::XRIGHT, YAnchoring::YNONE, 2, 0}, |
| 220 {XAnchoring::XNONE, YAnchoring::YTOP, 0, 2}, | 178 {XAnchoring::XNONE, YAnchoring::YTOP, 0, 2}, |
| 221 {XAnchoring::XNONE, YAnchoring::YBOTTOM, 0, -2}, | 179 {XAnchoring::XNONE, YAnchoring::YBOTTOM, 0, -2}, |
| 222 {XAnchoring::XLEFT, YAnchoring::YTOP, -2, 2}, | 180 {XAnchoring::XLEFT, YAnchoring::YTOP, -2, 2}, |
| 223 }; | 181 }; |
| 224 | 182 |
| 225 INSTANTIATE_TEST_CASE_P(AnchoringTestCases, | 183 INSTANTIATE_TEST_CASE_P(AnchoringTestCases, |
| 226 AnchoringTest, | 184 AnchoringTest, |
| 227 ::testing::ValuesIn(anchoring_test_cases)); | 185 ::testing::ValuesIn(anchoring_test_cases)); |
| 228 | 186 |
| 229 } // namespace vr_shell | 187 } // namespace vr_shell |
| OLD | NEW |