This commit is contained in:
黄嘉宇 2024-05-23 10:13:54 +08:00
parent f6a5646d44
commit bf0efcd1a2
314 changed files with 1 additions and 20505 deletions

View File

@ -1 +1 @@
Build from ADAM at 2024/5/22 16:57:32
Build from LGZN_H at 2024/5/23 10:13:34

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e1af6d7538e0c4382940c502ac857197
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3f61b635b575947e9abfac04cb82067f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d81ee1045c91f4c79852f85367eb106a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e419cc8c4878947a5971402dbdec76f0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1038a3399a6af4c639c0851aede5495f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,78 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: MockViewportMaterial
m_Shader: {fileID: 10750, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: -1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 9f7b60728c99d4fe6b67e0d86b1e7b5e, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 10
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 0
- _Metallic: 0
- _Mode: 3
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 0
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 0
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1b0611231af614f7b91169ff83a790cd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: cc28f1f6b8abe41dba1a8aba8c0b501d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,196 +0,0 @@
// Copyright (c) 2023 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.
#if UNITY_ANDROID
#pragma warning disable CS0618
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.Rendering;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView.Editor {
public static class AndroidEditorUtils {
public static void PreprocessBuild(string productName, string proguardRulesExpectedRelativePath, string nativeLibraryName, bool native2DSupported) {
_validateGraphicsApi(native2DSupported);
_forceInternetPermission();
_assertThatOculusLowOverheadModeIsDisabled();
_assertThatSrpBatcherIsDisabled();
_updateNativePluginSettings(nativeLibraryName);
_updateProguardFileIfNeeded(productName, proguardRulesExpectedRelativePath);
}
/// <summary>
/// Updates the proguard-user.txt file if needed to prevent the names of 3D WebView's Java classes from being obfuscated.
/// https://support.vuplex.com/articles/android-minification
/// </summary>
static void _updateProguardFileIfNeeded(string productName, string neededProguardRulesExpectedRelativePath) {
var minificationEnabled = false;
// minifyDebug and minifyRelease were added in 2020.1.
#if UNITY_2020_1_OR_NEWER
minificationEnabled = EditorUserBuildSettings.development ? PlayerSettings.Android.minifyDebug : PlayerSettings.Android.minifyRelease;
#endif
if (!minificationEnabled) {
return;
}
var neededProguardRulesFilePath = EditorUtils.FindFile(Path.Combine(Application.dataPath, neededProguardRulesExpectedRelativePath));
var neededProguardRules = File.ReadAllText(neededProguardRulesFilePath);
// Note: the prefix and suffix avoid using characters considered special characters in regexes, like parentheses.
var prefix = $"# --- Start of section automatically included for {productName} - PLEASE DO NOT EDIT ---";
var suffix = $"# --- End of section for {productName} ---";
var fullTextToAdd = $"{prefix}\n{neededProguardRules}\n{suffix}";
var androidPluginsFolderPath = Path.Combine(Application.dataPath, "Plugins", "Android");
var proguardUserFilePath = Path.Combine(androidPluginsFolderPath, "proguard-user.txt");
var proguardUserFileExists = File.Exists(proguardUserFilePath);
if (proguardUserFileExists) {
var existingFileText = File.ReadAllText(proguardUserFilePath);
var existingWebViewProguardRulesRegex = new Regex($"{prefix}.*{suffix}", RegexOptions.Singleline);
var existingWebViewProguardRulesResult = existingWebViewProguardRulesRegex.Match(existingFileText);
if (existingWebViewProguardRulesResult.Success) {
if (existingWebViewProguardRulesResult.Value != fullTextToAdd) {
// The proguard-user.txt file contains an older version of the rules, so update them.
var newFileText = existingFileText.Replace(existingWebViewProguardRulesResult.Value, fullTextToAdd);
File.WriteAllText(proguardUserFilePath, newFileText);
}
} else {
// A proguard-user.txt file exists, but it doesn't include the rules yet, so add them.
var newFileText = existingFileText + "\n\n" + fullTextToAdd;
File.WriteAllText(proguardUserFilePath, newFileText);
}
} else {
// No proguard-user.txt file exists yet, so create the file.
Directory.CreateDirectory(androidPluginsFolderPath);
File.WriteAllText(proguardUserFilePath, fullTextToAdd);
}
}
static void _assertThatSrpBatcherIsDisabled() {
#if UNITY_2018_2_OR_NEWER && !VUPLEX_DISABLE_SRP_WARNING
// Checking renderPipelineAsset is needed to verify that URP is enabled because useScriptableRenderPipelineBatching
// can sometimes be true even when the built-in render pipeline is in use.
if (GraphicsSettings.useScriptableRenderPipelineBatching && GraphicsSettings.renderPipelineAsset != null) {
throw new BuildFailedException("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. If the project uses a WebViewPrefab, please go to the URP Asset and disable \"SRP Batcher\". In newer versions of URP, it's necessary to click \"Show Additional Properties\" in order to show the SRP Batcher option, like described here: https://docs.unity3d.com/2021.3/Documentation/Manual/SRPBatcher.html . If the project only uses CanvasWebViewPrefab and not WebViewPrefab, you can instead add the scripting symbol VUPLEX_DISABLE_SRP_WARNING to the project to ignore this warning.");
}
#endif
}
static void _assertThatOculusLowOverheadModeIsDisabled() {
if (!EditorUtils.XRSdkIsEnabled("oculus")) {
return;
}
var lowOverheadModeEnabled = false;
#if VUPLEX_OCULUS
// The Oculus XR plugin is installed
Unity.XR.Oculus.OculusLoader oculusLoader = Unity.XR.Oculus.OculusSettings.CreateInstance<Unity.XR.Oculus.OculusLoader>();
Unity.XR.Oculus.OculusSettings oculusSettings = oculusLoader.GetSettings();
lowOverheadModeEnabled = oculusSettings.LowOverheadMode;
#elif UNITY_2019_2_OR_NEWER && !UNITY_2020_1_OR_NEWER
// VROculus.lowOverheadMode is only supported from Unity 2019.2 - 2019.4
lowOverheadModeEnabled = PlayerSettings.VROculus.lowOverheadMode;
#endif
if (lowOverheadModeEnabled) {
throw new BuildFailedException("XR settings error: Vuplex 3D WebView requires that \"Low Overhead Mode\" be disabled in Oculus XR settings. Please disable Low Overhead Mode in Oculus XR settings.");
}
}
static void _forceInternetPermission() {
#if !VUPLEX_ANDROID_DISABLE_REQUIRE_INTERNET
if (!PlayerSettings.Android.forceInternetPermission) {
PlayerSettings.Android.forceInternetPermission = true;
WebViewLogger.LogWarning("Just a heads-up: 3D WebView changed the Android player setting \"Internet Access\" to \"Require\" to ensure that it can fetch web pages from the internet. (This message will only be logged once.)");
}
#endif
}
static void _updateNativePluginSettings(string fileName) {
#if UNITY_2019_1_OR_NEWER
var pluginAbsolutePaths = Directory.GetFiles(Application.dataPath, fileName, SearchOption.AllDirectories).ToList();
// PluginImporter.GetAtPath() requires a relative path and doesn't support absolute paths.
var pluginRelativePaths = pluginAbsolutePaths.Select(path => path.Replace(Application.dataPath, "Assets"));
foreach (var filePath in pluginRelativePaths) {
var pluginImporter = (PluginImporter)PluginImporter.GetAtPath(filePath);
var changedSettings = false;
// Set the libVuplexWebViewAndroid.so or libVuplexWebViewAndroidGecko.so plugin files to be preloaded, which is equivalent to
// enabling their "Load on Startup" checkbox. This is done via a script because the .meta files
// for these plugins was generated with an older version of Unity in order to be compatible with
// 2018.4, which doesn't support the preload option. Enabling preloading is required for Vulkan support.
if (!pluginImporter.isPreloaded) {
pluginImporter.isPreloaded = true;
changedSettings = true;
}
// Unity 2020.3 and newer support x86_64 for Chrome OS. 3D WebView ships x86_64 libraries, but they
// are initially disabled because older versions of Unity can't handle if "CPU" is set to "X86_64".
// So, we enable those x86_64 libraries dynamically here.
#if UNITY_2020_3_OR_NEWER
if (filePath.Contains("x86_64")) {
if (!pluginImporter.GetCompatibleWithPlatform(BuildTarget.Android)) {
pluginImporter.SetCompatibleWithPlatform(BuildTarget.Android, true);
changedSettings = true;
}
if (pluginImporter.GetPlatformData(BuildTarget.Android, "CPU") != "X86_64") {
pluginImporter.SetPlatformData(BuildTarget.Android, "CPU", "X86_64");
changedSettings = true;
}
}
#endif
if (changedSettings) {
pluginImporter.SaveAndReimport();
}
}
#endif
}
static void _validateGraphicsApi(bool native2DSupported) {
#if !VUPLEX_DISABLE_GRAPHICS_API_WARNING
var autoGraphicsApiEnabled = PlayerSettings.GetUseDefaultGraphicsAPIs(BuildTarget.Android);
var selectedGraphicsApi = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android)[0];
var vulkanEnabled = selectedGraphicsApi == GraphicsDeviceType.Vulkan;
if (!(vulkanEnabled || autoGraphicsApiEnabled)) {
// OpenGLES is selected, so nothing to warn about.
return;
}
var warningPrefix = autoGraphicsApiEnabled ? "Auto Graphics API is enabled in Player Settings, which means that the Vulkan Graphics API may be used."
: "The Vulkan Graphics API is enabled in Player Settings.";
#if UNITY_2020_2_OR_NEWER
// At build time, XRSettings.enabled is always false, so to check if XR is enabled,
// we must instead check whether XRSettings.supportedDevices[0] != "None".
var xrDevices = VXUtils.XRSettings.supportedDevices;
var xrIsEnabled = xrDevices.Length > 0 && xrDevices[0] != "None";
if (!xrIsEnabled) {
WebViewLogger.LogWarning($"{warningPrefix} 3D WebView for Android supports Vulkan, but{(native2DSupported ? " unless the application only uses webviews in Native 2D Mode, then" : "")} the target Android devices must support the Vulkan extension VK_ANDROID_external_memory_android_hardware_buffer. That extension is supported on newer devices like Oculus Quest but isn't supported on all Android phones that support Vulkan. If your application is intended for general Android phones, it's recommended to{(native2DSupported ? " either only use Native 2D Mode or to" : "")} change the project's selected Graphics API to OpenGLES in Player Settings.{(native2DSupported ? " If your application is already only using Native 2D Mode, then please ignore this message." : "")} For more details, please see this page: <em>https://support.vuplex.com/articles/vulkan#android</em>");
}
#if !UNITY_2022_1_OR_NEWER
if (PlayerSettings.GetMobileMTRendering(BuildTargetGroup.Android)) {
WebViewLogger.LogWarning("Your project has Multithreaded Rendering and Vulkan enabled with a version of Unity older than 2022.1, which may cause web rendering to appear jittery. Unity 2022.1 or newer is recommended if your project requires Multithreaded Rendering to be enabled. For more details, please see this page: <em>https://support.vuplex.com/articles/vulkan</em>");
}
#endif
#else
throw new BuildFailedException(warningPrefix + " 3D WebView for Android requires Unity 2020.2 or newer in order to support Vulkan. So, please either upgrade to a newer version of Unity or change the selected Graphics API to OpenGLES in Player Settings.");
#endif
#endif
}
}
}
#endif

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: dd041d4a8ab324bc2899621ed1b3e5d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,108 +0,0 @@
// Copyright (c) 2023 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 UnityEditor;
namespace Vuplex.WebView.Editor {
public abstract class BaseWebViewPrefabInspector : UnityEditor.Editor {
public virtual void OnEnable() {
_clickingEnabled = serializedObject.FindProperty("ClickingEnabled");
_cursorIconsEnabled = serializedObject.FindProperty("CursorIconsEnabled");
_dragMode = serializedObject.FindProperty("DragMode");
_dragThreshold = serializedObject.FindProperty("DragThreshold");
_hoveringEnabled = serializedObject.FindProperty("HoveringEnabled");
_keyboardEnabled = serializedObject.FindProperty("KeyboardEnabled");
_logConsoleMessages = serializedObject.FindProperty("LogConsoleMessages");
_resolution = serializedObject.FindProperty("Resolution");
_initialUrl = serializedObject.FindProperty("InitialUrl");
_nativeOnScreenKeyboardEnabled = serializedObject.FindProperty("NativeOnScreenKeyboardEnabled");
_pixelDensity = serializedObject.FindProperty("PixelDensity");
_remoteDebuggingEnabled = serializedObject.FindProperty("RemoteDebuggingEnabled");
_scrollingEnabled = serializedObject.FindProperty("ScrollingEnabled");
_scrollingSensitivity = serializedObject.FindProperty("ScrollingSensitivity");
}
public override void OnInspectorGUI() {
DocumentationLinkDrawer.DrawDocumentationLink(_getDocumentationLink());
EditorGUILayout.Space();
serializedObject.Update();
EditorGUILayout.PropertyField(_initialUrl);
EditorGUILayout.PropertyField(_resolution);
EditorGUILayout.PropertyField(_dragMode);
EditorGUILayout.PropertyField(_keyboardEnabled);
EditorGUILayout.Space();
_renderCustomPlatformSpecificSettings();
EditorGUILayout.PropertyField(_nativeOnScreenKeyboardEnabled);
EditorGUILayout.PropertyField(_pixelDensity);
EditorGUILayout.PropertyField(_cursorIconsEnabled);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_remoteDebuggingEnabled);
EditorGUILayout.PropertyField(_logConsoleMessages);
EditorUtils.DrawLink("Troubleshooting help", "https://developer.vuplex.com/webview/troubleshooting", 24);
EditorUtils.DrawLink("Remote debugging help", "https://support.vuplex.com/articles/how-to-debug-web-content", 27);
EditorGUILayout.Space();
EditorGUILayout.Space();
#if UNITY_2019_1_OR_NEWER
// BeginFoldoutHeaderGroup and EndFoldoutHeaderGroup only exist in Unity 2019.1 and newer.
_showOtherSettings = EditorGUILayout.BeginFoldoutHeaderGroup(_showOtherSettings, "Other settings");
#else
// Fallback to creating a label for the section.
_showOtherSettings = true;
var style = new UnityEngine.GUIStyle { fontStyle = UnityEngine.FontStyle.Bold };
style.normal.textColor = EditorGUIUtility.isProSkin ? new UnityEngine.Color(0.77f, 0.77f, 0.77f) : UnityEngine.Color.black;
EditorGUILayout.LabelField("Other settings", style);
#endif
if (_showOtherSettings) {
_renderCustomOtherSettings();
EditorGUILayout.PropertyField(_clickingEnabled);
EditorGUILayout.PropertyField(_hoveringEnabled);
EditorGUILayout.PropertyField(_scrollingEnabled);
EditorGUILayout.PropertyField(_scrollingSensitivity);
EditorGUILayout.PropertyField(_dragThreshold);
}
#if UNITY_2019_1_OR_NEWER
EditorGUILayout.EndFoldoutHeaderGroup();
#endif
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
}
SerializedProperty _clickingEnabled;
SerializedProperty _cursorIconsEnabled;
SerializedProperty _dragMode;
SerializedProperty _dragThreshold;
SerializedProperty _hoveringEnabled;
SerializedProperty _keyboardEnabled;
SerializedProperty _logConsoleMessages;
SerializedProperty _resolution;
SerializedProperty _initialUrl;
SerializedProperty _nativeOnScreenKeyboardEnabled;
SerializedProperty _pixelDensity;
SerializedProperty _remoteDebuggingEnabled;
SerializedProperty _scrollingEnabled;
SerializedProperty _scrollingSensitivity;
bool _showOtherSettings;
protected abstract string _getDocumentationLink();
protected virtual void _renderCustomOtherSettings() {}
protected virtual void _renderCustomPlatformSpecificSettings() {}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 12235521ed9354bd29154cb73f4a7c9d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,30 +0,0 @@
// Copyright (c) 2023 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 UnityEditor;
namespace Vuplex.WebView.Editor {
/// <summary>
/// Adds a "View documentation" link to the inspector.
/// </summary>
[CustomEditor(typeof(CanvasPointerInputDetector))]
public class CanvasPointerInputDetectorInspector : UnityEditor.Editor {
public override void OnInspectorGUI() {
DocumentationLinkDrawer.DrawDocumentationLink("https://developer.vuplex.com/webview/IPointerInputDetector");
DrawDefaultInspector();
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a629eb6a80da745468dc349f3d92563f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,44 +0,0 @@
// Copyright (c) 2023 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 UnityEditor;
namespace Vuplex.WebView.Editor {
[CustomEditor(typeof(CanvasWebViewPrefab))]
public class CanvasWebViewPrefabInspector : BaseWebViewPrefabInspector {
public override void OnEnable() {
base.OnEnable();
serializedObject.Update();
_native2DModeEnabled = serializedObject.FindProperty("Native2DModeEnabled");
}
SerializedProperty _native2DModeEnabled;
protected override string _getDocumentationLink() {
return "https://developer.vuplex.com/webview/CanvasWebViewPrefab";
}
protected override void _renderCustomOtherSettings() {
EditorGUILayout.HelpBox("These settings are used with the default rendering mode but are ignored when running in native 2D mode.", MessageType.Info);
}
protected override void _renderCustomPlatformSpecificSettings() {
EditorGUILayout.PropertyField(_native2DModeEnabled);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bf1bcc6f301554381be0e9bdbbaf04b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,241 +0,0 @@
/*
* This file is a copy of Unity's [ConditionalCompilationUtility](https://github.com/Unity-Technologies/ConditionalCompilationUtility/tree/f364090bbda3728e1662074c969c2b7c3c34199b)
* with the following modifications:
* - Changed the namespace.
* - Removed the usage of k_EnableCCU and instead hardcoded the use of the Vuplex OptionalDependencyAttribute class.
* - Pasted the license below.
* - Updated ForEachAssembly() to catch TypeLoadException in addition to ReflectionTypeLoadException.
* - Made it so that if an optional dependency is removed, the scripting symbol for it is removed.
* - Made it so that the legacy VUPLEX_CCU scripting symbol previously used by this script is automatically removed from the project.
*
* Unity Companion License 1.0 ("License")
* Copyright (C) 2017-2018 Unity Technologies ApS ("Unity")
*
* Unity hereby grants to you a worldwide, non-exclusive, no-charge, and royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute the software that is made available with this License ("Software"), subject to the following terms and conditions:
*
* 1. Unity Companion Use Only. Exercise of the license granted herein is limited to exercise for the creation, use, and/or distribution of applications, software, or other content pursuant to a valid Unity development engine software license ("Engine License"). That means while use of the Software is not limited to use in the software licensed under the Engine License, the Software may not be used for any purpose other than the creation, use, and/or distribution of Engine License-dependent applications, software, or other content. No other exercise of the license granted herein is permitted.
*
* 2. No Modification of Engine License. Neither this License nor any exercise of the license granted herein modifies the Engine License in any way.
*
* 3. Ownership & Grant Back to You.
*
* 3.1 You own your content. In this License, "derivative works" means derivatives of the Software itself--works derived only from the Software by you under this License (for example, modifying the code of the Software itself to improve its efficacy); "derivative works" of the Software do not include, for example, games, apps, or content that you create using the Software. You keep all right, title, and interest to your own content.
*
* 3.2 Unity owns its content. While you keep all right, title, and interest to your own content per the above, as between Unity and you, Unity will own all right, title, and interest to all intellectual property rights (including patent, trademark, and copyright) in the Software and derivative works of the Software, and you hereby assign and agree to assign all such rights in those derivative works to Unity.
*
* 3.3 You have a license to those derivative works. Subject to this License, Unity grants to you the same worldwide, non-exclusive, no-charge, and royalty-free copyright license to derivative works of the Software you create as is granted to you for the Software under this License.
*
* 4. Trademarks. You are not granted any right or license under this License to use any trademarks, service marks, trade names, products names, or branding of Unity or its affiliates ("Trademarks"). Descriptive uses of Trademarks are permitted; see, for example, Unity's Branding Usage Guidelines at https://unity3d.com/public-relations/brand.
*
* 5. Notices & Third-Party Rights. This License, including the copyright notice above, must be provided in all substantial portions of the Software and derivative works thereof (or, if that is impracticable, in any other location where such notices are customarily placed). Further, if the Software is accompanied by a Unity "third-party notices" or similar file, you acknowledge and agree that software identified in that file is governed by those separate license terms.
*
* 6. DISCLAIMER, LIMITATION OF LIABILITY. THE SOFTWARE AND ANY DERIVATIVE WORKS THEREOF IS PROVIDED ON AN "AS IS" BASIS, AND IS PROVIDED WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT. IN NO EVENT SHALL ANY COPYRIGHT HOLDER OR AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES (WHETHER DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL, INCLUDING PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, AND BUSINESS INTERRUPTION), OR OTHER LIABILITY WHATSOEVER, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM OR OUT OF, OR IN CONNECTION WITH, THE SOFTWARE OR ANY DERIVATIVE WORKS THEREOF OR THE USE OF OR OTHER DEALINGS IN SAME, EVEN WHERE ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 7. USE IS ACCEPTANCE and License Versions. Your receipt and use of the Software constitutes your acceptance of this License and its terms and conditions. Software released by Unity under this License may be modified or updated and the License with it; upon any such modification or update, you will comply with the terms of the updated License for any use of any of the Software under the updated License.
*
* 8. Use in Compliance with Law and Termination. Your exercise of the license granted herein will at all times be in compliance with applicable law and will not infringe any proprietary rights (including intellectual property rights); this License will terminate immediately on any breach by you of this License.
*
* 9. Severability. If any provision of this License is held to be unenforceable or invalid, that provision will be enforced to the maximum extent possible and the other provisions will remain in full force and effect.
*
* 10. Governing Law and Venue. This License is governed by and construed in accordance with the laws of Denmark, except for its conflict of laws rules; the United Nations Convention on Contracts for the International Sale of Goods will not apply. If you reside (or your principal place of business is) within the United States, you and Unity agree to submit to the personal and exclusive jurisdiction of and venue in the state and federal courts located in San Francisco County, California concerning any dispute arising out of this License ("Dispute"). If you reside (or your principal place of business is) outside the United States, you and Unity agree to submit to the personal and exclusive jurisdiction of and venue in the courts located in Copenhagen, Denmark concerning any Dispute.
*/
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.Compilation;
using Assembly = System.Reflection.Assembly;
using Debug = UnityEngine.Debug;
using System.Threading;
using VuplexOptionalDependencyAttribute = Vuplex.WebView.Editor.OptionalDependencyAttribute;
namespace Vuplex.WebView.ConditionalCompilation
{
/// <summary>
/// The Conditional Compilation Utility (CCU) will add defines to the build settings once dependendent classes have been detected.
/// A goal of the CCU was to not require the CCU itself for other libraries to specify optional dependencies. So, it relies on the
/// specification of at least one custom attribute in a project that makes use of it. Here is an example:
///
/// [Conditional(UNITY_CCU)] // | This is necessary for CCU to pick up the right attributes
/// public class OptionalDependencyAttribute : Attribute // | Must derive from System.Attribute
/// {
/// public string dependentClass; // | Required field specifying the fully qualified dependent class
/// public string define; // | Required field specifying the define to add
/// }
///
/// Then, simply specify the assembly attribute(s) you created in any of your C# files:
/// [assembly: OptionalDependency("UnityEngine.InputNew.InputSystem", "USE_NEW_INPUT")]
/// [assembly: OptionalDependency("Valve.VR.IVRSystem", "ENABLE_STEAMVR_INPUT")]
///
/// namespace Foo
/// {
/// ...
/// }
/// </summary>
[InitializeOnLoad]
static class ConditionalCompilationUtility
{
const string k_PreviousUnsuccessfulDefines = "ConditionalCompilationUtility.PreviousUnsuccessfulDefines";
public static string[] defines { private set; get; }
static Type _dependencyAttributeType = typeof(VuplexOptionalDependencyAttribute);
static ConditionalCompilationUtility()
{
#if UNITY_2017_3_OR_NEWER
var errorsFound = false;
CompilationPipeline.assemblyCompilationFinished += (outputPath, compilerMessages) =>
{
var errorCount = compilerMessages.Count(m => m.type == CompilerMessageType.Error && m.message.Contains("CS0246"));
if (errorCount > 0 && !errorsFound)
{
var previousDefines = EditorPrefs.GetString(k_PreviousUnsuccessfulDefines);
var currentDefines = string.Join(";", defines);
if (currentDefines != previousDefines)
{
// Store the last set of unsuccessful defines to avoid ping-ponging
EditorPrefs.SetString(k_PreviousUnsuccessfulDefines, currentDefines);
// Since there were errors in compilation, try removing any dependency defines
UpdateDependencies(true);
}
errorsFound = true;
}
};
AssemblyReloadEvents.afterAssemblyReload += () =>
{
if (!errorsFound)
UpdateDependencies();
};
#else
UpdateDependencies();
#endif
}
static void UpdateDependencies(bool reset = false)
{
var buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
if (buildTargetGroup == BuildTargetGroup.Unknown)
{
var propertyInfo = typeof(EditorUserBuildSettings).GetProperty("activeBuildTargetGroup", BindingFlags.Static | BindingFlags.NonPublic);
if (propertyInfo != null)
buildTargetGroup = (BuildTargetGroup)propertyInfo.GetValue(null, null);
}
var previousProjectDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
var projectDefines = previousProjectDefines.Split(';').ToList();
var ccuDefines = new List<string>();
var conditionalAttributeType = typeof(ConditionalAttribute);
const string kDependentClass = "dependentClass";
const string kDefine = "define";
var dependencies = new Dictionary<string, string>();
ForEachAssembly(assembly =>
{
var typeAttributes = assembly.GetCustomAttributes(_dependencyAttributeType, false);
foreach (var typeAttribute in typeAttributes)
{
// These fields were already validated in a previous step
var dependentClass = _dependencyAttributeType.GetField(kDependentClass).GetValue(typeAttribute) as string;
var define = _dependencyAttributeType.GetField(kDefine).GetValue(typeAttribute) as string;
if (!string.IsNullOrEmpty(dependentClass) && !string.IsNullOrEmpty(define) && !dependencies.ContainsKey(dependentClass))
dependencies.Add(dependentClass, define);
}
});
ForEachAssembly(assembly =>
{
foreach (var dependency in dependencies)
{
var typeName = dependency.Key;
var define = dependency.Value;
var type = assembly.GetType(typeName);
if (type != null)
{
if (!projectDefines.Contains(define, StringComparer.OrdinalIgnoreCase))
projectDefines.Add(define);
ccuDefines.Add(define);
}
}
});
// Remove scripting symbols for optional dependencies that have been removed.
foreach (var define in dependencies.Values)
{
if (projectDefines.Contains(define) && !ccuDefines.Contains(define))
projectDefines.Remove(define);
}
// Remove the legacy VUPLEX_CCU scripting symbol that this script used to add.
if (projectDefines.Contains("VUPLEX_CCU"))
projectDefines.Remove("VUPLEX_CCU");
if (reset)
{
foreach (var define in dependencies.Values)
{
projectDefines.Remove(define);
}
ccuDefines.Clear();
}
ConditionalCompilationUtility.defines = ccuDefines.ToArray();
var newDefines = string.Join(";", projectDefines.ToArray());
if (previousProjectDefines != newDefines)
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, newDefines);
}
static void ForEachAssembly(Action<Assembly> callback)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
try
{
callback(assembly);
}
catch (Exception ex) when (ex is ReflectionTypeLoadException || ex is TypeLoadException)
{
// Skip any assemblies that don't load properly
continue;
}
}
}
static void ForEachType(Action<Type> callback)
{
ForEachAssembly(assembly =>
{
var types = assembly.GetTypes();
foreach (var t in types)
callback(t);
});
}
static IEnumerable<Type> GetAssignableTypes(Type type, Func<Type, bool> predicate = null)
{
var list = new List<Type>();
ForEachType(t =>
{
if (type.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract && (predicate == null || predicate(t)))
list.Add(t);
});
return list;
}
}
}
#endif

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 55a3f084f6ac84e1db970f412e251da0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,30 +0,0 @@
// Copyright (c) 2023 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 UnityEditor;
namespace Vuplex.WebView.Editor {
/// <summary>
/// Adds a "View documentation" link to the inspector.
/// </summary>
[CustomEditor(typeof(DefaultPointerInputDetector))]
public class DefaultPointerInputDetectorInspector : UnityEditor.Editor {
public override void OnInspectorGUI() {
DocumentationLinkDrawer.DrawDocumentationLink("https://developer.vuplex.com/webview/IPointerInputDetector");
DrawDefaultInspector();
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a4161c7b2198c4efcbd3123708e4091a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,29 +0,0 @@
// Copyright (c) 2023 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 UnityEngine;
using UnityEditor;
namespace Vuplex.WebView.Editor {
public static class DocumentationLinkDrawer {
/// <summary>
/// Draws a "View documentation" link.
/// </summary>
public static void DrawDocumentationLink(string url) {
EditorUtils.DrawLink("View documentation", url, 23);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 15705ab5708a341e0a98cb0af0b6fa84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,154 +0,0 @@
// Copyright (c) 2023 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.IO;
using System.Linq;
using UnityEngine;
using UnityEditor;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView.Editor {
public static class EditorUtils {
public static void CopyAndReplaceDirectory(string srcPath, string dstPath, bool ignoreMetaFiles = true) {
if (Directory.Exists(dstPath)) {
Directory.Delete(dstPath, true);
}
if (File.Exists(dstPath)) {
File.Delete(dstPath);
}
Directory.CreateDirectory(dstPath);
foreach (var file in Directory.GetFiles(srcPath)) {
if (!ignoreMetaFiles || Path.GetExtension(file) != ".meta") {
File.Copy(file, Path.Combine(dstPath, Path.GetFileName(file)));
}
}
foreach (var dir in Directory.GetDirectories(srcPath)) {
CopyAndReplaceDirectory(dir, Path.Combine(dstPath, Path.GetFileName(dir)), ignoreMetaFiles);
}
}
public static void DrawLink(string linkText, string url, int underlineLength) {
var linkStyle = new GUIStyle {
richText = true,
padding = new RectOffset {
top = 2,
bottom = 2
}
};
var linkClicked = GUILayout.Button(
EditorUtils.TextWithColor(linkText, EditorUtils.GetLinkColor()),
linkStyle
);
var linkRect = GUILayoutUtility.GetLastRect();
EditorGUIUtility.AddCursorRect(linkRect, MouseCursor.Link);
// Unity's editor GUI doesn't support underlines, so fake it.
var underscores = new string[underlineLength];
for (var i = 0; i < underlineLength; i++) {
underscores[i] = "_";
}
var underline = String.Join("", underscores);
GUI.Label(
linkRect,
EditorUtils.TextWithColor(underline, EditorUtils.GetLinkColor()),
new GUIStyle {
richText = true,
padding = new RectOffset {
top = 4,
bottom = 2
}
});
if (linkClicked) {
Application.OpenURL(url);
}
}
/// <summary>
/// Returns the path to a given directory, searching for it if needed.
/// If `directoryToSearch` isn't provided, `Application.dataPath` is used.
/// </summary>
public static string FindDirectory(string expectedPath, string directoryToSearch = null, string[] ignorePaths = null) {
if (Directory.Exists(expectedPath)) {
return expectedPath;
}
// The directory isn't in the expected location, so fall back to finding it.
var directoryName = Path.GetFileName(expectedPath);
if (directoryToSearch == null) {
directoryToSearch = Application.dataPath;
}
var directories = Directory.GetDirectories(directoryToSearch, directoryName, SearchOption.AllDirectories);
if (ignorePaths != null) {
directories = directories.ToList().Where(d => !ignorePaths.Contains(d)).ToArray();
}
return _returnOnePathOrThrow(directories, expectedPath, directoryToSearch, true);
}
/// <summary>
/// Returns the path to a given file, searching for it if needed.
/// If `directoryToSearch` isn't provided, `Application.dataPath` is used.
/// </summary>
public static string FindFile(string expectedPath, string directoryToSearch = null) {
if (File.Exists(expectedPath)) {
return expectedPath;
}
// The file isn't in the expected location, so fall back to finding it.
var fileName = Path.GetFileName(expectedPath);
if (directoryToSearch == null) {
directoryToSearch = Application.dataPath;
}
var files = Directory.GetFiles(directoryToSearch, fileName, SearchOption.AllDirectories);
return _returnOnePathOrThrow(files, expectedPath, directoryToSearch);
}
public static string GetLinkColor() => EditorGUIUtility.isProSkin ? "#7faef0ff" : "#11468aff";
public static string TextWithColor(string text, string color) => $"<color={color}>{text}</color>";
public static bool XRSdkIsEnabled(string sdkNameFragment) {
// This approach is taken because the legacy Oculus XR plugin identifies itself as "Oculus", but
// the new XR plugin shows up as two devices named "oculus input" and "oculus display". Similarly,
// the MockHMD plugin used to identify itself as "MockHMD" but now it shows up as "MockHMD Head Tracking"
// and "MockHMD Display".
foreach (var sdkName in VXUtils.XRSettings.supportedDevices) {
if (sdkName.ToLowerInvariant().Contains(sdkNameFragment.ToLowerInvariant())) {
return true;
}
}
return false;
}
static string _returnOnePathOrThrow(string[] paths, string expectedPath, string directorySearched, bool isDirectory = false) {
var itemName = isDirectory ? "directory" : "file";
if (paths.Length == 1) {
return paths[0];
}
var targetFileOrDirectoryName = Path.GetFileName(expectedPath);
if (paths.Length > 1) {
var joinedPaths = String.Join(", ", paths);
throw new Exception($"Unable to determine which version of the {itemName} {targetFileOrDirectoryName} to use because multiple instances ({paths.Length}) were unexpectedly found in the directory {directorySearched}. Please review the list of instances found and remove duplicates so that there is only one: {joinedPaths}");
}
throw new Exception($"Unable to locate the {itemName} {targetFileOrDirectoryName}. It's not in the expected location ({expectedPath}), and no instances were found in the directory {directorySearched}. To resolve this issue, please try deleting your existing Assets/Vuplex directory and reinstalling 3D WebView.");
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 70f8251b128d6ed4fb9dfd2c185496cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,28 +0,0 @@
// Copyright (c) 2023 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 UnityEngine;
using UnityEditor;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView.Editor {
[CustomPropertyDrawer(typeof(LabelAttribute))]
class LabelDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.PropertyField(position, property, new GUIContent((attribute as LabelAttribute).Label, property.tooltip));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f7cc4d471c1d54e75b87468526b602cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,37 +0,0 @@
// Copyright (c) 2023 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.
#if UNITY_EDITOR
using System;
using System.Diagnostics;
using Vuplex.WebView.ConditionalCompilation;
namespace Vuplex.WebView.Editor {
/// <summary>
/// From the example of how to use Unity's ConditionalCompilationUtility:
/// https://github.com/Unity-Technologies/ConditionalCompilationUtility/tree/f364090bbda3728e1662074c969c2b7c3c34199b
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
// Refer to System.Attribute by its full name in case the project has a class named "Attribute" in the global namespace.
public class OptionalDependencyAttribute : System.Attribute {
public string dependentClass;
public string define;
public OptionalDependencyAttribute(string dependentClass, string define) {
this.dependentClass = dependentClass;
this.define = define;
}
}
}
#endif

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 36b97f9b079074ee685a6ee41adc0f3b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,27 +0,0 @@
// Copyright (c) 2023 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.
// This can't be imported as just OptionalDependencyAttribute because
// it would clash with other packages that define that attribute, like
// XR Interaction Toolkit.
#if UNITY_EDITOR
using VuplexOptionalDependencyAttribute = Vuplex.WebView.Editor.OptionalDependencyAttribute;
// Detect if specific packages are installed and, if so,
// define scripting symbols so that 3D WebView can handle them.
[assembly: VuplexOptionalDependency("Unity.XR.Oculus.OculusLoader", "VUPLEX_OCULUS")]
[assembly: VuplexOptionalDependency("OVRProjectConfig", "VUPLEX_OCULUS_PROJECT_CONFIG")]
[assembly: VuplexOptionalDependency("UnityEngine.XR.Interaction.Toolkit.XRBaseInteractor", "VUPLEX_XR_INTERACTION_TOOLKIT")]
[assembly: VuplexOptionalDependency("Microsoft.MixedReality.Toolkit.MixedRealityToolkit", "VUPLEX_MRTK")]
[assembly: VuplexOptionalDependency("Vuplex.WebView.StandaloneWebPlugin", "VUPLEX_STANDALONE")]
#endif

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e6ee0f86057d9439896db7eb0e9cf5da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,25 +0,0 @@
// Copyright (c) 2023 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 UnityEditor;
namespace Vuplex.WebView.Editor {
[CustomEditor(typeof(WebViewPrefab))]
public class WebViewPrefabInspector : BaseWebViewPrefabInspector {
protected override string _getDocumentationLink() {
return "https://developer.vuplex.com/webview/WebViewPrefab";
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b88a73aa4eea34b3eb0c643e900629a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7db53a5c7645d49dc9cb47325b1c4c44
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c9e0722a5d73544aea97fc9f27d57a28
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,140 +0,0 @@
fileFormatVersion: 2
guid: 9f7b60728c99d4fe6b67e0d86b1e7b5e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e215f6e969624419f9f78abee1aacc76
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d50ed4d84413b4b38aef9d7a59ed5f22
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,91 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: AndroidWebMaterial
m_Shader: {fileID: 4800000, guid: 6e30a287c37c64ea8a78626f476223bb, type: 3}
m_ShaderKeywords: FLIP_Y _ALPHATEST_ON _STEREOMODE_NONE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: -1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _EnableGammaCorrection: 0
- _FlipX: 0
- _FlipY: 1
- _Gamma: 0.6
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 1
- _OcclusionStrength: 1
- _OverrideStereoToMono: 0
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _StereoMode: 0
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _CropRect: {r: 0, g: 0, b: 0, a: 0}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _VideoCutoutRect: {r: 0, g: 0, b: 0, a: 0}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b330f1b65a93d4b708726acb581f07b0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,91 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: DefaultWebMaterial
m_Shader: {fileID: 4800000, guid: 4e653f72759f94e82b22355692823efe, type: 3}
m_ShaderKeywords: FLIP_Y _ALPHATEST_ON _STEREOMODE_NONE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: -1, y: -1}
m_Offset: {x: 1, y: 1}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _EnableGammaCorrection: 0
- _FlipX: 0
- _FlipY: 1
- _Gamma: 0.6
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 1
- _OcclusionStrength: 1
- _OverrideStereoToMono: 0
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _StereoMode: 0
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _CropRect: {r: 0, g: 0, b: 0, a: 0}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _VideoCutoutRect: {r: 0, g: 0, b: 0, a: 0}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c1ebc368a4559473c933b46a16a9cc9e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 359a5662a859d4d0aa134fa4450a03cf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 36aa5171762764850acf79d6b107e3fd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,111 +0,0 @@
// Copyright (c) 2023 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.IO;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace Vuplex.WebViewUpgrade {
/// <summary>
/// Detects if the Vuplex/WebView folder needs to be deleted
/// because it contains subdirectories from old versions of
/// 3D WebView:
/// https://support.vuplex.com/articles/v4-changes#directory
/// </summary>
/// <remarks>
/// This script is located in Plugins/Editor so that it's included in the assembly Assembly-CSharp-Editor-firstpass
/// and can still function if there are C# compiler errors in other scripts:
/// https://docs.unity3d.com/Manual/ScriptCompileOrderFolders.html
/// </remarks>
[InitializeOnLoad]
class OldWebViewDirectoryDeleter {
static OldWebViewDirectoryDeleter() => _askPermissionToDeleteWebViewDirectoryIfNeeded();
static string[] _oldSubdirectoryNames = new string[] { "Editor", "Licenses", "Materials", "Plugins", "Prefabs", "Scripts", "Shaders" };
static void _askPermissionToDeleteWebViewDirectoryIfNeeded() {
var vuplexDirectoryPath = DirectoryDeleterUtils.FindDirectory(Path.Combine(Application.dataPath, "Vuplex"));
if (vuplexDirectoryPath == null) {
// The Vuplex directory couldn't be found. This can happen if the user renamed the Vuplex directory or
// moved it to the Packages folder.
return;
}
var webViewDirectoryPath = Path.Combine(vuplexDirectoryPath, "WebView");
var oldSubdirectoriesExist = _oldSubdirectoryNames.Any(dirName => Directory.Exists(Path.Combine(webViewDirectoryPath, dirName)));
if (!oldSubdirectoriesExist) {
return;
}
var userApprovedDeletingWebViewDirectory = EditorUtility.DisplayDialog(
"3D WebView v4 Upgrade",
$"Thank you for upgrading to 3D WebView v4! In v4, 3D WebView changed its directory structure compared to past versions. To upgrade, we need to delete your project's existing Vuplex/WebView folder, and then you'll need to reimport this new version of 3D WebView. Do you want 3D WebView to go ahead and delete the existing Vuplex/WebView folder so that you can reimport the new version?\n\nDirectory that will be deleted: {webViewDirectoryPath}\n\nMore info: https://support.vuplex.com/articles/v4-changes#directory\n",
"Yes, delete the old WebView folder, and then I'll reimport",
"Cancel"
);
if (!userApprovedDeletingWebViewDirectory) {
return;
}
try {
Directory.Delete(webViewDirectoryPath, true);
var metaFilePath = webViewDirectoryPath + ".meta";
if (File.Exists(metaFilePath)) {
File.Delete(metaFilePath);
}
Debug.Log("[3D WebView] Successfully finished deleting the old Vuplex/WebView directory. To finish upgrading, please reimport the new 3D WebView package.");
} catch (Exception ex) {
Debug.LogError($"[3D WebView] An exception occurred while deleting the old Vuplex/WebView directory. Please manually delete the directory {webViewDirectoryPath} and then reimport the new 3D WebView package. Exception: {ex}");
}
}
// Methods copied from EditorUtils.cs so that this script has no dependencies
// on classes in the Assembly-CSharp-Editor assembly.
static class DirectoryDeleterUtils {
public static string FindDirectory(string expectedPath, string directoryToSearch = null, string[] ignorePaths = null) {
if (Directory.Exists(expectedPath)) {
return expectedPath;
}
// The directory isn't in the expected location, so fall back to finding it.
var directoryName = Path.GetFileName(expectedPath);
if (directoryToSearch == null) {
directoryToSearch = Application.dataPath;
}
var directories = Directory.GetDirectories(directoryToSearch, directoryName, SearchOption.AllDirectories);
if (ignorePaths != null) {
directories = directories.ToList().Where(d => !ignorePaths.Contains(d)).ToArray();
}
return _returnOnePath(directories, expectedPath, directoryToSearch, true);
}
static string _returnOnePath(string[] paths, string expectedPath, string directorySearched, bool isDirectory = false) {
var itemName = isDirectory ? "directory" : "file";
if (paths.Length == 1) {
return paths[0];
}
var targetFileOrDirectoryName = Path.GetFileName(expectedPath);
if (paths.Length > 1) {
var joinedPaths = String.Join(", ", paths);
throw new Exception($"Unable to determine which version of the {itemName} {targetFileOrDirectoryName} to use because multiple instances ({paths.Length}) were unexpectedly found in the directory {directorySearched}. Please review the list of instances found and remove duplicates so that there is only one: {joinedPaths}");
}
return null;
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 28cf2cac9522d4214b26b3627f49f164
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: bf0ae6d90515142cd9ce04eea8ff11cc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 9bb640a76f5114841a21c052f5e9675b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,95 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1077352107545268}
m_IsPrefabParent: 1
--- !u!1 &1077352107545268
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 224209101858263596}
- component: {fileID: 114444086270251362}
- component: {fileID: 222742886503075740}
- component: {fileID: 114569966070787602}
m_Layer: 5
m_Name: CanvasKeyboard
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &114444086270251362
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1077352107545268}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bf3530b75f6314cc9a2e4796f3195ca2, type: 3}
m_Name:
m_EditorClassIdentifier:
_webViewPrefab: {fileID: 0}
InitialResolution: 1
--- !u!114 &114569966070787602
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1077352107545268}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
--- !u!222 &222742886503075740
CanvasRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1077352107545268}
--- !u!224 &224209101858263596
RectTransform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1077352107545268}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 650, y: 162}
m_Pivot: {x: 0.5, y: 0.5}

View File

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 8f67f2d646b0a4cc58c56790b3f53ef4
timeCreated: 1618101293
licenseType: Store
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,253 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1535822479614194}
m_IsPrefabParent: 1
--- !u!1 &1255051872871948
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 224970607326042290}
- component: {fileID: 222573612747050694}
- component: {fileID: 114113553939285968}
- component: {fileID: 114138872472689322}
m_Layer: 5
m_Name: VideoLayer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1535822479614194
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 224179541092979990}
- component: {fileID: 222163621197708754}
- component: {fileID: 114949863196309792}
m_Layer: 5
m_Name: CanvasWebViewPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1589489459947714
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 224664686071158562}
- component: {fileID: 222540676635965858}
- component: {fileID: 114031267652868270}
- component: {fileID: 114349837030292576}
- component: {fileID: 114451593925140236}
m_Layer: 5
m_Name: CanvasWebViewPrefabView
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &114031267652868270
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1589489459947714}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -98529514, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!114 &114113553939285968
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1255051872871948}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -98529514, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!114 &114138872472689322
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1255051872871948}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5494d9d7c39544539adab71793f4a16a, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114349837030292576
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1589489459947714}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5494d9d7c39544539adab71793f4a16a, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114451593925140236
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1589489459947714}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 70d2e4700f40744fe8b999f209d0253b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114949863196309792
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1535822479614194}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 879d31ebe92b040cbb3ef97e98278140, type: 3}
m_Name:
m_EditorClassIdentifier:
InitialUrl:
DragMode: 0
ClickingEnabled: 1
HoveringEnabled: 1
ScrollingEnabled: 1
DragThreshold: 20
RemoteDebuggingEnabled: 0
LogConsoleMessages: 0
_cachedVideoLayer: {fileID: 0}
_cachedView: {fileID: 0}
_pointerInputDetectorMonoBehaviour: {fileID: 0}
_webViewGameObject: {fileID: 0}
Native2DModeEnabled: 0
NativeOnScreenKeyboardEnabled: 1
InitialResolution: 1
ScrollingSensitivity: 15
--- !u!222 &222163621197708754
CanvasRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1535822479614194}
--- !u!222 &222540676635965858
CanvasRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1589489459947714}
--- !u!222 &222573612747050694
CanvasRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1255051872871948}
--- !u!224 &224179541092979990
RectTransform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1535822479614194}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 224970607326042290}
- {fileID: 224664686071158562}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!224 &224664686071158562
RectTransform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1589489459947714}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 224179541092979990}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!224 &224970607326042290
RectTransform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1255051872871948}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 224179541092979990}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 1}

