// Copyright (c) 2025 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 System.Threading.Tasks; using UnityEngine; using Vuplex.WebView; namespace Vuplex.Demos { /// /// Sets up the AdvancedWebViewDemo scene, which displays web content in a main /// world-space WebViewPrefab and renders a UI in a second webview to display the current URL /// and provide back / forward navigation controls.

/// /// Note: The address bar currently only displays the current URL and is not an input. /// I plan to add a dedicated browser prefab in the future that will include /// a functional address bar. In the meantime, you can edit the CONTROLS_HTML field /// below to implement a URL input. ///
/// /// This scene demonstrates the following:
/// - Programmatically instantiating WebViewPrefabs at runtime
/// - Programmatically instantiating an on-screen Keyboard prefab
/// - Using IWebView methods like LoadUrl(), LoadHtml(), GoBack(), and GoForward()
/// - Attaching handlers to the IWebView.UrlChanged and MessageEmitted events
/// - Sending messages from JavaScript to C# and vice versa
/// - Creating a transparent webview using the transparent meta tag

/// /// Links:
/// - WebViewPrefab docs: https://developer.vuplex.com/webview/WebViewPrefab
/// - Sending messages from JavaScript to C# and vice versa: https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp
/// - How to make a transparent webview: https://support.vuplex.com/articles/how-to-make-a-webview-transparent
/// - How clicking works: https://support.vuplex.com/articles/clicking
/// - Other examples: https://developer.vuplex.com/webview/overview#examples
///
class AdvancedWebViewDemo : MonoBehaviour { WebViewPrefab controlsWebViewPrefab; WebViewPrefab mainWebViewPrefab; async void Start() { Debug.Log("[AdvancedWebViewDemo] Just a heads-up: this scene's address bar currently only displays the current URL and is not an input. For more info, please see the comments in AdvancedWebViewDemo.cs."); // Use a desktop User-Agent to request the desktop versions of websites. // https://developer.vuplex.com/webview/Web#SetUserAgent Web.SetUserAgent(false); // Instantiate a 0.6 x 0.3 webview for the main web content. // https://developer.vuplex.com/webview/WebViewPrefab#Instantiate mainWebViewPrefab = WebViewPrefab.Instantiate(0.6f, 0.3f); mainWebViewPrefab.PixelDensity = 2; mainWebViewPrefab.transform.parent = transform; mainWebViewPrefab.transform.localPosition = new Vector3(0, -0.05f, 0.4f); mainWebViewPrefab.transform.localEulerAngles = new Vector3(0, 180, 0); // Instantiate a second webview above the first to show a UI that // displays the current URL and provides back / forward navigation buttons. controlsWebViewPrefab = WebViewPrefab.Instantiate(0.6f, 0.05f); controlsWebViewPrefab.KeyboardEnabled = false; controlsWebViewPrefab.transform.parent = mainWebViewPrefab.transform; controlsWebViewPrefab.transform.localPosition = new Vector3(0, 0.06f, 0); controlsWebViewPrefab.transform.localEulerAngles = Vector3.zero; // Add an on-screen keyboard under the main webview. // https://developer.vuplex.com/webview/Keyboard var keyboard = Keyboard.Instantiate(); keyboard.transform.SetParent(mainWebViewPrefab.transform, false); keyboard.transform.localPosition = new Vector3(0, -0.31f, 0); keyboard.transform.localEulerAngles = Vector3.zero; // Wait for the prefabs to initialize because the WebView property of each is null until then. // https://developer.vuplex.com/webview/WebViewPrefab#WaitUntilInitialized await Task.WhenAll(new Task[] { mainWebViewPrefab.WaitUntilInitialized(), controlsWebViewPrefab.WaitUntilInitialized() }); // Now that the WebViewPrefabs are initialized, we can use the IWebView APIs via its WebView property. // https://developer.vuplex.com/webview/IWebView mainWebViewPrefab.WebView.UrlChanged += (sender, eventArgs) => { _setDisplayedUrl(eventArgs.Url); // Refresh the back / forward button state after 1 second. Invoke("_refreshBackForwardState", 1); }; mainWebViewPrefab.WebView.LoadUrl("https://www.google.com"); controlsWebViewPrefab.WebView.MessageEmitted += Controls_MessageEmitted; controlsWebViewPrefab.WebView.LoadHtml(CONTROLS_HTML); await controlsWebViewPrefab.WebView.WaitForNextPageLoadToFinish(); _setDisplayedUrl(mainWebViewPrefab.WebView.Url); // Android Gecko and UWP w/ XR enabled don't support transparent webviews, so as a workaround, // configure the shader to turn black pixels transparent. var pluginType = controlsWebViewPrefab.WebView.PluginType; if (pluginType == WebPluginType.AndroidGecko || pluginType == WebPluginType.UniversalWindowsPlatform) { controlsWebViewPrefab.SetRenderBlackAsTransparent(true); } } async void _refreshBackForwardState() { // Get the main webview's back / forward state and then post a message // to the controls UI to update its buttons' state. var canGoBack = await mainWebViewPrefab.WebView.CanGoBack(); var canGoForward = await mainWebViewPrefab.WebView.CanGoForward(); var serializedMessage = $"{{ \"type\": \"SET_BUTTONS\", \"canGoBack\": {canGoBack.ToString().ToLowerInvariant()}, \"canGoForward\": {canGoForward.ToString().ToLowerInvariant()} }}"; controlsWebViewPrefab.WebView.PostMessage(serializedMessage); } void Controls_MessageEmitted(object sender, EventArgs eventArgs) { var message = eventArgs.Value; if (message == "GO_BACK") { mainWebViewPrefab.WebView.GoBack(); } else if (message == "GO_FORWARD") { mainWebViewPrefab.WebView.GoForward(); } } void _setDisplayedUrl(string url) { if (controlsWebViewPrefab.WebView != null) { var serializedMessage = $"{{ \"type\": \"SET_URL\", \"url\": \"{url}\" }}"; controlsWebViewPrefab.WebView.PostMessage(serializedMessage); } } const string CONTROLS_HTML = @"
"; } }