WebOverlayItem.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using NRKernal.NRExamples;
  5. namespace NRKernal.Experimental.NRExamples
  6. {
  7. public class WebOverlayItem : MonoBehaviour
  8. {
  9. [Tooltip("The Overlay used to draw the webpage.")]
  10. [SerializeField] NROverlay m_WebOverlay;
  11. [Tooltip("The close button.")]
  12. [SerializeField] NRInteractiveItem m_CloseBtn;
  13. [Tooltip("Used to obtain the touch coordinates of the screen.")]
  14. [SerializeField] InteractiveScreen m_InteractiveScreen;
  15. [Tooltip("Url of webpage.")]
  16. [SerializeField] string URL;
  17. public enum WebState
  18. {
  19. Normal,
  20. XRMode
  21. }
  22. private AndroidWebViewPlayer m_WebViewPlayer;
  23. public event Action OnClose;
  24. private GameObject m_OverlayObj;
  25. private bool isInSwitchingMode = false;
  26. private NRDataSourceProvider m_SourceProvider;
  27. private const int DefaultLayerWidth = 1920;
  28. private const int DefaultLayerHeight = 1080;
  29. void OnEnable()
  30. {
  31. m_OverlayObj = m_WebOverlay.gameObject;
  32. m_WebOverlay.externalSurfaceObjectCreated += InitWebSurface;
  33. m_InteractiveScreen.onUpdateTouchState += UpdateTouchState;
  34. m_CloseBtn.onPointerClick.AddListener(Close);
  35. }
  36. void OnDisable()
  37. {
  38. m_WebOverlay.externalSurfaceObjectCreated -= InitWebSurface;
  39. m_InteractiveScreen.onUpdateTouchState -= UpdateTouchState;
  40. m_CloseBtn.onPointerClick.RemoveListener(Close);
  41. }
  42. // Update touch data of webview.
  43. private void UpdateTouchState(InteractiveScreen.TouchState touchstate)
  44. {
  45. if (m_WebViewPlayer != null)
  46. {
  47. m_WebViewPlayer.UpdateTouchState(touchstate.touchPoint, touchstate.timeStamp, touchstate.isTouching);
  48. }
  49. }
  50. private void InitWebSurface()
  51. {
  52. NRDebugger.Info("[OverlayWebViewExample] OnLayerCreated.");
  53. var surfaceJo = m_WebOverlay.GetSurfaceId();
  54. if (surfaceJo == IntPtr.Zero)
  55. {
  56. NRDebugger.Error("[OverlayWebViewExample] Init videosurface failed!");
  57. return;
  58. }
  59. if (m_WebViewPlayer == null)
  60. {
  61. m_WebViewPlayer = new AndroidWebViewPlayer();
  62. m_SourceProvider = new NRDataSourceProvider();
  63. m_WebViewPlayer.Initialize(
  64. surfaceJo,
  65. m_SourceProvider,
  66. OnDrawBegin,
  67. OnDrawEnd,
  68. OnImmersiveStart,
  69. OnImmersiveEnd
  70. );
  71. m_WebViewPlayer.LoadURL(URL);
  72. }
  73. }
  74. // When the web page starts drawing.
  75. private void OnDrawBegin(Int64 nanos, int index) { }
  76. // When the web page ends drawing.
  77. private void OnDrawEnd(Int64 nanos, int index)
  78. {
  79. if (isInSwitchingMode ||
  80. (NRSessionManager.Instance.NRRenderer != null && NRSessionManager.Instance.NRRenderer.CurrentState != NRRenderer.RendererState.Running))
  81. {
  82. return;
  83. }
  84. Pose pose = Pose.identity;
  85. // Update the surface of overlay.
  86. if (!m_SourceProvider.GetCachePoseByTime(nanos, ref pose))
  87. {
  88. NRFrame.GetHeadPoseByTime(ref pose, (ulong)nanos);
  89. }
  90. NativeMat4f matrix = NativeMat4f.identity;
  91. ConversionUtility.UnityPoseToApiPose(pose, out matrix);
  92. m_WebOverlay.UpdateExternalSurface(matrix, nanos, index);
  93. }
  94. // When enterd vrmode of webxr page.
  95. private void OnImmersiveStart()
  96. {
  97. NRDebugger.Info("[OverlayWebViewExample] OnImmersiveStart");
  98. MainThreadDispather.QueueOnMainThread(() =>
  99. {
  100. StartCoroutine(SwitchSurface(WebState.XRMode));
  101. });
  102. }
  103. // When exited vrmode of webxr page.
  104. private void OnImmersiveEnd()
  105. {
  106. NRDebugger.Info("[WebOverlay] OnImmersiveEnd");
  107. MainThreadDispather.QueueOnMainThread(() =>
  108. {
  109. StartCoroutine(SwitchSurface(WebState.Normal));
  110. });
  111. }
  112. private IEnumerator SwitchSurface(WebState state)
  113. {
  114. NRDebugger.Info("[WebOverlay] Start switch web surface:" + state.ToString());
  115. isInSwitchingMode = true;
  116. if (m_WebOverlay != null)
  117. {
  118. GameObject.DestroyImmediate(m_WebOverlay);
  119. }
  120. m_WebOverlay = CreateOverlayByMode(state);
  121. Action<IntPtr> onSurfaceCreated = null;
  122. AsyncTask<IntPtr> createSurfaceTask = new AsyncTask<IntPtr>(out onSurfaceCreated);
  123. m_WebOverlay.externalSurfaceObjectCreated += () =>
  124. {
  125. onSurfaceCreated?.Invoke(m_WebOverlay.GetSurfaceId());
  126. };
  127. // Wait for the surface object of current overlay is created.
  128. yield return createSurfaceTask.WaitForCompletion();
  129. if (m_WebViewPlayer == null)
  130. {
  131. this.InitWebSurface();
  132. }
  133. else
  134. {
  135. // Switch the surface of webview.
  136. m_WebViewPlayer.SetSurface(m_WebOverlay.GetSurfaceId(), true);
  137. }
  138. isInSwitchingMode = false;
  139. NRDebugger.Info("[WebOverlay] End switch web surface:" + state.ToString());
  140. }
  141. public void Reset(WebState state)
  142. {
  143. if (m_WebOverlay == null)
  144. {
  145. return;
  146. }
  147. NRDebugger.Info("[WebOverlay] Reset Overlay ByMode...");
  148. AppyOverlayAttributes(m_WebOverlay, state);
  149. }
  150. private void AppyOverlayAttributes(NROverlay overlay, WebState state)
  151. {
  152. switch (state)
  153. {
  154. case WebState.Normal:
  155. overlay.isExternalSurface = true;
  156. overlay.externalSurfaceWidth = DefaultLayerWidth;
  157. overlay.externalSurfaceHeight = DefaultLayerHeight;
  158. overlay.is3DLayer = false;
  159. overlay.sourceUVRect[0] = new Rect(0, 0, 1, 1);
  160. overlay.sourceUVRect[1] = new Rect(0, 0, 1, 1);
  161. overlay.Apply();
  162. break;
  163. case WebState.XRMode:
  164. overlay.isExternalSurface = true;
  165. overlay.externalSurfaceWidth = 2 * DefaultLayerWidth;
  166. overlay.externalSurfaceHeight = DefaultLayerHeight;
  167. // Set the params of overlay to display the webxr page which entered vrmode.
  168. overlay.is3DLayer = true;
  169. // Left display uv.
  170. overlay.sourceUVRect[0] = new Rect(0, 0, 0.5f, 1f);
  171. // Right display uv.
  172. overlay.sourceUVRect[1] = new Rect(0.5f, 0, 0.5f, 1f);
  173. overlay.Apply();
  174. break;
  175. default:
  176. break;
  177. }
  178. }
  179. private NROverlay CreateOverlayByMode(WebState state)
  180. {
  181. NRDebugger.Info("[WebOverlay] Create Overlay ByMode...");
  182. NROverlay overlay = m_OverlayObj.AddComponent<NROverlay>();
  183. AppyOverlayAttributes(overlay, state);
  184. return overlay;
  185. }
  186. public void Close()
  187. {
  188. m_WebViewPlayer?.Close();
  189. GameObject.Destroy(gameObject);
  190. OnClose?.Invoke();
  191. }
  192. }
  193. }