View File

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 3e10f3b6a733e441c8352020cff2f1f6
timeCreated: 1583351967
licenseType: Store
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,142 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1174278342477064}
m_IsPrefabParent: 1
--- !u!1 &1063265092234352
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4875497843849992}
- component: {fileID: 33464908079229110}
- component: {fileID: 64244334316161624}
- component: {fileID: 23636716548355268}
m_Layer: 0
m_Name: Placeholder
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1174278342477064
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4402545345664314}
- component: {fileID: 114039135475586158}
m_Layer: 0
m_Name: Keyboard
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4402545345664314
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1174278342477064}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.5, y: 0.125, z: 1}
m_Children:
- {fileID: 4875497843849992}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4875497843849992
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1063265092234352}
m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
m_LocalPosition: {x: 0, y: -0.5, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4402545345664314}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
--- !u!23 &23636716548355268
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1063265092234352}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!33 &33464908079229110
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1063265092234352}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!64 &64244334316161624
MeshCollider:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1063265092234352}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 3
m_Convex: 0
m_CookingOptions: 14
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!114 &114039135475586158
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1174278342477064}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e6d8eb3193741445b822bfa85a0b39a6, type: 3}
m_Name:
m_EditorClassIdentifier:
_webViewPrefab: {fileID: 0}
InitialResolution: 1300

