7 using System.Collections.Generic;
8 using System.Collections.ObjectModel;
12 namespace HoloToolkit.Examples.SpatialUnderstandingFeatureOverview
17 public const float MenuWidth = 1.5f;
18 public const float MenuHeight = 1.0f;
19 public const float MenuMinDepth = 2.0f;
36 public List<Button> GridButtons =
new List<Button>();
43 public LayerMask UILayerMask;
46 public bool HasPlacedMenu {
get;
private set; }
48 public Panels ActivePanel {
get;
private set; }
51 private DateTime timeLastQuery = DateTime.MinValue;
52 private bool placedMenuNeedsBillboard =
false;
58 ParentCanvas.gameObject.SetActive(
false);
74 private void OnScanStateChanged()
87 StartCoroutine(SetupMenu());
91 private IEnumerator SetupMenu()
103 #if UNITY_EDITOR || !UNITY_WSA 104 new System.Threading.Thread
106 System.Threading.Tasks.Task.Run
119 placementResult = null;
123 #if UNITY_EDITOR || !UNITY_WSA 129 #
if UNITY_EDITOR || !UNITY_WSA
130 !thread.Join(TimeSpan.Zero)
138 if (placementResult != null)
140 Debug.Log(
"PlaceMenu - ObjectSolver-OnWall");
141 Vector3 posOnWall = placementResult.Position - placementResult.Forward * MenuMinDepth * 0.5f;
142 PlaceMenu(posOnWall, -placementResult.Forward);
152 resultsTopology.Length, resultsTopologyPtr);
153 if (locationCount > 0)
155 Debug.Log(
"PlaceMenu - LargestPositionsOnFloor");
157 Vector3 menuPosition = menuLocation.
position + Vector3.up * MenuHeight;
158 Vector3 menuLookVector = cameraTransform.position - menuPosition;
159 PlaceMenu(menuPosition, (
new Vector3(menuLookVector.x, 0.0f, menuLookVector.z)).normalized,
true);
166 Vector3 defaultPosition = cameraTransform.position + cameraTransform.forward * 2.0f;
167 PlaceMenu(
new Vector3(defaultPosition.x, Math.Max(defaultPosition.y, alignment.FloorYValue + 1.5f), defaultPosition.z), (
new Vector3(cameraTransform.forward.x, 0.0f, cameraTransform.forward.z)).normalized,
true);
168 Debug.Log(
"PlaceMenu - InFrontOfUser");
171 private void SetActiveTab(
Panels panel)
175 timeLastQuery = DateTime.MinValue;
181 private void Update_Colors()
183 const float TimeToFadeAfterQuery = 3.0f;
186 float timeSinceQuery = (float)(DateTime.Now - timeLastQuery).TotalSeconds;
187 float alphaScale = Mathf.SmoothStep(0.0f, 1.0f, Mathf.Clamp01(timeSinceQuery - TimeToFadeAfterQuery)) * 0.8f + 0.2f;
190 Color colorButtonActive =
new Color(1.0f, 1.0f, 1.0f, 0.8f * alphaScale);
191 Color colorButtonInactive =
new Color(1.0f, 1.0f, 1.0f, 0.25f * alphaScale);
192 Color colorPanelActive =
new Color(1.0f, 1.0f, 1.0f, 0.6f * alphaScale);
193 Color colorPanelInactive =
new Color(1.0f, 1.0f, 1.0f, 0.15f * alphaScale);
196 for (
int i = 0; i < (int)
Panels.PANEL_COUNT; ++i)
198 bool isEnabled = (i == (int)ActivePanel);
200 ButtonPanels[i].ButtonImage.color = isEnabled ? colorButtonActive : colorButtonInactive;
201 ButtonPanels[i].Background.enabled = isEnabled;
202 ButtonPanels[i].Background.color = isEnabled ? colorPanelActive : colorPanelInactive;
203 ButtonPanels[i].ButtonGrid.enabled = isEnabled;
205 for (
int j = 0; j < ButtonPanels[i].GridButtons.Count; ++j)
207 ButtonPanels[i].GridButtons[j].gameObject.SetActive(isEnabled);
212 private void SetupMenus()
215 ButtonPanels[(int)
Panels.Topology].Button.GetComponentInChildren<Text>().text =
"Topology Queries";
216 ButtonPanels[(int)
Panels.Topology].Button.onClick.AddListener(() => { SetActiveTab(Panels.Topology); });
217 AddButton(
"Position on wall",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindPositionOnWall(); timeLastQuery = DateTime.MinValue; });
218 AddButton(
"Large positions on wall",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindLargePositionsOnWalls(); timeLastQuery = DateTime.MinValue; });
219 AddButton(
"Largest wall",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindLargeWall(); timeLastQuery = DateTime.MinValue; });
220 AddButton(
"Positions on floor",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindPositionsOnFloor(); timeLastQuery = DateTime.MinValue; });
221 AddButton(
"Large positions on floor",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindLargestPositionsOnFloor(); timeLastQuery = DateTime.MinValue; });
222 AddButton(
"Place objects positions",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindPositionsPlaceable(); timeLastQuery = DateTime.MinValue; });
223 AddButton(
"Large positions sittable",
Panels.Topology, () => { SpaceVisualizer.Instance.Query_Topology_FindLargePositionsSittable(); timeLastQuery = DateTime.MinValue; });
226 ButtonPanels[(int)
Panels.Shapes].Button.GetComponentInChildren<Text>().text =
"Shape Queries";
227 ButtonPanels[(int)
Panels.Shapes].Button.onClick.AddListener(() => { SetActiveTab(Panels.Shapes); });
229 for (
int i = 0; i < customShapes.Count; ++i)
231 string shapeName = customShapes[i];
232 AddButton(shapeName,
Panels.Shapes, () =>
234 SpaceVisualizer.Instance.Query_Shape_FindShapeHalfDims(shapeName);
235 timeLastQuery = DateTime.MinValue;
240 ButtonPanels[(int)
Panels.LevelSolver].Button.GetComponentInChildren<Text>().text =
"Object Placement";
241 ButtonPanels[(int)
Panels.LevelSolver].Button.onClick.AddListener(() => { SetActiveTab(Panels.LevelSolver); timeLastQuery = DateTime.MinValue; });
242 AddButton(
"On Floor",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnFloor(); timeLastQuery = DateTime.MinValue; });
243 AddButton(
"On Wall",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnWall(); timeLastQuery = DateTime.MinValue; });
244 AddButton(
"On Ceiling",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnCeiling(); timeLastQuery = DateTime.MinValue; });
245 AddButton(
"On SurfaceEdge",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnEdge(); timeLastQuery = DateTime.MinValue; });
246 AddButton(
"On FloorAndCeiling",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnFloorAndCeiling(); timeLastQuery = DateTime.MinValue; });
247 AddButton(
"RandomInAir AwayFromMe",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_RandomInAir_AwayFromMe(); timeLastQuery = DateTime.MinValue; });
248 AddButton(
"OnEdge NearCenter",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnEdge_NearCenter(); timeLastQuery = DateTime.MinValue; });
249 AddButton(
"OnFloor AwayFromMe",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnFloor_AwayFromMe(); timeLastQuery = DateTime.MinValue; });
250 AddButton(
"OnFloor NearMe",
Panels.LevelSolver, () => { LevelSolver.Instance.Query_OnFloor_NearMe(); timeLastQuery = DateTime.MinValue; });
253 SetActiveTab(
Panels.Topology);
256 private void AddButton(
string text,
Panels panel,
UnityEngine.Events.UnityAction action)
258 Button button = Instantiate(PrefabButton);
259 button.GetComponentInChildren<Text>().text = text;
260 button.transform.SetParent(ButtonPanels[(
int)panel].ButtonGrid.transform,
false);
261 button.transform.localScale = Vector3.one;
262 button.onClick.AddListener(action);
264 ButtonPanels[(int)panel].GridButtons.Add(button);
267 private void PlaceMenu(Vector3 position, Vector3 normal,
bool needsBillboarding =
false)
270 position -= normal * 0.05f;
271 Quaternion rotation = Quaternion.LookRotation(normal, Vector3.up);
274 transform.position = position;
275 transform.rotation = rotation;
281 ParentCanvas.gameObject.SetActive(
true);
284 MenuAnimatedBox =
new AnimatedBox(0.0f, position, rotation,
new Color(1.0f, 1.0f, 1.0f, 0.25f),
new Vector3(MenuWidth * 0.5f, MenuHeight * 0.5f, 0.025f),
LineDrawer.
DefaultLineWidth * 0.5f);
287 transform.position = MenuAnimatedBox.AnimPosition.Evaluate(MenuAnimatedBox.Time);
288 transform.rotation = MenuAnimatedBox.Rotation * Quaternion.AngleAxis(360.0f * MenuAnimatedBox.AnimRotation.Evaluate(MenuAnimatedBox.Time), Vector3.up);
291 placedMenuNeedsBillboard = needsBillboarding;
294 HasPlacedMenu =
true;
297 private void Update()
302 if (MenuAnimatedBox != null)
305 MenuAnimatedBox.Update(Time.deltaTime);
308 if (MenuAnimatedBox.IsAnimationComplete &&
309 placedMenuNeedsBillboard)
312 transform.position = MenuAnimatedBox.AnimPosition.Evaluate(MenuAnimatedBox.Time);
313 Vector3 lookDirTarget =
CameraCache.
Main.transform.position - transform.position;
314 lookDirTarget = (
new Vector3(lookDirTarget.x, 0.0f, lookDirTarget.z)).normalized;
315 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(-lookDirTarget), Time.deltaTime * 10.0f);
320 transform.position = MenuAnimatedBox.AnimPosition.Evaluate(MenuAnimatedBox.Time);
321 transform.rotation = MenuAnimatedBox.Rotation * Quaternion.AngleAxis(360.0f * MenuAnimatedBox.AnimRotation.Evaluate(MenuAnimatedBox.Time), Vector3.up);