/** * Copyright (c) 2021 Vuplex Inc. All rights reserved. * * Licensed under the Vuplex Commercial Software Library License, you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * https://vuplex.com/commercial-library-license * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using UnityEngine; using UnityEngine.EventSystems; #if NET_4_6 || NET_STANDARD_2_0 using System.Threading.Tasks; #endif namespace Vuplex.WebView { /// /// `WebViewPrefab` is a prefab that makes it easy to view and interact with web content in world space. /// It takes care of creating an `IWebView`, displaying its texture, and handling pointer interactions /// from the user (i.e. clicking, dragging, and scrolling). So, all you need to do is specify a URL or HTML to load, /// and then the user can view and interact with it. For use in a Canvas, see `CanvasWebViewPrefab` instead. /// /// /// There are two ways to create a `WebViewPrefab`: /// 1. By dragging WebViewPrefab.prefab into your scene via the editor and then setting its "Initial URL" property. /// 2. Or by creating an instance programmatically with `WebViewPrefab.Instantiate()`, waiting for /// it to initialize, and then calling methods on its `WebView` property (like `webViewPrefab.WebView.LoadUrl("https://vuplex.com")`). /// /// `WebViewPrefab` handles standard events from Unity's input event system /// (like `IPointerDownHandler` and `IScrollHandler`), so it works with input modules that plug into the event system, /// like Unity's `StandaloneInputModule` and the Oculus `OVRInputModule`. /// /// If your use case requires a high degree of customization, you can instead create an `IWebView` /// outside of the prefab with `Web.CreateWebView()`. /// [HelpURL("https://developer.vuplex.com/webview/WebViewPrefab")] public class WebViewPrefab : BaseWebViewPrefab { /// /// The prefab's collider. /// public Collider Collider { get { return _view.GetComponent(); } } /// /// Sets the webview's initial resolution in pixels per Unity unit. /// You can change the resolution to make web content appear larger or smaller. /// For more information on scaling web content, see /// [this support article](https://support.vuplex.com/articles/how-to-scale-web-content). /// [Label("Initial Resolution (px / Unity unit)")] [Tooltip("You can change this to make web content appear larger or smaller.")] [HideInInspector] public float InitialResolution = 1300; [Obsolete("The static WebViewPrefab.ScrollSensitivity property is obsolete. Please use one of the following instance properties instead: WebViewPrefab.ScrollingSensitivity or CanvasWebViewPrefab.ScrollingSensitivity.")] public static float ScrollSensitivity { get; set; } /// /// Allows the scroll sensitivity to be adjusted. /// The default sensitivity is 0.005. /// [HideInInspector] public float ScrollingSensitivity = 0.005f; [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)] public void Init() { } [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)] public void Init(float width, float height) { } /// /// Like `Init(float, float)`, except it also accepts an object /// of options flags that can be used to alter the webview's behavior. /// [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)] public void Init(float width, float height, WebViewOptions options) { } [Obsolete("WebViewPrefab.Init() has been removed. The WebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)] public void Init(IWebView webView) { } /// /// Converts the given world position to a normalized screen point. /// /// /// A point where the x and y components are normalized /// values between 0 and 1. /// public Vector2 ConvertToScreenPoint(Vector3 worldPosition) { var localPosition = _viewResizer.transform.InverseTransformPoint(worldPosition); return new Vector2(1 - localPosition.x, -1 * localPosition.y); } /// /// Resizes the prefab mesh and webview to the given dimensions in Unity units. /// /// /// A webview's default resolution is 1300px per Unity unit but can be changed /// with `IWebView.SetResolution()`. /// public void Resize(float width, float height) { if (_webView != null) { _webView.Resize(width, height); } _setViewSize(width, height); } WebViewOptions _optionsForInitialization; Vector2 _sizeForInitialization = Vector2.zero; [SerializeField] [HideInInspector] Transform _videoRectPositioner; [SerializeField] [HideInInspector] protected Transform _viewResizer; IWebView _webViewForInitialization; protected override Vector2 _convertRatioPointToUnityUnits(Vector2 point) { var unityUnitsX = _viewResizer.transform.localScale.x * point.x; var unityUnitsY = _viewResizer.transform.localScale.y * point.y; return new Vector2(unityUnitsX, unityUnitsY); } protected override float _getInitialResolution() { return InitialResolution; } protected override float _getScrollingSensitivity() { return ScrollingSensitivity; } protected override ViewportMaterialView _getVideoLayer() { return _videoRectPositioner.GetComponentInChildren(); } protected override ViewportMaterialView _getView() { return transform.Find("WebViewPrefabResizer/WebViewPrefabView").GetComponent(); } void _initWebViewPrefab() { #if VUPLEX_XR_INTERACTION_TOOLKIT 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 https://support.vuplex.com/articles/xr-interaction-toolkit."); #endif #if UNITY_ANDROID && UNITY_2018_2_OR_NEWER if (UnityEngine.Rendering.GraphicsSettings.useScriptableRenderPipelineBatching) { 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."); } #endif if (_sizeForInitialization == Vector2.zero) { // The size was set via the editor instead of through arguments to Instantiate(). _sizeForInitialization = transform.localScale; _resetLocalScale(); } var width = _sizeForInitialization.x; var height = _sizeForInitialization.y; _viewResizer = transform.GetChild(0); _videoRectPositioner = _viewResizer.Find("VideoRectPositioner"); _setViewSize(width, height); _init(width, height, _optionsForInitialization, _webViewForInitialization); } /// /// The top-level WebViewPrefab object's scale must be (1, 1), /// so the scale that was set via the editor is transferred from WebViewPrefab /// to WebViewPrefabResizer, and WebViewPrefab is moved to compensate /// for how WebViewPrefabResizer is moved in _setViewSize. /// void _resetLocalScale() { var localScale = transform.localScale; var localPosition = transform.localPosition; transform.localScale = new Vector3(1, 1, localScale.z); var offsetMagnitude = 0.5f * localScale.x; transform.localPosition = transform.localPosition + Quaternion.Euler(transform.localEulerAngles) * new Vector3(offsetMagnitude, 0, 0); } protected override void _setVideoLayerPosition(Rect videoRect) { // The origins of the prefab and the video rect are in their top-right // corners instead of their top-left corners. _videoRectPositioner.localPosition = new Vector3( 1 - (videoRect.x + videoRect.width), -1 * videoRect.y, _videoRectPositioner.localPosition.z ); _videoRectPositioner.localScale = new Vector3(videoRect.width, videoRect.height, _videoRectPositioner.localScale.z); } void _setViewSize(float width, float height) { var depth = _viewResizer.localScale.z; _viewResizer.localScale = new Vector3(width, height, depth); var localPosition = _viewResizer.localPosition; // Set the view resizer so that its middle aligns with the middle of this parent class's gameobject. localPosition.x = width * -0.5f; _viewResizer.localPosition = localPosition; } void Start() { _initWebViewPrefab(); } } }