View File

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 309109dc3a1d64a9ebdb676ae99065ac
timeCreated: 1618100751
licenseType: Store
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,314 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1469133279829300}
m_IsPrefabParent: 1
--- !u!1 &1257759606553584
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4904221104159722}
m_Layer: 0
m_Name: WebViewPrefabResizer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1381583133826408
GameObject:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4495929391779928}
- component: {fileID: 33813818586652990}
- component: {fileID: 23178964100232268}
- component: {fileID: 114330170337970978}
- component: {fileID: 114810858755358174}
- component: {fileID: 64922995877070972}
m_Layer: 0
m_Name: WebViewPrefabView
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1469133279829300
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4307528708891540}
- component: {fileID: 114949350411584270}
m_Layer: 0
m_Name: WebViewPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1611328938895142
GameObject:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4249276903644494}
m_Layer: 0
m_Name: VideoRectPositioner
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!1 &1840072142318122
GameObject:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4747229143573016}
- component: {fileID: 33036464261626858}
- component: {fileID: 23654077301984142}
- component: {fileID: 114558935537698590}
m_Layer: 0
m_Name: VideoLayer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4249276903644494
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1611328938895142}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0.001}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4747229143573016}
m_Father: {fileID: 4904221104159722}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4307528708891540
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1469133279829300}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4904221104159722}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4495929391779928
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
m_LocalPosition: {x: 0.5, y: -0.5, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4904221104159722}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
--- !u!4 &4747229143573016
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1840072142318122}
m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
m_LocalPosition: {x: 0.5, y: -0.5, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4249276903644494}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
--- !u!4 &4904221104159722
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1257759606553584}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4495929391779928}
- {fileID: 4249276903644494}
m_Father: {fileID: 4307528708891540}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &23178964100232268
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: c1ebc368a4559473c933b46a16a9cc9e, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!23 &23654077301984142
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1840072142318122}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: c1ebc368a4559473c933b46a16a9cc9e, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!33 &33036464261626858
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1840072142318122}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &33813818586652990
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!64 &64922995877070972
MeshCollider:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 3
m_Convex: 0
m_CookingOptions: 14
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!114 &114330170337970978
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: acac58dff315c4e35bda0776f2daf873, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114558935537698590
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1840072142318122}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: acac58dff315c4e35bda0776f2daf873, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114810858755358174
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1381583133826408}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b5d2e4670d86405386a27a4b18941bf, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &114949350411584270
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1469133279829300}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f5e34c9f38a6c46db8c1b510a6090e8c, type: 3}
m_Name:
m_EditorClassIdentifier:
InitialUrl:
DragMode: 0
InitialResolution: 1300
ClickingEnabled: 1
HoveringEnabled: 1
ScrollingEnabled: 1
DragToScrollThreshold: 0.15
ScrollingSensitivity: 0.005

