forked from microsoft/MixedRealityToolkit-Unity
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathApplicationViewManager.cs
142 lines (137 loc) · 5.63 KB
/
ApplicationViewManager.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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System;
using System.Collections;
using UnityEngine;
#if !UNITY_EDITOR && UNITY_WSA
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#endif
namespace HoloToolkit.Unity
{
public delegate void ReturnValueCallback<TReturnValue>(TReturnValue returnValue);
/// <summary>
/// ApplicationViewManager ( For XAML UWP project) can switch app to Plan View, populate an Application View (New Window of UAP),
/// then navigate the Window root frame to a page.
/// After the page's logic called 'CallbackReturnValue' method, the newly created Application View will be closed, and the system will switch back to your Full3D view.
/// The coroutine which was waiting the callback will get the return value.
/// </summary>
public class ApplicationViewManager : MonoBehaviour
{
private void Start()
{
#if !UNITY_EDITOR && UNITY_WSA
UnityEngine.WSA.Application.InvokeOnUIThread(
() =>
{
Full3DViewId = ApplicationView.GetForCurrentView().Id;
}, true);
#endif
}
#if !UNITY_EDITOR && UNITY_WSA
static int Full3DViewId { get; set; }
static System.Collections.Concurrent.ConcurrentDictionary<int, Action<object>> CallbackDictionary
= new System.Collections.Concurrent.ConcurrentDictionary<int, Action<object>>();
#endif
/// <summary>
/// Call this method with Application View Dispatcher, or in Application View Thread, will return to Full3D View and close Application View
/// </summary>
/// <param name="returnValue">The return value of the XAML View Execution</param>
#if !UNITY_EDITOR && UNITY_WSA
public static async void CallbackReturnValue(object returnValue)
{
var viewId = ApplicationView.GetForCurrentView().Id;
var view = CoreApplication.GetCurrentView();
if (CallbackDictionary.TryRemove(viewId, out var cb))
{
try
{
cb(returnValue);
}
catch (Exception)
{
}
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(ApplicationViewManager.Full3DViewId).AsTask();
view.CoreWindow.Close();
}
}
#else
public static void CallbackReturnValue(object returnValue)
{
}
#endif
/// <summary>
/// Call this method in Unity App Thread can switch to Plan View, create and show a new XAML View.
/// </summary>
/// <typeparam name="TReturnValue"></typeparam>
/// <param name="xamlPageName"></param>
/// <param name="callback"></param>
/// <returns></returns>
public IEnumerator OnLaunchXamlView<TReturnValue>(string xamlPageName, Action<TReturnValue> callback, object pageNavigateParameter = null)
{
bool isCompleted = false;
#if !UNITY_EDITOR && UNITY_WSA
object returnValue = null;
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
var dispt = newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//This happens when User switch view back to Main App manually
void CoreWindow_VisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs args)
{
if (args.Visible == false)
{
CallbackReturnValue(null);
}
}
newView.CoreWindow.VisibilityChanged += CoreWindow_VisibilityChanged;
Frame frame = new Frame();
var pageType = Type.GetType(Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName.Replace(".App,", $".{xamlPageName},"));
var appv = ApplicationView.GetForCurrentView();
newViewId = appv.Id;
var cb = new Action<object>(rval =>
{
returnValue = rval;
isCompleted = true;
});
frame.Navigate(pageType,pageNavigateParameter);
CallbackDictionary[newViewId] = cb;
Window.Current.Content = frame;
Window.Current.Activate();
}).AsTask();
yield return new WaitUntil(() => dispt.IsCompleted || dispt.IsCanceled || dispt.IsFaulted);
Task viewShownTask = null;
UnityEngine.WSA.Application.InvokeOnUIThread(
() =>
{
viewShownTask = ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId).AsTask();
},
true);
yield return new WaitUntil(() => viewShownTask.IsCompleted || viewShownTask.IsCanceled || viewShownTask.IsFaulted);
yield return new WaitUntil(() => isCompleted);
try
{
if (returnValue is TReturnValue)
{
callback?.Invoke((TReturnValue)returnValue);
}
else
{
callback?.Invoke(default(TReturnValue));
}
}
catch (Exception ex)
{
Debug.LogError(ex);
}
#else
isCompleted = true;
yield return new WaitUntil(() => isCompleted);
#endif
}
}
}