1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/vr/windows_mixed_reality/wrappers/wmr_wrapper_factories.h"
6
7 #include <HolographicSpaceInterop.h>
8 #include <SpatialInteractionManagerInterop.h>
9 #include <windows.perception.h>
10 #include <windows.perception.spatial.h>
11 #include <wrl.h>
12
13 #include "base/strings/string_util.h"
14 #include "base/win/core_winrt_util.h"
15 #include "base/win/scoped_hstring.h"
16 #include "device/vr/windows_mixed_reality/mixed_reality_statics.h"
17 #include "device/vr/windows_mixed_reality/wrappers/test/mock_wmr_holographic_space.h"
18 #include "device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_manager.h"
19 #include "device/vr/windows_mixed_reality/wrappers/test/mock_wmr_origins.h"
20 #include "device/vr/windows_mixed_reality/wrappers/wmr_logging.h"
21
22 namespace WFN = ABI::Windows::Foundation::Numerics;
23 using SpatialMovementRange =
24 ABI::Windows::Perception::Spatial::SpatialMovementRange;
25 using ABI::Windows::Foundation::IEventHandler;
26 using ABI::Windows::Foundation::IReference;
27 using ABI::Windows::Graphics::Holographic::IHolographicSpace;
28 using ABI::Windows::Perception::Spatial::ISpatialAnchor;
29 using ABI::Windows::Perception::Spatial::ISpatialAnchorStatics;
30 using ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem;
31 using ABI::Windows::Perception::Spatial::ISpatialLocator;
32 using ABI::Windows::Perception::Spatial::
33 ISpatialLocatorAttachedFrameOfReference;
34 using ABI::Windows::Perception::Spatial::ISpatialLocatorStatics;
35 using ABI::Windows::Perception::Spatial::ISpatialStageFrameOfReference;
36 using ABI::Windows::Perception::Spatial::ISpatialStageFrameOfReferenceStatics;
37 using ABI::Windows::Perception::Spatial::ISpatialStationaryFrameOfReference;
38 using ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager;
39 using Microsoft::WRL::ComPtr;
40
41 namespace {
GetSpatialLocator()42 ComPtr<ISpatialLocator> GetSpatialLocator() {
43 ComPtr<ISpatialLocatorStatics> spatial_locator_statics;
44 base::win::ScopedHString spatial_locator_string =
45 base::win::ScopedHString::Create(
46 RuntimeClass_Windows_Perception_Spatial_SpatialLocator);
47 HRESULT hr = base::win::RoGetActivationFactory(
48 spatial_locator_string.get(), IID_PPV_ARGS(&spatial_locator_statics));
49 if (FAILED(hr)) {
50 device::WMRLogging::TraceError(device::WMRErrorLocation::kGetSpatialLocator,
51 hr);
52 return nullptr;
53 }
54
55 ComPtr<ISpatialLocator> locator;
56 hr = spatial_locator_statics->GetDefault(&locator);
57 if (FAILED(hr)) {
58 device::WMRLogging::TraceError(device::WMRErrorLocation::kGetSpatialLocator,
59 hr);
60 return nullptr;
61 }
62
63 return locator;
64 }
65 } // anonymous namespace
66
67 namespace device {
68
69 std::unique_ptr<WMRStationaryOrigin>
CreateAtCurrentLocation()70 WMRStationaryOriginFactory::CreateAtCurrentLocation() {
71 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
72 return std::make_unique<MockWMRStationaryOrigin>();
73 }
74
75 ComPtr<ISpatialLocator> locator = GetSpatialLocator();
76 if (!locator)
77 return nullptr;
78
79 ComPtr<ISpatialStationaryFrameOfReference> origin;
80 HRESULT hr =
81 locator->CreateStationaryFrameOfReferenceAtCurrentLocation(&origin);
82 if (FAILED(hr)) {
83 WMRLogging::TraceError(WMRErrorLocation::kStationaryReferenceCreation, hr);
84 return nullptr;
85 }
86
87 return std::make_unique<WMRStationaryOriginImpl>(origin);
88 }
89
90 std::unique_ptr<WMRAttachedOrigin>
CreateAtCurrentLocation()91 WMRAttachedOriginFactory::CreateAtCurrentLocation() {
92 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
93 return std::make_unique<MockWMRAttachedOrigin>();
94 }
95
96 ComPtr<ISpatialLocator> locator = GetSpatialLocator();
97 if (!locator)
98 return nullptr;
99
100 ComPtr<ISpatialLocatorAttachedFrameOfReference> origin;
101 HRESULT hr = locator->CreateAttachedFrameOfReferenceAtCurrentHeading(&origin);
102 if (FAILED(hr)) {
103 WMRLogging::TraceError(WMRErrorLocation::kAttachedReferenceCreation, hr);
104 return nullptr;
105 }
106
107 return std::make_unique<WMRAttachedOriginImpl>(origin);
108 }
109
Create()110 std::unique_ptr<WMRStageStatics> WMRStageStaticsFactory::Create() {
111 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
112 return std::make_unique<MockWMRStageStatics>();
113 }
114
115 ComPtr<ISpatialStageFrameOfReferenceStatics> stage_statics;
116 base::win::ScopedHString spatial_stage_string =
117 base::win::ScopedHString::Create(
118 RuntimeClass_Windows_Perception_Spatial_SpatialStageFrameOfReference);
119 HRESULT hr = base::win::RoGetActivationFactory(spatial_stage_string.get(),
120 IID_PPV_ARGS(&stage_statics));
121 if (FAILED(hr))
122 return nullptr;
123
124 return std::make_unique<WMRStageStaticsImpl>(stage_statics);
125 }
126
127 std::unique_ptr<WMRCoordinateSystem>
TryCreateRelativeTo(WMRCoordinateSystem * origin)128 WMRSpatialAnchorFactory::TryCreateRelativeTo(WMRCoordinateSystem* origin) {
129 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
130 MockWMRStationaryOrigin origin;
131 return origin.CoordinateSystem();
132 }
133
134 ComPtr<ISpatialAnchorStatics> anchor_statics;
135 base::win::ScopedHString spatial_anchor_string =
136 base::win::ScopedHString::Create(
137 RuntimeClass_Windows_Perception_Spatial_SpatialAnchor);
138 HRESULT hr = base::win::RoGetActivationFactory(spatial_anchor_string.get(),
139 IID_PPV_ARGS(&anchor_statics));
140 if (FAILED(hr))
141 return nullptr;
142
143 ComPtr<ISpatialAnchor> anchor;
144 hr = anchor_statics->TryCreateRelativeTo(origin->GetRawPtr(), &anchor);
145 if (FAILED(hr) || !anchor)
146 return nullptr;
147
148 // Make a WMRCoordinateSystemImpl wrapping the coordinate system.
149 ComPtr<ISpatialCoordinateSystem> coordinate_system;
150 hr = anchor->get_CoordinateSystem(&coordinate_system);
151 DCHECK(SUCCEEDED(hr));
152 return std::make_unique<WMRCoordinateSystemImpl>(coordinate_system);
153 }
154
GetForWindow(HWND hwnd)155 std::unique_ptr<WMRInputManager> WMRInputManagerFactory::GetForWindow(
156 HWND hwnd) {
157 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
158 return std::make_unique<MockWMRInputManager>();
159 }
160 if (!hwnd)
161 return nullptr;
162
163 ComPtr<ISpatialInteractionManagerInterop> spatial_interaction_interop;
164 base::win::ScopedHString spatial_interaction_interop_string =
165 base::win::ScopedHString::Create(
166 RuntimeClass_Windows_UI_Input_Spatial_SpatialInteractionManager);
167 HRESULT hr = base::win::RoGetActivationFactory(
168 spatial_interaction_interop_string.get(),
169 IID_PPV_ARGS(&spatial_interaction_interop));
170 if (FAILED(hr))
171 return nullptr;
172
173 ComPtr<ISpatialInteractionManager> manager;
174 hr = spatial_interaction_interop->GetForWindow(hwnd, IID_PPV_ARGS(&manager));
175 if (FAILED(hr))
176 return nullptr;
177
178 return std::make_unique<WMRInputManagerImpl>(manager);
179 }
180
181 std::unique_ptr<WMRHolographicSpace>
CreateForWindow(HWND hwnd)182 WMRHolographicSpaceFactory::CreateForWindow(HWND hwnd) {
183 if (MixedRealityDeviceStatics::ShouldUseMocks()) {
184 return std::make_unique<MockWMRHolographicSpace>();
185 }
186 if (!hwnd)
187 return nullptr;
188
189 ComPtr<IHolographicSpaceInterop> holographic_space_interop;
190 base::win::ScopedHString holographic_space_string =
191 base::win::ScopedHString::Create(
192 RuntimeClass_Windows_Graphics_Holographic_HolographicSpace);
193 HRESULT hr = base::win::RoGetActivationFactory(
194 holographic_space_string.get(), IID_PPV_ARGS(&holographic_space_interop));
195
196 if (FAILED(hr))
197 return nullptr;
198
199 ComPtr<IHolographicSpace> holographic_space;
200 hr = holographic_space_interop->CreateForWindow(
201 hwnd, IID_PPV_ARGS(&holographic_space));
202
203 if (FAILED(hr))
204 return nullptr;
205
206 return std::make_unique<WMRHolographicSpaceImpl>(holographic_space);
207 }
208
209 } // namespace device
210