View File

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: d704fe1266adf446ebcfa350586e1bc7
timeCreated: 1583351880
licenseType: Store
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1ce6fd89ece294d2fb7770f9ef2fb382
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,49 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Event args for AuthRequested. Either Continue() or Cancel() must be called in order
/// to resume the page.
/// </summary>
public class AuthRequestedEventArgs : EventArgs {
public AuthRequestedEventArgs(string host, Action<string, string> continueCallback, Action cancelCallback) {
Host = host;
_continueCallback = continueCallback;
_cancelCallback = cancelCallback;
}
/// <summary>
/// The host that requested authentication.
/// </summary>
public readonly string Host;
/// <summary>
/// Declines authentication and resumes the page.
/// </summary>
public void Cancel() => _cancelCallback();
/// <summary>
/// Sends an authentication request to the host.
/// </summary>
public void Continue(string username, string password) => _continueCallback(username, password);
Action _cancelCallback;
Action<string, string> _continueCallback;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6f309a6e65c0543618a6d7b49692ab97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,189 +0,0 @@
// Copyright (c) 2023 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.
#pragma warning disable CS0067
using System;
using System.Threading.Tasks;
using UnityEngine;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView {
public abstract class BaseKeyboard : MonoBehaviour {
/// <summary>
/// Indicates that the user pressed a key on the keyboard.
/// </summary>
public event EventHandler<EventArgs<string>> KeyPressed;
/// <summary>
/// Indicates that the keyboard finished initializing.
/// </summary>
public event EventHandler Initialized;
/// <summary>
/// If you want to load a customized version of the Keyboard UI, you can
/// do so by setting this field. For example, you could load a customized
/// Keyboard UI from StreamingAssets by using a URL like "streaming-assets://keyboard/index.html".
/// <summary>
[Label("Custom Keyboard URL (optional)")]
[Tooltip("If you want to load a customized version of the Keyboard UI, you can do so by setting this field. For example, you could load a customized Keyboard UI from StreamingAssets by using a URL like \"streaming-assets://keyboard/index.html\".")]
public string CustomKeyboardUrl;
/// <summary>
/// Returns a task that completes when the keyboard is initialized,
/// which means that its WebViewPrefab property is ready for use.
/// </summary>
/// <example>
/// <code>
/// await keyboard.WaitUntilInitialized();
/// keyboard.WebViewPrefab.Clicked += (sender, eventArgs) => {
/// Debug.Log("Keyboard was clicked");
/// };
/// </code>
/// </example>
public Task WaitUntilInitialized() {
var taskSource = new TaskCompletionSource<bool>();
if (_isInitialized) {
taskSource.SetResult(true);
} else {
Initialized += (sender, e) => taskSource.SetResult(true);
}
return taskSource.Task;
}
internal BaseWebViewPrefab BaseWebViewPrefab { get { return _webViewPrefab; }}
bool _isInitialized;
[SerializeField]
[HideInInspector]
protected BaseWebViewPrefab _webViewPrefab;
protected static readonly WebViewOptions _webViewOptions = new WebViewOptions {
clickWithoutStealingFocus = true,
disableVideo = true,
// If both Android plugins are installed, prefer the original Chromium
// plugin for the keyboard, since the Gecko plugin doesn't support
// transparent backgrounds.
preferredPlugins = new WebPluginType[] { WebPluginType.Android }
};
async protected void _init() {
_webViewPrefab.CursorIconsEnabled = false;
_webViewPrefab.KeyboardEnabled = false;
// Reset InitialUrl to null in case the developer modified WebViewPrefab.prefab to set a default InitialUrl.
_webViewPrefab.InitialUrl = null;
await _webViewPrefab.WaitUntilInitialized();
var pluginType = _webViewPrefab.WebView.PluginType;
if (pluginType == WebPluginType.AndroidGecko) {
// On Android Gecko, hovering steals focus.
_webViewPrefab.HoveringEnabled = false;
}
// Scrolling and dragging can also cause the keyboard
// to steal focus on Android Gecko, so just disable them.
_webViewPrefab.ScrollingEnabled = false;
_webViewPrefab.DragMode = DragMode.Disabled;
_webViewPrefab.WebView.MessageEmitted += WebView_MessageEmitted;
// Android Gecko and Hololens don't support transparent webviews, so set the cutout
// rect to the entire view so that the shader makes its black background
// pixels transparent.
if (pluginType == WebPluginType.AndroidGecko || pluginType == WebPluginType.UniversalWindowsPlatform) {
_webViewPrefab.SetCutoutRect(new Rect(0, 0, 1, 1));
}
if (!String.IsNullOrWhiteSpace(CustomKeyboardUrl)) {
_webViewPrefab.WebView.LoadUrl(CustomKeyboardUrl.Trim());
} else {
_webViewPrefab.WebView.LoadHtml(KeyboardUI.Html);
}
}
void OnDestroy() {
var keyboardInstance = Internal.KeyboardManager.Instance;
if (keyboardInstance != null) {
keyboardInstance.RemoveKeyboard(this);
}
}
void WebView_MessageEmitted(object sender, EventArgs<string> e) {
var serializedMessage = e.Value;
var messageType = JsonUtility.FromJson<BridgeMessage>(serializedMessage).type;
switch (messageType) {
case "keyboard.inputReceived":
var input = StringBridgeMessage.ParseValue(serializedMessage);
KeyPressed?.Invoke(this, new EventArgs<string>(input));
break;
case "keyboard.initialized":
_sendKeyboardLanguageMessage();
_isInitialized = true;
Internal.KeyboardManager.Instance.AddKeyboard(this);
Initialized?.Invoke(this, EventArgs.Empty);
break;
}
}
string _getKeyboardLanguage() {
switch (Application.systemLanguage) {
case SystemLanguage.Danish:
return "da";
case SystemLanguage.French:
return "fr";
case SystemLanguage.German:
return "de";
case SystemLanguage.Norwegian:
return "no";
case SystemLanguage.Russian:
return "ru";
case SystemLanguage.Spanish:
return "es";
case SystemLanguage.Swedish:
return "sv";
default:
return "en";
}
}
/// <summary>
/// Initializes the keyboard language based on the system language.
/// </summary>
void _sendKeyboardLanguageMessage() {
var message = new StringBridgeMessage {
type = "keyboard.setLanguage",
value = _getKeyboardLanguage()
};
var serializedMessage = JsonUtility.ToJson(message);
_webViewPrefab.WebView.PostMessage(serializedMessage);
}
protected static void _setLayerRecursively(GameObject gameObject, int layer) {
if (gameObject == null) {
return;
}
gameObject.layer = layer;
foreach (Transform child in gameObject.transform) {
if (child != null) {
_setLayerRecursively(child.gameObject, layer);
}
}
}
// Added in v1.0, removed in v4.3.
[Obsolete("Keyboard.InputReceived was removed in v4.3 because WebViewPrefab and CanvasWebViewPrefab now automatically handle keyboard input by default. Please remove your code that references Keyboard.InputReceived, and keyboard support will still work. For more info, including details about how you can still access keyboard input programmatically, please see this article: https://support.vuplex.com/articles/keyboard", true)]
public event EventHandler<EventArgs<string>> InputReceived;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 788d71bb8b006463bb656f92b1874908
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2514da53fdefd4d0cbece1e3b339470b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,107 +0,0 @@
// Copyright (c) 2023 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.Serialization;
using UnityEngine.UI;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView {
/// <summary>
/// Like the Keyboard prefab, except optimized for use in a Canvas.
/// You can add a CanvasKeyboard to your scene either by dragging the CanvasKeyboard.prefab file
/// into a Canvas via the editor or by programmatically calling CanvasKeyboard.Instantiate().
/// For an example, please see 3D WebView's CanvasWorldSpaceDemo scene.
/// </summary>
public class CanvasKeyboard : BaseKeyboard {
/// <summary>
/// Sets the keyboard's initial resolution in pixels per Unity unit.
/// You can change the resolution to make the keyboard's 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).
/// </summary>
[Label("Resolution (px / Unity unit)")]
[Tooltip("You can change this to make web content appear larger or smaller.")]
[FormerlySerializedAs("InitialResolution")]
public float Resolution = 1;
/// <summary>
/// Gets the WebViewPrefab used for the keyboard UI, or `null` if
/// the keyboard hasn't finished initializing yet.
/// You can use WaitUntilInitialized() to detect when the WebViewPrefab property is ready to use.
/// </summary>
/// <example>
/// <code>
/// await keyboard.WaitUntilInitialized();
/// keyboard.WebViewPrefab.Clicked += (sender, eventArgs) => {
/// Debug.Log("Keyboard was clicked");
/// };
/// </code>
/// </example>
public CanvasWebViewPrefab WebViewPrefab { get { return (CanvasWebViewPrefab)_webViewPrefab; }}
/// <summary>
/// Creates a new instance.
/// </summary>
/// <example>
/// <code>
/// // Create a CanvasKeyboard.
/// var keyboard = CanvasKeyboard.Instantiate();
/// keyboard.transform.SetParent(canvas.transform, false);
/// var rectTransform = keyboard.transform as RectTransform;
/// rectTransform.anchoredPosition3D = Vector3.zero;
/// rectTransform.offsetMin = Vector2.zero;
/// rectTransform.offsetMax = Vector2.zero;
/// rectTransform.sizeDelta = new Vector2(650, 162);
/// </code>
/// </example>
public static CanvasKeyboard Instantiate() {
var prefabPrototype = (GameObject)Resources.Load("CanvasKeyboard");
var gameObject = (GameObject)Instantiate(prefabPrototype);
return gameObject.GetComponent<CanvasKeyboard>();
}
void _initCanvasKeyboard() {
var canvasWebViewPrefab = CanvasWebViewPrefab.Instantiate(_webViewOptions);
_webViewPrefab = canvasWebViewPrefab;
_webViewPrefab.transform.SetParent(transform, false);
_setLayerRecursively(_webViewPrefab.gameObject, gameObject.layer);
var rectTransform = _webViewPrefab.transform as RectTransform;
rectTransform.anchoredPosition3D = Vector3.zero;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
_webViewPrefab.transform.localScale = Vector3.one;
canvasWebViewPrefab.Resolution = Resolution;
_init();
// Disable the image, which is just used as a placeholder in the editor.
var image = GetComponent<Image>();
if (image != null) {
image.enabled = false;
}
}
void Start() => _initCanvasKeyboard();
// Added in v3.12, deprecated in v4.0.
[Obsolete("CanvasKeyboard.InitialResolution is now deprecated. Please use CanvasKeyboard.Resolution instead.")]
public float InitialResolution {
get { return Resolution; }
set { Resolution = value; }
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bf3530b75f6314cc9a2e4796f3195ca2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,93 +0,0 @@
// Copyright (c) 2023 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.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Vuplex.WebView.Internal;
#if VUPLEX_MRTK
using Microsoft.MixedReality.Toolkit.Input;
#endif
namespace Vuplex.WebView {
[HelpURL("https://developer.vuplex.com/webview/IPointerInputDetector")]
public class CanvasPointerInputDetector : DefaultPointerInputDetector {
RectTransform _cachedRectTransform;
CachingGetter<Canvas> _canvasGetter;
protected override Vector2 _convertToNormalizedPoint(PointerEventData pointerEventData) {
if (_canvasGetter == null) {
_canvasGetter = new CachingGetter<Canvas>(GetComponentInParent<Canvas>, 1, this);
}
var canvas = _canvasGetter.GetValue();
var camera = canvas == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
Vector2 localPoint;
var mousePosition = pointerEventData.position;
#if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX) && !UNITY_EDITOR
// To handle multiple displays on Windows and macOS, Display.RelativeMouseAt() must be used
// to translate the mouse position. However, Unity's UI system still has a limitation where
// this may not work when the monitors have different sizes / resolutions.
// - https://issuetracker.unity3d.com/issues/buttons-hitbox-is-offset-when-building-standalone-project-for-two-screens
var positionForDisplay = Display.RelativeMouseAt(new Vector3(mousePosition.x, mousePosition.y));
// RelativeMouseAt() returns Vector3.zero when multiple displays aren't supported.
if (positionForDisplay != Vector3.zero) {
mousePosition = new Vector2(positionForDisplay.x, positionForDisplay.y);
}
#endif
RectTransformUtility.ScreenPointToLocalPointInRectangle(_getRectTransform(), mousePosition, camera, out localPoint);
return _convertVector2ToNormalizedPoint(localPoint);
}
protected override Vector2 _convertToNormalizedPoint(Vector3 worldPosition) {
var localPoint = _getRectTransform().InverseTransformPoint(worldPosition);
var normalizedPoint = _convertVector2ToNormalizedPoint(localPoint);
return normalizedPoint;
}
// Note: This method was originally named _convertToNormalizedPoint(Vector2), but since a Vector3 can be implicitly
// converted to a Vector2, it caused this method to incorrectly be called instead of _convertToNormalizedPoint(Vector3)
// in some cases.
Vector2 _convertVector2ToNormalizedPoint(Vector2 localPoint) {
var normalizedPoint = Rect.PointToNormalized(_getRectTransform().rect, localPoint);
normalizedPoint.y = 1 - normalizedPoint.y;
return normalizedPoint;
}
RectTransform _getRectTransform() {
if (_cachedRectTransform == null) {
_cachedRectTransform = GetComponent<RectTransform>();
}
return _cachedRectTransform;
}
protected override bool _positionIsZero(PointerEventData eventData) => eventData.position == Vector2.zero;
void Start() {
#if VUPLEX_MRTK
// Add a NearInteractionTouchable script to allow touch interactions
// to trigger the IMixedRealityPointerHandler methods.
var touchable = gameObject.AddComponent<NearInteractionTouchableUnityUI>();
touchable.EventsToReceive = TouchableEventType.Pointer;
#endif
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 70d2e4700f40744fe8b999f209d0253b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,531 +0,0 @@
// Copyright (c) 2023 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.UI;
using UnityEngine.Serialization;
using Vuplex.WebView.Internal;
namespace Vuplex.WebView {
/// <summary>
/// CanvasWebViewPrefab is a prefab that makes it easy to view and interact with an IWebView in a 2D Canvas.
/// It takes care of creating an IWebView, displaying its texture, and handling pointer interactions
/// from the user, like 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 outside of a Canvas, see WebViewPrefab instead.
/// </summary>
/// <remarks>
/// There are two ways to create a CanvasWebViewPrefab:
/// <list type="number">
/// <item>
/// By dragging the CanvasWebViewPrefab.prefab file into your scene via the editor and setting its "Initial URL" property.</item>
/// <item>
/// Or by creating an instance programmatically with CanvasWebViewPrefab.Instantiate(), waiting for
/// it to initialize, and then calling methods on its WebView property, like LoadUrl().
/// </item>
/// </list>
/// <para>
/// If your use case requires a high degree of customization, you can instead create an IWebView
/// outside of the prefab with Web.CreateWebView().
/// </para>
/// See also:
/// <list type="bullet">
/// <item>WebViewPrefab: https://developer.vuplex.com/webview/WebViewPrefab</item>
/// <item>How clicking and scrolling works: https://support.vuplex.com/articles/clicking</item>
/// <item>IWebView: https://developer.vuplex.com/webview/IWebView</item>
/// <item>Web (static methods): https://developer.vuplex.com/webview/Web</item>
/// </list>
/// </remarks>
[HelpURL("https://developer.vuplex.com/webview/CanvasWebViewPrefab")]
public partial class CanvasWebViewPrefab : BaseWebViewPrefab {
public override event EventHandler<ClickedEventArgs> Clicked {
add {
if (_native2DModeActive) {
_logNative2DModeWarning("The CanvasWebViewPrefab.Clicked event is not supported in Native 2D Mode.");
}
base.Clicked += value;
}
remove {
base.Clicked -= value;
}
}
public override event EventHandler<ScrolledEventArgs> Scrolled {
add {
if (_native2DModeActive) {
_logNative2DModeWarning("The CanvasWebViewPrefab.Scrolled event is not supported in Native 2D Mode.");
}
base.Scrolled += value;
}
remove {
base.Scrolled -= value;
}
}
/// <summary>
/// Enables or disables [Native 2D Mode](https://support.vuplex.com/articles/native-2d-mode/),
/// which makes it so that 3D WebView positions a native 2D webview in front of the Unity game view
/// instead of displaying web content as a texture in the Unity scene. The default is `false`. If set to `true` and the 3D WebView package
/// in use doesn't support Native 2D Mode, then the default rendering mode is used instead.
/// </summary>
/// <remarks>
/// Important notes:
/// <list type="bullet">
/// <item>
/// Native 2D Mode is only supported for 3D WebView for Android (non-Gecko) and 3D WebView for iOS.
/// For other packages, the default render mode is used instead.
/// </item>
/// <item>Native 2D Mode requires that the canvas's render mode be set to "Screen Space - Overlay".</item>
/// </list>
/// </remarks>
[Label("Native 2D Mode (Android, iOS, WebGL, and UWP only)")]
[Tooltip("Native 2D Mode positions a native 2D webview in front of the Unity game view instead of rendering web content as a texture in the Unity scene. Native 2D Mode provides better performance on iOS and UWP, because the default mode of rendering web content to a texture is slower. \n\nImportant notes:\n• Native 2D Mode is only supported for Android (non-Gecko), iOS, WebGL, and UWP. For the other 3D WebView packages, the default render mode is used instead.\n• Native 2D Mode requires that the canvas's render mode be set to \"Screen Space - Overlay\".")]
[HideInInspector]
[Header("Platform-specific")]
public bool Native2DModeEnabled;
/// <summary>
/// Determines whether the operating system's native on-screen keyboard is
/// automatically shown when a text input in the webview is focused. The default for
/// CanvasWebViewPrefab is `true`.
/// </summary>
/// <seealso cref="IWithNativeOnScreenKeyboard"/>
/// <remarks>
/// The native on-screen keyboard is only supported for the following packages:
/// <list type="bullet">
/// <item>3D WebView for Android (non-Gecko)</item>
/// <item>3D WebView for iOS</item>
/// </list>
/// </remarks>
/// <remarks>
/// 3D WebView for Android with Gecko Engine doesn't support automatically showing the native on-screen keyboard,
/// but you can use Unity's [TouchScreenKeyboard](https://docs.unity3d.com/ScriptReference/TouchScreenKeyboard.html)
/// API to show the keyboard and then send typed characters to the webview like described in [this article](https://support.vuplex.com/articles/how-to-use-a-third-party-keyboard).
/// </remarks>
/// <remarks>
/// On iOS, disabling the keyboard for one webview disables it for all webviews.
/// </remarks>
/// <seealso cref="IWithNativeOnScreenKeyboard"/>
/// <seealso cref="KeyboardEnabled"/>
[Label("Native On-Screen Keyboard (Android and iOS only)")]
[Tooltip("Determines whether the operating system's native on-screen keyboard is automatically shown when a text input in the webview is focused. The native on-screen keyboard is only supported for the following packages:\n• 3D WebView for Android (non-Gecko)\n• 3D WebView for iOS")]
public bool NativeOnScreenKeyboardEnabled = true;
/// <summary>
/// Gets or sets the prefab's resolution in pixels per Unity unit.
/// You can change the resolution to make web content appear larger or smaller.
/// The default resolution for CanvasWebViewPrefab is `1`.
/// </summary>
/// <remarks>
/// <para>
/// Setting a lower resolution decreases the pixel density, but has the effect
/// of making web content appear larger. Setting a higher resolution increases
/// the pixel density, but has the effect of making content appear smaller.
/// For more information on scaling web content, see
/// [this support article](https://support.vuplex.com/articles/how-to-scale-web-content).
/// </para>
/// <para>
/// When running in [Native 2D Mode](https://support.vuplex.com/articles/native-2d-mode), the Resolution field
/// isn't used because the device's native resolution is used instead. So, the Resolution field's value is inaccurate and changes to it are ignored.
/// </para>
/// </remarks>
/// <example>
/// <code>
/// // Set the resolution to 2.5px per Unity unit.
/// webViewPrefab.Resolution = 2.5f;
/// </code>
/// </example>
[Label("Resolution (px / Unity unit)")]
[Tooltip("You can change this to make web content appear larger or smaller. Note that This property is ignored when running in Native 2D Mode.")]
[HideInInspector]
[FormerlySerializedAs("InitialResolution")]
public float Resolution = 1;
/// <summary>
/// Determines the scroll sensitivity. The default sensitivity for CanvasWebViewPrefab is `15`.
/// </summary>
/// <remarks>
/// This property is ignored when running in [Native 2D Mode](https://support.vuplex.com/articles/native-2d-mode).
/// </remarks>
[HideInInspector]
[Tooltip("Determines the scroll sensitivity. Note that This property is ignored when running in Native 2D Mode.")]
public float ScrollingSensitivity = 15;
public override bool Visible {
get {
var native2DWebView = _getNative2DWebViewIfActive();
if (native2DWebView != null) {
return native2DWebView.Visible;
}
return base.Visible;
}
set {
var native2DWebView = _getNative2DWebViewIfActive();
if (native2DWebView != null) {
native2DWebView.SetVisible(value);
return;
}
base.Visible = value;
}
}
/// <summary>
/// Creates a new instance.
/// </summary>
/// <remarks>
/// The WebView property is available after initialization completes,
/// which is indicated by WaitUntilInitialized().
/// </remarks>
/// <example>
/// <code>
/// // Create a CanvasWebViewPrefab
/// var canvasWebViewPrefab = CanvasWebViewPrefab.Instantiate();
/// // Position the prefab how we want it
/// var canvas = GameObject.Find("Canvas");
/// canvasWebViewPrefab.transform.parent = canvas.transform;
/// var rectTransform = canvasWebViewPrefab.transform as RectTransform;
/// rectTransform.anchoredPosition3D = Vector3.zero;
/// rectTransform.offsetMin = Vector2.zero;
/// rectTransform.offsetMax = Vector2.zero;
/// canvasWebViewPrefab.transform.localScale = Vector3.one;
/// // Load a URL once the prefab finishes initializing
/// await canvasWebViewPrefab.WaitUntilInitialized();
/// canvasWebViewPrefab.WebView.LoadUrl("https://vuplex.com");
/// </code>
/// </example>
public static CanvasWebViewPrefab Instantiate() {
return Instantiate(new WebViewOptions());
}
/// <summary>
/// Like Instantiate(), except it also accepts an object
/// of options flags that can be used to alter the generated webview's behavior.
/// </summary>
public static CanvasWebViewPrefab Instantiate(WebViewOptions options) {
var prefabPrototype = (GameObject)Resources.Load("CanvasWebViewPrefab");
var gameObject = (GameObject)Instantiate(prefabPrototype);
var canvasWebViewPrefab = gameObject.GetComponent<CanvasWebViewPrefab>();
canvasWebViewPrefab._options = options;
return canvasWebViewPrefab;
}
/// <summary>
/// Like Instantiate(float, float), except it initializes the instance with an existing, initialized
/// IWebView instance. This causes the CanvasWebViewPrefab to use the existing
/// IWebView instance instead of creating a new one. This can be used, for example, to create multiple
/// WebViewPrefabs that are connected to the same IWebView, or to create a prefab for an IWebView
/// created by IWithPopups.PopupRequested.
/// </summary>
/// <example>
/// <code>
/// await firstWebViewPrefab.WaitUntilInitialized();
/// var secondWebViewPrefab = CanvasWebViewPrefab.Instantiate(firstWebViewPrefab.WebView);
/// // TODO: Position secondWebViewPrefab to the location where you want to display it.
/// </code>
/// </example>
public static CanvasWebViewPrefab Instantiate(IWebView webView) {
var prefabPrototype = (GameObject)Resources.Load("CanvasWebViewPrefab");
var gameObject = (GameObject)Instantiate(prefabPrototype);
var canvasWebViewPrefab = gameObject.GetComponent<CanvasWebViewPrefab>();
canvasWebViewPrefab.SetWebViewForInitialization(webView);
return canvasWebViewPrefab;
}
#region Non-public members
RectTransform _cachedRectTransform;
Canvas _canvas {
get {
if (_canvasGetter == null) {
_canvasGetter = new CachingGetter<Canvas>(GetComponentInParent<Canvas>, 1, this);
}
return _canvasGetter.GetValue();
}
}
CachingGetter<Canvas> _canvasGetter;
bool _native2DModeActive {
get {
var webViewWith2DMode = WebView as IWithNative2DMode;
return webViewWith2DMode != null && webViewWith2DMode.Native2DModeEnabled;
}
}
RectTransform _rectTransform {
get {
if (_cachedRectTransform == null) {
_cachedRectTransform = GetComponent<RectTransform>();
}
return _cachedRectTransform;
}
}
// Partial method implemented by various 3D WebView packages
// to provide platform-specific warnings.
partial void OnInit();
bool _canNative2DModeBeEnabled(bool logWarnings = false) {
if (_canvas != null && _canvas.renderMode == RenderMode.WorldSpace) {
if (logWarnings) {
_logNative2DModeWarning("CanvasWebViewPrefab.Native2DModeEnabled is enabled but the canvas's render mode is set to World Space, so Native 2D Mode will not be enabled. In order to use Native 2D Mode, please switch the canvas's render mode to \"Screen Space - Overlay\" or \"Screen Space - Camera\".");
}
return false;
}
if (VXUtils.XRSettings.enabled) {
if (logWarnings) {
_logNative2DModeWarning("CanvasWebViewPrefab.Native2DModeEnabled is enabled but XR is enabled, so Native 2D Mode will not be enabled.");
}
return false;
}
return true;
}
Rect _getRectForInitialization(bool preferNative2DMode) => preferNative2DMode ? _getScreenSpaceRect() : _rectTransform.rect;
protected override float _getResolution() {
if (Resolution > 0f) {
return Resolution;
}
WebViewLogger.LogError("Invalid value set for CanvasWebViewPrefab.Resolution: " + Resolution);
return 1;
}
IWithNative2DMode _getNative2DWebViewIfActive() {
var webViewWith2DMode = WebView as IWithNative2DMode;
if (webViewWith2DMode != null && webViewWith2DMode.Native2DModeEnabled) {
return webViewWith2DMode;
}
return null;
}
protected override bool _getNativeOnScreenKeyboardEnabled() => NativeOnScreenKeyboardEnabled;
protected override float _getScrollingSensitivity() => ScrollingSensitivity;
Rect _getScreenSpaceRect() {
var canvas = _canvas;
if (canvas == null) {
WebViewLogger.LogError("Unable to determine the screen space rect for Native 2D Mode because the CanvasWebViewPrefab is not placed in a Canvas. Please place the CanvasWebViewPrefab as the child of a Unity UI Canvas.");
return Rect.zero;
}
var worldCorners = new Vector3[4];
_rectTransform.GetWorldCorners(worldCorners);
var topLeftCorner = worldCorners[1];
var bottomRightCorner = worldCorners[3];
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay) {
var camera = canvas.worldCamera;
if (camera == null) {
WebViewLogger.LogError("Unable to determine the screen space rect for Native 2D Mode because the Canvas's render camera is not set. Please set the Canvas's \"Render Camera\" setting or change its render mode to \"Screen Space - Overlay\".");
} else {
topLeftCorner = camera.WorldToScreenPoint(topLeftCorner);
bottomRightCorner = camera.WorldToScreenPoint(bottomRightCorner);
}
}
var x = topLeftCorner.x;
var y = Screen.height - topLeftCorner.y;
var width = bottomRightCorner.x - topLeftCorner.x;
var height = topLeftCorner.y - bottomRightCorner.y;
var scaleFactor = _getScreenSpaceScaleFactor();
if (scaleFactor != 1f) {
x *= scaleFactor;
y *= scaleFactor;
width *= scaleFactor;
height *= scaleFactor;
}
return new Rect(x, y, width, height);
}
// Provides a scale factor to account for an issue where GetWorldCorners() is incorrect in the following scenarios:
// - If the screen resolution is changed at runtime using Screen.SetResolution().
// - If the "Resolution Scaling Mode" is set to "Fixed DPI" in Player Settings -> Resolution and Presentation (on Android).
float _getScreenSpaceScaleFactor() {
var display = Display.main;
if (display.renderingWidth == display.systemHeight && display.renderingHeight == display.systemWidth) {
// Some old versions of Unity (like 2019.4.33) have a bug in the Android player where after the device
// is rotated, the Display's rendering width and height are swapped but the system width and height aren't.
// Return 1 in that scenario to prevent computing an incorrect scale factor.
return 1f;
}
// Notes:
// - This approach doesn't work for detecting when "Resolution Scaling Mode" is set to "Fixed DPI" on iOS because
// display.systemWidth is equal to display.renderingWidth on iOS in that scenario. However, the native iOS plugin
// applies its own scale factor that works correctly for "Fixed DPI".
// - If an Android device has a notch and the "Render outside safe area" option is disabled, then the renderingWidth will be
// equal to the Screen.safeArea.width, which is less than the systemWidth. Unfortunately, it doesn't appear to
// be possible to detect if the "Resolution Scaling Mode" is set to "Fixed DPI" in that scenario because it doesn't
// appear to be possible to detect the "Fixed DPI" setting in native code like it is on iOS.
// - It's important to also check that display.systemWidth != Screen.currentResolution.width because on UWP,
// display.renderingWidth != display.systemWidth is true whenever the app's window isn't full screen, but
// display.systemWidth and Screen.currentResolution.width are still equal in that scenario.
// - This method used to work by comparing the current Screen.currentResolution to the original value of
// Screen.currentResolution from when the app started, but that approach caused an issue on iPads because
// Screen.currentResolution changes when multiple apps are shown side-by-side with the iPad's Split View.
var screenHasNotchAndRenderOutsideSafeAreaIsDisabled = false;
#if UNITY_ANDROID && !UNITY_EDITOR
screenHasNotchAndRenderOutsideSafeAreaIsDisabled = AndroidUtils.ScreenHasNotchAndRenderOutsideSafeAreaIsDisabled();
#endif
var screenResolutionChanged = display.renderingWidth != display.systemWidth &&
!screenHasNotchAndRenderOutsideSafeAreaIsDisabled &&
display.systemWidth != Screen.currentResolution.width;
if (screenResolutionChanged) {
float scaleFactor = (float)display.systemWidth / (float)display.renderingWidth;
return scaleFactor;
}
return 1f;
}
protected override ViewportMaterialView _getVideoLayer() {
var obj = transform.Find("VideoLayer");
return obj == null ? null : obj.GetComponent<ViewportMaterialView>();
}
protected override ViewportMaterialView _getView() {
var obj = transform.Find("CanvasWebViewPrefabView");
return obj == null ? null : obj.GetComponent<ViewportMaterialView>();
}
async void _initCanvasPrefab() {
try {
OnInit();
Initialized += _logNative2DRecommendationIfNeeded;
var preferNative2DMode = Native2DModeEnabled && _canNative2DModeBeEnabled(true);
var rect = _getRectForInitialization(preferNative2DMode);
if (_sizeIsInvalid(rect.size)) {
// If the prefab is nested in a LayoutGroup, its width and height will be zero on the first frame,
// so it's necessary to pass the LayoutGroup's RectTransform LayoutRebuilder.ForceRebuildLayoutImmediate().
// https://forum.unity.com/threads/force-immediate-layout-update.372630
var layoutGroup = GetComponentInParent<LayoutGroup>();
if (layoutGroup != null) {
LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)layoutGroup.transform);
rect = _getRectForInitialization(preferNative2DMode);
}
}
if (_logErrorIfSizeIsInvalid(rect.size)) {
return;
}
await _initBase(rect, preferNative2DMode);
} catch (Exception exception) {
// Catch any exceptions that occur during initialization because
// some applications terminate the application on uncaught exceptions.
Debug.LogException(exception);
}
}
bool _logErrorIfSizeIsInvalid(Vector2 size) {
if (_sizeIsInvalid(size)) {
WebViewLogger.LogError($"CanvasWebViewPrefab dimensions are invalid! Width: {size.x.ToString("f4")}, Height: {size.y.ToString("f4")}. To correct this, please adjust the CanvasWebViewPrefab's RectTransform to make it so that its width and height are both greater than zero. https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-RectTransform.html");
return true;
}
return false;
}
void _logNative2DModeWarning(string message) {
WebViewLogger.LogWarning(message + " For more info, please see this article: <em>https://support.vuplex.com/articles/native-2d-mode</em>");
}
void _logNative2DRecommendationIfNeeded(object sender, EventArgs eventArgs) {
var webViewWith2DMode = WebView as IWithNative2DMode;
if (_canNative2DModeBeEnabled() && webViewWith2DMode != null && !webViewWith2DMode.Native2DModeEnabled) {
WebViewLogger.LogTip("This platform supports Native 2D Mode, so consider enabling CanvasWebViewPrefab.Native2DModeEnabled for best results. For more info, see https://support.vuplex.com/articles/native-2d-mode .");
}
}
void OnDisable() {
// When in Native 2D Mode, hide the webview when the CanvasWebViewPrefab is deactivated.
var webView = _getNative2DWebViewIfActive();
if (webView != null) {
webView.SetVisible(false);
}
}
void OnEnable() {
// When in Native 2D Mode, show the webview when the CanvasWebViewPrefab is activated.
var webView = _getNative2DWebViewIfActive();
if (webView != null) {
webView.SetVisible(true);
}
}
protected override void _setVideoLayerPosition(Rect videoRect) {
var videoRectTransform = _videoLayer.transform as RectTransform;
// Use Vector2.Scale() because Vector2 * Vector2 isn't supported in Unity 2017.
videoRectTransform.anchoredPosition = Vector2.Scale(Vector2.Scale(videoRect.position, _rectTransform.rect.size), new Vector2(1, -1));
videoRectTransform.sizeDelta = Vector2.Scale(videoRect.size, _rectTransform.rect.size);
}
bool _sizeIsInvalid(Vector2 size) => !(size.x > 0f && size.y > 0f);
void Start() => _initCanvasPrefab();
protected override void Update() {
base.Update();
if (WebView == null) {
return;
}
_sizeInUnityUnits = _rectTransform.rect.size;
if (_logErrorIfSizeIsInvalid(_sizeInUnityUnits)) {
return;
}
// Handle updating the rect for a native 2D webview.
var native2DWebView = _getNative2DWebViewIfActive();
if (native2DWebView != null) {
var screenSpaceRect = _getScreenSpaceRect();
if (native2DWebView.Rect != screenSpaceRect) {
native2DWebView.SetRect(screenSpaceRect);
}
return;
}
// Handle resizing a regular webview.
_resizeWebViewIfNeeded();
}
#endregion
#region Obsolete APIs
// Added in v3.2, removed in v3.12.
[Obsolete("CanvasWebViewPrefab.Init() has been removed. The CanvasWebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
public void Init() {}
// Added in v3.2, removed in v3.12.
[Obsolete("CanvasWebViewPrefab.Init() has been removed. The CanvasWebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called.", true)]
public void Init(WebViewOptions options) {}
// Added in v3.10, removed in v3.12.
[Obsolete("CanvasWebViewPrefab.Init() has been removed. The CanvasWebViewPrefab script now initializes itself automatically, so Init() no longer needs to be called. Please use CanvasWebViewPrefab.SetWebViewForInitialization(IWebView) instead.", true)]
public void Init(IWebView webView) {}
// Deprecated in v4.0.
[Obsolete("CanvasWebViewPrefab.InitialResolution is now deprecated. Please use CanvasWebViewPrefab.Resolution instead.")]
public float InitialResolution {
get { return Resolution; }
set { Resolution = value; }
}
#endregion
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 879d31ebe92b040cbb3ef97e98278140
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,32 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Event args for WebViewPrefab.Clicked.
/// </summary>
public class ClickedEventArgs : EventArgs {
public ClickedEventArgs(Vector2 point) => Point = point;
/// <summary>
/// The normalized point that was passed to IWebView.Click().
/// </summary>
public readonly Vector2 Point;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 933218f5f10cb4e1eba142d6ef865e7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,53 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Event args for `ConsoleMessageLogged`.
/// </summary>
public class ConsoleMessageEventArgs : EventArgs {
public ConsoleMessageEventArgs(ConsoleMessageLevel level, string message, string source, int line) {
Level = level;
Message = message;
Source = source;
Line = line;
}
/// <summary>
/// The message's log level.
/// </summary>
public readonly ConsoleMessageLevel Level;
/// <summary>
/// The message logged to the JavaScript console.
/// </summary>
public readonly string Message;
/// <summary>
/// The name of the file from which the message was logged,
/// or `null` if the source is unknown.
/// </summary>
public readonly string Source;
/// <summary>
/// The line number of the file from which the message was logged,
/// or `0` if the source is unknown.
/// </summary>
public readonly int Line;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 409b384742d2744ed97f710a648314dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,25 +0,0 @@
// Copyright (c) 2023 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.
namespace Vuplex.WebView {
/// <summary>
/// Levels for messages logged to the JavaScript console.
/// </summary>
public enum ConsoleMessageLevel {
Debug,
Error,
Log,
Warning
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 46d435c1d5797420b83db35ed40f7526
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,120 +0,0 @@
// Copyright (c) 2023 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 Vuplex.WebView.Internal;
namespace Vuplex.WebView {
/// <summary>
/// An HTTP cookie.
/// </summary>
[Serializable]
public class Cookie {
/// <summary>
/// The name of the cookie.
/// </summary>
public string Name;
/// <summary>
/// The value of the cookie.
/// </summary>
public string Value;
/// <summary>
/// The domain to which the cookie belongs (e.g. "www.vuplex.com", "example.com").
/// </summary>
public string Domain;
/// <summary>
/// The URL path of the cookie (e.g. "/", "/products/1234").
/// The default is "/".
/// </summary>
public string Path = "/";
/// <summary>
/// A number representing the expiration date of the cookie as the number of seconds since the UNIX epoch, or 0
/// if there is no expiration date. An expiration date is not provided for session cookies.
/// </summary>
public int ExpirationDate;
/// <summary>
/// Indicates whether the cookie is marked as HttpOnly (i.e. the cookie is inaccessible to client-side scripts).
/// </summary>
public bool HttpOnly;
/// <summary>
/// Indicates whether cookie is marked as secure (i.e. its scope is limited to secure channels, typically HTTPS).
/// </summary>
public bool Secure;
/// <summary>
/// Indicates whether the cookie is valid.
/// </summary>
public bool IsValid {
get {
var isValid = true;
if (Name == null) {
WebViewLogger.LogWarning("Invalid value for Cookie.Name: " + Name);
isValid = false;
}
if (Value == null) {
WebViewLogger.LogWarning("Invalid value for Cookie.Value: " + Value);
isValid = false;
}
if (Domain == null || !Domain.Contains(".") || Domain.Contains("/")) {
WebViewLogger.LogWarning("Invalid value for Cookie.Domain: " + Domain);
isValid = false;
}
if (Path == null) {
WebViewLogger.LogWarning("Invalid value for Cookie.Path: " + Path);
isValid = false;
}
return isValid;
}
}
/// <summary>
/// Deserializes a Cookie array from JSON.
/// </summary>
public static Cookie[] ArrayFromJson(string serializedCookies) {
if (serializedCookies == "null") {
return new Cookie[0];
}
var cookiesWrapper = JsonUtility.FromJson<JsonArrayWrapper<Cookie>>(serializedCookies);
var cookies = cookiesWrapper.Items ?? new Cookie[0];
return cookies;
}
/// <summary>
/// Deserializes a Cookie from JSON.
/// </summary>
public static Cookie FromJson(string serializedCookie) {
if (serializedCookie == "null") {
return null;
}
return JsonUtility.FromJson<Cookie>(serializedCookie);
}
/// <summary>
/// Serializes the instance to JSON.
/// </summary>
public string ToJson() => JsonUtility.ToJson(this);
public override string ToString() => ToJson();
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 210d3253f4a834f5c912b7547d42c28e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,308 +0,0 @@
// Copyright (c) 2023 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.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Vuplex.WebView.Internal;
#if VUPLEX_MRTK
using Microsoft.MixedReality.Toolkit.Input;
#endif
namespace Vuplex.WebView {
[HelpURL("https://developer.vuplex.com/webview/IPointerInputDetector")]
public class DefaultPointerInputDetector : MonoBehaviour,
IPointerInputDetector,
IBeginDragHandler,
IDragHandler,
IPointerClickHandler,
IPointerDownHandler,
IPointerEnterHandler,
IPointerExitHandler,
IPointerUpHandler,
#if VUPLEX_MRTK
IMixedRealityPointerHandler,
#endif
IScrollHandler {
public event EventHandler<EventArgs<Vector2>> BeganDrag;
public event EventHandler<EventArgs<Vector2>> Dragged;
public event EventHandler<PointerEventArgs> PointerDown;
public event EventHandler PointerEntered;
public event EventHandler<EventArgs<Vector2>> PointerExited;
public event EventHandler<EventArgs<Vector2>> PointerMoved;
public event EventHandler<PointerEventArgs> PointerUp;
public event EventHandler<ScrolledEventArgs> Scrolled;
public bool PointerMovedEnabled { get; set; }
/// <see cref="IBeginDragHandler"/>
public void OnBeginDrag(PointerEventData eventData) {
_raiseBeganDragEvent(_convertToEventArgs(eventData));
}
/// <see cref="IDragHandler"/>
public void OnDrag(PointerEventData eventData) {
// The point is Vector3.zero when the user drags off of the screen.
if (!_positionIsZero(eventData)) {
_raiseDraggedEvent(_convertToEventArgs(eventData));
}
}
/// <summary>
/// VRIF requires IPointerClickHandler to be implemented in order to detect the object
/// and invoke its OnPointerDown() and OnPointerUp() methods.
/// </summary>
/// <see cref="IPointerClickHandler"/>
public void OnPointerClick(PointerEventData eventData) {}
/// <see cref="IPointerDownHandler"/>
public virtual void OnPointerDown(PointerEventData eventData) {
_raisePointerDownEvent(_convertToPointerEventArgs(eventData));
}
/// <see cref="IPointerEnterHandler"/>
public void OnPointerEnter(PointerEventData eventData) {
_isHovering = true;
_raisePointerEnteredEvent(EventArgs.Empty);
}
/// <see cref="IPointerExitHandler"/>
public void OnPointerExit(PointerEventData eventData) {
_isHovering = false;
// When StandaloneInputModule triggers OnPointerExit, eventData.pointerCurrentRaycast.worldPosition is usually Vector3.zero,
// so for world space, just fallback to sending a normalized point of Vector2.zero.
var point = _positionIsZero(eventData) ? Vector2.zero : _convertToNormalizedPoint(eventData);
// Since this is an exit event, the coordinate can sometimes be just outside the bounds of [0, 1], so clamp it to [0, 1].
for (var i = 0; i < 2; i++) {
if (point[i] < 0f) {
point[i] = 0f;
} else if (point[i] > 1f) {
point[i] = 1f;
}
}
_raisePointerExitedEvent(new EventArgs<Vector2>(point));
}
/// <see cref="IPointerUpHandler"/>
public virtual void OnPointerUp(PointerEventData eventData) {
_raisePointerUpEvent(_convertToPointerEventArgs(eventData));
}
/// <see cref="IScrollHandler"/>
public void OnScroll(PointerEventData eventData) {
var scrollDelta = -1 * eventData.scrollDelta;
_raiseScrolledEvent(new ScrolledEventArgs(scrollDelta, _convertToNormalizedPoint(eventData)));
}
bool _isHovering;
EventArgs<Vector2> _convertToEventArgs(Vector3 worldPosition) {
var screenPoint = _convertToNormalizedPoint(worldPosition);
return new EventArgs<Vector2>(screenPoint);
}
EventArgs<Vector2> _convertToEventArgs(PointerEventData pointerEventData) {
var screenPoint = _convertToNormalizedPoint(pointerEventData);
return new EventArgs<Vector2>(screenPoint);
}
protected virtual Vector2 _convertToNormalizedPoint(PointerEventData pointerEventData) {
return _convertToNormalizedPoint(pointerEventData.pointerCurrentRaycast.worldPosition);
}
protected virtual Vector2 _convertToNormalizedPoint(Vector3 worldPosition) {
// Note: transform.parent is WebViewPrefabResizer
var localPosition = transform.parent.InverseTransformPoint(worldPosition);
var point = new Vector2(1 - localPosition.x, -1 * localPosition.y);
// In some cases, the point may be outside the range of [0, 1], so we need to clamp it to [0, 1]. Scenarios where that's the case:
// - OnPointerExit()
// - OnPointerUp(), if the mouse button is released after dragging outside of the webview.
for (var i = 0; i < 2; i++) {
if (point[i] < 0f) {
point[i] = 0f;
} else if (point[i] > 1f) {
point[i] = 1f;
}
}
return point;
}
PointerEventArgs _convertToPointerEventArgs(PointerEventData eventData) {
return new PointerEventArgs {
Point = _convertToNormalizedPoint(eventData),
Button = (MouseButton)eventData.button,
// StandaloneInputModule incorrectly specifies a click count of 0
// for PointerDown events, so set the minimum to 1 click.
ClickCount = Math.Max(eventData.clickCount, 1)
};
}
/// <summary>
/// Unity's event system doesn't include a standard pointer event
/// for hovering (i.e. there's no `IPointerHoverHandler` interface).
/// So, this method implements the equivalent functionality for different input modules.
/// </summary>
PointerEventData _getLastPointerEventData() {
var currentInputModule = EventSystem.current == null ? null : EventSystem.current.currentInputModule;
// Support for input modules that derive from PointerInputModule, like StandaloneInputModule.
var pointerInputModule = currentInputModule as PointerInputModule;
if (pointerInputModule != null) {
// Use reflection to get access to the protected GetPointerData()
// method. Unity isn't going to change this API because most input modules
// extend PointerInputModule. Note that GetPointerData() is used instead
// of GetLastPointerEventData() because the latter doesn't work with
// the Oculus SDK's OVRInputModule.
var args = new object[] { PointerInputModule.kMouseLeftId, null, false };
pointerInputModule.GetType().InvokeMember(
"GetPointerData",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null,
pointerInputModule,
args
);
// The second argument is an out param.
var pointerEventData = args[1] as PointerEventData;
return pointerEventData;
}
#if ENABLE_INPUT_SYSTEM
// Support for the new InputSystem's InputSystemUIInputModule.
var uiInputModule = currentInputModule as UnityEngine.InputSystem.UI.InputSystemUIInputModule;
if (uiInputModule != null) {
var pointerEventData = new PointerEventData(EventSystem.current);
var raycastResult = uiInputModule.GetLastRaycastResult(0);
pointerEventData.position = raycastResult.screenPosition;
pointerEventData.pointerCurrentRaycast = uiInputModule.GetLastRaycastResult(0);
return pointerEventData;
}
#endif
#if VUPLEX_XR_INTERACTION_TOOLKIT
// Support for XR Interaction Toolkit.
return Internal.XritPointerEventHelper.Instance.LastPointerEventData;
#else
return null;
#endif
}
protected virtual bool _positionIsZero(PointerEventData eventData) => eventData.pointerCurrentRaycast.worldPosition == Vector3.zero;
protected void _raiseBeganDragEvent(EventArgs<Vector2> eventArgs) => BeganDrag?.Invoke(this, eventArgs);
protected void _raiseDraggedEvent(EventArgs<Vector2> eventArgs) => Dragged?.Invoke(this, eventArgs);
protected void _raisePointerDownEvent(PointerEventArgs eventArgs) => PointerDown?.Invoke(this, eventArgs);
protected void _raisePointerEnteredEvent(EventArgs eventArgs) => PointerEntered?.Invoke(this, eventArgs);
protected void _raisePointerExitedEvent(EventArgs<Vector2> eventArgs) => PointerExited?.Invoke(this, eventArgs);
void _raisePointerMovedIfNeeded() {
if (!(PointerMovedEnabled && _isHovering)) {
return;
}
var pointerEventData = _getLastPointerEventData();
if (pointerEventData == null) {
return;
}
var point = _convertToNormalizedPoint(pointerEventData);
if (!(point.x >= 0f && point.y >= 0f)) {
// This can happen while the prefab is being resized.
return;
}
_raisePointerMovedEvent(new EventArgs<Vector2>(point));
}
protected void _raisePointerMovedEvent(EventArgs<Vector2> eventArgs) => PointerMoved?.Invoke(this, eventArgs);
protected void _raisePointerUpEvent(PointerEventArgs eventArgs) => PointerUp?.Invoke(this, eventArgs);
protected void _raiseScrolledEvent(ScrolledEventArgs eventArgs) => Scrolled?.Invoke(this, eventArgs);
protected virtual void Update() => _raisePointerMovedIfNeeded();
// Code specific to Microsoft's Mixed Reality Toolkit.
#if VUPLEX_MRTK
bool _beganDragEmitted;
/// <see cref="IMixedRealityPointerHandler"/>
public void OnPointerClicked(MixedRealityPointerEventData eventData) {}
/// <see cref="IMixedRealityPointerHandler"/>
public void OnPointerDragged(MixedRealityPointerEventData eventData) {
var eventArgs = _convertToEventArgs(eventData.Pointer.Result.Details.Point);
if (_beganDragEmitted) {
_raiseDraggedEvent(eventArgs);
} else {
_beganDragEmitted = true;
_raiseBeganDragEvent(eventArgs);
}
}
/// <see cref="IMixedRealityPointerHandler"/>
public void OnPointerDown(MixedRealityPointerEventData eventData) {
// Set IsTargetPositionLockedOnFocusLock to false, or else the Point
// coordinates will be locked and won't change in OnPointerDragged or OnPointerUp.
eventData.Pointer.IsTargetPositionLockedOnFocusLock = false;
_beganDragEmitted = false;
var screenPoint = _convertToNormalizedPoint(eventData.Pointer.Result.Details.Point);
_raisePointerDownEvent(new PointerEventArgs { Point = screenPoint });
}
/// <see cref="IMixedRealityPointerHandler"/>
public void OnPointerUp(MixedRealityPointerEventData eventData) {
var screenPoint = _convertToNormalizedPoint(eventData.Pointer.Result.Details.Point);
_raisePointerUpEvent(new PointerEventArgs { Point = screenPoint });
}
void Start() {
WebViewLogger.Log("Just a heads-up: please ignore the warning 'BoxCollider is null...' warning from MRTK. WebViewPrefab doesn't use a BoxCollider, so it sets the bounds of NearInteractionTouchable manually, but MRTK doesn't provide a way to disable the warning.");
// Add a NearInteractionTouchable script to allow touch interactions
// to trigger the IMixedRealityPointerHandler methods.
var touchable = gameObject.AddComponent<NearInteractionTouchable>();
touchable.EventsToReceive = TouchableEventType.Pointer;
touchable.SetBounds(Vector2.one);
touchable.SetLocalForward(new Vector3(0, 0, -1));
}
#endif
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9b5d2e4670d86405386a27a4b18941bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,69 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Event args for IWithDownloads.DownloadProgressChanged.
/// </summary>
public class DownloadChangedEventArgs : EventArgs {
public DownloadChangedEventArgs(string contentType, string filePath, string id, float progress, ProgressChangeType type, string url) {
ContentType = contentType;
FilePath = filePath;
Id = id;
Progress = progress;
Type = type;
Url = url;
}
/// <summary>
/// The mime type indicated by the Content-Type response header,
/// or `null` if no content type was specified.
/// </summary>
public readonly string ContentType;
/// <summary>
/// The full file path of the downloaded file. Files are downloaded to
/// Application.temporaryCachePath, but you can move them to a different
/// location after they finish downloading.
/// </summary>
public readonly string FilePath;
/// <summary>
/// An identifier for the file, which can be used to track the
/// file's download progress across multiple invocations of the DownloadProgressChanged event.
/// </summary>
public readonly string Id;
/// <summary>
/// The estimated download progress, normalized to a float between 0 and 1.
/// Note that not all platforms support intermediate progress updates.
/// </summary>
public readonly float Progress;
/// <summary>
/// The download progress event type. Note that not all platforms
/// support the Updated event type.
/// </summary>
public readonly ProgressChangeType Type;
/// <summary>
/// The URL from which the file was downloaded.
/// </summary>
public readonly string Url;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f0e00d0f766c742a9976e3b2d7382468
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,47 +0,0 @@
// Copyright (c) 2023 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.
namespace Vuplex.WebView {
/// <summary>
/// Options for how drag interactions affect
/// WebViewPrefab and CanvasWebViewPrefab.
/// </summary>
/// <seealso cref="WebViewPrefab.DragMode"/>
/// <seealso cref="CanvasWebViewPrefab.DragMode"/>
public enum DragMode {
/// <summary>
/// Drag interactions trigger scrolling (default). On platforms that support
/// IWithTouch, touch events are used instead of mouse events. On platforms
/// that don't support IWithTouch, mouse events are used, but dragging
/// causes the page to be scrolled with IWebView.Scroll().
/// </summary>
DragToScroll,
/// <summary>
/// Drag interactions trigger dragging within the web page
/// via mouse events (e.g. dragging to select text, drag-and-drop).
/// </summary>
/// <remarks>
/// For information on the limitations of drag interactions on iOS and UWP, please see
/// https://support.vuplex.com/articles/hover-and-drag-limitations.
/// </remarks>
DragWithinPage,
/// <summary>
/// Drag interactions have no effect.
/// </summary>
Disabled
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 43e0cfa25fe0e4b95bfd9835c371ea65
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,28 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// A generic version of System.EventArgs.
/// </summary>
public class EventArgs<T> : EventArgs {
public T Value { get; private set; }
public EventArgs(T val) => Value = val;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4e7ac5abaf9484dd98eeb848895e34b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,59 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Event args for FileSelectionRequested. To handle file selection, the application
/// must either call Continue() to select files or call Cancel() to cancel file selection.
/// </summary>
public class FileSelectionEventArgs : EventArgs {
public FileSelectionEventArgs(string[] acceptFilters, bool multipleAllowed, Action<string[]> continueCallback, Action cancelCallback) {
AcceptFilters = acceptFilters;
MultipleAllowed = multipleAllowed;
Continue = continueCallback;
Cancel = cancelCallback;
}
/// <summary>
/// Filters provided by the page to specify the allowed file types. If the page didn't specify
/// any file types, then this array is empty.
/// </summary>
/// <seealso href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept">
/// MDN's documentation for the file input `accept` attribute
/// </seealso>
public readonly string[] AcceptFilters;
/// <summary>
/// Indicates whether multiple files are permitted.
/// </summary>
/// <seealso href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#multiple">
/// MDN's documentation for the file input `multiple` attribute
/// </seealso>
public readonly bool MultipleAllowed;
/// <summary>
/// To select files, call this callback with an array of one or more absolute file paths.
/// </summary>
public readonly Action<string[]> Continue;
/// <summary>
/// Call this callback to cancel file selection.
/// </summary>
public readonly Action Cancel;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9c5eee343014c4c80afed57a988e957c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,44 +0,0 @@
// Copyright (c) 2023 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 Vuplex.WebView.Internal;
namespace Vuplex.WebView {
/// <summary>
/// Event args for FocusedInputFieldChanged.
/// </summary>
public class FocusedInputFieldChangedEventArgs : EventArgs {
public FocusedInputFieldChangedEventArgs(FocusedInputFieldType type) => Type = type;
/// <summary>
/// The type of input field focused.
/// </summary>
public readonly FocusedInputFieldType Type;
public static FocusedInputFieldType ParseType(string typeString) {
switch (typeString) {
case "TEXT":
return FocusedInputFieldType.Text;
case "NONE":
return FocusedInputFieldType.None;
default:
WebViewLogger.LogWarning("Unrecognized FocusedInputFieldType string: " + typeString);
return FocusedInputFieldType.None;
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3b441f81b66cd453b9ce9d4b51bcd4fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,33 +0,0 @@
// Copyright (c) 2023 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.
namespace Vuplex.WebView {
/// <summary>
/// Indicates the type of input field focused.
/// </summary>
public enum FocusedInputFieldType {
/// <summary>
/// Indicates that a text input field is focused. Examples of a text input field include
/// an `input` element, a `textarea` element, and an element with a `contentEditable`
/// attribute.
/// </summary>
Text,
/// <summary>
/// Indicates that no input field is focused.
/// </summary>
None
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2b121a7f539b6486e943b21290c60197
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,111 +0,0 @@
// Copyright (c) 2023 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.Threading.Tasks;
namespace Vuplex.WebView {
/// <summary>
/// Provides methods for getting, setting, and deleting HTTP cookies.
/// You can access the ICookieManager via Web.CookieManager.
/// </summary>
/// <remarks>
/// When developing code that interacts with
/// cookies, it may also be helpful to view a webview's cookies using
/// [remote debugging](https://support.vuplex.com/articles/how-to-debug-web-content).
/// </remarks>
public interface ICookieManager {
/// <summary>
/// Deletes all of the cookies that match the given URL and returns a
/// Task&lt;bool&gt; indicating whether the deletion succeeded. A `cookieName`
/// can be optionally passed as a second parameter to further filter
/// to a specific cookie.
/// If a deletion fails, it could be because the URL was invalid.
/// For more details regarding a failure, check the Unity logs.
/// </summary>
/// <remarks>
/// Important notes:
/// <list type="bullet">
/// <item>On Windows and macOS, if this method is called without a `cookieName` it only deletes cookies that were set without an explicit Domain attribute.</item>
/// <item>On versions of iOS older than iOS 11, session cookies are excluded because WKHTTPCookieStore is only supported in iOS 11 and newer.</item>
/// </list>
/// </remarks>
/// <example>
/// <code>
/// if (Web.CookieManager == null) {
/// Debug.Log("Web.CookieManager isn't supported on this platform.");
/// return;
/// }
/// // Delete all the cookies for this cookie test page, which will reset the test.
/// var succeeded = await Web.CookieManager.DeleteCookies("http://www.whatarecookies.com/cookietest.asp");
/// Debug.Log("Cookie deletion succeeded: " + succeeded);
/// </code>
/// </example>
Task<bool> DeleteCookies(string url, string cookieName = null);
/// <summary>
/// Gets all of the cookies that match the given URL. A `cookieName`
/// can be optionally passed as a second parameter to further filter
/// results to a specific cookie.
/// </summary>
/// <remarks>
/// Important notes:
/// <list type="bullet">
/// <item>On Android, the cookies returned only have their Name and Value fields set. The other fields (e.g. Domain, Path) are set to their default values because Android doesn't provide a way to access those values.</item>
/// <item>On versions of iOS older than iOS 11, session cookies are excluded because WKHTTPCookieStore is only supported in iOS 11 and newer.</item>
/// </list>
/// </remarks>
/// <example>
/// <code>
/// if (Web.CookieManager == null) {
/// Debug.Log("Web.CookieManager isn't supported on this platform.");
/// return;
/// }
/// // Get the cookie named "NID" set by google.com.
/// var cookies = await Web.CookieManager.GetCookies("https://www.google.com", "NID");
/// if (cookies.Length > 0) {
/// Debug.Log("Cookie: " + cookies[0]);
/// } else {
/// Debug.Log("Cookie not found.");
/// }
/// </code>
/// </example>
Task<Cookie[]> GetCookies(string url, string cookieName = null);
/// <summary>
/// Sets the given cookie and returns a Task&lt;bool&gt; indicating
/// whether the cookie was set successfully.
/// If setting the cookie fails, it could be because the data in the provided Cookie
/// was malformed. For more details regarding a failure, please check the Unity logs.
/// </summary>
/// <example>
/// <code>
/// if (Web.CookieManager == null) {
/// Debug.Log("Web.CookieManager isn't supported on this platform.");
/// return;
/// }
/// var success = await Web.CookieManager.SetCookie(new Cookie {
/// Domain = "vuplex.com",
/// Path = "/",
/// Name = "example_name",
/// Value = "example_value",
/// Secure = true,
/// // Expire one day from now
/// ExpirationDate = (int)DateTimeOffset.Now.ToUnixTimeSeconds() + 60 * 60 * 24
/// });
/// </code>
/// </example>
Task<bool> SetCookie(Cookie cookie);
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4f02f1602fbb4443fa664b18925d2725
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,73 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// An interface that can be passed to WebViewPrefab.SetPointerInputDetector()
/// CanvasWebViewPrefab.SetPointerInputDetector() to override how the prefab detects pointer input.
/// For example implementations of this interface, please see 3D WebView's DefaultPointerInputDetector.cs
/// and CanvasPointerInputDetector.cs scripts.
/// </summary>
public interface IPointerInputDetector {
/// <summary>
/// Indicates the normalized point for the beginning of a drag interaction.
/// </summary>
event EventHandler<EventArgs<Vector2>> BeganDrag;
/// <summary>
/// Indicates the normalized point for the continuation of a drag interaction.
/// </summary>
event EventHandler<EventArgs<Vector2>> Dragged;
/// <summary>
/// Indicates a pointer down interaction occurred.
/// </summary>
event EventHandler<PointerEventArgs> PointerDown;
/// <summary>
/// Indicates that the pointer entered.
/// </summary>
event EventHandler PointerEntered;
/// <summary>
/// Indicates the normalized point where the pointer exited.
/// </summary>
event EventHandler<EventArgs<Vector2>> PointerExited;
/// <summary>
/// Indicates the normalized point where the pointer moved.
/// </summary>
event EventHandler<EventArgs<Vector2>> PointerMoved;
/// <summary>
/// Indicates a pointer up interaction occurred.
/// </summary>
event EventHandler<PointerEventArgs> PointerUp;
/// <summary>
/// Indicates a scroll interaction occurred.
/// </summary>
event EventHandler<ScrolledEventArgs> Scrolled;
/// <summary>
/// The prefab sets this property to indicate whether
/// the PointerMoved event should be enabled.
/// </summary>
bool PointerMovedEnabled { get; set; }
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d10c6c706509f46afa9a965d80cf0848
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,946 +0,0 @@
// Copyright (c) 2023 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.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
namespace Vuplex.WebView {
/// <summary>
/// IWebView is the primary interface for loading and interacting with web content.
/// It contains methods and properties for common browser-related functionality,
/// like LoadUrl(), GoBack(), Reload(), and ExecuteJavaScript().
/// </summary>
/// <remarks>
/// <para>
/// To create an IWebView, instantiate a WebViewPrefab or CanvasWebViewPrefab. After
/// the prefab is initialized, you can access its IWebView via the WebViewPrefab.WebView property.
/// If your use case requires a high degree of customization, you can instead create
/// an IWebView outside of a prefab (to connect to your own custom GameObject) by
/// using Web.CreateWebView().
/// </para>
/// <para>
/// For additional functionality, you can cast an IWebView to an interface for a specific
/// feature, like IWithDownloads or IWithPopups. For a list of additional feature interfaces and
/// information about how to use them, see this page: https://developer.vuplex.com/webview/additional-interfaces
/// </para>
/// See also:
/// <list type="bullet">
/// <item>WebViewPrefab: https://developer.vuplex.com/webview/WebViewPrefab</item>
/// <item>CanvasWebViewPrefab: https://developer.vuplex.com/webview/CanvasWebViewPrefab</item>
/// <item>Web (static methods): https://developer.vuplex.com/webview/Web</item>
/// </list>
/// </remarks>
public interface IWebView {
/// <summary>
/// Indicates that JavaScript in the page has called window.close(). Calling window.close()
/// doesn't automatically close a webview, but the application can listen to this CloseRequested
/// event to detect when window.close() is called and then choose whether to destroy the
/// webview in response to it.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.CloseRequested += (sender, eventArgs) => {
/// Debug.Log("Destroying the WebViewPrefab because window.close() was called.");
/// webViewPrefab.Destroy();
/// };
/// </code>
/// </example>
event EventHandler CloseRequested;
/// <summary>
/// Indicates that a message was logged to the JavaScript console.
/// </summary>
/// <remarks>
/// The 3D WebView packages for Android with Gecko, iOS, and UWP have the following limitations:
/// <list type="bullet">
/// <item>
/// Only messages explicitly passed to a console method like console.log() are included,
/// and other messages like uncaught errors or network errors aren't automatically included.
/// </item>
/// <item>Messages from iframes aren't included.</item>
/// <item>Messages logged early when the page starts loading may be missed.</item>
/// </list>
/// For Android Gecko, an alternative that avoids these limitations is to call
/// AndroidGeckoWebView.SetConsoleOutputEnabled().
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.ConsoleMessageLogged += (sender, eventArgs) => {
/// Debug.Log($"Console message logged: [{eventArgs.Level}] {eventArgs.Message}");
/// };
/// </code>
/// </example>
/// <seealso cref="WebViewPrefab.LogConsoleMessages"/>
/// <seealso href="https://support.vuplex.com/articles/how-to-debug-web-content">Remote debugging</seealso>
event EventHandler<ConsoleMessageEventArgs> ConsoleMessageLogged;
/// <summary>
/// Indicates when an input field has been focused or unfocused. This can be used,
/// for example, to determine when to show or hide an on-screen keyboard.
/// This event is also raised when a focused input field is clicked subsequent times.
/// Note that this event is currently only fired for input fields focused in the main frame
/// and is not fired for input fields in iframes.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.FocusedInputFieldChanged += (sender, eventArgs) => {
/// Debug.Log("Focused input field changed. Text input is focused: " + eventArgs.Type == FocusedInputFieldType.Text);
/// };
/// </code>
/// </example>
event EventHandler<FocusedInputFieldChangedEventArgs> FocusedInputFieldChanged;
/// <summary>
/// Indicates changes in the loading status of a web page. This event can be used, for example,
/// to detect when a page finishes loading or to implement a load progress bar. This event indicates
/// the following types of load events:<br/>
/// - `Started`: a new page started loading.<br/>
/// - `Updated`: the load progress percentage was updated.<br/>
/// - `Finished`: a page finished loading.<br/>
/// - `Failed`: a page failed to load.<br/>
/// </summary>
/// <remarks>
/// For 2D WebView for WebGL, LoadProgressChanged only indicates the ProgressChangeType.Started and Finished events,
/// and it's unable to indicate the Failed or Updated events.
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.LoadProgressChanged += (sender, eventArgs) => {
/// Debug.Log($"Load progress changed: {eventArgs.Type}, {eventArgs.Progress}");
/// if (eventArgs.Type == ProgressChangeType.Finished) {
/// Debug.Log("The page finished loading");
/// }
/// };
/// </code>
/// </example>
/// <seealso cref="WaitForNextPageLoadToFinish"/>
event EventHandler<ProgressChangedEventArgs> LoadProgressChanged;
/// <summary>
/// Indicates that JavaScript running in the page used the `window.vuplex.postMessage`
/// JavaScript API to emit a message to the Unity application. For more details, please see
/// [this support article](https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp).
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// // Add JavaScript to the page that sends a message.
/// webViewPrefab.WebView.PageLoadScripts.Add(@"
/// window.vuplex.postMessage('Hello from JavaScript!');
/// ");
/// webViewPrefab.WebView.MessageEmitted += (sender, eventArgs) => {
/// Debug.Log("Message received from JavaScript: " + eventArgs.Value);
/// };
/// </code>
/// </example>
/// <seealso cref="ExecuteJavaScript"/>
/// <seealso cref="PageLoadScripts"/>
event EventHandler<EventArgs<string>> MessageEmitted;
/// <summary>
/// Indicates that the page failed to load. This can happen, for instance,
/// if DNS is unable to resolve the hostname.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.PageLoadFailed += (sender, eventArgs) => {
/// Debug.Log("Page load failed");
/// };
/// </code>
/// </example>
event EventHandler PageLoadFailed;
/// <summary>
/// Indicates that the browser engine reported that its process for the webview terminated unexpectedly,
/// either because the web process crashed or because it was killed by the
/// operating system. The webview cannot be used after it has been terminated, so if this event occurs, the webview must be
/// destroyed, and then the appication can optionally create a new webview to replace it.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.Terminated += (sender, eventArgs) => {
/// Debug.Log("The web content process was terminated. Reason: " + eventArgs.Type);
/// // Destroy the webview because it can't be used any more.
/// webViewPrefab.Destroy();
/// // TODO: If the application still needs a webview, it can create a new one with WebViewPrefab.Instantiate().
/// };
/// </code>
/// </example>
event EventHandler<TerminatedEventArgs> Terminated;
/// <summary>
/// Indicates that the page's title changed.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.TitleChanged += (sender, eventArgs) => {
/// Debug.Log("Page title changed: " + eventArgs.Value);
/// };
/// </code>
/// </example>
event EventHandler<EventArgs<string>> TitleChanged;
/// <summary>
/// Indicates that the URL of the webview changed, either
/// due to user interaction or JavaScript.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.UrlChanged += (sender, eventArgs) => {
/// Debug.Log("URL changed: " + eventArgs.Url);
/// };
/// </code>
/// </example>
/// <seealso cref="Url"/>
event EventHandler<UrlChangedEventArgs> UrlChanged;
/// <summary>
/// Gets a value indicating whether the instance has been disposed via Dispose().
/// </summary>
bool IsDisposed { get; }
/// <summary>
/// Gets a value indicating whether the instance has been initialized via Init().
/// </summary>
bool IsInitialized { get; }
/// <summary>
/// Gets a list of JavaScript scripts that are automatically executed in every new page that is loaded.
/// </summary>
/// <remarks>
/// This list is empty by default, but the application can add scripts. When used in conjunction
/// with 3D WebView's [message passing API](https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp),
/// it's possible to modify the browser's behavior in significant ways, similar to creating browser extensions.
/// </remarks>
/// <example>
/// <code>
/// // Add a script that automatically hides all scrollbars.
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.PageLoadScripts.Add(@"
/// var styleElement = document.createElement('style');
/// styleElement.innerText = 'body::-webkit-scrollbar { display: none; }';
/// document.head.appendChild(styleElement);
/// ");
/// </code>
/// </example>
/// <seealso cref="ExecuteJavaScript"/>
/// <seealso href="https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp">JS-to-C# message passing</seealso>
List<string> PageLoadScripts { get; }
/// <summary>
/// Gets the instance's plugin type.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// Debug.Log("Plugin type: " + webViewPrefab.WebView.PluginType);
/// </code>
/// </example>
WebPluginType PluginType { get; }
/// <summary>
/// Gets the webview's size in pixels.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// Debug.Log("Size: " + webViewPrefab.WebView.Size);
/// </code>
/// </example>
/// <seealso cref="Resize"/>
/// <seealso cref="WebViewPrefab.Resolution"/>
Vector2Int Size { get; }
/// <summary>
/// Gets the texture for the webview's web content, or `null` if running in
/// Native 2D Mode. In order to render the texture, the application must use
/// a Material created with CreateMaterial().
/// </summary>
/// <remarks>
/// <para>
/// This texture is an "external texture" created with
/// Texture2D.CreateExternalTexture(). An undocumented characteristic
/// of external textures in Unity is that not all Texture2D methods work for them.
/// For example, Texture2D.GetRawTextureData() and ImageConversion.EncodeToPNG()
/// fail for external textures. To compensate, the IWebView interface includes
/// its own GetRawTextureData() and CaptureScreenshot() methods to replace them.
/// </para>
/// <para>
/// Another quirk of this texture is that Unity always reports its size as
/// 1300px × 1300px in the editor. In reality, 3D WebView resizes the
/// texture in native code to match the dimensions of the webview, but
/// Unity doesn't provide an API to notify the engine that an external texture's size
/// has changed. So, Unity always reports its size as the initial size that was
/// passed to Texture2D.CreateExternalTexture(), which in 3D WebView's case is
/// 1300px × 1300px.
/// </para>
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// var material = webViewPrefab.WebView.CreateMaterial();
/// // Note: the material returned by CreateMaterial() already
/// // has its mainTexture set to IWebView.Texture, so setting
/// // it explicitly like this is really only needed if you are
/// // switching a material from one webview's texture to another.
/// material.mainTexture = webViewPrefab.WebView.Texture;
/// </code>
/// </example>
Texture2D Texture { get; }
/// <summary>
/// Gets the current web page title.
/// </summary>
/// <example>
/// <code>
/// // Get the page's title after it finishes loading.
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// Debug.Log("Page title: " + webViewPrefab.WebView.Title);
/// </code>
/// </example>
/// <seealso cref="TitleChanged"/>
string Title { get; }
/// <summary>
/// Gets the current URL.
/// </summary>
/// <example>
/// <code>
/// // Get the page's URL after it finishes loading.
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// Debug.Log("Page URL: " + webViewPrefab.WebView.Url);
/// </code>
/// </example>
/// <seealso cref="UrlChanged"/>
string Url { get; }
/// <summary>
/// Checks whether the webview can go back with a call to GoBack().
/// </summary>
/// <example>
/// <c>var canGoBack = await webViewPrefab.CanGoBack();</c>
/// </example>
/// <seealso cref="GoBack"/>
Task<bool> CanGoBack();
/// <summary>
/// Checks whether the webview can go forward with a call to GoForward().
/// </summary>
/// <example>
/// <c>var canGoForward = await webViewPrefab.CanGoForward();</c>
/// </example>
/// <seealso cref="GoForward"/>
Task<bool> CanGoForward();
/// <summary>
/// Returns a PNG image of the content visible in the webview.
/// </summary>
/// <remarks>
/// On iOS, screenshots do not include video content, which appears black.
/// </remarks>
/// <example>
/// <code>
/// // Get a screenshot and write it to a file.
/// var screenshotBytes = await webViewPrefab.WebView.CaptureScreenshot();
/// var filePath = Path.Combine(Application.peristentDataPath, "screenshot.png");
/// File.WriteAllBytes(filePath, screenshotBytes);
/// </code>
/// </example>
/// <seealso href="https://docs.unity3d.com/ScriptReference/ImageConversion.LoadImage.html">ImageConversion.LoadImage()</seealso>
/// <seealso cref="GetRawTextureData"/>
Task<byte[]> CaptureScreenshot();
/// <summary>
/// Clicks at the given coordinates in pixels in the web page, dispatching both a mouse
/// down and a mouse up event.
/// </summary>
/// <example>
/// <code>
/// // Click at (250px, 100px).
/// webViewPrefab.WebView.Click(250, 100);
///
/// // Click at (50px, 150px) and prevent stealing focus from another webview.
/// webViewPrefab.WebView.Click(50, 150, true);
/// </code>
/// </example>
void Click(int xInPixels, int yInPixels, bool preventStealingFocus = false);
/// <summary>
/// Like Click(int, int, bool?), except it takes a normalized point instead of
/// pixel coordinates.
/// </summary>
/// <example>
/// <code>
/// // Click in the exact center of the page.
/// webViewPrefab.WebView.Click(new Vector2(0.5f, 0.5f));
///
/// // Click in the upper right quadrant of the page
/// // and prevent stealing focus from another webview.
/// webViewPrefab.WebView.Click(new Vector2(0.75f, 0.25f), true);
/// </code>
/// </example>
void Click(Vector2 normalizedPoint, bool preventStealingFocus = false);
/// <summary>
/// Copies the selected text to the clipboard.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.Copy();</c>
/// </example>
/// <seealso cref="Cut"/>
/// <seealso cref="Paste"/>
/// <seealso cref="SelectAll"/>
void Copy();
/// <summary>
/// Creates a Material that can be used to display the webview.
/// The returned material already has the webview's Texture set as its mainTexture.
/// </summary>
/// <remarks>
/// Note that WebViewPrefab and CanvasWebViewPrefab take care of material creation for you, so you only need
/// to call this method directly if you need to create an IWebView instance outside of a prefab with
/// Web.CreateWebView().
/// </remarks>
/// <example>
/// <code>
/// GetComponent&lt;Renderer&gt;().material = webView.CreateMaterial();
/// </code>
/// </example>
Material CreateMaterial();
/// <summary>
/// Copies the selected text to the clipboard and removes it.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.Cut();</c>
/// </example>
/// <seealso cref="Copy"/>
/// <seealso cref="Paste"/>
/// <seealso cref="SelectAll"/>
void Cut();
/// <summary>
/// Destroys the webview, releasing all of its resources.
/// </summary>
/// <remarks>
/// If you're using a WebViewPrefab or CanvasWebViewPrefab, please call Destroy() on the prefab instead
/// of calling IWebView.Dispose(). Calling IWebView.Dispose() while the prefab is still using the webview
/// can cause issues.
/// </remarks>
void Dispose();
/// <summary>
/// Executes the given JavaScript in the context of the page and returns the result.
/// </summary>
/// <remarks>
/// In order to run JavaScript, a web page must first be loaded. You can use WaitForNextPageLoadToFinish() or the
/// LoadProgressChanged event to run JavaScript after a page loads.
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// var headerText = await webViewPrefab.WebView.ExecuteJavaScript("document.getElementsByTagName('h1')[0].innerText");
/// Debug.Log("H1 text: " + headerText);
/// </code>
/// </example>
/// <seealso cref="PageLoadScripts"/>
/// <seealso href="https://support.vuplex.com/articles/javascript-promise-result">How to get ExecuteJavaScript() to return the result of a Promise?</seealso>
/// <seealso href="https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp">JS-to-C# message passing</seealso>
/// <seealso href="https://support.vuplex.com/articles/how-to-get-html">How to get HTML, text, images, or other info from a web page?</seealso>
Task<string> ExecuteJavaScript(string javaScript);
/// <summary>
/// Like the other version of ExecuteJavaScript(), except it uses a callback instead
/// of a Task to return the result. If you don't need the result from executing the JavaScript, you can
/// improve the method's efficiency by passing `null` as the callback argument.
/// </summary>
void ExecuteJavaScript(string javaScript, Action<string> callback);
/// <summary>
/// A replacement for [Texture2D.GetRawTextureData()](https://docs.unity3d.com/ScriptReference/Texture2D.GetRawTextureData.html)
/// for IWebView.Texture.
/// </summary>
/// <remarks>
/// Unity's Texture2D.GetRawTextureData() method currently does not work for textures created with
/// Texture2D.CreateExternalTexture(). So, this method serves as a replacement by providing
/// the equivalent functionality. You can load the bytes returned by this method into another
/// texture using [Texture2D.LoadRawTextureData()](https://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html).
/// Note that on iOS, the texture data excludes video content, which appears black.
/// </remarks>
/// <example>
/// <code>
/// var webView = webViewPrefab.WebView;
/// var textureData = await webView.GetRawTextureData();
/// var texture = new Texture2D(
/// webView.Size.x,
/// webView.Size.y,
/// TextureFormat.RGBA32,
/// false,
/// false
/// );
/// texture.LoadRawTextureData(textureData);
/// texture.Apply();
/// </code>
/// </example>
/// <seealso href="https://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html">Texture2D.GetRawTextureData()</seealso>
/// <seealso cref="CaptureScreenshot"/>
Task<byte[]> GetRawTextureData();
/// <summary>
/// Navigates back to the previous page in the webview's history.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.GoBack();</c>
/// </example>
/// <seealso cref="CanGoBack"/>
void GoBack();
/// <summary>
/// Navigates forward to the next page in the webview's history.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.GoForward();</c>
/// </example>
/// <seealso cref="CanGoForward"/>
void GoForward();
/// <summary>
/// Asynchronously initializes the webview with the given the dimensions in pixels.
/// </summary>
/// <remarks>
/// Note that you don't need to call this method if you're using one of the prefabs, like WebViewPrefab.
/// You only need to call Init() if you create an IWebView directly with Web.CreateWebView()].
/// Also, this method's signature was [updated in 3D WebView v4](https://support.vuplex.com/articles/v4-changes#init).
/// </remarks>
Task Init(int width, int height);
/// <summary>
/// Loads the web page contained in the given HTML string. Note that HTML loaded via this method
/// cannot load subresources (e.g. images, CSS, JavaScript) from the local file system (i.e. via file:// URLs).
/// If you need to load subresources from the local file system, please use one of the approaches described
/// in <see="https://support.vuplex.com/articles/how-to-load-local-files">this article</see> instead.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.LoadHtml(@"
/// <!DOCTYPE html>
/// <html>
/// <head>
/// <title>Test Page</title>
/// <style>
/// h1 {
/// font-family: Helvetica, Arial, Sans-Serif;
/// }
/// </style>
/// </head>
/// <body>
/// <h1>LoadHtml Example</h1>
/// <script>
/// console.log('This page was loaded!');
/// </script>
/// </body>
/// </html>"
/// );
/// ]]>
/// </code>
/// </example>
/// <seealso cref="LoadUrl"/>
void LoadHtml(string html);
/// <summary>
/// Loads the given URL. Supported URL schemes:
/// - `http://`, `https://` - loads a remote page over HTTP
/// - `streaming-assets://` - loads a local page from StreamingAssets
/// (equivalent to `"file://" + Application.streamingAssetsPath + path`)
/// - `file://` - some platforms support loading arbitrary file URLs
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.LoadUrl("https://vuplex.com");
/// </code>
/// </example>
/// <seealso href="https://support.vuplex.com/articles/how-to-load-local-files">How to load local files</seealso>
/// <seealso cref="LoadHtml"/>
/// <seealso cref="WebViewPrefab.InitialUrl"/>
void LoadUrl(string url);
/// <summary>
/// Like LoadUrl(string url), but also sends the given additional HTTP request headers
/// when loading the URL. The headers are sent for the initial page load request but are not sent
/// for requests for subsequent resources, like linked JavaScript or CSS files.
/// </summary>
/// <remarks>
/// On Windows and macOS, this method cannot be used to set the Accept-Language header.
/// For more info, please see [this article](https://support.vuplex.com/articles/how-to-change-accept-language-header).
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// webViewPrefab.WebView.LoadUrl("https://vuplex.com", new Dictionary&lt;string, string&gt; {
/// ["Authorization"] = "Basic YWxhZGRpbjpvcGVuc2VzYW1l",
/// ["Cookie"] = "foo=bar"
/// });
/// </code>
/// </example>
void LoadUrl(string url, Dictionary<string, string> additionalHttpHeaders);
/// <summary>
/// Returns a point in pixels for the given normalized point.
/// </summary>
/// <seealso cref="PointToNormalized"/>
Vector2Int NormalizedToPoint(Vector2 normalizedPoint);
/// <summary>
/// Pastes text from the clipboard.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.Paste();</c>
/// </example>
/// <seealso cref="Copy"/>
/// <seealso cref="Cut"/>
void Paste();
/// <summary>
/// Returns a normalized point for the given x and y coordinates in pixels.
/// This can be used to create normalized points for APIs that accept them, like MovePointer().
/// </summary>
/// <example>
/// <code>
/// var webView = webViewPrefab.WebView;
/// // Scroll to the right by 50 pixels at (100px, 1300px).
/// webView.Scroll(
/// webView.PointToNormalized(50, 0),
/// webView.PointToNormalized(100, 1300)
/// );
/// </code>
/// </example>
/// <seealso cref="NormalizedToPoint"/>
Vector2 PointToNormalized(int xInPixels, int yInPixels);
/// <summary>
/// Posts a message that JavaScript within the webview can listen for
/// using `window.vuplex.addEventListener('message', function(message) {})`.
/// The provided data string is passed as the data property of the message object.
/// For more details, please see [this support article](https://support.vuplex.com/articles/how-to-send-messages-from-javascript-to-c-sharp).
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WebView.WaitUntilInitialized();
/// // Add some JavaScript to the page to receive the message.
/// webViewPrefab.WebView.PageLoadScripts(@"
/// window.vuplex.addEventListener('message', function(event) {
/// console.log('Message received from C#: ' + event.data);
/// });
/// ");
/// // When the page finishes loading, send a message from C# to JavaScript.
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// webViewPrefab.WebView.PostMessage("Hello from C#");
/// </code>
/// </example>
void PostMessage(string data);
/// <summary>
/// Reloads the current page.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.Reload();</c>
/// </example>
void Reload();
/// <summary>
/// Resizes the webview to the given dimensions in pixels.
/// </summary>
/// <remarks>
/// If you're using WebViewPrefab, you should call WebViewPrefab.Resize() instead.
/// </remarks>
/// <seealso cref="Size"/>
/// <seealso cref="WebViewPrefab.Resolution"/>
void Resize(int width, int height);
/// <summary>
/// Scrolls the top-level document by the given delta in pixels.
/// This method works by calling window.scrollBy(), which works for simple web
/// pages but not for all pages. An alternative is to instead use Scroll(Vector2, Vector2)
/// to scroll at a specific location in the page.
/// </summary>
/// <example>
/// <code>
/// // Scroll down by 50 pixels.
/// webViewPrefab.WebView.Scroll(0, 50);
///
/// // Scroll to the left by 20 pixels.
/// webViewPrefab.WebView.Scroll(-20, 0);
/// </code>
/// </example>
void Scroll(int scrollDeltaXInPixels, int scrollDeltaYInPixels);
/// <summary>
/// Like Scroll(int, int), but accepts a normalized scroll delta instead of
/// values in pixels.
/// </summary>
/// <example>
/// <code>
/// // Scroll down one quarter of the page.
/// webViewPrefab.WebView.Scroll(new Vector2(0, 0.25f));
/// </code>
/// </example>
void Scroll(Vector2 normalizedScrollDelta);
/// <summary>
/// Scrolls by the given normalized scroll delta at the given normalized pointer position.
/// </summary>
/// <example>
/// <code>
/// var webView = webViewPrefab.WebView;
/// // Scroll down by a quarter of the page in the center of the page
/// webView.Scroll(new Vector2(0, 0.25f), new Vector2(0.5f, 0.5f));
///
/// // Scroll to the right by 50 pixels at (100px, 1300px).
/// webView.Scroll(
/// webView.PointToNormalized(50, 0),
/// webView.PointToNormalized(100, 1300)
/// );
/// </code>
/// </example>
void Scroll(Vector2 normalizedScrollDelta, Vector2 normalizedPoint);
/// <summary>
/// Selects all text, depending on the page's focused element.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.SelectAll();</c>
/// </example>
/// <seealso cref="Copy"/>
void SelectAll();
/// <summary>
/// Dispatches the given keyboard key to the webview.
/// </summary>
/// <param name="key">
/// A key can either be a single character representing
/// a unicode character (e.g. "A", "b", "?") or a [JavaScript key value](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
/// (e.g. "ArrowUp", "Enter", "Backspace", "Delete").
/// </param>
/// <example>
/// <code>
/// // Type "Hi!" and then submit the Enter key.
/// webViewPrefab.WebView.SendKey("H");
/// webViewPrefab.WebView.SendKey("i");
/// webViewPrefab.WebView.SendKey("!");
/// webViewPrefab.WebView.SendKey("Enter");
/// </code>
/// </example>
/// <seealso cref="IWithKeyDownAndUp"/>
void SendKey(string key);
/// <summary>
/// By default, if a web page doesn't specify a background, 3D WebView sets the page's
/// background to white because that's what web browsers typically do. However, an
/// application can use this method to disable the default white background so that pages
/// that don't set a background will instead have a transparent background. Note that this method
/// must be called before a web page is loaded in order for it to take effect for that page.
/// </summary>
/// <remarks>
/// Nearly all of the 3D WebView packages support transparent webviews, but there are two exceptions: <br/>
/// - 3D WebView for Android with Gecko Engine doesn't support transparency because the mobile Gecko browser engine doesn't currently support it. <br/>
/// - 3D WebView for UWP doesn't support transparency on mixed reality headsets like Hololens.
/// </remarks>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// // Disable the default white background so the page can be transparent.
/// webViewPrefab.WebView.SetDefaultBackgroundEnabled(false);
/// </code>
/// </example>
/// <seealso href="https://support.vuplex.com/articles/how-to-make-a-webview-transparent">How to make a webview transparent?</seealso>
void SetDefaultBackgroundEnabled(bool enabled);
/// <summary>
/// Makes the webview take or relinquish focus.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.SetFocused(true);</c>
/// </example>
void SetFocused(bool focused);
/// <summary>
/// Enables or disables the webview's ability to render to its texture.
/// By default, a webview renders web content to its texture, but you can
/// use this method to disable or re-enable rendering.
/// </summary>
/// <remarks>
/// This method is ignored when running in [Native 2D Mode](https://support.vuplex.com/articles/native-2d-mode).
/// </remarks>
/// <example>
/// <c>webViewPrefab.WebView.SetRenderingEnabled(false);</c>
/// </example>
void SetRenderingEnabled(bool enabled);
/// <summary>
/// Stops the current page load if one is in progress.
/// </summary>
/// <example>
/// <c>webViewPrefab.WebView.StopLoad();</c>
/// </example>
void StopLoad();
/// <summary>
/// Returns a task that completes when the next page load finishes loading, or
/// throws a PageLoadFailedException if the page load fails.
/// </summary>
/// <example>
/// <code>
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// Debug.Log("The web page finished loading.");
/// </code>
/// </example>
/// <seealso cref="LoadProgressChanged"/>
Task WaitForNextPageLoadToFinish();
/// <summary>
/// Zooms into the currently loaded web content. Note that the zoom level gets reset when a new page is loaded.
/// </summary>
/// <remarks>
/// On Windows and macOS, adjusting the zoom also affects other webviews viewing the same site,
/// similar to how tabs behave in a desktop browser.
/// </remarks>
/// <example>
/// <code>
/// // Zoom in after the page finishes loading.
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// webViewPrefab.WebView.ZoomIn();
/// </code>
/// </example>
void ZoomIn();
/// <summary>
/// Zooms back out after a previous call to ZoomIn(). Note that the zoom level gets reset when a new page is loaded.
/// </summary>
/// <remarks>
/// On Windows and macOS, adjusting the zoom also affects other webviews viewing the same site,
/// similar to how tabs behave in a desktop browser.
/// </remarks>
/// <example>
/// <code>
/// // Zoom out after the page finishes loading.
/// await webViewPrefab.WaitUntilInitialized();
/// await webViewPrefab.WebView.WaitForNextPageLoadToFinish();
/// webViewPrefab.WebView.ZoomOut();
/// </code>
/// </example>
void ZoomOut();
#region Obsolete APIs
// Added in v1.0, deprecated in v3.13, removed in v4.0.
[Obsolete(ObsoletionMessages.Blur, true)]
void Blur();
// Added in v1.0, deprecated in v3.16, removed in v4.0.
[Obsolete(ObsoletionMessages.CanGoBack, true)]
void CanGoBack(Action<bool> callback);
// Added in v1.0, deprecated in v3.16, removed in v4.0.
[Obsolete(ObsoletionMessages.CanGoForward, true)]
void CanGoForward(Action<bool> callback);
// Added in v2.4, deprecated in v3.16, removed in v4.0.
[Obsolete(ObsoletionMessages.CaptureScreenshot, true)]
void CaptureScreenshot(Action<byte[]> callback);
[Obsolete(ObsoletionMessages.DisableViewUpdates, true)]
void DisableViewUpdates();
[Obsolete(ObsoletionMessages.EnableViewUpdates, true)]
void EnableViewUpdates();
// Added in v1.0, deprecated in v3.13, removed in v4.0.
[Obsolete(ObsoletionMessages.Focus, true)]
void Focus();
// Added in v2.6, deprecated in v3.16, removed in v4.0.
[Obsolete(ObsoletionMessages.GetRawTextureData, true)]
void GetRawTextureData(Action<byte[]> callback);
// Added in v1.0, deprecated in v4.0.
[Obsolete(ObsoletionMessages.HandleKeyboardInput)]
void HandleKeyboardInput(string key);
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.Init, true)]
void Init(Texture2D texture, float width, float height);
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.Init2, true)]
void Init(Texture2D texture, float width, float height, Texture2D videoTexture);
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.Resolution, true)]
float Resolution { get; }
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.SetResolution, true)]
void SetResolution(float pixelsPerUnityUnit);
// Deprecated in v4.0
[Obsolete(ObsoletionMessages.SizeInPixels)]
Vector2 SizeInPixels { get; }
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.VideoRectChanged, true)]
event EventHandler<EventArgs<Rect>> VideoRectChanged;
// Added in v1.0, removed in v4.0.
[Obsolete(ObsoletionMessages.VideoTexture, true)]
Texture2D VideoTexture { get; }
#endregion
}
static class ObsoletionMessages {
public const string Blur = "IWebView.Blur() has been removed. Please use SetFocused(false) instead: https://developer.vuplex.com/webview/IWebView#SetFocused";
public const string CanGoBack = "The callback-based CanGoBack(Action) version of this method has been removed. Please switch to the Task-based CanGoBack() version instead. If you prefer using a callback instead of awaiting the Task, you can still use a callback like this: CanGoBack().ContinueWith(result => {...})";
public const string CanGoForward = "The callback-based CanGoForward(Action) version of this method has been removed. Please switch to the Task-based CanGoForward() version instead. If you prefer using a callback instead of awaiting the Task, you can still use a callback like this: CanGoForward().ContinueWith(result => {...})";
public const string CaptureScreenshot = "The callback-based CaptureScreenshot(Action) version of this method has been removed. Please switch to the Task-based CaptureScreenshot() version instead. If you prefer using a callback instead of awaiting the Task, you can still use a callback like this: CaptureScreenshot().ContinueWith(result => {...})";
public const string DisableViewUpdates = "DisableViewUpdates() has been removed. Please use SetRenderingEnabled(false) instead: https://developer.vuplex.com/webview/IWebView#SetRenderingEnabled";
public const string EnableViewUpdates = "EnableViewUpdates() has been removed. Please use SetRenderingEnabled(true) instead: https://developer.vuplex.com/webview/IWebView#SetRenderingEnabled";
public const string Focus = "IWebView.Focus() has been removed. Please use SetFocused(false) instead: https://developer.vuplex.com/webview/IWebView#SetFocused";
public const string GetRawTextureData = "The callback-based GetRawTextureData(Action) version of this method has been removed. Please switch to the Task-based GetRawTextureData() version instead. If you prefer using a callback instead of awaiting the Task, you can still use a callback like this: GetRawTextureData().ContinueWith(result => {...})";
public const string HandleKeyboardInput = "IWebView.HandleKeyboardInput() has been renamed to IWebView.SendKey(). Please switch to SendKey().";
public const string Init = "IWebView.Init(Texture2D, float, float) has been removed in v4. Please switch to IWebView.Init(int, int) and await the Task it returns. For more details, please see this article: https://support.vuplex.com/articles/v4-changes#init";
public const string Init2 = "IWebView.Init(Texture2D, float, float, Texture2D) has been removed in v4. Please switch to IWebView.Init(int, int) and await the Task it returns. For more details, please see this article: https://support.vuplex.com/articles/v4-changes#init";
public const string Resolution = "IWebView.Resolution has been removed in v4. Please use WebViewPrefab.Resolution or CanvasWebViewPrefab.Resolution instead. For more details, please see this article: https://support.vuplex.com/articles/v4-changes#resolution";
public const string SetResolution = "IWebView.SetResolution() has been removed in v4. Please set the WebViewPrefab.Resolution or CanvasWebViewPrefab.Resolution property instead. For more details, please see this article: https://support.vuplex.com/articles/v4-changes#resolution";
public const string SizeInPixels = "IWebView.SizeInPixels is now deprecated. Please use IWebView.Size instead: https://developer.vuplex.com/webview/IWebView#Size";
public const string VideoRectChanged = "IWebView.VideoRectChanged has been removed. Please use IWithFallbackVideo.VideoRectChanged instead: https://developer.vuplex.com/webview/IWithFallbackVideo#VideoRectChanged";
public const string VideoTexture = "IWebView.VideoTexture has been removed. Please use IWithFallbackVideo.VideoTexture instead: https://developer.vuplex.com/webview/IWithFallbackVideo#VideoTexture";
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 50fd149ca81084699834f1aab50202f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,30 +0,0 @@
// Copyright (c) 2023 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;
namespace Vuplex.WebView {
/// <summary>
/// Unity added support for using Texture2D.CreateExternalTexture() with Vulkan in 2020.2,
/// but support for Texture2D.UpdateExternalTexture() wasn't added until 2022.1.
/// So, this interface is used by 3D WebView on Android to update the texture
/// when Vulkan is used with versions of Unity prior to 2022.1.
/// https://issuetracker.unity3d.com/issues/android-vulkan-texture2d-dot-updateexternaltexture-does-not-respond-when-a-project-is-built-on-android-with-vulkan-graphics-api
/// </summary>
public interface IWithChangingTexture {
event EventHandler<EventArgs<Texture2D>> TextureChanged;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 749ba8541c9624896bf3788189c9477e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More