UrhoAppView.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using System;
  2. using System.Numerics;
  3. using System.Runtime.InteropServices;
  4. using System.Threading.Tasks;
  5. using Windows.ApplicationModel;
  6. using Windows.ApplicationModel.Activation;
  7. using Windows.ApplicationModel.Core;
  8. using Windows.Graphics.Holographic;
  9. using Windows.Perception.Spatial;
  10. using Windows.UI.Core;
  11. using Windows.UI.Input.Spatial;
  12. namespace Urho.SharpReality
  13. {
  14. public class UrhoAppView : IFrameworkView, IDisposable
  15. {
  16. Type holoAppType;
  17. ApplicationOptions options;
  18. CoreWindow window;
  19. bool windowVisible = true;
  20. bool windowClosed;
  21. bool appInited;
  22. public HolographicFrame CurrentFrame { get; private set; }
  23. public HolographicSpace HolographicSpace { get; private set; }
  24. public StereoApplication Game { get; private set; }
  25. public SpatialInteractionManager InteractionManager { get; private set; }
  26. public SpatialGestureRecognizer SpatialGerstureRecognizer { get; private set; }
  27. public SpatialStationaryFrameOfReference ReferenceFrame { get; private set; }
  28. public GesturesManager GesturesManager { get; private set; }
  29. public SpatialMappingManager SpatialMappingManager { get; private set; }
  30. public VoiceManager VoiceManager { get; private set; }
  31. public static UrhoAppView Current { get; private set; }
  32. UrhoAppView(Type holoAppType, ApplicationOptions opts)
  33. {
  34. this.holoAppType = holoAppType;
  35. this.options = opts;
  36. this.windowVisible = true;
  37. Current = this;
  38. }
  39. public static UrhoAppView Create<T>(ApplicationOptions opts) where T : StereoApplication
  40. {
  41. return new UrhoAppView(typeof(T), opts);
  42. }
  43. public void Dispose()
  44. {
  45. Disposed?.Invoke();
  46. }
  47. public event Action<CoreApplicationView> Initialized;
  48. public event Action Uninitialized;
  49. public event Action Disposed;
  50. public event Action<CoreWindow> WindowIsSet;
  51. public event Action<string> Loaded;
  52. public event Action AppStarting;
  53. public event Action<StereoApplication> AppStarted;
  54. #region IFrameworkView Members
  55. /// <summary>
  56. /// The first method called when the IFrameworkView is being created.
  57. /// Use this method to subscribe for Windows shell events and to initialize your app.
  58. /// </summary>
  59. public void Initialize(CoreApplicationView applicationView)
  60. {
  61. Initialized?.Invoke(applicationView);
  62. applicationView.Activated += this.OnViewActivated;
  63. CoreApplication.Suspending += this.OnSuspending;
  64. CoreApplication.Resuming += this.OnResuming;
  65. }
  66. /// <summary>
  67. /// Called when the CoreWindow object is created (or re-created).
  68. /// </summary>
  69. public void SetWindow(CoreWindow coreWindow)
  70. {
  71. window = coreWindow;
  72. window.KeyDown += OnKeyDown;
  73. window.KeyUp += OnKeyUp;
  74. window.Closed += OnWindowClosed;
  75. window.VisibilityChanged += OnVisibilityChanged;
  76. HolographicSpace = HolographicSpace.CreateForCoreWindow(window);
  77. WindowIsSet?.Invoke(window);
  78. }
  79. void OnKeyUp(CoreWindow sender, KeyEventArgs args)
  80. {
  81. // Sdl.SendKeyboardEvent(SdlKeyState.SDL_RELEASED, (int)args.KeyStatus.ScanCode);
  82. }
  83. void OnKeyDown(CoreWindow sender, KeyEventArgs args)
  84. {
  85. // Sdl.SendKeyboardEvent(SdlKeyState.SDL_PRESSED, (int)args.KeyStatus.ScanCode);
  86. }
  87. /// <summary>
  88. /// The Load method can be used to initialize scene resources or to load a
  89. /// previously saved app state.
  90. /// </summary>
  91. public void Load(string entryPoint)
  92. {
  93. Loaded?.Invoke(entryPoint);
  94. }
  95. [DllImport(Consts.NativeImport, CallingConvention = CallingConvention.Cdecl)]
  96. static extern void InitializeSpace();
  97. public unsafe void Run()
  98. {
  99. AppStarting?.Invoke();
  100. ReferenceFrame = SpatialLocator.GetDefault().CreateStationaryFrameOfReferenceAtCurrentLocation();
  101. var coreWindow = CoreWindow.GetForCurrentThread();
  102. coreWindow.CustomProperties.Add(nameof(HolographicSpace), HolographicSpace);
  103. InitializeSpace();
  104. HolographicSpace.CameraAdded += HolographicSpace_CameraAdded;
  105. InteractionManager = SpatialInteractionManager.GetForCurrentView();
  106. if (InteractionManager != null)
  107. InteractionManager.InteractionDetected += (s, e) => GesturesManager?.HandleInteraction(e.Interaction);
  108. while (!windowClosed)
  109. {
  110. if (appInited && windowVisible && (null != HolographicSpace))
  111. {
  112. if (Game != null)
  113. {
  114. CurrentFrame = HolographicSpace.CreateNextFrame();
  115. CurrentFrame.UpdateCurrentPrediction();
  116. var prediction = CurrentFrame.CurrentPrediction;
  117. if (prediction.CameraPoses.Count < 1)
  118. continue;
  119. var cameraPose = prediction.CameraPoses[0];
  120. var viewBox = cameraPose.TryGetViewTransform(ReferenceFrame.CoordinateSystem);
  121. if (viewBox != null)
  122. {
  123. Matrix4x4 leftViewMatrixDx = viewBox.Value.Left;
  124. Matrix4x4 rightViewMatrixDx = viewBox.Value.Right;
  125. Matrix4x4 leftProjMatrixDx = cameraPose.ProjectionTransform.Left;
  126. Matrix4x4 rightProjMatrixDx = cameraPose.ProjectionTransform.Right;
  127. Matrix4 leftViewMatrixUrho = *(Matrix4*)(void*)&leftViewMatrixDx;
  128. Matrix4 rightViewMatrixUrho = *(Matrix4*)(void*)&rightViewMatrixDx;
  129. Matrix4 leftProjMatrixUrho = *(Matrix4*)(void*)&leftProjMatrixDx;
  130. Matrix4 rightProjMatrixUrho = *(Matrix4*)(void*)&rightProjMatrixDx;
  131. Game.UpdateStereoView(leftViewMatrixUrho, rightViewMatrixUrho, leftProjMatrixUrho, rightProjMatrixUrho);
  132. }
  133. var parameters = CurrentFrame.GetRenderingParameters(cameraPose);
  134. if (Game.FocusWorldPoint != Vector3.Zero)
  135. parameters.SetFocusPoint(ReferenceFrame.CoordinateSystem,
  136. new System.Numerics.Vector3(
  137. Game.FocusWorldPoint.X,
  138. Game.FocusWorldPoint.Y,
  139. -Game.FocusWorldPoint.Z)); //LH->RH
  140. Game.Engine.RunFrame();
  141. CurrentFrame.PresentUsingCurrentPrediction(HolographicFramePresentWaitBehavior.WaitForFrameToFinish);
  142. }
  143. CoreWindow.GetForCurrentThread().Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);
  144. }
  145. else
  146. {
  147. CoreWindow.GetForCurrentThread().Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessOneAndAllPending);
  148. }
  149. }
  150. }
  151. async void HolographicSpace_CameraAdded(HolographicSpace sender, HolographicSpaceCameraAddedEventArgs args)
  152. {
  153. if (!appInited)
  154. {
  155. await window.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
  156. {
  157. SpatialMappingManager = new SpatialMappingManager();
  158. VoiceManager = new VoiceManager();
  159. if (options == null)
  160. options = new ApplicationOptions();
  161. //override some options:
  162. options.LimitFps = false;
  163. options.Width = (int)args.Camera.RenderTargetSize.Width;
  164. options.Height = (int)args.Camera.RenderTargetSize.Height;
  165. Game = (StereoApplication)Activator.CreateInstance(holoAppType, options);
  166. Game.Run();
  167. GesturesManager = new GesturesManager(Game, ReferenceFrame);
  168. AppStarted?.Invoke(Game);
  169. appInited = true;
  170. });
  171. }
  172. }
  173. /// <summary>
  174. /// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
  175. /// class is torn down while the app is in the foreground.
  176. // This method is not often used, but IFrameworkView requires it and it will be called for
  177. // holographic apps.
  178. /// </summary>
  179. public void Uninitialize()
  180. {
  181. Uninitialized?.Invoke();
  182. }
  183. #endregion
  184. #region Application lifecycle event handlers
  185. /// <summary>
  186. /// Called when the app view is activated. Activates the app's CoreWindow.
  187. /// </summary>
  188. void OnViewActivated(CoreApplicationView sender, IActivatedEventArgs args)
  189. {
  190. // Run() won't start until the CoreWindow is activated.
  191. sender.CoreWindow.Activate();
  192. }
  193. void OnSuspending(object sender, SuspendingEventArgs args)
  194. {
  195. // Sdl.SendWindowEvent(SdlWindowEvent.SDL_WINDOWEVENT_HIDDEN);
  196. // Save app state asynchronously after requesting a deferral. Holding a deferral
  197. // indicates that the application is busy performing suspending operations. Be
  198. // aware that a deferral may not be held indefinitely; after about five seconds,
  199. // the app will be forced to exit.
  200. var deferral = args.SuspendingOperation.GetDeferral();
  201. Task.Run(() => deferral.Complete());
  202. }
  203. void OnResuming(object sender, object args)
  204. {
  205. // Sdl.SendWindowEvent(SdlWindowEvent.SDL_WINDOWEVENT_RESTORED);
  206. }
  207. #endregion;
  208. #region Window event handlers
  209. void OnVisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs args)
  210. {
  211. windowVisible = args.Visible;
  212. }
  213. void OnWindowClosed(CoreWindow sender, CoreWindowEventArgs arg)
  214. {
  215. windowClosed = true;
  216. }
  217. #endregion
  218. }
  219. }