WebViewPrefab.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /**
  2. * Copyright (c) 2021 Vuplex Inc. All rights reserved.
  3. *
  4. * Licensed under the Vuplex Commercial Software Library License, you may
  5. * not use this file except in compliance with the License. You may obtain
  6. * a copy of the License at
  7. *
  8. * https://vuplex.com/commercial-library-license
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. using UnityEngine;
  18. using UnityEngine.EventSystems;
  19. #if NET_4_6 || NET_STANDARD_2_0
  20. using System.Threading.Tasks;
  21. #endif
  22. namespace Vuplex.WebView
  23. {
  24. /// <summary>
  25. /// `WebViewPrefab` is a prefab that makes it easy to view and interact with web content in world space.
  26. /// It takes care of creating an `IWebView`, displaying its texture, and handling pointer interactions
  27. /// from the user (i.e. clicking, dragging, and scrolling). So, all you need to do is specify a URL or HTML to load,
  28. /// and then the user can view and interact with it. For use in a Canvas, see `CanvasWebViewPrefab` instead.
  29. /// </summary>
  30. /// <remarks>
  31. /// There are two ways to create a `WebViewPrefab`:
  32. /// 1. By dragging WebViewPrefab.prefab into your scene via the editor and then setting its "Initial URL" property.
  33. /// 2. Or by creating an instance programmatically with `WebViewPrefab.Instantiate()`, waiting for
  34. /// it to initialize, and then calling methods on its `WebView` property (like `webViewPrefab.WebView.LoadUrl("https://vuplex.com")`).
  35. ///
  36. /// `WebViewPrefab` handles standard events from Unity's input event system
  37. /// (like `IPointerDownHandler` and `IScrollHandler`), so it works with input modules that plug into the event system,
  38. /// like Unity's `StandaloneInputModule` and the Oculus `OVRInputModule`.
  39. ///
  40. /// If your use case requires a high degree of customization, you can instead create an `IWebView`
  41. /// outside of the prefab with `Web.CreateWebView()`.
  42. /// </remarks>
  43. [HelpURL("https://developer.vuplex.com/webview/WebViewPrefab")]
  44. public class WebViewPrefab : BaseWebViewPrefab
  45. {
  46. /// <summary>
  47. /// The prefab's collider.
  48. /// </summary>
  49. public Collider Collider
  50. {
  51. get
  52. {
  53. return _view.GetComponent<Collider>();
  54. }
  55. }
  56. /// <summary>
  57. /// Sets the webview's initial resolution in pixels per Unity unit.
  58. /// You can change the resolution to make web content appear larger or smaller.
  59. /// For more information on scaling web content, see
  60. /// [this support article](https://support.vuplex.com/articles/how-to-scale-web-content).
  61. /// </summary>
  62. [Label("Initial Resolution (px / Unity unit)")]
  63. [Tooltip("You can change this to make web content appear larger or smaller.")]
  64. [HideInInspector]
  65. public float InitialResolution = 1300;
  66. [Obsolete("The static WebViewPrefab.ScrollSensitivity property is obsolete. Please use one of the following instance properties instead: WebViewPrefab.ScrollingSensitivity or CanvasWebViewPrefab.ScrollingSensitivity.")]
  67. public static float ScrollSensitivity { get; set; }
  68. /// <summary>
  69. /// Allows the scroll sensitivity to be adjusted.
  70. /// The default sensitivity is 0.005.
  71. /// </summary>
  72. [HideInInspector]
  73. public float ScrollingSensitivity = 0.005f;
  74. [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
  75. public void Init() { }
  76. [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
  77. public void Init(float width, float height) { }
  78. /// <summary>
  79. /// Like `Init(float, float)`, except it also accepts an object
  80. /// of options flags that can be used to alter the webview's behavior.
  81. /// </summary>
  82. [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
  83. public void Init(float width, float height, WebViewOptions options) { }
  84. [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
  85. public void Init(IWebView webView) { }
  86. /// <summary>
  87. /// Converts the given world position to a normalized screen point.
  88. /// </summary>
  89. /// <returns>
  90. /// A point where the x and y components are normalized
  91. /// values between 0 and 1.
  92. /// </returns>
  93. public Vector2 ConvertToScreenPoint(Vector3 worldPosition)
  94. {
  95. var localPosition = _viewResizer.transform.InverseTransformPoint(worldPosition);
  96. return new Vector2(1 - localPosition.x, -1 * localPosition.y);
  97. }
  98. /// <summary>
  99. /// Resizes the prefab mesh and webview to the given dimensions in Unity units.
  100. /// </summary>
  101. /// <remarks>
  102. /// A webview's default resolution is 1300px per Unity unit but can be changed
  103. /// with `IWebView.SetResolution()`.
  104. /// </remarks>
  105. public void Resize(float width, float height)
  106. {
  107. if (_webView != null)
  108. {
  109. _webView.Resize(width, height);
  110. }
  111. _setViewSize(width, height);
  112. }
  113. WebViewOptions _optionsForInitialization;
  114. Vector2 _sizeForInitialization = Vector2.zero;
  115. [SerializeField]
  116. [HideInInspector]
  117. Transform _videoRectPositioner;
  118. [SerializeField]
  119. [HideInInspector]
  120. protected Transform _viewResizer;
  121. IWebView _webViewForInitialization;
  122. protected override Vector2 _convertRatioPointToUnityUnits(Vector2 point)
  123. {
  124. var unityUnitsX = _viewResizer.transform.localScale.x * point.x;
  125. var unityUnitsY = _viewResizer.transform.localScale.y * point.y;
  126. return new Vector2(unityUnitsX, unityUnitsY);
  127. }
  128. protected override float _getInitialResolution()
  129. {
  130. return InitialResolution;
  131. }
  132. protected override float _getScrollingSensitivity()
  133. {
  134. return ScrollingSensitivity;
  135. }
  136. protected override ViewportMaterialView _getVideoLayer()
  137. {
  138. return _videoRectPositioner.GetComponentInChildren<ViewportMaterialView>();
  139. }
  140. protected override ViewportMaterialView _getView()
  141. {
  142. return transform.Find("WebViewPrefabResizer/WebViewPrefabView").GetComponent<ViewportMaterialView>();
  143. }
  144. void _initWebViewPrefab()
  145. {
  146. #if VUPLEX_XR_INTERACTION_TOOLKIT
  147. WebViewLogger.LogWarning("It looks like you're using a WebViewPrefab with XR Interaction Toolkit. Please use a CanvasWebViewPrefab inside a world space Canvas instead. For more information, please see <em>https://support.vuplex.com/articles/xr-interaction-toolkit</em>.");
  148. #endif
  149. #if UNITY_ANDROID && UNITY_2018_2_OR_NEWER
  150. if (UnityEngine.Rendering.GraphicsSettings.useScriptableRenderPipelineBatching) {
  151. WebViewLogger.LogError("URP settings error: \"SRP Batcher\" is enabled in Universal Render Pipeline (URP) settings, but URP for Android has an issue that prevents 3D WebView's textures from showing up outside of a Canvas. Please either go to \"UniversalRenderPipelineAsset\" -> \"Advanced\" and disable SRP Batcher or switch to using CanvasWebViewPrefab.");
  152. }
  153. #endif
  154. if (_sizeForInitialization == Vector2.zero)
  155. {
  156. // The size was set via the editor instead of through arguments to Instantiate().
  157. _sizeForInitialization = transform.localScale;
  158. _resetLocalScale();
  159. }
  160. var width = _sizeForInitialization.x;
  161. var height = _sizeForInitialization.y;
  162. _viewResizer = transform.GetChild(0);
  163. _videoRectPositioner = _viewResizer.Find("VideoRectPositioner");
  164. _setViewSize(width, height);
  165. _init(width, height, _optionsForInitialization, _webViewForInitialization);
  166. }
  167. /// <summary>
  168. /// The top-level WebViewPrefab object's scale must be (1, 1),
  169. /// so the scale that was set via the editor is transferred from WebViewPrefab
  170. /// to WebViewPrefabResizer, and WebViewPrefab is moved to compensate
  171. /// for how WebViewPrefabResizer is moved in _setViewSize.
  172. /// </summary>
  173. void _resetLocalScale()
  174. {
  175. var localScale = transform.localScale;
  176. var localPosition = transform.localPosition;
  177. transform.localScale = new Vector3(1, 1, localScale.z);
  178. var offsetMagnitude = 0.5f * localScale.x;
  179. transform.localPosition = transform.localPosition + Quaternion.Euler(transform.localEulerAngles) * new Vector3(offsetMagnitude, 0, 0);
  180. }
  181. protected override void _setVideoLayerPosition(Rect videoRect)
  182. {
  183. // The origins of the prefab and the video rect are in their top-right
  184. // corners instead of their top-left corners.
  185. _videoRectPositioner.localPosition = new Vector3(
  186. 1 - (videoRect.x + videoRect.width),
  187. -1 * videoRect.y,
  188. _videoRectPositioner.localPosition.z
  189. );
  190. _videoRectPositioner.localScale = new Vector3(videoRect.width, videoRect.height, _videoRectPositioner.localScale.z);
  191. }
  192. void _setViewSize(float width, float height)
  193. {
  194. var depth = _viewResizer.localScale.z;
  195. _viewResizer.localScale = new Vector3(width, height, depth);
  196. var localPosition = _viewResizer.localPosition;
  197. // Set the view resizer so that its middle aligns with the middle of this parent class's gameobject.
  198. localPosition.x = width * -0.5f;
  199. _viewResizer.localPosition = localPosition;
  200. }
  201. void Start()
  202. {
  203. _initWebViewPrefab();
  204. }
  205. }
  206. }