-
Notifications
You must be signed in to change notification settings - Fork 4
/
UIManager.cs
275 lines (237 loc) · 9.77 KB
/
UIManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// based on a script from https://github.com/Unity-Technologies/arfoundation-samples/tree/2.1
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.XR.ARFoundation;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
[SerializeField]
[Tooltip("The ARCameraManager which will produce frame events.")]
ARCameraManager m_CameraManager;
/// <summary>
/// Get or set the <c>ARCameraManager</c>.
/// </summary>
public ARCameraManager cameraManager
{
get { return m_CameraManager; }
set
{
if (m_CameraManager == value)
return;
if (m_CameraManager != null)
m_CameraManager.frameReceived -= FrameChanged;
m_CameraManager = value;
if (m_CameraManager != null & enabled)
m_CameraManager.frameReceived += FrameChanged;
}
}
// アニメーションをフェードオフして消すトリガーとなるパラメータ名
const string k_FadeOffAnim = "FadeOff";
// アニメーションをフェードオンして表示するトリガーとなるパラメータ名
const string k_FadeOnAnim = "FadeOn";
[SerializeField]
ARPlaneManager m_PlaneManager;
public ARPlaneManager planeManager
{
get { return m_PlaneManager; }
set { m_PlaneManager = value; }
}
[SerializeField]
Animator m_MoveDeviceAnimation;
public Animator moveDeviceAnimation
{
get { return m_MoveDeviceAnimation; }
set { m_MoveDeviceAnimation = value; }
}
[SerializeField]
Animator m_TapToPlaceAnimation;
public Animator tapToPlaceAnimation
{
get { return m_TapToPlaceAnimation; }
set { m_TapToPlaceAnimation = value; }
}
public PlaceObject placeObject; // 子猫を配置するスクリプトコンポーネント
public BallControl ballControl; // ボールを配置するスクリプトコンポーネント
public FoodControl foodControl; // ごはんを配置するスクリプトコンポーネント
public InputField CloudAnchorIdField; // Cloud Anchor ID入力フィールド
static List<ARPlane> s_Planes = new List<ARPlane>();
// "Tap to Place"(タップして配置)ガイドの表示中を示すフラグ
bool m_ShowingTapToPlace = false;
// "Move Device Slowly"(端末をゆっくり動かす)ガイドの表示中を示すフラグ
bool m_ShowingMoveDevice = true;
int selectedIdx; // Dropdownで選択されたインデックス
// 起動時に1度呼び出される
void Start()
{
#if UNITY_EDITOR // Unityのエディタで実行する場合
if (moveDeviceAnimation)
moveDeviceAnimation.SetTrigger(k_FadeOffAnim);
// "Tap to Place" ガイドのアニメーションを表示する
if (tapToPlaceAnimation)
tapToPlaceAnimation.SetTrigger(k_FadeOnAnim);
m_ShowingTapToPlace = true;
m_ShowingMoveDevice = false;
#endif
// Cloud Anchor ID入力フィールドに入力された際に呼び出されるリスナーを登録
CloudAnchorIdField.onEndEdit.AddListener(OnInputEndEdit);
// Cloud Anchor ID入力フィールドは非表示にしておく
CloudAnchorIdField.gameObject.SetActive(false);
}
// Cloud Anchor ID入力フィールドに入力された際に呼び出されるリスナー
void OnInputEndEdit(string text)
{
// 入力されたIDに対応するCloud Anchorを取得する
// CloudAnchorIdField.gameObjectを渡してCloud Anchor取得完了時に
// 入力フィールドを非表示にしてもらう
placeObject.ResolveAnchor(text, CloudAnchorIdField.gameObject);
}
// オブジェクトが有効になった時に呼び出される
void OnEnable()
{
// カメラから新しいフレームを取得した際に呼び出されるコールバックとして登録する
if (m_CameraManager != null)
m_CameraManager.frameReceived += FrameChanged;
// 子猫を配置した際に呼び出されるコールバックとして登録する
PlaceObject.onPlacedObject += PlacedObject;
}
// オブジェクトが無効になった時に呼び出される
void OnDisable()
{
// カメラから新しいフレームを取得した際のコールバックを解除する
if (m_CameraManager != null)
m_CameraManager.frameReceived -= FrameChanged;
// 子猫を配置した際に呼び出されるコールバックを解除する
PlaceObject.onPlacedObject -= PlacedObject;
}
// カメラから新しいフレームを取得した際に呼び出されるコールバック用
void FrameChanged(ARCameraFrameEventArgs args)
{
// 平面を検出済みで且つ "Move Device" ガイドが表示中ならば
if (PlanesFound() && m_ShowingMoveDevice)
{
// "Move Device" ガイドのアニメーションを消す
if (moveDeviceAnimation)
moveDeviceAnimation.SetTrigger(k_FadeOffAnim);
// "Tap to Place" ガイドのアニメーションを表示する
if (tapToPlaceAnimation)
tapToPlaceAnimation.SetTrigger(k_FadeOnAnim);
m_ShowingTapToPlace = true;
m_ShowingMoveDevice = false;
}
}
// 平面を検出したか判断する
bool PlanesFound()
{
if (planeManager == null)
return false;
// 検出した平面の数が0より大きければ検出したと判断する
return planeManager.trackables.count > 0;
}
// 子猫を配置した際に呼び出されるコールバック用
void PlacedObject()
{
// "Tap to Place" ガイドが表示中ならば
if (m_ShowingTapToPlace)
{
// "Tap to Place" ガイドのアニメーションを消す
if (tapToPlaceAnimation)
tapToPlaceAnimation.SetTrigger(k_FadeOffAnim);
m_ShowingTapToPlace = false;
}
}
// タッチ位置を取得する
bool TryGetTouchPosition(out Vector2 touchPosition)
{
#if UNITY_EDITOR
// Unityエディターで実行される場合
if (Input.GetMouseButtonDown(0))
{
// UI要素をタップした際はAR空間のオブジェクトへのタップ通知が届かないようにする
if (EventSystem.current.IsPointerOverGameObject())
{
touchPosition = default;
Debug.Log("IsPointerOverGameObject");
return false;
}
// マウスボタンが押された位置を取得する
var mousePosition = Input.mousePosition;
touchPosition = new Vector2(mousePosition.x, mousePosition.y);
return true;
}
#else
// スマートフォンで実行される場合
if (Input.touchCount == 1)
{
// UI要素をタップした際はAR空間のオブジェクトへのタップ通知が届かないようにする
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) {
touchPosition = default;
Debug.Log("IsPointerOverGameObject");
return false;
}
var touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began) {
// 画面がタッチされた位置を取得する
touchPosition = touch.position;
return true;
}
}
#endif
touchPosition = default;
return false;
}
// 毎フレーム呼び出される
void Update()
{
// タッチされていない場合は処理をぬける
if (!TryGetTouchPosition(out Vector2 touchPosition))
{
return;
}
// "Move Device" ガイドが表示中ではない場合で
if (!m_ShowingMoveDevice)
{
if (m_ShowingTapToPlace)
{
// "Tap to Place" ガイドが表示中ならば
// 子猫のオブジェクトを配置する
placeObject.OnTouch(touchPosition);
} else
{
// "Tap to Place" ガイドが表示中ではないならば
// Dropdownで選択中の要素に対応する機能が呼び出される
SelectControl(selectedIdx, touchPosition);
}
}
}
// Dropdownの要素が選択された時に呼び出される
// 引数のidxに選択された番号が渡される
public void OnValueChanged(int idx)
{
selectedIdx = idx;
if (selectedIdx == 4)
{
// 4番目の要素が選択された際はCloud Anchor ID入力フィールドを表示状態にする
CloudAnchorIdField.gameObject.SetActive(true);
}
}
// Dropdownで選択中の要素に対応する機能が呼び出す
void SelectControl(int idx, Vector2 touchPosition)
{
switch (idx)
{
case 0: // 子猫を配置する
placeObject.OnTouch(touchPosition);
break;
case 1: // ご飯をあげる
foodControl.OnTouch(touchPosition);
break;
case 2: // ボールを配置して投げる
ballControl.OnTouch(touchPosition);
break;
case 3: // 子猫を配置してCloud Anchorに登録する
placeObject.OnTouch(touchPosition, true);
break;
}
}
}